MediaWiki  master
SpecialRedirect.php
Go to the documentation of this file.
1 <?php
25 
34 
42  protected $mType;
43 
51  protected $mValue;
52 
54  private $repoGroup;
55 
57  private $userFactory;
58 
63  public function __construct(
66  ) {
67  parent::__construct( 'Redirect' );
68  $this->mType = null;
69  $this->mValue = null;
70 
71  $this->repoGroup = $repoGroup;
72  $this->userFactory = $userFactory;
73  }
74 
79  public function setParameter( $subpage ) {
80  // parse $subpage to pull out the parts
81  $parts = explode( '/', $subpage, 2 );
82  $this->mType = $parts[0];
83  $this->mValue = $parts[1] ?? null;
84  }
85 
91  public function dispatchUser() {
92  if ( !ctype_digit( $this->mValue ) ) {
93  // Message: redirect-not-numeric
94  return Status::newFatal( $this->getMessagePrefix() . '-not-numeric' );
95  }
96  $user = $this->userFactory->newFromId( (int)$this->mValue );
97  $user->load(); // Make sure the id is validated by loading the user
98  if ( $user->isAnon() ) {
99  // Message: redirect-not-exists
100  return Status::newFatal( $this->getMessagePrefix() . '-not-exists' );
101  }
102  if ( $user->isHidden() && !$this->getAuthority()->isAllowed( 'hideuser' ) ) {
103  throw new PermissionsError( null, [ 'badaccess-group0' ] );
104  }
105 
106  return Status::newGood( [
107  $user->getUserPage()->getFullURL( '', false, PROTO_CURRENT ), 302
108  ] );
109  }
110 
116  public function dispatchFile() {
117  try {
118  $title = Title::newFromTextThrow( $this->mValue, NS_FILE );
119  if ( $title && !$title->inNamespace( NS_FILE ) ) {
120  // If the given value contains a namespace enforce file namespace
121  $title = Title::newFromTextThrow( Title::makeName( NS_FILE, $this->mValue ) );
122  }
123  } catch ( MalformedTitleException $e ) {
124  return Status::newFatal( $e->getMessageObject() );
125  }
126  $file = $this->repoGroup->findFile( $title );
127 
128  if ( !$file || !$file->exists() ) {
129  // Message: redirect-not-exists
130  return Status::newFatal( $this->getMessagePrefix() . '-not-exists' );
131  }
132  // Default behavior: Use the direct link to the file.
133  $url = $file->getUrl();
134  $request = $this->getRequest();
135  $width = $request->getInt( 'width', -1 );
136  $height = $request->getInt( 'height', -1 );
137 
138  // If a width is requested...
139  if ( $width != -1 ) {
140  $mto = $file->transform( [ 'width' => $width, 'height' => $height ] );
141  // ... and we can
142  if ( $mto && !$mto->isError() ) {
143  // ... change the URL to point to a thumbnail.
144  // Note: This url is more temporary as can change
145  // if file is reuploaded and has different aspect ratio.
146  $url = [ $mto->getUrl(), $height === -1 ? 301 : 302 ];
147  }
148  }
149 
150  return Status::newGood( $url );
151  }
152 
159  public function dispatchRevision() {
160  $oldid = $this->mValue;
161  if ( !ctype_digit( $oldid ) ) {
162  // Message: redirect-not-numeric
163  return Status::newFatal( $this->getMessagePrefix() . '-not-numeric' );
164  }
165  $oldid = (int)$oldid;
166  if ( $oldid === 0 ) {
167  // Message: redirect-not-exists
168  return Status::newFatal( $this->getMessagePrefix() . '-not-exists' );
169  }
170 
171  return Status::newGood( wfAppendQuery( wfScript( 'index' ), [
172  'oldid' => $oldid
173  ] ) );
174  }
175 
181  public function dispatchPage() {
182  $curid = $this->mValue;
183  if ( !ctype_digit( $curid ) ) {
184  // Message: redirect-not-numeric
185  return Status::newFatal( $this->getMessagePrefix() . '-not-numeric' );
186  }
187  $curid = (int)$curid;
188  if ( $curid === 0 ) {
189  // Message: redirect-not-exists
190  return Status::newFatal( $this->getMessagePrefix() . '-not-exists' );
191  }
192 
193  return Status::newGood( wfAppendQuery( wfScript( 'index' ), [
194  'curid' => $curid
195  ] ) );
196  }
197 
205  public function dispatchLog() {
206  $logid = $this->mValue;
207  if ( !ctype_digit( $logid ) ) {
208  // Message: redirect-not-numeric
209  return Status::newFatal( $this->getMessagePrefix() . '-not-numeric' );
210  }
211  $logid = (int)$logid;
212  if ( $logid === 0 ) {
213  // Message: redirect-not-exists
214  return Status::newFatal( $this->getMessagePrefix() . '-not-exists' );
215  }
216  $query = [ 'title' => 'Special:Log', 'logid' => $logid ];
217  return Status::newGood( wfAppendQuery( wfScript( 'index' ), $query ) );
218  }
219 
228  private function dispatch() {
229  // the various namespaces supported by Special:Redirect
230  switch ( $this->mType ) {
231  case 'user':
232  $status = $this->dispatchUser();
233  break;
234  case 'file':
235  $status = $this->dispatchFile();
236  break;
237  case 'revision':
238  $status = $this->dispatchRevision();
239  break;
240  case 'page':
241  $status = $this->dispatchPage();
242  break;
243  case 'logid':
244  $status = $this->dispatchLog();
245  break;
246  default:
247  $status = null;
248  break;
249  }
250  if ( $status && $status->isGood() ) {
251  // These urls can sometimes be linked from prominent places,
252  // so varnish cache.
253  $value = $status->getValue();
254  if ( is_array( $value ) ) {
255  list( $url, $code ) = $value;
256  } else {
257  $url = $value;
258  $code = 301;
259  }
260  if ( $code === 301 ) {
261  $this->getOutput()->setCdnMaxage( 60 * 60 );
262  } else {
263  $this->getOutput()->setCdnMaxage( 10 );
264  }
265  $this->getOutput()->redirect( $url, $code );
266 
267  return true;
268  }
269  if ( $this->mValue !== null ) {
270  $this->getOutput()->setStatusCode( 404 );
271 
272  return $status;
273  }
274 
275  return false;
276  }
277 
278  protected function getFormFields() {
279  $mp = $this->getMessagePrefix();
280  $ns = [
281  // subpage => message
282  // Messages: redirect-user, redirect-page, redirect-revision,
283  // redirect-file, redirect-logid
284  'user' => $mp . '-user',
285  'page' => $mp . '-page',
286  'revision' => $mp . '-revision',
287  'file' => $mp . '-file',
288  'logid' => $mp . '-logid',
289  ];
290  $a = [];
291  $a['type'] = [
292  'type' => 'select',
293  'label-message' => $mp . '-lookup', // Message: redirect-lookup
294  'options' => [],
295  'default' => current( array_keys( $ns ) ),
296  ];
297  foreach ( $ns as $n => $m ) {
298  $m = $this->msg( $m )->text();
299  $a['type']['options'][$m] = $n;
300  }
301  $a['value'] = [
302  'type' => 'text',
303  'label-message' => $mp . '-value' // Message: redirect-value
304  ];
305  // set the defaults according to the parsed subpage path
306  if ( !empty( $this->mType ) ) {
307  $a['type']['default'] = $this->mType;
308  }
309  if ( !empty( $this->mValue ) ) {
310  $a['value']['default'] = $this->mValue;
311  }
312 
313  return $a;
314  }
315 
316  public function onSubmit( array $data ) {
317  if ( !empty( $data['type'] ) && !empty( $data['value'] ) ) {
318  $this->setParameter( $data['type'] . '/' . $data['value'] );
319  }
320 
321  /* if this returns false, will show the form */
322  return $this->dispatch();
323  }
324 
325  public function onSuccess() {
326  /* do nothing, we redirect in $this->dispatch if successful. */
327  }
328 
329  protected function alterForm( HTMLForm $form ) {
330  /* display summary at top of page */
331  $this->outputHeader();
332  // tweak label on submit button
333  // Message: redirect-submit
334  $form->setSubmitTextMsg( $this->getMessagePrefix() . '-submit' );
335  /* submit form every time */
336  $form->setMethod( 'get' );
337  }
338 
339  protected function getDisplayFormat() {
340  return 'ooui';
341  }
342 
348  protected function getSubpagesForPrefixSearch() {
349  return [
350  'file',
351  'page',
352  'revision',
353  'user',
354  'logid',
355  ];
356  }
357 
361  public function requiresWrite() {
362  return false;
363  }
364 
368  public function requiresUnblock() {
369  return false;
370  }
371 
372  protected function getGroupName() {
373  return 'redirects';
374  }
375 }
SpecialPage\msg
msg( $key,... $params)
Wrapper around wfMessage that sets the current context.
Definition: SpecialPage.php:912
Title\makeName
static makeName( $ns, $title, $fragment='', $interwiki='', $canonicalNamespace=false)
Make a prefixed DB key from a DB key and a namespace index.
Definition: Title.php:856
StatusValue\newFatal
static newFatal( $message,... $parameters)
Factory function for fatal errors.
Definition: StatusValue.php:70
SpecialRedirect\dispatchLog
dispatchLog()
Handle Special:Redirect/logid/xxx (by redirecting to index.php?title=Special:Log&logid=xxx)
Definition: SpecialRedirect.php:205
SpecialPage\getOutput
getOutput()
Get the OutputPage being used for this instance.
Definition: SpecialPage.php:790
SpecialRedirect\$mValue
string $mValue
The identifier/value for the redirect (which id, which file)
Definition: SpecialRedirect.php:51
SpecialRedirect\onSubmit
onSubmit(array $data)
Process the form on POST submission.
Definition: SpecialRedirect.php:316
SpecialRedirect\__construct
__construct(RepoGroup $repoGroup, UserFactory $userFactory)
Definition: SpecialRedirect.php:63
SpecialRedirect\$repoGroup
RepoGroup $repoGroup
Definition: SpecialRedirect.php:54
SpecialRedirect\onSuccess
onSuccess()
Do something exciting on successful processing of the form, most likely to show a confirmation messag...
Definition: SpecialRedirect.php:325
MalformedTitleException\getMessageObject
getMessageObject()
Definition: MalformedTitleException.php:86
$file
if(PHP_SAPI !='cli-server') if(!isset( $_SERVER['SCRIPT_FILENAME'])) $file
Item class for a filearchive table row.
Definition: router.php:42
FormSpecialPage
Special page which uses an HTMLForm to handle processing.
Definition: FormSpecialPage.php:31
SpecialRedirect\$mType
string $mType
The type of the redirect (user/file/revision)
Definition: SpecialRedirect.php:42
PermissionsError
Show an error when a user tries to do something they do not have the necessary permissions for.
Definition: PermissionsError.php:32
HTMLForm\setMethod
setMethod( $method='post')
Set the method used to submit the form.
Definition: HTMLForm.php:1677
SpecialRedirect\getDisplayFormat
getDisplayFormat()
Get display format for the form.
Definition: SpecialRedirect.php:339
wfAppendQuery
wfAppendQuery( $url, $query)
Append a query string to an existing URL, which may or may not already have query string parameters a...
Definition: GlobalFunctions.php:422
FormSpecialPage\getMessagePrefix
getMessagePrefix()
Get message prefix for HTMLForm.
Definition: FormSpecialPage.php:79
SpecialRedirect
A special page that redirects to: the user for a numeric user id, the file for a given filename,...
Definition: SpecialRedirect.php:33
SpecialRedirect\$userFactory
UserFactory $userFactory
Definition: SpecialRedirect.php:57
wfScript
wfScript( $script='index')
Get the path to a specified script file, respecting file extensions; this is a wrapper around $wgScri...
Definition: GlobalFunctions.php:2285
SpecialRedirect\dispatch
dispatch()
Use appropriate dispatch* method to obtain a redirection URL, and either: redirect,...
Definition: SpecialRedirect.php:228
SpecialRedirect\getFormFields
getFormFields()
Get an HTMLForm descriptor array.
Definition: SpecialRedirect.php:278
$title
$title
Definition: testCompression.php:38
SpecialRedirect\dispatchRevision
dispatchRevision()
Handle Special:Redirect/revision/xxx (by redirecting to index.php?oldid=xxx)
Definition: SpecialRedirect.php:159
Title\newFromTextThrow
static newFromTextThrow( $text, $defaultNamespace=NS_MAIN)
Like Title::newFromText(), but throws MalformedTitleException when the title is invalid,...
Definition: Title.php:417
PROTO_CURRENT
const PROTO_CURRENT
Definition: Defines.php:195
StatusValue\newGood
static newGood( $value=null)
Factory function for good results.
Definition: StatusValue.php:82
SpecialRedirect\dispatchFile
dispatchFile()
Handle Special:Redirect/file/xxxx.
Definition: SpecialRedirect.php:116
SpecialPage\getRequest
getRequest()
Get the WebRequest being used for this instance.
Definition: SpecialPage.php:780
SpecialRedirect\dispatchUser
dispatchUser()
Handle Special:Redirect/user/xxxx (by redirecting to User:YYYY)
Definition: SpecialRedirect.php:91
SpecialRedirect\dispatchPage
dispatchPage()
Handle Special:Redirect/page/xxx (by redirecting to index.php?curid=xxx)
Definition: SpecialRedirect.php:181
HTMLForm\setSubmitTextMsg
setSubmitTextMsg( $msg)
Set the text for the submit button to a message.
Definition: HTMLForm.php:1420
SpecialRedirect\getSubpagesForPrefixSearch
getSubpagesForPrefixSearch()
Return an array of subpages that this special page will accept.
Definition: SpecialRedirect.php:348
SpecialRedirect\alterForm
alterForm(HTMLForm $form)
Play with the HTMLForm if you need to more substantially.
Definition: SpecialRedirect.php:329
MalformedTitleException
MalformedTitleException is thrown when a TitleParser is unable to parse a title string.
Definition: MalformedTitleException.php:26
SpecialRedirect\getGroupName
getGroupName()
Under which header this special page is listed in Special:SpecialPages See messages 'specialpages-gro...
Definition: SpecialRedirect.php:372
RepoGroup
Prioritized list of file repositories.
Definition: RepoGroup.php:32
NS_FILE
const NS_FILE
Definition: Defines.php:70
SpecialRedirect\setParameter
setParameter( $subpage)
Set $mType and $mValue based on parsed value of $subpage.
Definition: SpecialRedirect.php:79
MediaWiki\User\UserFactory
Creates User objects.
Definition: UserFactory.php:41
SpecialPage\outputHeader
outputHeader( $summaryMessageKey='')
Outputs a summary message on top of special pages Per default the message key is the canonical name o...
Definition: SpecialPage.php:709
SpecialRedirect\requiresWrite
requiresWrite()
Definition: SpecialRedirect.php:361
SpecialRedirect\requiresUnblock
requiresUnblock()
Definition: SpecialRedirect.php:368
HTMLForm
Object handling generic submission, CSRF protection, layout and other logic for UI forms in a reusabl...
Definition: HTMLForm.php:143