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