Merge "Added line to rel notes about CacheHelper class"
[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 $db = $this->getDB();
53 $dbw = $this->getDB( DB_MASTER );
54
55 $timestamp = null;
56 if ( isset( $params['timestamp'] ) ) {
57 $timestamp = $dbw->timestamp( $params['timestamp'] );
58 }
59
60 if ( !$params['entirewatchlist'] ) {
61 $pageSet->execute();
62 }
63
64 if ( isset( $params['torevid'] ) ) {
65 if ( $params['entirewatchlist'] || $pageSet->getGoodTitleCount() > 1 ) {
66 $this->dieUsage( 'torevid may only be used with a single page', 'multpages' );
67 }
68 $title = reset( $pageSet->getGoodTitles() );
69 $timestamp = Revision::getTimestampFromId( $title, $params['torevid'] );
70 if ( $timestamp ) {
71 $timestamp = $dbw->timestamp( $timestamp );
72 } else {
73 $timestamp = null;
74 }
75 } elseif ( isset( $params['newerthanrevid'] ) ) {
76 if ( $params['entirewatchlist'] || $pageSet->getGoodTitleCount() > 1 ) {
77 $this->dieUsage( 'newerthanrevid may only be used with a single page', 'multpages' );
78 }
79 $title = reset( $pageSet->getGoodTitles() );
80 $revid = $title->getNextRevisionID( $params['newerthanrevid'] );
81 if ( $revid ) {
82 $timestamp = $dbw->timestamp( Revision::getTimestampFromId( $title, $revid ) );
83 } else {
84 $timestamp = null;
85 }
86 }
87
88 $apiResult = $this->getResult();
89 $result = array();
90 if ( $params['entirewatchlist'] ) {
91 // Entire watchlist mode: Just update the thing and return a success indicator
92 $dbw->update( 'watchlist', array( 'wl_notificationtimestamp' => $timestamp ),
93 array( 'wl_user' => $user->getID() ),
94 __METHOD__
95 );
96
97 $result['notificationtimestamp'] = ( is_null( $timestamp ) ? '' : wfTimestamp( TS_ISO_8601, $timestamp ) );
98 } else {
99 // First, log the invalid titles
100 foreach( $pageSet->getInvalidTitles() as $title ) {
101 $r = array();
102 $r['title'] = $title;
103 $r['invalid'] = '';
104 $result[] = $r;
105 }
106 foreach( $pageSet->getMissingPageIDs() as $p ) {
107 $page = array();
108 $page['pageid'] = $p;
109 $page['missing'] = '';
110 $page['notwatched'] = '';
111 $result[] = $page;
112 }
113 foreach( $pageSet->getMissingRevisionIDs() as $r ) {
114 $rev = array();
115 $rev['revid'] = $r;
116 $rev['missing'] = '';
117 $rev['notwatched'] = '';
118 $result[] = $rev;
119 }
120
121 // Now process the valid titles
122 $lb = new LinkBatch( $pageSet->getTitles() );
123 $dbw->update( 'watchlist', array( 'wl_notificationtimestamp' => $timestamp ),
124 array( 'wl_user' => $user->getID(), $lb->constructSet( 'wl', $dbw ) ),
125 __METHOD__
126 );
127
128 // Query the results of our update
129 $timestamps = array();
130 $res = $dbw->select( 'watchlist', array( 'wl_namespace', 'wl_title', 'wl_notificationtimestamp' ),
131 array( 'wl_user' => $user->getID(), $lb->constructSet( 'wl', $dbw ) ),
132 __METHOD__
133 );
134 foreach ( $res as $row ) {
135 $timestamps[$row->wl_namespace][$row->wl_title] = $row->wl_notificationtimestamp;
136 }
137
138 // Now, put the valid titles into the result
139 $pages = array();
140 foreach ( $pageSet->getTitles() as $title ) {
141 $ns = $title->getNamespace();
142 $dbkey = $title->getDBkey();
143 $r = array(
144 'ns' => intval( $ns ),
145 'title' => $title->getPrefixedText(),
146 );
147 if ( !$title->exists() ) {
148 $r['missing'] = '';
149 }
150 if ( isset( $timestamps[$ns] ) && array_key_exists( $dbkey, $timestamps[$ns] ) ) {
151 $r['notificationtimestamp'] = '';
152 if ( $timestamps[$ns][$dbkey] !== null ) {
153 $r['notificationtimestamp'] = wfTimestamp( TS_ISO_8601, $timestamps[$ns][$dbkey] );
154 }
155 } else {
156 $r['notwatched'] = '';
157 }
158 $result[] = $r;
159 }
160
161 $apiResult->setIndexedTagName( $result, 'page' );
162 }
163 $apiResult->addValue( null, $this->getModuleName(), $result );
164 }
165
166 public function mustBePosted() {
167 return true;
168 }
169
170 public function isWriteMode() {
171 return true;
172 }
173
174 public function needsToken() {
175 return true;
176 }
177
178 public function getTokenSalt() {
179 return '';
180 }
181
182 public function getAllowedParams() {
183 $psModule = new ApiPageSet( $this );
184 return $psModule->getAllowedParams() + array(
185 'entirewatchlist' => array(
186 ApiBase::PARAM_TYPE => 'boolean'
187 ),
188 'token' => null,
189 'timestamp' => array(
190 ApiBase::PARAM_TYPE => 'timestamp'
191 ),
192 'torevid' => array(
193 ApiBase::PARAM_TYPE => 'integer'
194 ),
195 'newerthanrevid' => array(
196 ApiBase::PARAM_TYPE => 'integer'
197 ),
198 );
199 }
200
201 public function getParamDescription() {
202 $psModule = new ApiPageSet( $this );
203 return $psModule->getParamDescription() + array(
204 'entirewatchlist' => 'Work on all watched pages',
205 'timestamp' => 'Timestamp to which to set the notification timestamp',
206 'torevid' => 'Revision to set the notification timestamp to (one page only)',
207 'newerthanrevid' => 'Revision to set the notification timestamp newer than (one page only)',
208 'token' => 'A token previously acquired via prop=info',
209 );
210 }
211
212 public function getResultProperties() {
213 return array(
214 ApiBase::PROP_LIST => true,
215 ApiBase::PROP_ROOT => array(
216 'notificationtimestamp' => array(
217 ApiBase::PROP_TYPE => 'timestamp',
218 ApiBase::PROP_NULLABLE => true
219 )
220 ),
221 '' => array(
222 'ns' => array(
223 ApiBase::PROP_TYPE => 'namespace',
224 ApiBase::PROP_NULLABLE => true
225 ),
226 'title' => array(
227 ApiBase::PROP_TYPE => 'string',
228 ApiBase::PROP_NULLABLE => true
229 ),
230 'pageid' => array(
231 ApiBase::PROP_TYPE => 'integer',
232 ApiBase::PROP_NULLABLE => true
233 ),
234 'revid' => array(
235 ApiBase::PROP_TYPE => 'integer',
236 ApiBase::PROP_NULLABLE => true
237 ),
238 'invalid' => 'boolean',
239 'missing' => 'boolean',
240 'notwatched' => 'boolean',
241 'notificationtimestamp' => array(
242 ApiBase::PROP_TYPE => 'timestamp',
243 ApiBase::PROP_NULLABLE => true
244 )
245 )
246 );
247 }
248
249 public function getDescription() {
250 return array( 'Update the notification timestamp for watched pages.',
251 'This affects the highlighting of changed pages in the watchlist and history,',
252 'and the sending of email when the "E-mail me when a page on my watchlist is',
253 'changed" preference is enabled.'
254 );
255 }
256
257 public function getPossibleErrors() {
258 $psModule = new ApiPageSet( $this );
259 return array_merge(
260 parent::getPossibleErrors(),
261 $psModule->getPossibleErrors(),
262 $this->getRequireMaxOneParameterErrorMessages( array( 'timestamp', 'torevid', 'newerthanrevid' ) ),
263 $this->getRequireOnlyOneParameterErrorMessages( array_merge( array( 'entirewatchlist' ), array_keys( $psModule->getAllowedParams() ) ) ),
264 array(
265 array( 'code' => 'notloggedin', 'info' => 'Anonymous users cannot use watchlist change notifications' ),
266 array( 'code' => 'multpages', 'info' => 'torevid may only be used with a single page' ),
267 array( 'code' => 'multpages', 'info' => 'newerthanrevid may only be used with a single page' ),
268 )
269 );
270 }
271
272 public function getExamples() {
273 return array(
274 'api.php?action=setnotificationtimestamp&entirewatchlist=&token=ABC123' => 'Reset the notification status for the entire watchlist',
275 'api.php?action=setnotificationtimestamp&titles=Main_page&token=ABC123' => 'Reset the notification status for "Main page"',
276 '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',
277 );
278 }
279
280 public function getHelpUrls() {
281 return 'https://www.mediawiki.org/wiki/API:SetNotificationTimestamp';
282 }
283
284 public function getVersion() {
285 return __CLASS__ . ': $Id$';
286 }
287 }