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