MediaWiki  master
ApiSetNotificationTimestamp.php
Go to the documentation of this file.
1 <?php
2 
28 
34 
35  private $mPageSet = null;
36 
38  private $revisionStore;
39 
41  private $loadBalancer;
42 
45 
53  public function __construct(
54  ApiMain $main,
55  $action,
59  ) {
60  parent::__construct( $main, $action );
61 
62  $this->loadBalancer = $loadBalancer;
63  $this->revisionStore = $revisionStore;
64  $this->watchedItemStore = $watchedItemStore;
65  }
66 
67  public function execute() {
68  $user = $this->getUser();
69 
70  if ( !$user->isRegistered() ) {
71  $this->dieWithError( 'watchlistanontext', 'notloggedin' );
72  }
73  $this->checkUserRightsAny( 'editmywatchlist' );
74 
75  $params = $this->extractRequestParams();
76  $this->requireMaxOneParameter( $params, 'timestamp', 'torevid', 'newerthanrevid' );
77 
78  $continuationManager = new ApiContinuationManager( $this, [], [] );
79  $this->setContinuationManager( $continuationManager );
80 
81  $pageSet = $this->getPageSet();
82  if ( $params['entirewatchlist'] && $pageSet->getDataSource() !== null ) {
83  $this->dieWithError(
84  [
85  'apierror-invalidparammix-cannotusewith',
86  $this->encodeParamName( 'entirewatchlist' ),
87  $pageSet->encodeParamName( $pageSet->getDataSource() )
88  ],
89  'multisource'
90  );
91  }
92 
93  $dbw = $this->loadBalancer->getConnectionRef( DB_PRIMARY, 'api' );
94 
95  $timestamp = null;
96  if ( isset( $params['timestamp'] ) ) {
97  $timestamp = $dbw->timestamp( $params['timestamp'] );
98  }
99 
100  if ( !$params['entirewatchlist'] ) {
101  $pageSet->execute();
102  }
103 
104  if ( isset( $params['torevid'] ) ) {
105  if ( $params['entirewatchlist'] || $pageSet->getGoodTitleCount() > 1 ) {
106  $this->dieWithError( [ 'apierror-multpages', $this->encodeParamName( 'torevid' ) ] );
107  }
108  $titles = $pageSet->getGoodTitles();
109  $title = reset( $titles );
110  if ( $title ) {
111  // XXX $title isn't actually used, can we just get rid of the previous six lines?
112  $timestamp = $this->revisionStore->getTimestampFromId(
113  $params['torevid'],
114  IDBAccessObject::READ_LATEST
115  );
116  if ( $timestamp ) {
117  $timestamp = $dbw->timestamp( $timestamp );
118  } else {
119  $timestamp = null;
120  }
121  }
122  } elseif ( isset( $params['newerthanrevid'] ) ) {
123  if ( $params['entirewatchlist'] || $pageSet->getGoodTitleCount() > 1 ) {
124  $this->dieWithError( [ 'apierror-multpages', $this->encodeParamName( 'newerthanrevid' ) ] );
125  }
126  $titles = $pageSet->getGoodTitles();
127  $title = reset( $titles );
128  if ( $title ) {
129  $timestamp = null;
130  $currRev = $this->revisionStore->getRevisionById(
131  $params['newerthanrevid'],
132  Title::READ_LATEST
133  );
134  if ( $currRev ) {
135  $nextRev = $this->revisionStore->getNextRevision(
136  $currRev,
137  Title::READ_LATEST
138  );
139  if ( $nextRev ) {
140  $timestamp = $dbw->timestamp( $nextRev->getTimestamp() );
141  }
142  }
143  }
144  }
145 
146  $apiResult = $this->getResult();
147  $result = [];
148  if ( $params['entirewatchlist'] ) {
149  // Entire watchlist mode: Just update the thing and return a success indicator
150  $this->watchedItemStore->resetAllNotificationTimestampsForUser( $user, $timestamp );
151 
152  $result['notificationtimestamp'] = $timestamp === null
153  ? ''
154  : wfTimestamp( TS_ISO_8601, $timestamp );
155  } else {
156  // First, log the invalid titles
157  foreach ( $pageSet->getInvalidTitlesAndReasons() as $r ) {
158  $r['invalid'] = true;
159  $result[] = $r;
160  }
161  foreach ( $pageSet->getMissingPageIDs() as $p ) {
162  $page = [];
163  $page['pageid'] = $p;
164  $page['missing'] = true;
165  $page['notwatched'] = true;
166  $result[] = $page;
167  }
168  foreach ( $pageSet->getMissingRevisionIDs() as $r ) {
169  $rev = [];
170  $rev['revid'] = $r;
171  $rev['missing'] = true;
172  $rev['notwatched'] = true;
173  $result[] = $rev;
174  }
175 
176  if ( $pageSet->getPages() ) {
177  // Now process the valid titles
178  $this->watchedItemStore->setNotificationTimestampsForUser(
179  $user,
180  $timestamp,
181  $pageSet->getPages()
182  );
183 
184  // Query the results of our update
185  $timestamps = $this->watchedItemStore->getNotificationTimestampsBatch(
186  $user,
187  $pageSet->getPages()
188  );
189 
190  // Now, put the valid titles into the result
192  foreach ( $pageSet->getTitles() as $title ) {
193  $ns = $title->getNamespace();
194  $dbkey = $title->getDBkey();
195  $r = [
196  'ns' => $ns,
197  'title' => $title->getPrefixedText(),
198  ];
199  if ( !$title->exists() ) {
200  $r['missing'] = true;
201  if ( $title->isKnown() ) {
202  $r['known'] = true;
203  }
204  }
205  if ( isset( $timestamps[$ns] ) && array_key_exists( $dbkey, $timestamps[$ns] ) ) {
206  $r['notificationtimestamp'] = '';
207  if ( $timestamps[$ns][$dbkey] !== null ) {
208  $r['notificationtimestamp'] = wfTimestamp( TS_ISO_8601, $timestamps[$ns][$dbkey] );
209  }
210  } else {
211  $r['notwatched'] = true;
212  }
213  $result[] = $r;
214  }
215  }
216 
217  ApiResult::setIndexedTagName( $result, 'page' );
218  }
219  $apiResult->addValue( null, $this->getModuleName(), $result );
220 
221  $this->setContinuationManager( null );
222  $continuationManager->setContinuationIntoResult( $apiResult );
223  }
224 
229  private function getPageSet() {
230  if ( $this->mPageSet === null ) {
231  $this->mPageSet = new ApiPageSet( $this );
232  }
233 
234  return $this->mPageSet;
235  }
236 
237  public function mustBePosted() {
238  return true;
239  }
240 
241  public function isWriteMode() {
242  return true;
243  }
244 
245  public function needsToken() {
246  return 'csrf';
247  }
248 
249  public function getAllowedParams( $flags = 0 ) {
250  $result = [
251  'entirewatchlist' => [
252  ApiBase::PARAM_TYPE => 'boolean'
253  ],
254  'timestamp' => [
255  ApiBase::PARAM_TYPE => 'timestamp'
256  ],
257  'torevid' => [
258  ApiBase::PARAM_TYPE => 'integer'
259  ],
260  'newerthanrevid' => [
261  ApiBase::PARAM_TYPE => 'integer'
262  ],
263  'continue' => [
264  ApiBase::PARAM_HELP_MSG => 'api-help-param-continue',
265  ],
266  ];
267  if ( $flags ) {
268  $result += $this->getPageSet()->getFinalParams( $flags );
269  }
270 
271  return $result;
272  }
273 
274  protected function getExamplesMessages() {
275  return [
276  'action=setnotificationtimestamp&entirewatchlist=&token=123ABC'
277  => 'apihelp-setnotificationtimestamp-example-all',
278  'action=setnotificationtimestamp&titles=Main_page&token=123ABC'
279  => 'apihelp-setnotificationtimestamp-example-page',
280  'action=setnotificationtimestamp&titles=Main_page&' .
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 
288  public function getHelpUrls() {
289  return 'https://www.mediawiki.org/wiki/Special:MyLanguage/API:SetNotificationTimestamp';
290  }
291 }
ApiMain
This is the main API class, used for both external and internal processing.
Definition: ApiMain.php:49
MediaWiki\Revision\RevisionStore
Service for looking up page revisions.
Definition: RevisionStore.php:88
ApiContinuationManager
This manages continuation state.
Definition: ApiContinuationManager.php:26
ApiBase\dieWithError
dieWithError( $msg, $code=null, $data=null, $httpCode=null)
Abort execution with an error.
Definition: ApiBase.php:1436
ApiBase\PARAM_HELP_MSG
const PARAM_HELP_MSG
(string|array|Message) Specify an alternative i18n documentation message for this parameter.
Definition: ApiBase.php:162
wfTimestamp
wfTimestamp( $outputtype=TS_UNIX, $ts=0)
Get a timestamp string in one of various formats.
Definition: GlobalFunctions.php:1665
ApiBase\PARAM_TYPE
const PARAM_TYPE
Definition: ApiBase.php:81
ApiBase\getResult
getResult()
Get the result object.
Definition: ApiBase.php:628
ApiSetNotificationTimestamp\getExamplesMessages
getExamplesMessages()
Returns usage examples for this module.
Definition: ApiSetNotificationTimestamp.php:274
ApiBase\checkUserRightsAny
checkUserRightsAny( $rights, $user=null)
Helper function for permission-denied errors.
Definition: ApiBase.php:1545
ApiSetNotificationTimestamp\mustBePosted
mustBePosted()
Indicates whether this module must be called with a POST request.
Definition: ApiSetNotificationTimestamp.php:237
ApiBase\setContinuationManager
setContinuationManager(ApiContinuationManager $manager=null)
Definition: ApiBase.php:672
ApiSetNotificationTimestamp\$revisionStore
RevisionStore $revisionStore
Definition: ApiSetNotificationTimestamp.php:38
ContextSource\getUser
getUser()
Definition: ContextSource.php:136
ApiPageSet
This class contains a list of pages that the client has requested.
Definition: ApiPageSet.php:45
ApiBase
This abstract class implements many basic API functions, and is the base of all API classes.
Definition: ApiBase.php:55
ApiSetNotificationTimestamp\$loadBalancer
ILoadBalancer $loadBalancer
Definition: ApiSetNotificationTimestamp.php:41
ApiBase\extractRequestParams
extractRequestParams( $options=[])
Using getAllowedParams(), this function makes an array of the values provided by the user,...
Definition: ApiBase.php:764
$title
$title
Definition: testCompression.php:38
ApiSetNotificationTimestamp\getPageSet
getPageSet()
Get a cached instance of an ApiPageSet object.
Definition: ApiSetNotificationTimestamp.php:229
ApiResult\setIndexedTagName
static setIndexedTagName(array &$arr, $tag)
Set the tag name for numeric-keyed values in XML format.
Definition: ApiResult.php:603
ApiBase\requireMaxOneParameter
requireMaxOneParameter( $params,... $required)
Die if more than one of a certain set of parameters is set and not false.
Definition: ApiBase.php:936
ApiBase\encodeParamName
encodeParamName( $paramName)
This method mangles parameter name based on the prefix supplied to the constructor.
Definition: ApiBase.php:742
DB_PRIMARY
const DB_PRIMARY
Definition: defines.php:27
ApiSetNotificationTimestamp\__construct
__construct(ApiMain $main, $action, ILoadBalancer $loadBalancer, RevisionStore $revisionStore, WatchedItemStoreInterface $watchedItemStore)
Definition: ApiSetNotificationTimestamp.php:53
ApiSetNotificationTimestamp\$watchedItemStore
WatchedItemStoreInterface $watchedItemStore
Definition: ApiSetNotificationTimestamp.php:44
Title
Represents a title within MediaWiki.
Definition: Title.php:47
ApiSetNotificationTimestamp\$mPageSet
$mPageSet
Definition: ApiSetNotificationTimestamp.php:35
ApiBase\getModuleName
getModuleName()
Get the name of the module being executed by this instance.
Definition: ApiBase.php:497
ApiSetNotificationTimestamp\execute
execute()
Evaluates the parameters, performs the requested query, and sets up the result.
Definition: ApiSetNotificationTimestamp.php:67
ApiSetNotificationTimestamp
API interface for setting the wl_notificationtimestamp field.
Definition: ApiSetNotificationTimestamp.php:33
ApiSetNotificationTimestamp\needsToken
needsToken()
Returns the token type this module requires in order to execute.
Definition: ApiSetNotificationTimestamp.php:245
ApiSetNotificationTimestamp\getAllowedParams
getAllowedParams( $flags=0)
Definition: ApiSetNotificationTimestamp.php:249
WatchedItemStoreInterface
Definition: WatchedItemStoreInterface.php:31
ApiSetNotificationTimestamp\isWriteMode
isWriteMode()
Indicates whether this module requires write mode.
Definition: ApiSetNotificationTimestamp.php:241
Wikimedia\Rdbms\ILoadBalancer
Database cluster connection, tracking, load balancing, and transaction manager interface.
Definition: ILoadBalancer.php:81
ApiSetNotificationTimestamp\getHelpUrls
getHelpUrls()
Return links to more detailed help pages about the module.
Definition: ApiSetNotificationTimestamp.php:288