MediaWiki  master
SpecialRedirect.php
Go to the documentation of this file.
1 <?php
25 
34 
42  protected $mType;
43 
51  protected $mValue;
52 
53  function __construct() {
54  parent::__construct( 'Redirect' );
55  $this->mType = null;
56  $this->mValue = null;
57  }
58 
63  function setParameter( $subpage ) {
64  // parse $subpage to pull out the parts
65  $parts = explode( '/', $subpage, 2 );
66  $this->mType = $parts[0];
67  $this->mValue = $parts[1] ?? null;
68  }
69 
75  function dispatchUser() {
76  if ( !ctype_digit( $this->mValue ) ) {
77  // Message: redirect-not-numeric
78  return Status::newFatal( $this->getMessagePrefix() . '-not-numeric' );
79  }
80  $user = User::newFromId( (int)$this->mValue );
81  $username = $user->getName(); // load User as side-effect
82  if ( $user->isAnon() ) {
83  // Message: redirect-not-exists
84  return Status::newFatal( $this->getMessagePrefix() . '-not-exists' );
85  }
86  if ( $user->isHidden() && !MediaWikiServices::getInstance()->getPermissionManager()
87  ->userHasRight( $this->getUser(), 'hideuser' )
88  ) {
89  throw new PermissionsError( null, [ 'badaccess-group0' ] );
90  }
91  $userpage = Title::makeTitle( NS_USER, $username );
92 
93  return Status::newGood( [
94  $userpage->getFullURL( '', false, PROTO_CURRENT ), 302
95  ] );
96  }
97 
103  function dispatchFile() {
104  try {
105  $title = Title::newFromTextThrow( $this->mValue, NS_FILE );
106  if ( $title && !$title->inNamespace( NS_FILE ) ) {
107  // If the given value contains a namespace enforce file namespace
108  $title = Title::newFromTextThrow( Title::makeName( NS_FILE, $this->mValue ) );
109  }
110  } catch ( MalformedTitleException $e ) {
111  return Status::newFatal( $e->getMessageObject() );
112  }
113  $file = MediaWikiServices::getInstance()->getRepoGroup()->findFile( $title );
114 
115  if ( !$file || !$file->exists() ) {
116  // Message: redirect-not-exists
117  return Status::newFatal( $this->getMessagePrefix() . '-not-exists' );
118  }
119  // Default behavior: Use the direct link to the file.
120  $url = $file->getUrl();
121  $request = $this->getRequest();
122  $width = $request->getInt( 'width', -1 );
123  $height = $request->getInt( 'height', -1 );
124 
125  // If a width is requested...
126  if ( $width != -1 ) {
127  $mto = $file->transform( [ 'width' => $width, 'height' => $height ] );
128  // ... and we can
129  if ( $mto && !$mto->isError() ) {
130  // ... change the URL to point to a thumbnail.
131  // Note: This url is more temporary as can change
132  // if file is reuploaded and has different aspect ratio.
133  $url = [ $mto->getUrl(), $height === -1 ? 301 : 302 ];
134  }
135  }
136 
137  return Status::newGood( $url );
138  }
139 
146  function dispatchRevision() {
147  $oldid = $this->mValue;
148  if ( !ctype_digit( $oldid ) ) {
149  // Message: redirect-not-numeric
150  return Status::newFatal( $this->getMessagePrefix() . '-not-numeric' );
151  }
152  $oldid = (int)$oldid;
153  if ( $oldid === 0 ) {
154  // Message: redirect-not-exists
155  return Status::newFatal( $this->getMessagePrefix() . '-not-exists' );
156  }
157 
158  return Status::newGood( wfAppendQuery( wfScript( 'index' ), [
159  'oldid' => $oldid
160  ] ) );
161  }
162 
168  function dispatchPage() {
169  $curid = $this->mValue;
170  if ( !ctype_digit( $curid ) ) {
171  // Message: redirect-not-numeric
172  return Status::newFatal( $this->getMessagePrefix() . '-not-numeric' );
173  }
174  $curid = (int)$curid;
175  if ( $curid === 0 ) {
176  // Message: redirect-not-exists
177  return Status::newFatal( $this->getMessagePrefix() . '-not-exists' );
178  }
179 
180  return Status::newGood( wfAppendQuery( wfScript( 'index' ), [
181  'curid' => $curid
182  ] ) );
183  }
184 
192  function dispatchLog() {
193  $logid = $this->mValue;
194  if ( !ctype_digit( $logid ) ) {
195  // Message: redirect-not-numeric
196  return Status::newFatal( $this->getMessagePrefix() . '-not-numeric' );
197  }
198  $logid = (int)$logid;
199  if ( $logid === 0 ) {
200  // Message: redirect-not-exists
201  return Status::newFatal( $this->getMessagePrefix() . '-not-exists' );
202  }
203  $query = [ 'title' => 'Special:Log', 'logid' => $logid ];
204  return Status::newGood( wfAppendQuery( wfScript( 'index' ), $query ) );
205  }
206 
215  function dispatch() {
216  // the various namespaces supported by Special:Redirect
217  switch ( $this->mType ) {
218  case 'user':
219  $status = $this->dispatchUser();
220  break;
221  case 'file':
222  $status = $this->dispatchFile();
223  break;
224  case 'revision':
225  $status = $this->dispatchRevision();
226  break;
227  case 'page':
228  $status = $this->dispatchPage();
229  break;
230  case 'logid':
231  $status = $this->dispatchLog();
232  break;
233  default:
234  $status = null;
235  break;
236  }
237  if ( $status && $status->isGood() ) {
238  // These urls can sometimes be linked from prominent places,
239  // so varnish cache.
240  $value = $status->getValue();
241  if ( is_array( $value ) ) {
242  list( $url, $code ) = $value;
243  } else {
244  $url = $value;
245  $code = 301;
246  }
247  if ( $code === 301 ) {
248  $this->getOutput()->setCdnMaxage( 60 * 60 );
249  } else {
250  $this->getOutput()->setCdnMaxage( 10 );
251  }
252  $this->getOutput()->redirect( $url, $code );
253 
254  return true;
255  }
256  if ( !is_null( $this->mValue ) ) {
257  $this->getOutput()->setStatusCode( 404 );
258 
259  return $status;
260  }
261 
262  return false;
263  }
264 
265  protected function getFormFields() {
266  $mp = $this->getMessagePrefix();
267  $ns = [
268  // subpage => message
269  // Messages: redirect-user, redirect-page, redirect-revision,
270  // redirect-file, redirect-logid
271  'user' => $mp . '-user',
272  'page' => $mp . '-page',
273  'revision' => $mp . '-revision',
274  'file' => $mp . '-file',
275  'logid' => $mp . '-logid',
276  ];
277  $a = [];
278  $a['type'] = [
279  'type' => 'select',
280  'label-message' => $mp . '-lookup', // Message: redirect-lookup
281  'options' => [],
282  'default' => current( array_keys( $ns ) ),
283  ];
284  foreach ( $ns as $n => $m ) {
285  $m = $this->msg( $m )->text();
286  $a['type']['options'][$m] = $n;
287  }
288  $a['value'] = [
289  'type' => 'text',
290  'label-message' => $mp . '-value' // Message: redirect-value
291  ];
292  // set the defaults according to the parsed subpage path
293  if ( !empty( $this->mType ) ) {
294  $a['type']['default'] = $this->mType;
295  }
296  if ( !empty( $this->mValue ) ) {
297  $a['value']['default'] = $this->mValue;
298  }
299 
300  return $a;
301  }
302 
303  public function onSubmit( array $data ) {
304  if ( !empty( $data['type'] ) && !empty( $data['value'] ) ) {
305  $this->setParameter( $data['type'] . '/' . $data['value'] );
306  }
307 
308  /* if this returns false, will show the form */
309  return $this->dispatch();
310  }
311 
312  public function onSuccess() {
313  /* do nothing, we redirect in $this->dispatch if successful. */
314  }
315 
316  protected function alterForm( HTMLForm $form ) {
317  /* display summary at top of page */
318  $this->outputHeader();
319  // tweak label on submit button
320  // Message: redirect-submit
321  $form->setSubmitTextMsg( $this->getMessagePrefix() . '-submit' );
322  /* submit form every time */
323  $form->setMethod( 'get' );
324  }
325 
326  protected function getDisplayFormat() {
327  return 'ooui';
328  }
329 
335  protected function getSubpagesForPrefixSearch() {
336  return [
337  'file',
338  'page',
339  'revision',
340  'user',
341  'logid',
342  ];
343  }
344 
348  public function requiresWrite() {
349  return false;
350  }
351 
355  public function requiresUnblock() {
356  return false;
357  }
358 
359  protected function getGroupName() {
360  return 'redirects';
361  }
362 }
dispatchRevision()
Handle Special:Redirect/revision/xxx (by redirecting to index.php?oldid=xxx)
static newFatal( $message,... $parameters)
Factory function for fatal errors.
Definition: StatusValue.php:69
dispatchPage()
Handle Special:Redirect/page/xxx (by redirecting to index.php?curid=xxx)
if(PHP_SAPI !='cli-server') if(!isset( $_SERVER['SCRIPT_FILENAME'])) $file
Item class for a filearchive table row.
Definition: router.php:42
getSubpagesForPrefixSearch()
Return an array of subpages that this special page will accept.
onSubmit(array $data)
dispatch()
Use appropriate dispatch* method to obtain a redirection URL, and either: redirect, set a 404 error code and error message, or do nothing (if $mValue wasn&#39;t set) allowing the form to be displayed.
setParameter( $subpage)
Set $mType and $mValue based on parsed value of $subpage.
$mValue
The identifier/value for the redirect (which id, which file)
const PROTO_CURRENT
Definition: Defines.php:202
getOutput()
Get the OutputPage being used for this instance.
Special page which uses an HTMLForm to handle processing.
setMethod( $method='post')
Set the method used to submit the form.
Definition: HTMLForm.php:1633
wfScript( $script='index')
Get the path to a specified script file, respecting file extensions; this is a wrapper around $wgScri...
wfAppendQuery( $url, $query)
Append a query string to an existing URL, which may or may not already have query string parameters a...
msg( $key,... $params)
Wrapper around wfMessage that sets the current context.
alterForm(HTMLForm $form)
static newGood( $value=null)
Factory function for good results.
Definition: StatusValue.php:81
const NS_FILE
Definition: Defines.php:66
static newFromTextThrow( $text, $defaultNamespace=NS_MAIN)
Like Title::newFromText(), but throws MalformedTitleException when the title is invalid, rather than returning null.
Definition: Title.php:354
dispatchUser()
Handle Special:Redirect/user/xxxx (by redirecting to User:YYYY)
static makeTitle( $ns, $title, $fragment='', $interwiki='')
Create a new Title from a namespace index and a DB key.
Definition: Title.php:586
getMessagePrefix()
Get message prefix for HTMLForm.
static newFromId( $id)
Static factory method for creation from a given user ID.
Definition: User.php:539
getUser()
Shortcut to get the User executing this instance.
Show an error when a user tries to do something they do not have the necessary permissions for...
A special page that redirects to: the user for a numeric user id, the file for a given filename...
setSubmitTextMsg( $msg)
Set the text for the submit button to a message.
Definition: HTMLForm.php:1392
dispatchLog()
Handle Special:Redirect/logid/xxx (by redirecting to index.php?title=Special:Log&logid=xxx) ...
getRequest()
Get the WebRequest being used for this instance.
static makeName( $ns, $title, $fragment='', $interwiki='', $canonicalNamespace=false)
Make a prefixed DB key from a DB key and a namespace index.
Definition: Title.php:813
outputHeader( $summaryMessageKey='')
Outputs a summary message on top of special pages Per default the message key is the canonical name o...
dispatchFile()
Handle Special:Redirect/file/xxxx.
$mType
The type of the redirect (user/file/revision)