Completed
Branch master (939199)
by
unknown
39:35
created

includes/api/ApiSetNotificationTimestamp.php (2 issues)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
3
/**
4
 * API for MediaWiki 1.14+
5
 *
6
 * Created on Jun 18, 2012
7
 *
8
 * Copyright © 2012 Brad Jorsch
9
 *
10
 * This program is free software; you can redistribute it and/or modify
11
 * it under the terms of the GNU General Public License as published by
12
 * the Free Software Foundation; either version 2 of the License, or
13
 * (at your option) any later version.
14
 *
15
 * This program is distributed in the hope that it will be useful,
16
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18
 * GNU General Public License for more details.
19
 *
20
 * You should have received a copy of the GNU General Public License along
21
 * with this program; if not, write to the Free Software Foundation, Inc.,
22
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
23
 * http://www.gnu.org/copyleft/gpl.html
24
 *
25
 * @file
26
 */
27
use MediaWiki\MediaWikiServices;
28
29
/**
30
 * API interface for setting the wl_notificationtimestamp field
31
 * @ingroup API
32
 */
33
class ApiSetNotificationTimestamp extends ApiBase {
34
35
	private $mPageSet;
36
37
	public function execute() {
38
		$user = $this->getUser();
39
40
		if ( $user->isAnon() ) {
41
			$this->dieUsage( 'Anonymous users cannot use watchlist change notifications', 'notloggedin' );
42
		}
43
		if ( !$user->isAllowed( 'editmywatchlist' ) ) {
44
			$this->dieUsage( 'You don\'t have permission to edit your watchlist', 'permissiondenied' );
45
		}
46
47
		$params = $this->extractRequestParams();
48
		$this->requireMaxOneParameter( $params, 'timestamp', 'torevid', 'newerthanrevid' );
49
50
		$continuationManager = new ApiContinuationManager( $this, [], [] );
51
		$this->setContinuationManager( $continuationManager );
52
53
		$pageSet = $this->getPageSet();
54
		if ( $params['entirewatchlist'] && $pageSet->getDataSource() !== null ) {
55
			$this->dieUsage(
56
				"Cannot use 'entirewatchlist' at the same time as '{$pageSet->getDataSource()}'",
57
				'multisource'
58
			);
59
		}
60
61
		$dbw = wfGetDB( DB_MASTER, 'api' );
62
63
		$timestamp = null;
64
		if ( isset( $params['timestamp'] ) ) {
65
			$timestamp = $dbw->timestamp( $params['timestamp'] );
66
		}
67
68
		if ( !$params['entirewatchlist'] ) {
69
			$pageSet->execute();
70
		}
71
72
		if ( isset( $params['torevid'] ) ) {
73
			if ( $params['entirewatchlist'] || $pageSet->getGoodTitleCount() > 1 ) {
74
				$this->dieUsage( 'torevid may only be used with a single page', 'multpages' );
75
			}
76
			$title = reset( $pageSet->getGoodTitles() );
0 ignored issues
show
$pageSet->getGoodTitles() cannot be passed to reset() as the parameter $array expects a reference.
Loading history...
77 View Code Duplication
			if ( $title ) {
78
				$timestamp = Revision::getTimestampFromId(
79
					$title, $params['torevid'], Revision::READ_LATEST );
80
				if ( $timestamp ) {
81
					$timestamp = $dbw->timestamp( $timestamp );
82
				} else {
83
					$timestamp = null;
84
				}
85
			}
86
		} elseif ( isset( $params['newerthanrevid'] ) ) {
87
			if ( $params['entirewatchlist'] || $pageSet->getGoodTitleCount() > 1 ) {
88
				$this->dieUsage( 'newerthanrevid may only be used with a single page', 'multpages' );
89
			}
90
			$title = reset( $pageSet->getGoodTitles() );
0 ignored issues
show
$pageSet->getGoodTitles() cannot be passed to reset() as the parameter $array expects a reference.
Loading history...
91 View Code Duplication
			if ( $title ) {
92
				$revid = $title->getNextRevisionID(
93
					$params['newerthanrevid'], Title::GAID_FOR_UPDATE );
94
				if ( $revid ) {
95
					$timestamp = $dbw->timestamp( Revision::getTimestampFromId( $title, $revid ) );
96
				} else {
97
					$timestamp = null;
98
				}
99
			}
100
		}
101
102
		$watchedItemStore = MediaWikiServices::getInstance()->getWatchedItemStore();
103
		$apiResult = $this->getResult();
104
		$result = [];
105
		if ( $params['entirewatchlist'] ) {
106
			// Entire watchlist mode: Just update the thing and return a success indicator
107
			$watchedItemStore->setNotificationTimestampsForUser(
108
				$user,
109
				$timestamp
110
			);
111
112
			$result['notificationtimestamp'] = is_null( $timestamp )
113
				? ''
114
				: wfTimestamp( TS_ISO_8601, $timestamp );
115
		} else {
116
			// First, log the invalid titles
117
			foreach ( $pageSet->getInvalidTitlesAndReasons() as $r ) {
118
				$r['invalid'] = true;
119
				$result[] = $r;
120
			}
121
			foreach ( $pageSet->getMissingPageIDs() as $p ) {
122
				$page = [];
123
				$page['pageid'] = $p;
124
				$page['missing'] = true;
125
				$page['notwatched'] = true;
126
				$result[] = $page;
127
			}
128
			foreach ( $pageSet->getMissingRevisionIDs() as $r ) {
129
				$rev = [];
130
				$rev['revid'] = $r;
131
				$rev['missing'] = true;
132
				$rev['notwatched'] = true;
133
				$result[] = $rev;
134
			}
135
136
			if ( $pageSet->getTitles() ) {
137
				// Now process the valid titles
138
				$watchedItemStore->setNotificationTimestampsForUser(
139
					$user,
140
					$timestamp,
141
					$pageSet->getTitles()
142
				);
143
144
				// Query the results of our update
145
				$timestamps = $watchedItemStore->getNotificationTimestampsBatch(
146
					$user,
147
					$pageSet->getTitles()
148
				);
149
150
				// Now, put the valid titles into the result
151
				/** @var $title Title */
152
				foreach ( $pageSet->getTitles() as $title ) {
153
					$ns = $title->getNamespace();
154
					$dbkey = $title->getDBkey();
155
					$r = [
156
						'ns' => intval( $ns ),
157
						'title' => $title->getPrefixedText(),
158
					];
159 View Code Duplication
					if ( !$title->exists() ) {
160
						$r['missing'] = true;
161
						if ( $title->isKnown() ) {
162
							$r['known'] = true;
163
						}
164
					}
165
					if ( isset( $timestamps[$ns] ) && array_key_exists( $dbkey, $timestamps[$ns] ) ) {
166
						$r['notificationtimestamp'] = '';
167
						if ( $timestamps[$ns][$dbkey] !== null ) {
168
							$r['notificationtimestamp'] = wfTimestamp( TS_ISO_8601, $timestamps[$ns][$dbkey] );
169
						}
170
					} else {
171
						$r['notwatched'] = true;
172
					}
173
					$result[] = $r;
174
				}
175
			}
176
177
			ApiResult::setIndexedTagName( $result, 'page' );
178
		}
179
		$apiResult->addValue( null, $this->getModuleName(), $result );
180
181
		$this->setContinuationManager( null );
182
		$continuationManager->setContinuationIntoResult( $apiResult );
183
	}
184
185
	/**
186
	 * Get a cached instance of an ApiPageSet object
187
	 * @return ApiPageSet
188
	 */
189
	private function getPageSet() {
190
		if ( !isset( $this->mPageSet ) ) {
191
			$this->mPageSet = new ApiPageSet( $this );
192
		}
193
194
		return $this->mPageSet;
195
	}
196
197
	public function mustBePosted() {
198
		return true;
199
	}
200
201
	public function isWriteMode() {
202
		return true;
203
	}
204
205
	public function needsToken() {
206
		return 'csrf';
207
	}
208
209
	public function getAllowedParams( $flags = 0 ) {
210
		$result = [
211
			'entirewatchlist' => [
212
				ApiBase::PARAM_TYPE => 'boolean'
213
			],
214
			'timestamp' => [
215
				ApiBase::PARAM_TYPE => 'timestamp'
216
			],
217
			'torevid' => [
218
				ApiBase::PARAM_TYPE => 'integer'
219
			],
220
			'newerthanrevid' => [
221
				ApiBase::PARAM_TYPE => 'integer'
222
			],
223
			'continue' => [
224
				ApiBase::PARAM_HELP_MSG => 'api-help-param-continue',
225
			],
226
		];
227
		if ( $flags ) {
228
			$result += $this->getPageSet()->getFinalParams( $flags );
229
		}
230
231
		return $result;
232
	}
233
234
	protected function getExamplesMessages() {
235
		return [
236
			'action=setnotificationtimestamp&entirewatchlist=&token=123ABC'
237
				=> 'apihelp-setnotificationtimestamp-example-all',
238
			'action=setnotificationtimestamp&titles=Main_page&token=123ABC'
239
				=> 'apihelp-setnotificationtimestamp-example-page',
240
			'action=setnotificationtimestamp&titles=Main_page&' .
241
				'timestamp=2012-01-01T00:00:00Z&token=123ABC'
242
				=> 'apihelp-setnotificationtimestamp-example-pagetimestamp',
243
			'action=setnotificationtimestamp&generator=allpages&gapnamespace=2&token=123ABC'
244
				=> 'apihelp-setnotificationtimestamp-example-allpages',
245
		];
246
	}
247
248
	public function getHelpUrls() {
249
		return 'https://www.mediawiki.org/wiki/API:SetNotificationTimestamp';
250
	}
251
}
252