MediaWiki  master
ApiSetNotificationTimestamp.php
Go to the documentation of this file.
1 <?php
2 
27 
33 
34  private $mPageSet = null;
35 
36  public function execute() {
37  $user = $this->getUser();
38 
39  if ( $user->isAnon() ) {
40  $this->dieWithError( 'watchlistanontext', 'notloggedin' );
41  }
42  $this->checkUserRightsAny( 'editmywatchlist' );
43 
44  $params = $this->extractRequestParams();
45  $this->requireMaxOneParameter( $params, 'timestamp', 'torevid', 'newerthanrevid' );
46 
47  $continuationManager = new ApiContinuationManager( $this, [], [] );
48  $this->setContinuationManager( $continuationManager );
49 
50  $pageSet = $this->getPageSet();
51  if ( $params['entirewatchlist'] && $pageSet->getDataSource() !== null ) {
52  $this->dieWithError(
53  [
54  'apierror-invalidparammix-cannotusewith',
55  $this->encodeParamName( 'entirewatchlist' ),
56  $pageSet->encodeParamName( $pageSet->getDataSource() )
57  ],
58  'multisource'
59  );
60  }
61 
62  $dbw = wfGetDB( DB_MASTER, 'api' );
63 
64  $timestamp = null;
65  if ( isset( $params['timestamp'] ) ) {
66  $timestamp = $dbw->timestamp( $params['timestamp'] );
67  }
68 
69  if ( !$params['entirewatchlist'] ) {
70  $pageSet->execute();
71  }
72 
73  if ( isset( $params['torevid'] ) ) {
74  if ( $params['entirewatchlist'] || $pageSet->getGoodTitleCount() > 1 ) {
75  $this->dieWithError( [ 'apierror-multpages', $this->encodeParamName( 'torevid' ) ] );
76  }
77  $titles = $pageSet->getGoodTitles();
78  $title = reset( $titles );
79  if ( $title ) {
80  // XXX $title isn't actually used, can we just get rid of the previous six lines?
81  $timestamp = MediaWikiServices::getInstance()->getRevisionStore()
82  ->getTimestampFromId( $params['torevid'], IDBAccessObject::READ_LATEST );
83  if ( $timestamp ) {
84  $timestamp = $dbw->timestamp( $timestamp );
85  } else {
86  $timestamp = null;
87  }
88  }
89  } elseif ( isset( $params['newerthanrevid'] ) ) {
90  if ( $params['entirewatchlist'] || $pageSet->getGoodTitleCount() > 1 ) {
91  $this->dieWithError( [ 'apierror-multpages', $this->encodeParamName( 'newerthanrevid' ) ] );
92  }
93  $titles = $pageSet->getGoodTitles();
94  $title = reset( $titles );
95  if ( $title ) {
96  $timestamp = null;
97  $rl = MediaWikiServices::getInstance()->getRevisionLookup();
98  $currRev = $rl->getRevisionById( $params['newerthanrevid'], Title::READ_LATEST );
99  if ( $currRev ) {
100  $nextRev = $rl->getNextRevision( $currRev, Title::READ_LATEST );
101  if ( $nextRev ) {
102  $timestamp = $dbw->timestamp( $nextRev->getTimestamp() );
103  }
104  }
105  }
106  }
107 
108  $watchedItemStore = MediaWikiServices::getInstance()->getWatchedItemStore();
109  $apiResult = $this->getResult();
110  $result = [];
111  if ( $params['entirewatchlist'] ) {
112  // Entire watchlist mode: Just update the thing and return a success indicator
113  $watchedItemStore->resetAllNotificationTimestampsForUser( $user, $timestamp );
114 
115  $result['notificationtimestamp'] = is_null( $timestamp )
116  ? ''
117  : wfTimestamp( TS_ISO_8601, $timestamp );
118  } else {
119  // First, log the invalid titles
120  foreach ( $pageSet->getInvalidTitlesAndReasons() as $r ) {
121  $r['invalid'] = true;
122  $result[] = $r;
123  }
124  foreach ( $pageSet->getMissingPageIDs() as $p ) {
125  $page = [];
126  $page['pageid'] = $p;
127  $page['missing'] = true;
128  $page['notwatched'] = true;
129  $result[] = $page;
130  }
131  foreach ( $pageSet->getMissingRevisionIDs() as $r ) {
132  $rev = [];
133  $rev['revid'] = $r;
134  $rev['missing'] = true;
135  $rev['notwatched'] = true;
136  $result[] = $rev;
137  }
138 
139  if ( $pageSet->getTitles() ) {
140  // Now process the valid titles
141  $watchedItemStore->setNotificationTimestampsForUser(
142  $user,
143  $timestamp,
144  $pageSet->getTitles()
145  );
146 
147  // Query the results of our update
148  $timestamps = $watchedItemStore->getNotificationTimestampsBatch(
149  $user,
150  $pageSet->getTitles()
151  );
152 
153  // Now, put the valid titles into the result
155  foreach ( $pageSet->getTitles() as $title ) {
156  $ns = $title->getNamespace();
157  $dbkey = $title->getDBkey();
158  $r = [
159  'ns' => (int)$ns,
160  'title' => $title->getPrefixedText(),
161  ];
162  if ( !$title->exists() ) {
163  $r['missing'] = true;
164  if ( $title->isKnown() ) {
165  $r['known'] = true;
166  }
167  }
168  if ( isset( $timestamps[$ns] ) && array_key_exists( $dbkey, $timestamps[$ns] ) ) {
169  $r['notificationtimestamp'] = '';
170  if ( $timestamps[$ns][$dbkey] !== null ) {
171  $r['notificationtimestamp'] = wfTimestamp( TS_ISO_8601, $timestamps[$ns][$dbkey] );
172  }
173  } else {
174  $r['notwatched'] = true;
175  }
176  $result[] = $r;
177  }
178  }
179 
180  ApiResult::setIndexedTagName( $result, 'page' );
181  }
182  $apiResult->addValue( null, $this->getModuleName(), $result );
183 
184  $this->setContinuationManager( null );
185  $continuationManager->setContinuationIntoResult( $apiResult );
186  }
187 
192  private function getPageSet() {
193  if ( $this->mPageSet === null ) {
194  $this->mPageSet = new ApiPageSet( $this );
195  }
196 
197  return $this->mPageSet;
198  }
199 
200  public function mustBePosted() {
201  return true;
202  }
203 
204  public function isWriteMode() {
205  return true;
206  }
207 
208  public function needsToken() {
209  return 'csrf';
210  }
211 
212  public function getAllowedParams( $flags = 0 ) {
213  $result = [
214  'entirewatchlist' => [
215  ApiBase::PARAM_TYPE => 'boolean'
216  ],
217  'timestamp' => [
218  ApiBase::PARAM_TYPE => 'timestamp'
219  ],
220  'torevid' => [
221  ApiBase::PARAM_TYPE => 'integer'
222  ],
223  'newerthanrevid' => [
224  ApiBase::PARAM_TYPE => 'integer'
225  ],
226  'continue' => [
227  ApiBase::PARAM_HELP_MSG => 'api-help-param-continue',
228  ],
229  ];
230  if ( $flags ) {
231  $result += $this->getPageSet()->getFinalParams( $flags );
232  }
233 
234  return $result;
235  }
236 
237  protected function getExamplesMessages() {
238  return [
239  'action=setnotificationtimestamp&entirewatchlist=&token=123ABC'
240  => 'apihelp-setnotificationtimestamp-example-all',
241  'action=setnotificationtimestamp&titles=Main_page&token=123ABC'
242  => 'apihelp-setnotificationtimestamp-example-page',
243  'action=setnotificationtimestamp&titles=Main_page&' .
244  'timestamp=2012-01-01T00:00:00Z&token=123ABC'
245  => 'apihelp-setnotificationtimestamp-example-pagetimestamp',
246  'action=setnotificationtimestamp&generator=allpages&gapnamespace=2&token=123ABC'
247  => 'apihelp-setnotificationtimestamp-example-allpages',
248  ];
249  }
250 
251  public function getHelpUrls() {
252  return 'https://www.mediawiki.org/wiki/Special:MyLanguage/API:SetNotificationTimestamp';
253  }
254 }
const PARAM_TYPE
(string|string[]) Either an array of allowed value strings, or a string type as described below...
Definition: ApiBase.php:94
getResult()
Get the result object.
Definition: ApiBase.php:640
This class contains a list of pages that the client has requested.
Definition: ApiPageSet.php:40
wfGetDB( $db, $groups=[], $wiki=false)
Get a Database object.
This manages continuation state.
dieWithError( $msg, $code=null, $data=null, $httpCode=null)
Abort execution with an error.
Definition: ApiBase.php:2006
extractRequestParams( $options=[])
Using getAllowedParams(), this function makes an array of the values provided by the user...
Definition: ApiBase.php:761
static setIndexedTagName(array &$arr, $tag)
Set the tag name for numeric-keyed values in XML format.
Definition: ApiResult.php:616
const DB_MASTER
Definition: defines.php:26
wfTimestamp( $outputtype=TS_UNIX, $ts=0)
Get a timestamp string in one of various formats.
setContinuationManager(ApiContinuationManager $manager=null)
Set the continuation manager.
Definition: ApiBase.php:694
getModuleName()
Get the name of the module being executed by this instance.
Definition: ApiBase.php:520
API interface for setting the wl_notificationtimestamp field.
const PARAM_HELP_MSG
(string|array|Message) Specify an alternative i18n documentation message for this parameter...
Definition: ApiBase.php:131
encodeParamName( $paramName)
This method mangles parameter name based on the prefix supplied to the constructor.
Definition: ApiBase.php:739
This abstract class implements many basic API functions, and is the base of all API classes...
Definition: ApiBase.php:42
requireMaxOneParameter( $params,... $required)
Die if more than one of a certain set of parameters is set and not false.
Definition: ApiBase.php:928
checkUserRightsAny( $rights, $user=null)
Helper function for permission-denied errors.
Definition: ApiBase.php:2122
getPageSet()
Get a cached instance of an ApiPageSet object.