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