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