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