Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
0.00% |
0 / 32 |
|
0.00% |
0 / 3 |
CRAP | |
0.00% |
0 / 1 |
ActivityUpdateJob | |
0.00% |
0 / 31 |
|
0.00% |
0 / 3 |
42 | |
0.00% |
0 / 1 |
__construct | |
0.00% |
0 / 8 |
|
0.00% |
0 / 1 |
6 | |||
run | |
0.00% |
0 / 4 |
|
0.00% |
0 / 1 |
6 | |||
updateWatchlistNotification | |
0.00% |
0 / 19 |
|
0.00% |
0 / 1 |
6 |
1 | <?php |
2 | /** |
3 | * This program is free software; you can redistribute it and/or modify |
4 | * it under the terms of the GNU General Public License as published by |
5 | * the Free Software Foundation; either version 2 of the License, or |
6 | * (at your option) any later version. |
7 | * |
8 | * This program is distributed in the hope that it will be useful, |
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
11 | * GNU General Public License for more details. |
12 | * |
13 | * You should have received a copy of the GNU General Public License along |
14 | * with this program; if not, write to the Free Software Foundation, Inc., |
15 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
16 | * http://www.gnu.org/copyleft/gpl.html |
17 | * |
18 | * @file |
19 | */ |
20 | |
21 | namespace MediaWiki\Watchlist; |
22 | |
23 | use InvalidArgumentException; |
24 | use Job; |
25 | use MediaWiki\Linker\LinkTarget; |
26 | use MediaWiki\MediaWikiServices; |
27 | use MediaWiki\Page\PageReference; |
28 | |
29 | /** |
30 | * Job for updating user activity like "last viewed" timestamps |
31 | * |
32 | * Job parameters include: |
33 | * - type: one of (updateWatchlistNotification) [required] |
34 | * - userid: affected user ID [required] |
35 | * - notifTime: timestamp to set watchlist entries to [required] |
36 | * - curTime: UNIX timestamp of the event that triggered this job [required] |
37 | * |
38 | * @since 1.26 |
39 | * @ingroup JobQueue |
40 | */ |
41 | class ActivityUpdateJob extends Job { |
42 | /** |
43 | * @param LinkTarget|PageReference $title |
44 | * @param array $params |
45 | */ |
46 | public function __construct( $title, array $params ) { |
47 | // If we know its a PageReference, we could just pass that to the parent |
48 | // constructor, but its simpler to just extract namespace and dbkey, and |
49 | // that works for both LinkTarget and PageReference |
50 | $params['namespace'] = $title->getNamespace(); |
51 | $params['title'] = $title->getDBkey(); |
52 | |
53 | parent::__construct( 'activityUpdateJob', $params ); |
54 | |
55 | static $required = [ 'type', 'userid', 'notifTime', 'curTime' ]; |
56 | $missing = implode( ', ', array_diff( $required, array_keys( $this->params ) ) ); |
57 | if ( $missing != '' ) { |
58 | throw new InvalidArgumentException( "Missing parameter(s) $missing" ); |
59 | } |
60 | |
61 | $this->removeDuplicates = true; |
62 | } |
63 | |
64 | public function run() { |
65 | if ( $this->params['type'] === 'updateWatchlistNotification' ) { |
66 | $this->updateWatchlistNotification(); |
67 | } else { |
68 | throw new InvalidArgumentException( "Invalid 'type' '{$this->params['type']}'." ); |
69 | } |
70 | |
71 | return true; |
72 | } |
73 | |
74 | protected function updateWatchlistNotification() { |
75 | $casTimestamp = $this->params['notifTime'] ?? $this->params['curTime']; |
76 | |
77 | // TODO: Inject |
78 | $dbw = MediaWikiServices::getInstance()->getConnectionProvider()->getPrimaryDatabase(); |
79 | // Add a "check and set" style comparison to handle conflicts. |
80 | // The inequality always avoids updates when the current value |
81 | // is already NULL per ANSI SQL. This is desired since NULL means |
82 | // that the user is "caught up" on edits already. When the field |
83 | // is non-NULL, make sure not to set it back in time or set it to |
84 | // NULL when newer revisions were in fact added to the page. |
85 | $casTimeCond = $dbw->expr( 'wl_notificationtimestamp', '<', $dbw->timestamp( $casTimestamp ) ); |
86 | |
87 | // select primary key first instead of directly update to avoid deadlocks per T204561 |
88 | $wlId = $dbw->newSelectQueryBuilder() |
89 | ->select( 'wl_id' ) |
90 | ->from( 'watchlist' ) |
91 | ->where( [ |
92 | 'wl_user' => $this->params['userid'], |
93 | 'wl_namespace' => $this->title->getNamespace(), |
94 | 'wl_title' => $this->title->getDBkey(), |
95 | $casTimeCond |
96 | ] )->caller( __METHOD__ )->fetchField(); |
97 | |
98 | if ( !$wlId ) { |
99 | return; |
100 | } |
101 | $dbw->newUpdateQueryBuilder() |
102 | ->update( 'watchlist' ) |
103 | ->set( [ 'wl_notificationtimestamp' => $dbw->timestampOrNull( $this->params['notifTime'] ) ] ) |
104 | ->where( [ 'wl_id' => (int)$wlId, $casTimeCond ] ) |
105 | ->caller( __METHOD__ )->execute(); |
106 | } |
107 | } |
108 | /** @deprecated class alias since 1.43 */ |
109 | class_alias( ActivityUpdateJob::class, 'ActivityUpdateJob' ); |