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