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