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