Merge "Fix order of @var parameter in PHP"
[lhc/web/wiklou.git] / includes / jobqueue / jobs / ClearWatchlistNotificationsJob.php
index 94c1351..f53174a 100644 (file)
 use MediaWiki\MediaWikiServices;
 
 /**
- * Job for clearing all of the "last viewed" timestamps for a user's watchlist
+ * Job for clearing all of the "last viewed" timestamps for a user's watchlist, or setting them all
+ * to the same value.
  *
  * Job parameters include:
  *   - userId: affected user ID [required]
  *   - casTime: UNIX timestamp of the event that triggered this job [required]
+ *   - timestamp: value to set all of the "last viewed" timestamps to [optional, defaults to null]
  *
  * @ingroup JobQueue
  * @since 1.31
  */
-class ClearWatchlistNotificationsJob extends Job {
-       function __construct( Title $title, array $params ) {
-               parent::__construct( 'clearWatchlistNotifications', $title, $params );
+class ClearWatchlistNotificationsJob extends Job implements GenericParameterJob {
+       function __construct( array $params ) {
+               parent::__construct( 'clearWatchlistNotifications', $params );
 
                static $required = [ 'userId', 'casTime' ];
                $missing = implode( ', ', array_diff( $required, array_keys( $this->params ) ) );
                if ( $missing != '' ) {
-                       throw new InvalidArgumentException( "Missing paramter(s) $missing" );
+                       throw new InvalidArgumentException( "Missing parameter(s) $missing" );
                }
 
                $this->removeDuplicates = true;
@@ -51,29 +53,49 @@ class ClearWatchlistNotificationsJob extends Job {
 
                $dbw = $lbFactory->getMainLB()->getConnection( DB_MASTER );
                $ticket = $lbFactory->getEmptyTransactionTicket( __METHOD__ );
+               $timestamp = $this->params['timestamp'] ?? null;
+               if ( $timestamp === null ) {
+                       $timestampCond = 'wl_notificationtimestamp IS NOT NULL';
+               } else {
+                       $timestamp = $dbw->timestamp( $timestamp );
+                       $timestampCond = 'wl_notificationtimestamp != ' . $dbw->addQuotes( $timestamp ) .
+                               ' OR wl_notificationtimestamp IS NULL';
+               }
+               // New notifications since the reset should not be cleared
+               $casTimeCond = 'wl_notificationtimestamp < ' .
+                       $dbw->addQuotes( $dbw->timestamp( $this->params['casTime'] ) ) .
+                       ' OR wl_notificationtimestamp IS NULL';
 
-               $asOfTimes = array_unique( $dbw->selectFieldValues(
-                       'watchlist',
-                       'wl_notificationtimestamp',
-                       [ 'wl_user' => $this->params['userId'], 'wl_notificationtimestamp IS NOT NULL' ],
-                       __METHOD__,
-                       [ 'ORDER BY' => 'wl_notificationtimestamp DESC' ]
-               ) );
-
-               foreach ( array_chunk( $asOfTimes, $rowsPerQuery ) as $asOfTimeBatch ) {
-                       $dbw->update(
+               $firstBatch = true;
+               do {
+                       $idsToUpdate = $dbw->selectFieldValues(
                                'watchlist',
-                               [ 'wl_notificationtimestamp' => null ],
+                               'wl_id',
                                [
                                        'wl_user' => $this->params['userId'],
-                                       'wl_notificationtimestamp' => $asOfTimeBatch,
-                                       // New notifications since the reset should not be cleared
-                                       'wl_notificationtimestamp < ' .
-                                               $dbw->addQuotes( $dbw->timestamp( $this->params['casTime'] ) )
+                                       $timestampCond,
+                                       $casTimeCond,
                                ],
-                               __METHOD__
+                               __METHOD__,
+                               [ 'LIMIT' => $rowsPerQuery ]
                        );
-                       $lbFactory->commitAndWaitForReplication( __METHOD__, $ticket );
-               }
+                       if ( $idsToUpdate ) {
+                               $dbw->update(
+                                       'watchlist',
+                                       [ 'wl_notificationtimestamp' => $timestamp ],
+                                       [
+                                               'wl_id' => $idsToUpdate,
+                                               // For paranoia, enforce the CAS time condition here too
+                                               $casTimeCond
+                                       ],
+                                       __METHOD__
+                               );
+                               if ( !$firstBatch ) {
+                                       $lbFactory->commitAndWaitForReplication( __METHOD__, $ticket );
+                               }
+                               $firstBatch = false;
+                       }
+               } while ( $idsToUpdate );
+               return true;
        }
 }