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