Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 44
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 / 39
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 / 22
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( [ "rl_id > $maxId", 'rl_deleted' => 0, ] )
52                    ->limit( 1000 )
53                    ->orderBy( 'rl_id', 'ASC' )
54                    ->caller( __METHOD__ )->fetchFieldValues();
55                if ( !$ids ) {
56                    break;
57                }
58                foreach ( $ids as $id ) {
59                    $changed = $this->fixRow( $id );
60                    if ( $changed ) {
61                        $i++;
62                    }
63                    $maxId = (int)$id;
64                }
65                $this->waitForReplication();
66            }
67            $this->output( "Fixed $i lists.\n" );
68        }
69    }
70
71    /**
72     * Recalculate the size of the given list.
73     * @param int $listId
74     * @return bool True if the row was changed.
75     * @throws ReadingListRepositoryException
76     */
77    private function fixRow( $listId ) {
78        $repo = Utils::makeMaintenanceRepository();
79        try {
80            $this->output( "Fixing list $listId... " );
81            $changed = $repo->fixListSize( $listId );
82        } catch ( ReadingListRepositoryException $e ) {
83            if ( $e->getMessageObject()->getKey() === 'readinglists-db-error-no-such-list' ) {
84                $this->error( "not found, skipping\n" );
85                return false;
86            } else {
87                throw $e;
88            }
89        }
90        $this->output( $changed ? "done\n" : "no change needed\n" );
91        return $changed;
92    }
93
94}
95
96$maintClass = FixListSize::class;
97require_once RUN_MAINTENANCE_IF_MAIN;