Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 47
0.00% covered (danger)
0.00%
0 / 4
CRAP
0.00% covered (danger)
0.00%
0 / 1
FixListSize
0.00% covered (danger)
0.00%
0 / 42
0.00% covered (danger)
0.00%
0 / 4
156
0.00% covered (danger)
0.00%
0 / 1
 __construct
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 1
2
 setupServices
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
2
 execute
0.00% covered (danger)
0.00%
0 / 25
0.00% covered (danger)
0.00%
0 / 1
42
 fixRow
0.00% covered (danger)
0.00%
0 / 10
0.00% covered (danger)
0.00%
0 / 1
20
1<?php
2
3namespace MediaWiki\Extension\ReadingLists\Maintenance;
4
5use Maintenance;
6use MediaWiki\Extension\ReadingLists\ReadingListRepositoryException;
7use MediaWiki\Extension\ReadingLists\Utils;
8use MediaWiki\MediaWikiServices;
9use Wikimedia\Rdbms\IDatabase;
10
11require_once getenv( 'MW_INSTALL_PATH' ) !== false
12    ? getenv( 'MW_INSTALL_PATH' ) . '/maintenance/Maintenance.php'
13    : __DIR__ . '/../../../maintenance/Maintenance.php';
14
15/**
16 * Fill the database with test data, or remove it.
17 */
18class FixListSize extends Maintenance {
19    /** @var IDatabase */
20    private $dbw;
21
22    public function __construct() {
23        parent::__construct();
24        $this->addDescription( 'Recalculate the reading_list.rl_size field.' );
25        $this->addOption( 'list', 'List ID', false, true );
26        $this->requireExtension( 'ReadingLists' );
27    }
28
29    private function setupServices() {
30        // Can't do this in the constructor, initialization not done yet.
31        $this->dbw = MediaWikiServices::getInstance()->getDBLoadBalancerFactory()->getPrimaryDatabase(
32            Utils::VIRTUAL_DOMAIN
33        );
34    }
35
36    /**
37     * @inheritDoc
38     */
39    public function execute() {
40        $this->setupServices();
41
42        if ( $this->hasOption( 'list' ) ) {
43            $this->fixRow( $this->getOption( 'list' ) );
44        } else {
45            $i = $maxId = 0;
46            while ( true ) {
47                $ids = $this->dbw->newSelectQueryBuilder()
48                    ->select( 'rl_id' )
49                    ->from( 'reading_list' )
50                    // No point in wasting resources on fixing deleted lists.
51                    ->where( [
52                        $this->dbw->expr( 'rl_id', '>', $maxId ),
53                        'rl_deleted' => 0,
54                    ] )
55                    ->limit( 1000 )
56                    ->orderBy( 'rl_id', 'ASC' )
57                    ->caller( __METHOD__ )->fetchFieldValues();
58                if ( !$ids ) {
59                    break;
60                }
61                foreach ( $ids as $id ) {
62                    $changed = $this->fixRow( $id );
63                    if ( $changed ) {
64                        $i++;
65                    }
66                    $maxId = (int)$id;
67                }
68                $this->waitForReplication();
69            }
70            $this->output( "Fixed $i lists.\n" );
71        }
72    }
73
74    /**
75     * Recalculate the size of the given list.
76     * @param int $listId
77     * @return bool True if the row was changed.
78     * @throws ReadingListRepositoryException
79     */
80    private function fixRow( $listId ) {
81        $repo = Utils::makeMaintenanceRepository();
82        try {
83            $this->output( "Fixing list $listId... " );
84            $changed = $repo->fixListSize( $listId );
85        } catch ( ReadingListRepositoryException $e ) {
86            if ( $e->getMessageObject()->getKey() === 'readinglists-db-error-no-such-list' ) {
87                $this->error( "not found, skipping\n" );
88                return false;
89            } else {
90                throw $e;
91            }
92        }
93        $this->output( $changed ? "done\n" : "no change needed\n" );
94        return $changed;
95    }
96
97}
98
99$maintClass = FixListSize::class;
100require_once RUN_MAINTENANCE_IF_MAIN;