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