Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
0.00% |
0 / 31 |
|
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 | use MediaWiki\Linker\LinkTarget; |
22 | use MediaWiki\MediaWikiServices; |
23 | use MediaWiki\Page\PageReference; |
24 | |
25 | /** |
26 | * Job for updating user activity like "last viewed" timestamps |
27 | * |
28 | * Job parameters include: |
29 | * - type: one of (updateWatchlistNotification) [required] |
30 | * - userid: affected user ID [required] |
31 | * - notifTime: timestamp to set watchlist entries to [required] |
32 | * - curTime: UNIX timestamp of the event that triggered this job [required] |
33 | * |
34 | * @since 1.26 |
35 | * @ingroup JobQueue |
36 | */ |
37 | class ActivityUpdateJob extends Job { |
38 | /** |
39 | * @param LinkTarget|PageReference $title |
40 | * @param array $params |
41 | */ |
42 | public function __construct( $title, array $params ) { |
43 | // If we know its a PageReference, we could just pass that to the parent |
44 | // constructor, but its simpler to just extract namespace and dbkey, and |
45 | // that works for both LinkTarget and PageReference |
46 | $params['namespace'] = $title->getNamespace(); |
47 | $params['title'] = $title->getDBkey(); |
48 | |
49 | parent::__construct( 'activityUpdateJob', $params ); |
50 | |
51 | static $required = [ 'type', 'userid', 'notifTime', 'curTime' ]; |
52 | $missing = implode( ', ', array_diff( $required, array_keys( $this->params ) ) ); |
53 | if ( $missing != '' ) { |
54 | throw new InvalidArgumentException( "Missing parameter(s) $missing" ); |
55 | } |
56 | |
57 | $this->removeDuplicates = true; |
58 | } |
59 | |
60 | public function run() { |
61 | if ( $this->params['type'] === 'updateWatchlistNotification' ) { |
62 | $this->updateWatchlistNotification(); |
63 | } else { |
64 | throw new InvalidArgumentException( "Invalid 'type' '{$this->params['type']}'." ); |
65 | } |
66 | |
67 | return true; |
68 | } |
69 | |
70 | protected function updateWatchlistNotification() { |
71 | $casTimestamp = $this->params['notifTime'] ?? $this->params['curTime']; |
72 | |
73 | // TODO: Inject |
74 | $dbw = MediaWikiServices::getInstance()->getConnectionProvider()->getPrimaryDatabase(); |
75 | // Add a "check and set" style comparison to handle conflicts. |
76 | // The inequality always avoids updates when the current value |
77 | // is already NULL per ANSI SQL. This is desired since NULL means |
78 | // that the user is "caught up" on edits already. When the field |
79 | // is non-NULL, make sure not to set it back in time or set it to |
80 | // NULL when newer revisions were in fact added to the page. |
81 | $casTimeCond = $dbw->expr( 'wl_notificationtimestamp', '<', $dbw->timestamp( $casTimestamp ) ); |
82 | |
83 | // select primary key first instead of directly update to avoid deadlocks per T204561 |
84 | $wlId = $dbw->newSelectQueryBuilder() |
85 | ->select( 'wl_id' ) |
86 | ->from( 'watchlist' ) |
87 | ->where( [ |
88 | 'wl_user' => $this->params['userid'], |
89 | 'wl_namespace' => $this->title->getNamespace(), |
90 | 'wl_title' => $this->title->getDBkey(), |
91 | $casTimeCond |
92 | ] )->caller( __METHOD__ )->fetchField(); |
93 | |
94 | if ( !$wlId ) { |
95 | return; |
96 | } |
97 | $dbw->newUpdateQueryBuilder() |
98 | ->update( 'watchlist' ) |
99 | ->set( [ 'wl_notificationtimestamp' => $dbw->timestampOrNull( $this->params['notifTime'] ) ] ) |
100 | ->where( [ 'wl_id' => (int)$wlId, $casTimeCond ] ) |
101 | ->caller( __METHOD__ )->execute(); |
102 | } |
103 | } |