Merge "Follow-up I0b781c11 (2a55449): use User::getAutomaticGroups()."
[lhc/web/wiklou.git] / includes / api / ApiSetNotificationTimestamp.php
1 <?php
2
3 /**
4 * API for MediaWiki 1.14+
5 *
6 * Created on Jun 18, 2012
7 *
8 * Copyright © 2012 Brad Jorsch
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License along
21 * with this program; if not, write to the Free Software Foundation, Inc.,
22 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
23 * http://www.gnu.org/copyleft/gpl.html
24 *
25 * @file
26 */
27
28 /**
29 * API interface for setting the wl_notificationtimestamp field
30 * @ingroup API
31 */
32 class ApiSetNotificationTimestamp extends ApiBase {
33
34 public function __construct( $main, $action ) {
35 parent::__construct( $main, $action );
36 }
37
38 public function execute() {
39 $user = $this->getUser();
40
41 if ( $user->isAnon() ) {
42 $this->dieUsage( 'Anonymous users cannot use watchlist change notifications', 'notloggedin' );
43 }
44
45 $params = $this->extractRequestParams();
46 $this->requireMaxOneParameter( $params, 'timestamp', 'torevid', 'newerthanrevid' );
47
48 $pageSet = new ApiPageSet( $this );
49 $args = array_merge( array( $params, 'entirewatchlist' ), array_keys( $pageSet->getAllowedParams() ) );
50 call_user_func_array( array( $this, 'requireOnlyOneParameter' ), $args );
51
52 $dbw = $this->getDB( DB_MASTER );
53
54 $timestamp = null;
55 if ( isset( $params['timestamp'] ) ) {
56 $timestamp = $dbw->timestamp( $params['timestamp'] );
57 }
58
59 if ( !$params['entirewatchlist'] ) {
60 $pageSet->execute();
61 }
62
63 if ( isset( $params['torevid'] ) ) {
64 if ( $params['entirewatchlist'] || $pageSet->getGoodTitleCount() > 1 ) {
65 $this->dieUsage( 'torevid may only be used with a single page', 'multpages' );
66 }
67 $title = reset( $pageSet->getGoodTitles() );
68 $timestamp = Revision::getTimestampFromId( $title, $params['torevid'] );
69 if ( $timestamp ) {
70 $timestamp = $dbw->timestamp( $timestamp );
71 } else {
72 $timestamp = null;
73 }
74 } elseif ( isset( $params['newerthanrevid'] ) ) {
75 if ( $params['entirewatchlist'] || $pageSet->getGoodTitleCount() > 1 ) {
76 $this->dieUsage( 'newerthanrevid may only be used with a single page', 'multpages' );
77 }
78 $title = reset( $pageSet->getGoodTitles() );
79 $revid = $title->getNextRevisionID( $params['newerthanrevid'] );
80 if ( $revid ) {
81 $timestamp = $dbw->timestamp( Revision::getTimestampFromId( $title, $revid ) );
82 } else {
83 $timestamp = null;
84 }
85 }
86
87 $apiResult = $this->getResult();
88 $result = array();
89 if ( $params['entirewatchlist'] ) {
90 // Entire watchlist mode: Just update the thing and return a success indicator
91 $dbw->update( 'watchlist', array( 'wl_notificationtimestamp' => $timestamp ),
92 array( 'wl_user' => $user->getID() ),
93 __METHOD__
94 );
95
96 $result['notificationtimestamp'] = ( is_null( $timestamp ) ? '' : wfTimestamp( TS_ISO_8601, $timestamp ) );
97 } else {
98 // First, log the invalid titles
99 foreach( $pageSet->getInvalidTitles() as $title ) {
100 $r = array();
101 $r['title'] = $title;
102 $r['invalid'] = '';
103 $result[] = $r;
104 }
105 foreach( $pageSet->getMissingPageIDs() as $p ) {
106 $page = array();
107 $page['pageid'] = $p;
108 $page['missing'] = '';
109 $page['notwatched'] = '';
110 $result[] = $page;
111 }
112 foreach( $pageSet->getMissingRevisionIDs() as $r ) {
113 $rev = array();
114 $rev['revid'] = $r;
115 $rev['missing'] = '';
116 $rev['notwatched'] = '';
117 $result[] = $rev;
118 }
119
120 // Now process the valid titles
121 $lb = new LinkBatch( $pageSet->getTitles() );
122 $dbw->update( 'watchlist', array( 'wl_notificationtimestamp' => $timestamp ),
123 array( 'wl_user' => $user->getID(), $lb->constructSet( 'wl', $dbw ) ),
124 __METHOD__
125 );
126
127 // Query the results of our update
128 $timestamps = array();
129 $res = $dbw->select( 'watchlist', array( 'wl_namespace', 'wl_title', 'wl_notificationtimestamp' ),
130 array( 'wl_user' => $user->getID(), $lb->constructSet( 'wl', $dbw ) ),
131 __METHOD__
132 );
133 foreach ( $res as $row ) {
134 $timestamps[$row->wl_namespace][$row->wl_title] = $row->wl_notificationtimestamp;
135 }
136
137 // Now, put the valid titles into the result
138 foreach ( $pageSet->getTitles() as $title ) {
139 $ns = $title->getNamespace();
140 $dbkey = $title->getDBkey();
141 $r = array(
142 'ns' => intval( $ns ),
143 'title' => $title->getPrefixedText(),
144 );
145 if ( !$title->exists() ) {
146 $r['missing'] = '';
147 }
148 if ( isset( $timestamps[$ns] ) && array_key_exists( $dbkey, $timestamps[$ns] ) ) {
149 $r['notificationtimestamp'] = '';
150 if ( $timestamps[$ns][$dbkey] !== null ) {
151 $r['notificationtimestamp'] = wfTimestamp( TS_ISO_8601, $timestamps[$ns][$dbkey] );
152 }
153 } else {
154 $r['notwatched'] = '';
155 }
156 $result[] = $r;
157 }
158
159 $apiResult->setIndexedTagName( $result, 'page' );
160 }
161 $apiResult->addValue( null, $this->getModuleName(), $result );
162 }
163
164 public function mustBePosted() {
165 return true;
166 }
167
168 public function isWriteMode() {
169 return true;
170 }
171
172 public function needsToken() {
173 return true;
174 }
175
176 public function getTokenSalt() {
177 return '';
178 }
179
180 public function getAllowedParams() {
181 $psModule = new ApiPageSet( $this );
182 return $psModule->getAllowedParams() + array(
183 'entirewatchlist' => array(
184 ApiBase::PARAM_TYPE => 'boolean'
185 ),
186 'token' => null,
187 'timestamp' => array(
188 ApiBase::PARAM_TYPE => 'timestamp'
189 ),
190 'torevid' => array(
191 ApiBase::PARAM_TYPE => 'integer'
192 ),
193 'newerthanrevid' => array(
194 ApiBase::PARAM_TYPE => 'integer'
195 ),
196 );
197 }
198
199 public function getParamDescription() {
200 $psModule = new ApiPageSet( $this );
201 return $psModule->getParamDescription() + array(
202 'entirewatchlist' => 'Work on all watched pages',
203 'timestamp' => 'Timestamp to which to set the notification timestamp',
204 'torevid' => 'Revision to set the notification timestamp to (one page only)',
205 'newerthanrevid' => 'Revision to set the notification timestamp newer than (one page only)',
206 'token' => 'A token previously acquired via prop=info',
207 );
208 }
209
210 public function getResultProperties() {
211 return array(
212 ApiBase::PROP_LIST => true,
213 ApiBase::PROP_ROOT => array(
214 'notificationtimestamp' => array(
215 ApiBase::PROP_TYPE => 'timestamp',
216 ApiBase::PROP_NULLABLE => true
217 )
218 ),
219 '' => array(
220 'ns' => array(
221 ApiBase::PROP_TYPE => 'namespace',
222 ApiBase::PROP_NULLABLE => true
223 ),
224 'title' => array(
225 ApiBase::PROP_TYPE => 'string',
226 ApiBase::PROP_NULLABLE => true
227 ),
228 'pageid' => array(
229 ApiBase::PROP_TYPE => 'integer',
230 ApiBase::PROP_NULLABLE => true
231 ),
232 'revid' => array(
233 ApiBase::PROP_TYPE => 'integer',
234 ApiBase::PROP_NULLABLE => true
235 ),
236 'invalid' => 'boolean',
237 'missing' => 'boolean',
238 'notwatched' => 'boolean',
239 'notificationtimestamp' => array(
240 ApiBase::PROP_TYPE => 'timestamp',
241 ApiBase::PROP_NULLABLE => true
242 )
243 )
244 );
245 }
246
247 public function getDescription() {
248 return array( 'Update the notification timestamp for watched pages.',
249 'This affects the highlighting of changed pages in the watchlist and history,',
250 'and the sending of email when the "E-mail me when a page on my watchlist is',
251 'changed" preference is enabled.'
252 );
253 }
254
255 public function getPossibleErrors() {
256 $psModule = new ApiPageSet( $this );
257 return array_merge(
258 parent::getPossibleErrors(),
259 $psModule->getPossibleErrors(),
260 $this->getRequireMaxOneParameterErrorMessages( array( 'timestamp', 'torevid', 'newerthanrevid' ) ),
261 $this->getRequireOnlyOneParameterErrorMessages( array_merge( array( 'entirewatchlist' ), array_keys( $psModule->getAllowedParams() ) ) ),
262 array(
263 array( 'code' => 'notloggedin', 'info' => 'Anonymous users cannot use watchlist change notifications' ),
264 array( 'code' => 'multpages', 'info' => 'torevid may only be used with a single page' ),
265 array( 'code' => 'multpages', 'info' => 'newerthanrevid may only be used with a single page' ),
266 )
267 );
268 }
269
270 public function getExamples() {
271 return array(
272 'api.php?action=setnotificationtimestamp&entirewatchlist=&token=ABC123' => 'Reset the notification status for the entire watchlist',
273 'api.php?action=setnotificationtimestamp&titles=Main_page&token=ABC123' => 'Reset the notification status for "Main page"',
274 'api.php?action=setnotificationtimestamp&titles=Main_page&timestamp=2012-01-01T00:00:00Z&token=ABC123' => 'Set the notification timestamp for "Main page" so all edits since 1 January 2012 are unviewed',
275 );
276 }
277
278 public function getHelpUrls() {
279 return 'https://www.mediawiki.org/wiki/API:SetNotificationTimestamp';
280 }
281
282 public function getVersion() {
283 return __CLASS__ . ': $Id$';
284 }
285 }