Merge "Set relevant title on Special:RecentChangesLinked"
[lhc/web/wiklou.git] / includes / specials / SpecialRedirect.php
1 <?php
2 /**
3 * Implements Special:Redirect
4 *
5 * @section LICENSE
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19 * http://www.gnu.org/copyleft/gpl.html
20 *
21 * @file
22 * @ingroup SpecialPage
23 */
24
25 /**
26 * A special page that redirects to: the user for a numeric user id,
27 * the file for a given filename, or the page for a given revision id.
28 *
29 * @ingroup SpecialPage
30 * @since 1.22
31 */
32 class SpecialRedirect extends FormSpecialPage {
33
34 /**
35 * The type of the redirect (user/file/revision)
36 *
37 * @var string $mType
38 * @example 'user'
39 */
40 protected $mType;
41
42 /**
43 * The identifier/value for the redirect (which id, which file)
44 *
45 * @var string $mValue
46 * @example '42'
47 */
48 protected $mValue;
49
50 function __construct() {
51 parent::__construct( 'Redirect' );
52 $this->mType = null;
53 $this->mValue = null;
54 }
55
56 /**
57 * Set $mType and $mValue based on parsed value of $subpage.
58 * @param string $subpage
59 */
60 function setParameter( $subpage ) {
61 // parse $subpage to pull out the parts
62 $parts = explode( '/', $subpage, 2 );
63 $this->mType = count( $parts ) > 0 ? $parts[0] : null;
64 $this->mValue = count( $parts ) > 1 ? $parts[1] : null;
65 }
66
67 /**
68 * Handle Special:Redirect/user/xxxx (by redirecting to User:YYYY)
69 *
70 * @return string|null Url to redirect to, or null if $mValue is invalid.
71 */
72 function dispatchUser() {
73 if ( !ctype_digit( $this->mValue ) ) {
74 return null;
75 }
76 $user = User::newFromId( (int)$this->mValue );
77 $username = $user->getName(); // load User as side-effect
78 if ( $user->isAnon() ) {
79 return null;
80 }
81 $userpage = Title::makeTitle( NS_USER, $username );
82
83 return $userpage->getFullURL( '', false, PROTO_CURRENT );
84 }
85
86 /**
87 * Handle Special:Redirect/file/xxxx
88 *
89 * @return string|null Url to redirect to, or null if $mValue is not found.
90 */
91 function dispatchFile() {
92 $title = Title::makeTitleSafe( NS_FILE, $this->mValue );
93
94 if ( !$title instanceof Title ) {
95 return null;
96 }
97 $file = wfFindFile( $title );
98
99 if ( !$file || !$file->exists() ) {
100 return null;
101 }
102 // Default behavior: Use the direct link to the file.
103 $url = $file->getURL();
104 $request = $this->getRequest();
105 $width = $request->getInt( 'width', -1 );
106 $height = $request->getInt( 'height', -1 );
107
108 // If a width is requested...
109 if ( $width != -1 ) {
110 $mto = $file->transform( array( 'width' => $width, 'height' => $height ) );
111 // ... and we can
112 if ( $mto && !$mto->isError() ) {
113 // ... change the URL to point to a thumbnail.
114 $url = $mto->getURL();
115 }
116 }
117
118 return $url;
119 }
120
121 /**
122 * Handle Special:Redirect/revision/xxx
123 * (by redirecting to index.php?oldid=xxx)
124 *
125 * @return string|null Url to redirect to, or null if $mValue is invalid.
126 */
127 function dispatchRevision() {
128 $oldid = $this->mValue;
129 if ( !ctype_digit( $oldid ) ) {
130 return null;
131 }
132 $oldid = (int)$oldid;
133 if ( $oldid === 0 ) {
134 return null;
135 }
136
137 return wfAppendQuery( wfScript( 'index' ), array(
138 'oldid' => $oldid
139 ) );
140 }
141
142 /**
143 * Handle Special:Redirect/page/xxx (by redirecting to index.php?curid=xxx)
144 *
145 * @return string|null Url to redirect to, or null if $mValue is invalid.
146 */
147 function dispatchPage() {
148 $curid = $this->mValue;
149 if ( !ctype_digit( $curid ) ) {
150 return null;
151 }
152 $curid = (int)$curid;
153 if ( $curid === 0 ) {
154 return null;
155 }
156
157 return wfAppendQuery( wfScript( 'index' ), array(
158 'curid' => $curid
159 ) );
160 }
161
162 /**
163 * Use appropriate dispatch* method to obtain a redirection URL,
164 * and either: redirect, set a 404 error code and error message,
165 * or do nothing (if $mValue wasn't set) allowing the form to be
166 * displayed.
167 *
168 * @return bool True if a redirect was successfully handled.
169 */
170 function dispatch() {
171 // the various namespaces supported by Special:Redirect
172 switch ( $this->mType ) {
173 case 'user':
174 $url = $this->dispatchUser();
175 break;
176 case 'file':
177 $url = $this->dispatchFile();
178 break;
179 case 'revision':
180 $url = $this->dispatchRevision();
181 break;
182 case 'page':
183 $url = $this->dispatchPage();
184 break;
185 default:
186 $this->getOutput()->setStatusCode( 404 );
187 $url = null;
188 break;
189 }
190 if ( $url ) {
191 $this->getOutput()->redirect( $url );
192
193 return true;
194 }
195 if ( !is_null( $this->mValue ) ) {
196 $this->getOutput()->setStatusCode( 404 );
197 // Message: redirect-not-exists
198 $msg = $this->getMessagePrefix() . '-not-exists';
199
200 return Status::newFatal( $msg );
201 }
202
203 return false;
204 }
205
206 protected function getFormFields() {
207 $mp = $this->getMessagePrefix();
208 $ns = array(
209 // subpage => message
210 // Messages: redirect-user, redirect-page, redirect-revision,
211 // redirect-file
212 'user' => $mp . '-user',
213 'page' => $mp . '-page',
214 'revision' => $mp . '-revision',
215 'file' => $mp . '-file',
216 );
217 $a = array();
218 $a['type'] = array(
219 'type' => 'select',
220 'label-message' => $mp . '-lookup', // Message: redirect-lookup
221 'options' => array(),
222 'default' => current( array_keys( $ns ) ),
223 );
224 foreach ( $ns as $n => $m ) {
225 $m = $this->msg( $m )->text();
226 $a['type']['options'][$m] = $n;
227 }
228 $a['value'] = array(
229 'type' => 'text',
230 'label-message' => $mp . '-value' // Message: redirect-value
231 );
232 // set the defaults according to the parsed subpage path
233 if ( !empty( $this->mType ) ) {
234 $a['type']['default'] = $this->mType;
235 }
236 if ( !empty( $this->mValue ) ) {
237 $a['value']['default'] = $this->mValue;
238 }
239
240 return $a;
241 }
242
243 public function onSubmit( array $data ) {
244 if ( !empty( $data['type'] ) && !empty( $data['value'] ) ) {
245 $this->setParameter( $data['type'] . '/' . $data['value'] );
246 }
247
248 /* if this returns false, will show the form */
249 return $this->dispatch();
250 }
251
252 public function onSuccess() {
253 /* do nothing, we redirect in $this->dispatch if successful. */
254 }
255
256 protected function alterForm( HTMLForm $form ) {
257 /* display summary at top of page */
258 $this->outputHeader();
259 // tweak label on submit button
260 // Message: redirect-submit
261 $form->setSubmitTextMsg( $this->getMessagePrefix() . '-submit' );
262 /* submit form every time */
263 $form->setMethod( 'get' );
264 }
265
266 protected function getGroupName() {
267 return 'redirects';
268 }
269 }