MediaWiki REL1_39
ApiSetNotificationTimestamp.php
Go to the documentation of this file.
1<?php
2
29
35
36 private $mPageSet = null;
37
39 private $revisionStore;
40
42 private $loadBalancer;
43
45 private $watchedItemStore;
46
54 public function __construct(
55 ApiMain $main,
56 $action,
57 ILoadBalancer $loadBalancer,
58 RevisionStore $revisionStore,
59 WatchedItemStoreInterface $watchedItemStore
60 ) {
61 parent::__construct( $main, $action );
62
63 $this->loadBalancer = $loadBalancer;
64 $this->revisionStore = $revisionStore;
65 $this->watchedItemStore = $watchedItemStore;
66 }
67
68 public function execute() {
69 $user = $this->getUser();
70
71 if ( !$user->isRegistered() ) {
72 $this->dieWithError( 'watchlistanontext', 'notloggedin' );
73 }
74 $this->checkUserRightsAny( 'editmywatchlist' );
75
76 $params = $this->extractRequestParams();
77 $this->requireMaxOneParameter( $params, 'timestamp', 'torevid', 'newerthanrevid' );
78
79 $continuationManager = new ApiContinuationManager( $this, [], [] );
80 $this->setContinuationManager( $continuationManager );
81
82 $pageSet = $this->getPageSet();
83 if ( $params['entirewatchlist'] && $pageSet->getDataSource() !== null ) {
84 $this->dieWithError(
85 [
86 'apierror-invalidparammix-cannotusewith',
87 $this->encodeParamName( 'entirewatchlist' ),
88 $pageSet->encodeParamName( $pageSet->getDataSource() )
89 ],
90 'multisource'
91 );
92 }
93
94 $dbw = $this->loadBalancer->getConnectionRef( DB_PRIMARY );
95
96 $timestamp = null;
97 if ( isset( $params['timestamp'] ) ) {
98 $timestamp = $dbw->timestamp( $params['timestamp'] );
99 }
100
101 if ( !$params['entirewatchlist'] ) {
102 $pageSet->execute();
103 }
104
105 if ( isset( $params['torevid'] ) ) {
106 if ( $params['entirewatchlist'] || $pageSet->getGoodTitleCount() > 1 ) {
107 $this->dieWithError( [ 'apierror-multpages', $this->encodeParamName( 'torevid' ) ] );
108 }
109 $titles = $pageSet->getGoodTitles();
110 $title = reset( $titles );
111 if ( $title ) {
112 // XXX $title isn't actually used, can we just get rid of the previous six lines?
113 $timestamp = $this->revisionStore->getTimestampFromId(
114 $params['torevid'],
115 IDBAccessObject::READ_LATEST
116 );
117 if ( $timestamp ) {
118 $timestamp = $dbw->timestamp( $timestamp );
119 } else {
120 $timestamp = null;
121 }
122 }
123 } elseif ( isset( $params['newerthanrevid'] ) ) {
124 if ( $params['entirewatchlist'] || $pageSet->getGoodTitleCount() > 1 ) {
125 $this->dieWithError( [ 'apierror-multpages', $this->encodeParamName( 'newerthanrevid' ) ] );
126 }
127 $titles = $pageSet->getGoodTitles();
128 $title = reset( $titles );
129 if ( $title ) {
130 $timestamp = null;
131 $currRev = $this->revisionStore->getRevisionById(
132 $params['newerthanrevid'],
133 Title::READ_LATEST
134 );
135 if ( $currRev ) {
136 $nextRev = $this->revisionStore->getNextRevision(
137 $currRev,
138 Title::READ_LATEST
139 );
140 if ( $nextRev ) {
141 $timestamp = $dbw->timestamp( $nextRev->getTimestamp() );
142 }
143 }
144 }
145 }
146
147 $apiResult = $this->getResult();
148 $result = [];
149 if ( $params['entirewatchlist'] ) {
150 // Entire watchlist mode: Just update the thing and return a success indicator
151 $this->watchedItemStore->resetAllNotificationTimestampsForUser( $user, $timestamp );
152
153 $result['notificationtimestamp'] = $timestamp === null
154 ? ''
155 : wfTimestamp( TS_ISO_8601, $timestamp );
156 } else {
157 // First, log the invalid titles
158 foreach ( $pageSet->getInvalidTitlesAndReasons() as $r ) {
159 $r['invalid'] = true;
160 $result[] = $r;
161 }
162 foreach ( $pageSet->getMissingPageIDs() as $p ) {
163 $page = [];
164 $page['pageid'] = $p;
165 $page['missing'] = true;
166 $page['notwatched'] = true;
167 $result[] = $page;
168 }
169 foreach ( $pageSet->getMissingRevisionIDs() as $r ) {
170 $rev = [];
171 $rev['revid'] = $r;
172 $rev['missing'] = true;
173 $rev['notwatched'] = true;
174 $result[] = $rev;
175 }
176
177 if ( $pageSet->getPages() ) {
178 // Now process the valid titles
179 $this->watchedItemStore->setNotificationTimestampsForUser(
180 $user,
181 $timestamp,
182 $pageSet->getPages()
183 );
184
185 // Query the results of our update
186 $timestamps = $this->watchedItemStore->getNotificationTimestampsBatch(
187 $user,
188 $pageSet->getPages()
189 );
190
191 // Now, put the valid titles into the result
193 foreach ( $pageSet->getTitles() as $title ) {
194 $ns = $title->getNamespace();
195 $dbkey = $title->getDBkey();
196 $r = [
197 'ns' => $ns,
198 'title' => $title->getPrefixedText(),
199 ];
200 if ( !$title->exists() ) {
201 $r['missing'] = true;
202 if ( $title->isKnown() ) {
203 $r['known'] = true;
204 }
205 }
206 if ( isset( $timestamps[$ns] ) && array_key_exists( $dbkey, $timestamps[$ns] )
207 && $timestamps[$ns][$dbkey] !== false
208 ) {
209 $r['notificationtimestamp'] = '';
210 if ( $timestamps[$ns][$dbkey] !== null ) {
211 $r['notificationtimestamp'] = wfTimestamp( TS_ISO_8601, $timestamps[$ns][$dbkey] );
212 }
213 } else {
214 $r['notwatched'] = true;
215 }
216 $result[] = $r;
217 }
218 }
219
220 ApiResult::setIndexedTagName( $result, 'page' );
221 }
222 $apiResult->addValue( null, $this->getModuleName(), $result );
223
224 $this->setContinuationManager( null );
225 $continuationManager->setContinuationIntoResult( $apiResult );
226 }
227
232 private function getPageSet() {
233 if ( $this->mPageSet === null ) {
234 $this->mPageSet = new ApiPageSet( $this );
235 }
236
237 return $this->mPageSet;
238 }
239
240 public function mustBePosted() {
241 return true;
242 }
243
244 public function isWriteMode() {
245 return true;
246 }
247
248 public function needsToken() {
249 return 'csrf';
250 }
251
252 public function getAllowedParams( $flags = 0 ) {
253 $result = [
254 'entirewatchlist' => [
255 ParamValidator::PARAM_TYPE => 'boolean'
256 ],
257 'timestamp' => [
258 ParamValidator::PARAM_TYPE => 'timestamp'
259 ],
260 'torevid' => [
261 ParamValidator::PARAM_TYPE => 'integer'
262 ],
263 'newerthanrevid' => [
264 ParamValidator::PARAM_TYPE => 'integer'
265 ],
266 'continue' => [
267 ApiBase::PARAM_HELP_MSG => 'api-help-param-continue',
268 ],
269 ];
270 if ( $flags ) {
271 $result += $this->getPageSet()->getFinalParams( $flags );
272 }
273
274 return $result;
275 }
276
277 protected function getExamplesMessages() {
278 $title = Title::newMainPage()->getPrefixedText();
279 $mp = rawurlencode( $title );
280
281 return [
282 'action=setnotificationtimestamp&entirewatchlist=&token=123ABC'
283 => 'apihelp-setnotificationtimestamp-example-all',
284 "action=setnotificationtimestamp&titles={$mp}&token=123ABC"
285 => 'apihelp-setnotificationtimestamp-example-page',
286 "action=setnotificationtimestamp&titles={$mp}&" .
287 'timestamp=2012-01-01T00:00:00Z&token=123ABC'
288 => 'apihelp-setnotificationtimestamp-example-pagetimestamp',
289 'action=setnotificationtimestamp&generator=allpages&gapnamespace=2&token=123ABC'
290 => 'apihelp-setnotificationtimestamp-example-allpages',
291 ];
292 }
293
294 public function getHelpUrls() {
295 return 'https://www.mediawiki.org/wiki/Special:MyLanguage/API:SetNotificationTimestamp';
296 }
297}
wfTimestamp( $outputtype=TS_UNIX, $ts=0)
Get a timestamp string in one of various formats.
This abstract class implements many basic API functions, and is the base of all API classes.
Definition ApiBase.php:56
dieWithError( $msg, $code=null, $data=null, $httpCode=0)
Abort execution with an error.
Definition ApiBase.php:1454
checkUserRightsAny( $rights, $user=null)
Helper function for permission-denied errors.
Definition ApiBase.php:1560
encodeParamName( $paramName)
This method mangles parameter name based on the prefix supplied to the constructor.
Definition ApiBase.php:743
requireMaxOneParameter( $params,... $required)
Die if more than one of a certain set of parameters is set and not false.
Definition ApiBase.php:938
setContinuationManager(ApiContinuationManager $manager=null)
Definition ApiBase.php:673
getResult()
Get the result object.
Definition ApiBase.php:629
extractRequestParams( $options=[])
Using getAllowedParams(), this function makes an array of the values provided by the user,...
Definition ApiBase.php:765
const PARAM_HELP_MSG
(string|array|Message) Specify an alternative i18n documentation message for this parameter.
Definition ApiBase.php:163
getModuleName()
Get the name of the module being executed by this instance.
Definition ApiBase.php:498
This manages continuation state.
This is the main API class, used for both external and internal processing.
Definition ApiMain.php:52
This class contains a list of pages that the client has requested.
API interface for setting the wl_notificationtimestamp field.
getExamplesMessages()
Returns usage examples for this module.
execute()
Evaluates the parameters, performs the requested query, and sets up the result.
getHelpUrls()
Return links to more detailed help pages about the module.
mustBePosted()
Indicates whether this module must be called with a POST request.
__construct(ApiMain $main, $action, ILoadBalancer $loadBalancer, RevisionStore $revisionStore, WatchedItemStoreInterface $watchedItemStore)
needsToken()
Returns the token type this module requires in order to execute.
isWriteMode()
Indicates whether this module requires write mode.
Service for looking up page revisions.
Represents a title within MediaWiki.
Definition Title.php:49
Service for formatting and validating API parameters.
Create and track the database connections and transactions for a given database cluster.
const DB_PRIMARY
Definition defines.php:28