X-Git-Url: https://git.heureux-cyclage.org/?a=blobdiff_plain;f=includes%2FWatchedItemQueryService.php;h=c80e4a53198ddcc8ba8df8aadd93561566ef75f6;hb=f5f026d4b7192e51c63336895d51406301c84cba;hp=b7cdc53ab03d01ca7a4d9530cce4e8f63786838e;hpb=b68f99ccc61412827377b56d6dcc556e4b2a3ca4;p=lhc%2Fweb%2Fwiklou.git diff --git a/includes/WatchedItemQueryService.php b/includes/WatchedItemQueryService.php index b7cdc53ab0..c80e4a5319 100644 --- a/includes/WatchedItemQueryService.php +++ b/includes/WatchedItemQueryService.php @@ -50,10 +50,24 @@ class WatchedItemQueryService { */ private $loadBalancer; + /** @var WatchedItemQueryServiceExtension[]|null */ + private $extensions = null; + public function __construct( LoadBalancer $loadBalancer ) { $this->loadBalancer = $loadBalancer; } + /** + * @return WatchedItemQueryServiceExtension[] + */ + private function getExtensions() { + if ( $this->extensions === null ) { + $this->extensions = []; + Hooks::run( 'WatchedItemQueryServiceExtensions', [ &$this->extensions, $this ] ); + } + return $this->extensions; + } + /** * @return IDatabase * @throws MWException @@ -84,9 +98,6 @@ class WatchedItemQueryService { * timestamp to start enumerating from * 'end' => string (format accepted by wfTimestamp) requires 'dir' option, * timestamp to end enumerating - * 'startFrom' => [ string $rcTimestamp, int $rcId ] requires 'dir' option, - * return items starting from the RecentChange specified by this, - * $rcTimestamp should be in the format accepted by wfTimestamp * 'watchlistOwner' => User user whose watchlist items should be listed if different * than the one specified with $user param, * requires 'watchlistOwnerToken' option @@ -97,6 +108,7 @@ class WatchedItemQueryService { * generator ('rc_cur_id' or 'rc_this_oldid') if true, or all * id fields ('rc_cur_id', 'rc_this_oldid', 'rc_last_oldid') * if false (default) + * @param array|null &$startFrom Continuation value: [ string $rcTimestamp, int $rcId ] * @return array of pairs ( WatchedItem $watchedItem, string[] $recentChangeInfo ), * where $recentChangeInfo contains the following keys: * - 'rc_id', @@ -107,7 +119,9 @@ class WatchedItemQueryService { * - 'rc_deleted', * Additional keys could be added by specifying the 'includeFields' option */ - public function getWatchedItemsWithRecentChangeInfo( User $user, array $options = [] ) { + public function getWatchedItemsWithRecentChangeInfo( + User $user, array $options = [], &$startFrom = null + ) { $options += [ 'includeFields' => [], 'namespaceIds' => [], @@ -128,15 +142,19 @@ class WatchedItemQueryService { 'must be DIR_OLDER or DIR_NEWER' ); Assert::parameter( - !isset( $options['start'] ) && !isset( $options['end'] ) && !isset( $options['startFrom'] ) + !isset( $options['start'] ) && !isset( $options['end'] ) && $startFrom === null || isset( $options['dir'] ), '$options[\'dir\']', - 'must be provided when providing any of options: start, end, startFrom' + 'must be provided when providing the "start" or "end" options or the $startFrom parameter' ); Assert::parameter( - !isset( $options['startFrom'] ) - || ( is_array( $options['startFrom'] ) && count( $options['startFrom'] ) === 2 ), + !isset( $options['startFrom'] ), '$options[\'startFrom\']', + 'must not be provided, use $startFrom instead' + ); + Assert::parameter( + !isset( $startFrom ) || ( is_array( $startFrom ) && count( $startFrom ) === 2 ), + '$startFrom', 'must be a two-element array' ); if ( array_key_exists( 'watchlistOwner', $options ) ) { @@ -164,6 +182,21 @@ class WatchedItemQueryService { $dbOptions = $this->getWatchedItemsWithRCInfoQueryDbOptions( $options ); $joinConds = $this->getWatchedItemsWithRCInfoQueryJoinConds( $options ); + if ( $startFrom !== null ) { + $conds[] = $this->getStartFromConds( $db, $options, $startFrom ); + } + + foreach ( $this->getExtensions() as $extension ) { + $extension->modifyWatchedItemsWithRCInfoQuery( + $user, $options, $db, + $tables, + $fields, + $conds, + $dbOptions, + $joinConds + ); + } + $res = $db->select( $tables, $fields, @@ -173,8 +206,15 @@ class WatchedItemQueryService { $joinConds ); + $limit = isset( $dbOptions['LIMIT'] ) ? $dbOptions['LIMIT'] : INF; $items = []; + $startFrom = null; foreach ( $res as $row ) { + if ( --$limit <= 0 ) { + $startFrom = [ $row->rc_timestamp, $row->rc_id ]; + break; + } + $items[] = [ new WatchedItem( $user, @@ -185,6 +225,10 @@ class WatchedItemQueryService { ]; } + foreach ( $this->getExtensions() as $extension ) { + $extension->modifyWatchedItemsWithRCInfo( $user, $options, $db, $items, $res, $startFrom ); + } + return $items; } @@ -368,10 +412,6 @@ class WatchedItemQueryService { $conds[] = $deletedPageLogCond; } - if ( array_key_exists( 'startFrom', $options ) ) { - $conds[] = $this->getStartFromConds( $db, $options ); - } - return $conds; } @@ -382,10 +422,7 @@ class WatchedItemQueryService { $ownersToken = $watchlistOwner->getOption( 'watchlisttoken' ); $token = $options['watchlistOwnerToken']; if ( $ownersToken == '' || !hash_equals( $ownersToken, $token ) ) { - throw new UsageException( - 'Incorrect watchlist token provided -- please set a correct token in Special:Preferences', - 'bad_wltoken' - ); + throw ApiUsageException::newWithMessage( null, 'apierror-bad-watchlist-token', 'bad_wltoken' ); } return $watchlistOwner->getId(); } @@ -434,7 +471,7 @@ class WatchedItemQueryService { } private function getStartEndConds( IDatabase $db, array $options ) { - if ( !isset( $options['start'] ) && ! isset( $options['end'] ) ) { + if ( !isset( $options['start'] ) && !isset( $options['end'] ) ) { return []; } @@ -499,9 +536,9 @@ class WatchedItemQueryService { return ''; } - private function getStartFromConds( IDatabase $db, array $options ) { + private function getStartFromConds( IDatabase $db, array $options, array $startFrom ) { $op = $options['dir'] === self::DIR_OLDER ? '<' : '>'; - list( $rcTimestamp, $rcId ) = $options['startFrom']; + list( $rcTimestamp, $rcId ) = $startFrom; $rcTimestamp = $db->addQuotes( $db->timestamp( $rcTimestamp ) ); $rcId = (int)$rcId; return $db->makeList( @@ -583,7 +620,7 @@ class WatchedItemQueryService { } if ( array_key_exists( 'limit', $options ) ) { - $dbOptions['LIMIT'] = (int)$options['limit']; + $dbOptions['LIMIT'] = (int)$options['limit'] + 1; } return $dbOptions;