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