MediaWiki  1.31.0
SpecialRedirect.php
Go to the documentation of this file.
1 <?php
32 
40  protected $mType;
41 
49  protected $mValue;
50 
51  function __construct() {
52  parent::__construct( 'Redirect' );
53  $this->mType = null;
54  $this->mValue = null;
55  }
56 
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;
66  }
67 
73  function dispatchUser() {
74  if ( !ctype_digit( $this->mValue ) ) {
75  return null;
76  }
77  $user = User::newFromId( (int)$this->mValue );
78  $username = $user->getName(); // load User as side-effect
79  if ( $user->isAnon() ) {
80  return null;
81  }
82  $userpage = Title::makeTitle( NS_USER, $username );
83 
84  return $userpage->getFullURL( '', false, PROTO_CURRENT );
85  }
86 
92  function dispatchFile() {
93  $title = Title::makeTitleSafe( NS_FILE, $this->mValue );
94 
95  if ( !$title instanceof Title ) {
96  return null;
97  }
98  $file = wfFindFile( $title );
99 
100  if ( !$file || !$file->exists() ) {
101  return null;
102  }
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 );
108 
109  // If a width is requested...
110  if ( $width != -1 ) {
111  $mto = $file->transform( [ 'width' => $width, 'height' => $height ] );
112  // ... and we can
113  if ( $mto && !$mto->isError() ) {
114  // ... change the URL to point to a thumbnail.
115  $url = $mto->getUrl();
116  }
117  }
118 
119  return $url;
120  }
121 
128  function dispatchRevision() {
129  $oldid = $this->mValue;
130  if ( !ctype_digit( $oldid ) ) {
131  return null;
132  }
133  $oldid = (int)$oldid;
134  if ( $oldid === 0 ) {
135  return null;
136  }
137 
138  return wfAppendQuery( wfScript( 'index' ), [
139  'oldid' => $oldid
140  ] );
141  }
142 
148  function dispatchPage() {
149  $curid = $this->mValue;
150  if ( !ctype_digit( $curid ) ) {
151  return null;
152  }
153  $curid = (int)$curid;
154  if ( $curid === 0 ) {
155  return null;
156  }
157 
158  return wfAppendQuery( wfScript( 'index' ), [
159  'curid' => $curid
160  ] );
161  }
162 
170  function dispatchLog() {
171  $logid = $this->mValue;
172  if ( !ctype_digit( $logid ) ) {
173  return null;
174  }
175  $logid = (int)$logid;
176  if ( $logid === 0 ) {
177  return null;
178  }
179 
180  $logQuery = ActorMigration::newMigration()->getJoin( 'log_user' );
181 
182  $logparams = [
183  'log_id' => 'log_id',
184  'log_timestamp' => 'log_timestamp',
185  'log_type' => 'log_type',
186  'log_user_text' => $logQuery['fields']['log_user_text'],
187  ];
188 
189  $dbr = wfGetDB( DB_REPLICA );
190 
191  // Gets the nested SQL statement which
192  // returns timestamp of the log with the given log ID
193  $inner = $dbr->selectSQLText(
194  'logging',
195  [ 'log_timestamp' ],
196  [ 'log_id' => $logid ]
197  );
198 
199  // Returns all fields mentioned in $logparams of the logs
200  // with the same timestamp as the one returned by the statement above
201  $logsSameTimestamps = $dbr->select(
202  [ 'logging' ] + $logQuery['tables'],
203  $logparams,
204  [ "log_timestamp = ($inner)" ],
205  __METHOD__,
206  [],
207  $logQuery['joins']
208  );
209  if ( $logsSameTimestamps->numRows() === 0 ) {
210  return null;
211  }
212 
213  // Stores the row with the same log ID as the one given
214  $rowMain = [];
215  foreach ( $logsSameTimestamps as $row ) {
216  if ( (int)$row->log_id === $logid ) {
217  $rowMain = $row;
218  }
219  }
220 
221  array_shift( $logparams );
222 
223  // Stores all the rows with the same values in each column
224  // as $rowMain
225  foreach ( $logparams as $key => $dummy ) {
226  $matchedRows = [];
227  foreach ( $logsSameTimestamps as $row ) {
228  if ( $row->$key === $rowMain->$key ) {
229  $matchedRows[] = $row;
230  }
231  }
232  if ( count( $matchedRows ) === 1 ) {
233  break;
234  }
235  $logsSameTimestamps = $matchedRows;
236  }
237  $query = [ 'title' => 'Special:Log', 'limit' => count( $matchedRows ) ];
238 
239  // A map of database field names from table 'logging' to the values of $logparams
240  $keys = [
241  'log_timestamp' => 'offset',
242  'log_type' => 'type',
243  'log_user_text' => 'user'
244  ];
245 
246  foreach ( $logparams as $logKey => $dummy ) {
247  $query[$keys[$logKey]] = $matchedRows[0]->$logKey;
248  }
249  $query['offset'] = $query['offset'] + 1;
250  $url = $query;
251 
252  return wfAppendQuery( wfScript( 'index' ), $url );
253  }
254 
263  function dispatch() {
264  // the various namespaces supported by Special:Redirect
265  switch ( $this->mType ) {
266  case 'user':
267  $url = $this->dispatchUser();
268  break;
269  case 'file':
270  $url = $this->dispatchFile();
271  break;
272  case 'revision':
273  $url = $this->dispatchRevision();
274  break;
275  case 'page':
276  $url = $this->dispatchPage();
277  break;
278  case 'logid':
279  $url = $this->dispatchLog();
280  break;
281  default:
282  $url = null;
283  break;
284  }
285  if ( $url ) {
286  $this->getOutput()->redirect( $url );
287 
288  return true;
289  }
290  if ( !is_null( $this->mValue ) ) {
291  $this->getOutput()->setStatusCode( 404 );
292  // Message: redirect-not-exists
293  $msg = $this->getMessagePrefix() . '-not-exists';
294 
295  return Status::newFatal( $msg );
296  }
297 
298  return false;
299  }
300 
301  protected function getFormFields() {
302  $mp = $this->getMessagePrefix();
303  $ns = [
304  // subpage => message
305  // Messages: redirect-user, redirect-page, redirect-revision,
306  // redirect-file, redirect-logid
307  'user' => $mp . '-user',
308  'page' => $mp . '-page',
309  'revision' => $mp . '-revision',
310  'file' => $mp . '-file',
311  'logid' => $mp . '-logid',
312  ];
313  $a = [];
314  $a['type'] = [
315  'type' => 'select',
316  'label-message' => $mp . '-lookup', // Message: redirect-lookup
317  'options' => [],
318  'default' => current( array_keys( $ns ) ),
319  ];
320  foreach ( $ns as $n => $m ) {
321  $m = $this->msg( $m )->text();
322  $a['type']['options'][$m] = $n;
323  }
324  $a['value'] = [
325  'type' => 'text',
326  'label-message' => $mp . '-value' // Message: redirect-value
327  ];
328  // set the defaults according to the parsed subpage path
329  if ( !empty( $this->mType ) ) {
330  $a['type']['default'] = $this->mType;
331  }
332  if ( !empty( $this->mValue ) ) {
333  $a['value']['default'] = $this->mValue;
334  }
335 
336  return $a;
337  }
338 
339  public function onSubmit( array $data ) {
340  if ( !empty( $data['type'] ) && !empty( $data['value'] ) ) {
341  $this->setParameter( $data['type'] . '/' . $data['value'] );
342  }
343 
344  /* if this returns false, will show the form */
345  return $this->dispatch();
346  }
347 
348  public function onSuccess() {
349  /* do nothing, we redirect in $this->dispatch if successful. */
350  }
351 
352  protected function alterForm( HTMLForm $form ) {
353  /* display summary at top of page */
354  $this->outputHeader();
355  // tweak label on submit button
356  // Message: redirect-submit
357  $form->setSubmitTextMsg( $this->getMessagePrefix() . '-submit' );
358  /* submit form every time */
359  $form->setMethod( 'get' );
360  }
361 
362  protected function getDisplayFormat() {
363  return 'ooui';
364  }
365 
371  protected function getSubpagesForPrefixSearch() {
372  return [
373  'file',
374  'page',
375  'revision',
376  'user',
377  'logid',
378  ];
379  }
380 
384  public function requiresWrite() {
385  return false;
386  }
387 
391  public function requiresUnblock() {
392  return false;
393  }
394 
395  protected function getGroupName() {
396  return 'redirects';
397  }
398 }
$user
please add to it if you re going to add events to the MediaWiki code where normally authentication against an external auth plugin would be creating a account $user
Definition: hooks.txt:244
User\newFromId
static newFromId( $id)
Static factory method for creation from a given user ID.
Definition: User.php:614
SpecialPage\msg
msg( $key)
Wrapper around wfMessage that sets the current context.
Definition: SpecialPage.php:747
SpecialRedirect\dispatchLog
dispatchLog()
Handle Special:Redirect/logid/xxx (by redirecting to index.php?title=Special:Log)
Definition: SpecialRedirect.php:170
SpecialPage\getOutput
getOutput()
Get the OutputPage being used for this instance.
Definition: SpecialPage.php:676
captcha-old.count
count
Definition: captcha-old.py:249
SpecialRedirect\$mValue
$mValue
The identifier/value for the redirect (which id, which file)
Definition: SpecialRedirect.php:49
SpecialRedirect\onSubmit
onSubmit(array $data)
Process the form on POST submission.
Definition: SpecialRedirect.php:339
SpecialRedirect\onSuccess
onSuccess()
Do something exciting on successful processing of the form, most likely to show a confirmation messag...
Definition: SpecialRedirect.php:348
StatusValue\newFatal
static newFatal( $message)
Factory function for fatal errors.
Definition: StatusValue.php:68
NS_FILE
const NS_FILE
Definition: Defines.php:71
FormSpecialPage
Special page which uses an HTMLForm to handle processing.
Definition: FormSpecialPage.php:31
SpecialRedirect\$mType
$mType
The type of the redirect (user/file/revision)
Definition: SpecialRedirect.php:40
HTMLForm\setMethod
setMethod( $method='post')
Set the method used to submit the form.
Definition: HTMLForm.php:1584
ActorMigration\newMigration
static newMigration()
Static constructor.
Definition: ActorMigration.php:89
php
injection txt This is an overview of how MediaWiki makes use of dependency injection The design described here grew from the discussion of RFC T384 The term dependency this means that anything an object needs to operate should be injected from the the object itself should only know narrow no concrete implementation of the logic it relies on The requirement to inject everything typically results in an architecture that based on two main types of and essentially stateless service objects that use other service objects to operate on the value objects As of the beginning MediaWiki is only starting to use the DI approach Much of the code still relies on global state or direct resulting in a highly cyclical dependency which acts as the top level factory for services in MediaWiki which can be used to gain access to default instances of various services MediaWikiServices however also allows new services to be defined and default services to be redefined Services are defined or redefined by providing a callback the instantiator that will return a new instance of the service When it will create an instance of MediaWikiServices and populate it with the services defined in the files listed by thereby bootstrapping the DI framework Per $wgServiceWiringFiles lists includes ServiceWiring php
Definition: injection.txt:35
SpecialRedirect\getDisplayFormat
getDisplayFormat()
Get display format for the form.
Definition: SpecialRedirect.php:362
$dbr
$dbr
Definition: testCompression.php:50
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:469
FormSpecialPage\getMessagePrefix
getMessagePrefix()
Get message prefix for HTMLForm.
Definition: FormSpecialPage.php:73
SpecialRedirect
A special page that redirects to: the user for a numeric user id, the file for a given filename,...
Definition: SpecialRedirect.php:31
$query
null for the wiki Added should default to null in handler for backwards compatibility add a value to it if you want to add a cookie that have to vary cache options can modify $query
Definition: hooks.txt:1591
$title
namespace and then decline to actually register it file or subcat img or subcat $title
Definition: hooks.txt:934
wfScript
wfScript( $script='index')
Get the path to a specified script file, respecting file extensions; this is a wrapper around $wgScri...
Definition: GlobalFunctions.php:2878
wfGetDB
wfGetDB( $db, $groups=[], $wiki=false)
Get a Database object.
Definition: GlobalFunctions.php:2800
SpecialRedirect\dispatch
dispatch()
Use appropriate dispatch* method to obtain a redirection URL, and either: redirect,...
Definition: SpecialRedirect.php:263
PROTO_CURRENT
const PROTO_CURRENT
Definition: Defines.php:223
SpecialRedirect\getFormFields
getFormFields()
Get an HTMLForm descriptor array.
Definition: SpecialRedirect.php:301
Title\makeTitle
static makeTitle( $ns, $title, $fragment='', $interwiki='')
Create a new Title from a namespace index and a DB key.
Definition: Title.php:534
SpecialRedirect\dispatchRevision
dispatchRevision()
Handle Special:Redirect/revision/xxx (by redirecting to index.php?oldid=xxx)
Definition: SpecialRedirect.php:128
DB_REPLICA
const DB_REPLICA
Definition: defines.php:25
$request
do that in ParserLimitReportFormat instead use this to modify the parameters of the image all existing parser cache entries will be invalid To avoid you ll need to handle that somehow(e.g. with the RejectParserCacheValue hook) because MediaWiki won 't do it for you. & $defaults also a ContextSource after deleting those rows but within the same transaction you ll probably need to make sure the header is varied on $request
Definition: hooks.txt:2604
Title\makeTitleSafe
static makeTitleSafe( $ns, $title, $fragment='', $interwiki='')
Create a new Title from a namespace index and a DB key.
Definition: Title.php:562
SpecialRedirect\__construct
__construct()
Definition: SpecialRedirect.php:51
SpecialRedirect\dispatchFile
dispatchFile()
Handle Special:Redirect/file/xxxx.
Definition: SpecialRedirect.php:92
SpecialPage\getRequest
getRequest()
Get the WebRequest being used for this instance.
Definition: SpecialPage.php:666
SpecialRedirect\dispatchUser
dispatchUser()
Handle Special:Redirect/user/xxxx (by redirecting to User:YYYY)
Definition: SpecialRedirect.php:73
SpecialRedirect\dispatchPage
dispatchPage()
Handle Special:Redirect/page/xxx (by redirecting to index.php?curid=xxx)
Definition: SpecialRedirect.php:148
wfFindFile
wfFindFile( $title, $options=[])
Find a file.
Definition: GlobalFunctions.php:2841
HTMLForm\setSubmitTextMsg
setSubmitTextMsg( $msg)
Set the text for the submit button to a message.
Definition: HTMLForm.php:1356
SpecialRedirect\getSubpagesForPrefixSearch
getSubpagesForPrefixSearch()
Return an array of subpages that this special page will accept.
Definition: SpecialRedirect.php:371
SpecialRedirect\alterForm
alterForm(HTMLForm $form)
Play with the HTMLForm if you need to more substantially.
Definition: SpecialRedirect.php:352
Title
Represents a title within MediaWiki.
Definition: Title.php:39
SpecialRedirect\getGroupName
getGroupName()
Under which header this special page is listed in Special:SpecialPages See messages 'specialpages-gro...
Definition: SpecialRedirect.php:395
as
This document is intended to provide useful advice for parties seeking to redistribute MediaWiki to end users It s targeted particularly at maintainers for Linux since it s been observed that distribution packages of MediaWiki often break We ve consistently had to recommend that users seeking support use official tarballs instead of their distribution s and this often solves whatever problem the user is having It would be nice if this could such as
Definition: distributors.txt:9
$keys
$keys
Definition: testCompression.php:67
NS_USER
const NS_USER
Definition: Defines.php:67
SpecialRedirect\setParameter
setParameter( $subpage)
Set $mType and $mValue based on parsed value of $subpage.
Definition: SpecialRedirect.php:61
$username
this hook is for auditing only or null if authentication failed before getting that far $username
Definition: hooks.txt:783
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:583
SpecialRedirect\requiresWrite
requiresWrite()
Definition: SpecialRedirect.php:384
SpecialRedirect\requiresUnblock
requiresUnblock()
Definition: SpecialRedirect.php:391
array
the array() calling protocol came about after MediaWiki 1.4rc1.
HTMLForm
Object handling generic submission, CSRF protection, layout and other logic for UI forms.
Definition: HTMLForm.php:130