Normalise casing of svn:keywords Id
[lhc/web/wiklou.git] / includes / api / ApiMove.php
1 <?php
2 /**
3 *
4 *
5 * Created on Oct 31, 2007
6 *
7 * Copyright © 2007 Roan Kattouw <Firstname>.<Lastname>@gmail.com
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License along
20 * with this program; if not, write to the Free Software Foundation, Inc.,
21 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
22 * http://www.gnu.org/copyleft/gpl.html
23 *
24 * @file
25 */
26
27 if ( !defined( 'MEDIAWIKI' ) ) {
28 // Eclipse helper - will be ignored in production
29 require_once( "ApiBase.php" );
30 }
31
32 /**
33 * API Module to move pages
34 * @ingroup API
35 */
36 class ApiMove extends ApiBase {
37
38 public function __construct( $main, $action ) {
39 parent::__construct( $main, $action );
40 }
41
42 public function execute() {
43 global $wgUser;
44 $params = $this->extractRequestParams();
45 if ( is_null( $params['reason'] ) ) {
46 $params['reason'] = '';
47 }
48
49 $this->requireOnlyOneParameter( $params, 'from', 'fromid' );
50
51 if ( isset( $params['from'] ) ) {
52 $fromTitle = Title::newFromText( $params['from'] );
53 if ( !$fromTitle ) {
54 $this->dieUsageMsg( array( 'invalidtitle', $params['from'] ) );
55 }
56 } elseif ( isset( $params['fromid'] ) ) {
57 $fromTitle = Title::newFromID( $params['fromid'] );
58 if ( !$fromTitle ) {
59 $this->dieUsageMsg( array( 'nosuchpageid', $params['fromid'] ) );
60 }
61 }
62
63 if ( !$fromTitle->exists() ) {
64 $this->dieUsageMsg( array( 'notanarticle' ) );
65 }
66 $fromTalk = $fromTitle->getTalkPage();
67
68 $toTitle = Title::newFromText( $params['to'] );
69 if ( !$toTitle ) {
70 $this->dieUsageMsg( array( 'invalidtitle', $params['to'] ) );
71 }
72 $toTalk = $toTitle->getTalkPage();
73
74 if ( $toTitle->getNamespace() == NS_FILE
75 && !RepoGroup::singleton()->getLocalRepo()->findFile( $toTitle )
76 && wfFindFile( $toTitle ) )
77 {
78 if ( !$params['ignorewarnings'] && $wgUser->isAllowed( 'reupload-shared' ) ) {
79 $this->dieUsageMsg( array( 'sharedfile-exists' ) );
80 } elseif ( !$wgUser->isAllowed( 'reupload-shared' ) ) {
81 $this->dieUsageMsg( array( 'cantoverwrite-sharedfile' ) );
82 }
83 }
84
85 // Move the page
86 $retval = $fromTitle->moveTo( $toTitle, true, $params['reason'], !$params['noredirect'] );
87 if ( $retval !== true ) {
88 $this->dieUsageMsg( reset( $retval ) );
89 }
90
91 $r = array( 'from' => $fromTitle->getPrefixedText(), 'to' => $toTitle->getPrefixedText(), 'reason' => $params['reason'] );
92 if ( !$params['noredirect'] || !$wgUser->isAllowed( 'suppressredirect' ) ) {
93 $r['redirectcreated'] = '';
94 }
95
96 // Move the talk page
97 if ( $params['movetalk'] && $fromTalk->exists() && !$fromTitle->isTalkPage() ) {
98 $retval = $fromTalk->moveTo( $toTalk, true, $params['reason'], !$params['noredirect'] );
99 if ( $retval === true ) {
100 $r['talkfrom'] = $fromTalk->getPrefixedText();
101 $r['talkto'] = $toTalk->getPrefixedText();
102 } else {
103 // We're not gonna dieUsage() on failure, since we already changed something
104 $parsed = $this->parseMsg( reset( $retval ) );
105 $r['talkmove-error-code'] = $parsed['code'];
106 $r['talkmove-error-info'] = $parsed['info'];
107 }
108 }
109
110 // Move subpages
111 if ( $params['movesubpages'] ) {
112 $r['subpages'] = $this->moveSubpages( $fromTitle, $toTitle,
113 $params['reason'], $params['noredirect'] );
114 $this->getResult()->setIndexedTagName( $r['subpages'], 'subpage' );
115 if ( $params['movetalk'] ) {
116 $r['subpages-talk'] = $this->moveSubpages( $fromTalk, $toTalk,
117 $params['reason'], $params['noredirect'] );
118 $this->getResult()->setIndexedTagName( $r['subpages-talk'], 'subpage' );
119 }
120 }
121
122 $watch = "preferences";
123 if ( isset( $params['watchlist'] ) ) {
124 $watch = $params['watchlist'];
125 } elseif ( $params['watch'] ) {
126 $watch = 'watch';
127 } elseif ( $params['unwatch'] ) {
128 $watch = 'unwatch';
129 }
130
131 // Watch pages
132 $this->setWatch( $watch, $fromTitle, 'watchmoves' );
133 $this->setWatch( $watch, $toTitle, 'watchmoves' );
134
135 $this->getResult()->addValue( null, $this->getModuleName(), $r );
136 }
137
138 public function moveSubpages( $fromTitle, $toTitle, $reason, $noredirect ) {
139 $retval = array();
140 $success = $fromTitle->moveSubpages( $toTitle, true, $reason, !$noredirect );
141 if ( isset( $success[0] ) ) {
142 return array( 'error' => $this->parseMsg( $success ) );
143 } else {
144 // At least some pages could be moved
145 // Report each of them separately
146 foreach ( $success as $oldTitle => $newTitle ) {
147 $r = array( 'from' => $oldTitle );
148 if ( is_array( $newTitle ) ) {
149 $r['error'] = $this->parseMsg( reset( $newTitle ) );
150 } else {
151 // Success
152 $r['to'] = $newTitle;
153 }
154 $retval[] = $r;
155 }
156 }
157 return $retval;
158 }
159
160 public function mustBePosted() {
161 return true;
162 }
163
164 public function isWriteMode() {
165 return true;
166 }
167
168 public function getAllowedParams() {
169 return array(
170 'from' => null,
171 'fromid' => array(
172 ApiBase::PARAM_TYPE => 'integer'
173 ),
174 'to' => array(
175 ApiBase::PARAM_TYPE => 'string',
176 ApiBase::PARAM_REQUIRED => true
177 ),
178 'token' => null,
179 'reason' => null,
180 'movetalk' => false,
181 'movesubpages' => false,
182 'noredirect' => false,
183 'watch' => array(
184 ApiBase::PARAM_DFLT => false,
185 ApiBase::PARAM_DEPRECATED => true,
186 ),
187 'unwatch' => array(
188 ApiBase::PARAM_DFLT => false,
189 ApiBase::PARAM_DEPRECATED => true,
190 ),
191 'watchlist' => array(
192 ApiBase::PARAM_DFLT => 'preferences',
193 ApiBase::PARAM_TYPE => array(
194 'watch',
195 'unwatch',
196 'preferences',
197 'nochange'
198 ),
199 ),
200 'ignorewarnings' => false
201 );
202 }
203
204 public function getParamDescription() {
205 $p = $this->getModulePrefix();
206 return array(
207 'from' => "Title of the page you want to move. Cannot be used together with {$p}fromid",
208 'fromid' => "Page ID of the page you want to move. Cannot be used together with {$p}from",
209 'to' => 'Title you want to rename the page to',
210 'token' => 'A move token previously retrieved through prop=info',
211 'reason' => 'Reason for the move (optional)',
212 'movetalk' => 'Move the talk page, if it exists',
213 'movesubpages' => 'Move subpages, if applicable',
214 'noredirect' => 'Don\'t create a redirect',
215 'watch' => 'Add the page and the redirect to your watchlist',
216 'unwatch' => 'Remove the page and the redirect from your watchlist',
217 'watchlist' => 'Unconditionally add or remove the page from your watchlist, use preferences or do not change watch',
218 'ignorewarnings' => 'Ignore any warnings'
219 );
220 }
221
222 public function getDescription() {
223 return 'Move a page';
224 }
225
226 public function getPossibleErrors() {
227 return array_merge( parent::getPossibleErrors(), array(
228 array( 'code' => 'missingparam', 'info' => 'One of the parameters from, fromid is required' ),
229 array( 'code' => 'invalidparammix', 'info' => 'The parameters from, fromid can not be used together' ),
230 array( 'invalidtitle', 'from' ),
231 array( 'nosuchpageid', 'fromid' ),
232 array( 'notanarticle' ),
233 array( 'invalidtitle', 'to' ),
234 array( 'sharedfile-exists' ),
235 ) );
236 }
237
238 public function needsToken() {
239 return true;
240 }
241
242 public function getTokenSalt() {
243 return '';
244 }
245
246 protected function getExamples() {
247 return array(
248 'api.php?action=move&from=Exampel&to=Example&token=123ABC&reason=Misspelled%20title&movetalk=&noredirect='
249 );
250 }
251
252 public function getVersion() {
253 return __CLASS__ . ': $Id$';
254 }
255 }