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