Localisation updates from https://translatewiki.net.
[mediawiki.git] / includes / api / ApiSetNotificationTimestamp.php
blob23a4c5bf9a992188520759f929f77c3aeb666294
1 <?php
3 /**
4 * API for MediaWiki 1.14+
6 * Copyright © 2012 Wikimedia Foundation and contributors
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License along
19 * with this program; if not, write to the Free Software Foundation, Inc.,
20 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
21 * http://www.gnu.org/copyleft/gpl.html
23 * @file
26 namespace MediaWiki\Api;
28 use MediaWiki\Revision\RevisionStore;
29 use MediaWiki\Title\Title;
30 use MediaWiki\Title\TitleFactory;
31 use MediaWiki\Title\TitleFormatter;
32 use MediaWiki\Watchlist\WatchedItemStoreInterface;
33 use Wikimedia\ParamValidator\ParamValidator;
34 use Wikimedia\Rdbms\IConnectionProvider;
35 use Wikimedia\Rdbms\IDBAccessObject;
37 /**
38 * API interface for setting the wl_notificationtimestamp field
39 * @ingroup API
41 class ApiSetNotificationTimestamp extends ApiBase {
43 /** @var ApiPageSet|null */
44 private $mPageSet = null;
46 private RevisionStore $revisionStore;
47 private IConnectionProvider $dbProvider;
48 private WatchedItemStoreInterface $watchedItemStore;
49 private TitleFormatter $titleFormatter;
50 private TitleFactory $titleFactory;
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 );
63 $this->dbProvider = $dbProvider;
64 $this->revisionStore = $revisionStore;
65 $this->watchedItemStore = $watchedItemStore;
66 $this->titleFormatter = $titleFormatter;
67 $this->titleFactory = $titleFactory;
70 public function execute() {
71 $user = $this->getUser();
73 if ( !$user->isRegistered() ) {
74 $this->dieWithError( 'watchlistanontext', 'notloggedin' );
76 $this->checkUserRightsAny( 'editmywatchlist' );
78 $params = $this->extractRequestParams();
79 $this->requireMaxOneParameter( $params, 'timestamp', 'torevid', 'newerthanrevid' );
81 $continuationManager = new ApiContinuationManager( $this, [], [] );
82 $this->setContinuationManager( $continuationManager );
84 $pageSet = $this->getPageSet();
85 if ( $params['entirewatchlist'] && $pageSet->getDataSource() !== null ) {
86 $this->dieWithError(
88 'apierror-invalidparammix-cannotusewith',
89 $this->encodeParamName( 'entirewatchlist' ),
90 $pageSet->encodeParamName( $pageSet->getDataSource() )
92 'multisource'
96 $dbw = $this->dbProvider->getPrimaryDatabase();
98 $timestamp = null;
99 if ( isset( $params['timestamp'] ) ) {
100 $timestamp = $dbw->timestamp( $params['timestamp'] );
103 if ( !$params['entirewatchlist'] ) {
104 $pageSet->execute();
107 if ( isset( $params['torevid'] ) ) {
108 if ( $params['entirewatchlist'] || $pageSet->getGoodTitleCount() > 1 ) {
109 $this->dieWithError( [ 'apierror-multpages', $this->encodeParamName( 'torevid' ) ] );
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
119 if ( $timestamp ) {
120 $timestamp = $dbw->timestamp( $timestamp );
121 } else {
122 $timestamp = null;
125 } elseif ( isset( $params['newerthanrevid'] ) ) {
126 if ( $params['entirewatchlist'] || $pageSet->getGoodTitleCount() > 1 ) {
127 $this->dieWithError( [ 'apierror-multpages', $this->encodeParamName( 'newerthanrevid' ) ] );
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
137 if ( $currRev ) {
138 $nextRev = $this->revisionStore->getNextRevision(
139 $currRev,
140 IDBAccessObject::READ_LATEST
142 if ( $nextRev ) {
143 $timestamp = $dbw->timestamp( $nextRev->getTimestamp() );
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 );
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;
164 foreach ( $pageSet->getMissingPageIDs() as $p ) {
165 $page = [];
166 $page['pageid'] = $p;
167 $page['missing'] = true;
168 $page['notwatched'] = true;
169 $result[] = $page;
171 foreach ( $pageSet->getMissingRevisionIDs() as $r ) {
172 $rev = [];
173 $rev['revid'] = $r;
174 $rev['missing'] = true;
175 $rev['notwatched'] = true;
176 $result[] = $rev;
179 $pages = $pageSet->getPages();
180 if ( $pages ) {
181 // Now process the valid titles
182 $this->watchedItemStore->setNotificationTimestampsForUser(
183 $user,
184 $timestamp,
185 $pages
188 // Query the results of our update
189 $timestamps = $this->watchedItemStore->getNotificationTimestampsBatch(
190 $user,
191 $pages
194 // Now, put the valid titles into the result
195 /** @var \MediaWiki\Page\PageIdentity $page */
196 foreach ( $pages as $page ) {
197 $ns = $page->getNamespace();
198 $dbkey = $page->getDBkey();
199 $r = [
200 'ns' => $ns,
201 'title' => $this->titleFormatter->getPrefixedText( $page ),
203 if ( !$page->exists() ) {
204 $r['missing'] = true;
205 $title = $this->titleFactory->newFromPageIdentity( $page );
206 if ( $title->isKnown() ) {
207 $r['known'] = true;
210 if ( isset( $timestamps[$ns] ) && array_key_exists( $dbkey, $timestamps[$ns] )
211 && $timestamps[$ns][$dbkey] !== false
213 $r['notificationtimestamp'] = '';
214 if ( $timestamps[$ns][$dbkey] !== null ) {
215 $r['notificationtimestamp'] = wfTimestamp( TS_ISO_8601, $timestamps[$ns][$dbkey] );
217 } else {
218 $r['notwatched'] = true;
220 $result[] = $r;
224 ApiResult::setIndexedTagName( $result, 'page' );
226 $apiResult->addValue( null, $this->getModuleName(), $result );
228 $this->setContinuationManager( null );
229 $continuationManager->setContinuationIntoResult( $apiResult );
233 * Get a cached instance of an ApiPageSet object
234 * @return ApiPageSet
236 private function getPageSet() {
237 $this->mPageSet ??= new ApiPageSet( $this );
239 return $this->mPageSet;
242 public function mustBePosted() {
243 return true;
246 public function isWriteMode() {
247 return true;
250 public function needsToken() {
251 return 'csrf';
254 public function getAllowedParams( $flags = 0 ) {
255 $result = [
256 'entirewatchlist' => [
257 ParamValidator::PARAM_TYPE => 'boolean'
259 'timestamp' => [
260 ParamValidator::PARAM_TYPE => 'timestamp'
262 'torevid' => [
263 ParamValidator::PARAM_TYPE => 'integer'
265 'newerthanrevid' => [
266 ParamValidator::PARAM_TYPE => 'integer'
268 'continue' => [
269 ApiBase::PARAM_HELP_MSG => 'api-help-param-continue',
272 if ( $flags ) {
273 $result += $this->getPageSet()->getFinalParams( $flags );
276 return $result;
279 protected function getExamplesMessages() {
280 $title = Title::newMainPage()->getPrefixedText();
281 $mp = rawurlencode( $title );
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',
296 public function getHelpUrls() {
297 return 'https://www.mediawiki.org/wiki/Special:MyLanguage/API:SetNotificationTimestamp';
301 /** @deprecated class alias since 1.43 */
302 class_alias( ApiSetNotificationTimestamp::class, 'ApiSetNotificationTimestamp' );