3 * Implements Special:Redirect
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 * http://www.gnu.org/copyleft/gpl.html
21 * @ingroup SpecialPage
25 * A special page that redirects to: the user for a numeric user id,
26 * the file for a given filename, or the page for a given revision id.
28 * @ingroup SpecialPage
31 class SpecialRedirect extends FormSpecialPage {
34 * The type of the redirect (user/file/revision)
36 * Example value: `'user'`
43 * The identifier/value for the redirect (which id, which file)
45 * Example value: `'42'`
51 function __construct() {
52 parent::__construct( 'Redirect' );
58 * Set $mType and $mValue based on parsed value of $subpage.
59 * @param string $subpage
61 function setParameter( $subpage ) {
62 // parse $subpage to pull out the parts
63 $parts = explode( '/', $subpage, 2 );
64 $this->mType = count( $parts ) > 0 ? $parts[0] : null;
65 $this->mValue = count( $parts ) > 1 ? $parts[1] : null;
69 * Handle Special:Redirect/user/xxxx (by redirecting to User:YYYY)
71 * @return string|null Url to redirect to, or null if $mValue is invalid.
73 function dispatchUser() {
74 if ( !ctype_digit( $this->mValue ) ) {
77 $user = User::newFromId( (int)$this->mValue );
78 $username = $user->getName(); // load User as side-effect
79 if ( $user->isAnon() ) {
82 $userpage = Title::makeTitle( NS_USER, $username );
84 return $userpage->getFullURL( '', false, PROTO_CURRENT );
88 * Handle Special:Redirect/file/xxxx
90 * @return string|null Url to redirect to, or null if $mValue is not found.
92 function dispatchFile() {
93 $title = Title::makeTitleSafe( NS_FILE, $this->mValue );
95 if ( !$title instanceof Title ) {
98 $file = wfFindFile( $title );
100 if ( !$file || !$file->exists() ) {
103 // Default behavior: Use the direct link to the file.
104 $url = $file->getUrl();
105 $request = $this->getRequest();
106 $width = $request->getInt( 'width', -1 );
107 $height = $request->getInt( 'height', -1 );
109 // If a width is requested...
110 if ( $width != -1 ) {
111 $mto = $file->transform( [ 'width' => $width, 'height' => $height ] );
113 if ( $mto && !$mto->isError() ) {
114 // ... change the URL to point to a thumbnail.
115 $url = $mto->getUrl();
123 * Handle Special:Redirect/revision/xxx
124 * (by redirecting to index.php?oldid=xxx)
126 * @return string|null Url to redirect to, or null if $mValue is invalid.
128 function dispatchRevision() {
129 $oldid = $this->mValue;
130 if ( !ctype_digit( $oldid ) ) {
133 $oldid = (int)$oldid;
134 if ( $oldid === 0 ) {
138 return wfAppendQuery( wfScript( 'index' ), [
144 * Handle Special:Redirect/page/xxx (by redirecting to index.php?curid=xxx)
146 * @return string|null Url to redirect to, or null if $mValue is invalid.
148 function dispatchPage() {
149 $curid = $this->mValue;
150 if ( !ctype_digit( $curid ) ) {
153 $curid = (int)$curid;
154 if ( $curid === 0 ) {
158 return wfAppendQuery( wfScript( 'index' ), [
164 * Handle Special:Redirect/logid/xxx
165 * (by redirecting to index.php?title=Special:Log&logid=xxx)
168 * @return string|null Url to redirect to, or null if $mValue is invalid.
170 function dispatchLog() {
171 $logid = $this->mValue;
172 if ( !ctype_digit( $logid ) ) {
175 $logid = (int)$logid;
176 if ( $logid === 0 ) {
180 $query = [ 'title' => 'Special:Log', 'logid' => $logid ];
181 return wfAppendQuery( wfScript( 'index' ), $query );
185 * Use appropriate dispatch* method to obtain a redirection URL,
186 * and either: redirect, set a 404 error code and error message,
187 * or do nothing (if $mValue wasn't set) allowing the form to be
190 * @return bool True if a redirect was successfully handled.
192 function dispatch() {
193 // the various namespaces supported by Special:Redirect
194 switch ( $this->mType ) {
196 $url = $this->dispatchUser();
199 $url = $this->dispatchFile();
202 $url = $this->dispatchRevision();
205 $url = $this->dispatchPage();
208 $url = $this->dispatchLog();
215 $this->getOutput()->redirect( $url );
219 if ( !is_null( $this->mValue ) ) {
220 $this->getOutput()->setStatusCode( 404 );
221 // Message: redirect-not-exists
222 $msg = $this->getMessagePrefix() . '-not-exists';
224 return Status::newFatal( $msg );
230 protected function getFormFields() {
231 $mp = $this->getMessagePrefix();
233 // subpage => message
234 // Messages: redirect-user, redirect-page, redirect-revision,
235 // redirect-file, redirect-logid
236 'user' => $mp . '-user',
237 'page' => $mp . '-page',
238 'revision' => $mp . '-revision',
239 'file' => $mp . '-file',
240 'logid' => $mp . '-logid',
245 'label-message' => $mp . '-lookup', // Message: redirect-lookup
247 'default' => current( array_keys( $ns ) ),
249 foreach ( $ns as $n => $m ) {
250 $m = $this->msg( $m )->text();
251 $a['type']['options'][$m] = $n;
255 'label-message' => $mp . '-value' // Message: redirect-value
257 // set the defaults according to the parsed subpage path
258 if ( !empty( $this->mType ) ) {
259 $a['type']['default'] = $this->mType;
261 if ( !empty( $this->mValue ) ) {
262 $a['value']['default'] = $this->mValue;
268 public function onSubmit( array $data ) {
269 if ( !empty( $data['type'] ) && !empty( $data['value'] ) ) {
270 $this->setParameter( $data['type'] . '/' . $data['value'] );
273 /* if this returns false, will show the form */
274 return $this->dispatch();
277 public function onSuccess() {
278 /* do nothing, we redirect in $this->dispatch if successful. */
281 protected function alterForm( HTMLForm $form ) {
282 /* display summary at top of page */
283 $this->outputHeader();
284 // tweak label on submit button
285 // Message: redirect-submit
286 $form->setSubmitTextMsg( $this->getMessagePrefix() . '-submit' );
287 /* submit form every time */
288 $form->setMethod( 'get' );
291 protected function getDisplayFormat() {
296 * Return an array of subpages that this special page will accept.
298 * @return string[] subpages
300 protected function getSubpagesForPrefixSearch() {
313 public function requiresWrite() {
320 public function requiresUnblock() {
324 protected function getGroupName() {