Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 58
0.00% covered (danger)
0.00%
0 / 2
CRAP
0.00% covered (danger)
0.00%
0 / 1
RecomputeNotifCounts
0.00% covered (danger)
0.00%
0 / 53
0.00% covered (danger)
0.00%
0 / 2
132
0.00% covered (danger)
0.00%
0 / 1
 __construct
0.00% covered (danger)
0.00%
0 / 9
0.00% covered (danger)
0.00%
0 / 1
2
 execute
0.00% covered (danger)
0.00%
0 / 44
0.00% covered (danger)
0.00%
0 / 1
110
1<?php
2/**
3 * Recompute notification counts for all users.
4 *
5 * @ingroup Maintenance
6 */
7
8use MediaWiki\Extension\Notifications\DbFactory;
9use MediaWiki\Extension\Notifications\NotifUser;
10use MediaWiki\User\User;
11
12require_once getenv( 'MW_INSTALL_PATH' ) !== false
13    ? getenv( 'MW_INSTALL_PATH' ) . '/maintenance/Maintenance.php'
14    : __DIR__ . '/../../../maintenance/Maintenance.php';
15
16/**
17 * Maintenance script that recomputes notification counts
18 *
19 * @ingroup Maintenance
20 */
21class RecomputeNotifCounts extends Maintenance {
22
23    public function __construct() {
24        parent::__construct();
25
26        $this->addDescription( 'Recompute notification counts for all users.' );
27        $this->addOption( 'user-ids',
28            'Comma-separated list of users to recompute notification counts for', false, true );
29        $this->addOption( 'notif-types',
30            'Recompute counts for all users who have unread notifications of one of these types (comma-separated)',
31            false, true );
32
33        $this->setBatchSize( 500 );
34
35        $this->requireExtension( 'Echo' );
36    }
37
38    public function execute() {
39        $dbFactory = DbFactory::newFromDefault();
40        $dbrEcho = $dbFactory->getEchoDb( DB_REPLICA );
41
42        $userIDs = $this->getOption( 'user-ids' );
43        $userIDs = $userIDs ? explode( ',', $userIDs ) : null;
44        $notifTypes = $this->getOption( 'notif-types' );
45        $notifTypes = $notifTypes ? explode( ',', $notifTypes ) : null;
46
47        if ( $userIDs ) {
48            $userIterator = array_chunk( $userIDs, $this->getBatchSize() );
49        } elseif ( $notifTypes ) {
50            $userIterator = new BatchRowIterator(
51                $dbrEcho,
52                [ 'echo_event', 'echo_notification' ],
53                'notification_user',
54                $this->getBatchSize()
55            );
56            $userIterator->addJoinConditions( [
57                'echo_notification' => [ 'INNER JOIN', 'notification_event=event_id' ]
58            ] );
59            $userIterator->addConditions( [
60                'event_type' => $notifTypes,
61                'notification_read_timestamp' => null
62            ] );
63            $userIterator->addOptions( [
64                'GROUP BY' => 'notification_user'
65            ] );
66            $userIterator->setCaller( __METHOD__ );
67        } else {
68            $userQuery = User::getQueryInfo();
69            $userIterator = new BatchRowIterator(
70                $this->getReplicaDB(), $userQuery['tables'], 'user_id', $this->getBatchSize()
71            );
72            $userIterator->setFetchColumns( $userQuery['fields'] );
73            $userIterator->addJoinConditions( $userQuery['joins'] );
74            $userIterator->setCaller( __METHOD__ );
75        }
76
77        $count = 0;
78        foreach ( $userIterator as $batch ) {
79            foreach ( $batch as $rowOrID ) {
80                if ( is_object( $rowOrID ) && isset( $rowOrID->user_id ) ) {
81                    $user = User::newFromRow( $rowOrID );
82                } else {
83                    $user = User::newFromId( is_object( $rowOrID ) ? $rowOrID->notification_user : $rowOrID );
84                }
85                $notifUser = NotifUser::newFromUser( $user );
86                $notifUser->resetNotificationCount();
87            }
88            $count += count( $batch );
89            $this->output( "$count users' counts recomputed.\n" );
90            $this->waitForReplication();
91        }
92    }
93}
94
95$maintClass = RecomputeNotifCounts::class;
96require_once RUN_MAINTENANCE_IF_MAIN;