MediaWiki  REL1_22
SpecialPage.php
Go to the documentation of this file.
00001 <?php
00029 class SpecialPage {
00030     // The canonical name of this special page
00031     // Also used for the default <h1> heading, @see getDescription()
00032     protected $mName;
00033 
00034     // The local name of this special page
00035     private $mLocalName;
00036 
00037     // Minimum user level required to access this page, or "" for anyone.
00038     // Also used to categorise the pages in Special:Specialpages
00039     private $mRestriction;
00040 
00041     // Listed in Special:Specialpages?
00042     private $mListed;
00043 
00044     // Function name called by the default execute()
00045     private $mFunction;
00046 
00047     // File which needs to be included before the function above can be called
00048     private $mFile;
00049 
00050     // Whether or not this special page is being included from an article
00051     protected $mIncluding;
00052 
00053     // Whether the special page can be included in an article
00054     protected $mIncludable;
00055 
00060     protected $mContext;
00061 
00067     static function initList() {
00068         wfDeprecated( __METHOD__, '1.18' );
00069         // Noop
00070     }
00071 
00075     static function initAliasList() {
00076         wfDeprecated( __METHOD__, '1.18' );
00077         // Noop
00078     }
00079 
00088     static function resolveAlias( $alias ) {
00089         wfDeprecated( __METHOD__, '1.18' );
00090         list( $name, /*...*/ ) = SpecialPageFactory::resolveAlias( $alias );
00091         return $name;
00092     }
00093 
00103     static function resolveAliasWithSubpage( $alias ) {
00104         return SpecialPageFactory::resolveAlias( $alias );
00105     }
00106 
00114     static function setGroup( $page, $group ) {
00115         wfDeprecated( __METHOD__, '1.18' );
00116         SpecialPageFactory::setGroup( $page, $group );
00117     }
00118 
00126     static function getGroup( &$page ) {
00127         wfDeprecated( __METHOD__, '1.18' );
00128         return SpecialPageFactory::getGroup( $page );
00129     }
00130 
00139     static function removePage( $name ) {
00140         wfDeprecated( __METHOD__, '1.18' );
00141         unset( SpecialPageFactory::getList()->$name );
00142     }
00143 
00151     static function exists( $name ) {
00152         wfDeprecated( __METHOD__, '1.18' );
00153         return SpecialPageFactory::exists( $name );
00154     }
00155 
00163     static function getPage( $name ) {
00164         wfDeprecated( __METHOD__, '1.18' );
00165         return SpecialPageFactory::getPage( $name );
00166     }
00167 
00176     static function getPageByAlias( $alias ) {
00177         wfDeprecated( __METHOD__, '1.18' );
00178         return SpecialPageFactory::getPage( $alias );
00179     }
00180 
00190     static function getUsablePages( User $user = null ) {
00191         wfDeprecated( __METHOD__, '1.18' );
00192         return SpecialPageFactory::getUsablePages( $user );
00193     }
00194 
00201     static function getRegularPages() {
00202         wfDeprecated( __METHOD__, '1.18' );
00203         return SpecialPageFactory::getRegularPages();
00204     }
00205 
00213     static function getRestrictedPages() {
00214         wfDeprecated( __METHOD__, '1.18' );
00215         return SpecialPageFactory::getRestrictedPages();
00216     }
00217 
00232     public static function executePath( &$title, IContextSource &$context, $including = false ) {
00233         wfDeprecated( __METHOD__, '1.18' );
00234         return SpecialPageFactory::executePath( $title, $context, $including );
00235     }
00236 
00246     static function getLocalNameFor( $name, $subpage = false ) {
00247         wfDeprecated( __METHOD__, '1.18' );
00248         return SpecialPageFactory::getLocalNameFor( $name, $subpage );
00249     }
00250 
00260     public static function getTitleFor( $name, $subpage = false, $fragment = '' ) {
00261         $name = SpecialPageFactory::getLocalNameFor( $name, $subpage );
00262         if ( $name ) {
00263             return Title::makeTitle( NS_SPECIAL, $name, $fragment );
00264         } else {
00265             throw new MWException( "Invalid special page name \"$name\"" );
00266         }
00267     }
00268 
00276     public static function getSafeTitleFor( $name, $subpage = false ) {
00277         $name = SpecialPageFactory::getLocalNameFor( $name, $subpage );
00278         if ( $name ) {
00279             return Title::makeTitleSafe( NS_SPECIAL, $name );
00280         } else {
00281             return null;
00282         }
00283     }
00284 
00292     static function getTitleForAlias( $alias ) {
00293         wfDeprecated( __METHOD__, '1.18' );
00294         return SpecialPageFactory::getTitleForAlias( $alias );
00295     }
00296 
00316     public function __construct(
00317         $name = '', $restriction = '', $listed = true,
00318         $function = false, $file = 'default', $includable = false
00319     ) {
00320         $this->init( $name, $restriction, $listed, $function, $file, $includable );
00321     }
00322 
00335     private function init( $name, $restriction, $listed, $function, $file, $includable ) {
00336         $this->mName = $name;
00337         $this->mRestriction = $restriction;
00338         $this->mListed = $listed;
00339         $this->mIncludable = $includable;
00340         if ( !$function ) {
00341             $this->mFunction = 'wfSpecial' . $name;
00342         } else {
00343             $this->mFunction = $function;
00344         }
00345         if ( $file === 'default' ) {
00346             $this->mFile = __DIR__ . "/specials/Special$name.php";
00347         } else {
00348             $this->mFile = $file;
00349         }
00350     }
00351 
00361     public function __call( $fName, $a ) {
00362         // Deprecated messages now, remove in 1.19 or 1.20?
00363         wfDeprecated( __METHOD__, '1.17' );
00364 
00365         // Sometimes $fName is SpecialPage, sometimes it's specialpage. <3 PHP
00366         if ( strtolower( $fName ) == 'specialpage' ) {
00367             $name = isset( $a[0] ) ? $a[0] : '';
00368             $restriction = isset( $a[1] ) ? $a[1] : '';
00369             $listed = isset( $a[2] ) ? $a[2] : true;
00370             $function = isset( $a[3] ) ? $a[3] : false;
00371             $file = isset( $a[4] ) ? $a[4] : 'default';
00372             $includable = isset( $a[5] ) ? $a[5] : false;
00373             $this->init( $name, $restriction, $listed, $function, $file, $includable );
00374         } else {
00375             $className = get_class( $this );
00376             throw new MWException( "Call to undefined method $className::$fName" );
00377         }
00378     }
00379 
00384     function getName() {
00385         return $this->mName;
00386     }
00387 
00392     function getRestriction() {
00393         return $this->mRestriction;
00394     }
00395 
00403     function getFile() {
00404         wfDeprecated( __METHOD__, '1.18' );
00405         return $this->mFile;
00406     }
00407 
00408     // @todo FIXME: Decide which syntax to use for this, and stick to it
00414     function isListed() {
00415         return $this->mListed;
00416     }
00423     function setListed( $listed ) {
00424         return wfSetVar( $this->mListed, $listed );
00425     }
00432     function listed( $x = null ) {
00433         return wfSetVar( $this->mListed, $x );
00434     }
00435 
00440     public function isIncludable() {
00441         return $this->mIncludable;
00442     }
00443 
00451     function name( $x = null ) {
00452         wfDeprecated( __METHOD__, '1.18' );
00453         return wfSetVar( $this->mName, $x );
00454     }
00455 
00463     function restriction( $x = null ) {
00464         wfDeprecated( __METHOD__, '1.18' );
00465         return wfSetVar( $this->mRestriction, $x );
00466     }
00467 
00475     function func( $x = null ) {
00476         wfDeprecated( __METHOD__, '1.18' );
00477         return wfSetVar( $this->mFunction, $x );
00478     }
00479 
00487     function file( $x = null ) {
00488         wfDeprecated( __METHOD__, '1.18' );
00489         return wfSetVar( $this->mFile, $x );
00490     }
00491 
00499     function includable( $x = null ) {
00500         wfDeprecated( __METHOD__, '1.18' );
00501         return wfSetVar( $this->mIncludable, $x );
00502     }
00503 
00509     function including( $x = null ) {
00510         return wfSetVar( $this->mIncluding, $x );
00511     }
00512 
00516     function getLocalName() {
00517         if ( !isset( $this->mLocalName ) ) {
00518             $this->mLocalName = SpecialPageFactory::getLocalNameFor( $this->mName );
00519         }
00520         return $this->mLocalName;
00521     }
00522 
00531     public function isExpensive() {
00532         return false;
00533     }
00534 
00544     public function isCached() {
00545         return false;
00546     }
00547 
00555     public function isRestricted() {
00556         // DWIM: If anons can do something, then it is not restricted
00557         return $this->mRestriction != '' && !User::groupHasPermission( '*', $this->mRestriction );
00558     }
00559 
00568     public function userCanExecute( User $user ) {
00569         return $user->isAllowed( $this->mRestriction );
00570     }
00571 
00575     function displayRestrictionError() {
00576         throw new PermissionsError( $this->mRestriction );
00577     }
00578 
00584     public function checkPermissions() {
00585         if ( !$this->userCanExecute( $this->getUser() ) ) {
00586             $this->displayRestrictionError();
00587         }
00588     }
00589 
00596     public function checkReadOnly() {
00597         if ( wfReadOnly() ) {
00598             throw new ReadOnlyError;
00599         }
00600     }
00601 
00605     function setHeaders() {
00606         $out = $this->getOutput();
00607         $out->setArticleRelated( false );
00608         $out->setRobotPolicy( "noindex,nofollow" );
00609         $out->setPageTitle( $this->getDescription() );
00610     }
00611 
00619     final public function run( $subPage ) {
00628         wfRunHooks( 'SpecialPageBeforeExecute', array( $this, $subPage ) );
00629 
00630         $this->beforeExecute( $subPage );
00631         $this->execute( $subPage );
00632         $this->afterExecute( $subPage );
00633 
00642         wfRunHooks( 'SpecialPageAfterExecute', array( $this, $subPage ) );
00643     }
00644 
00652     protected function beforeExecute( $subPage ) {
00653         // No-op
00654     }
00655 
00663     protected function afterExecute( $subPage ) {
00664         // No-op
00665     }
00666 
00675     public function execute( $subPage ) {
00676         $this->setHeaders();
00677         $this->checkPermissions();
00678 
00679         $func = $this->mFunction;
00680         // only load file if the function does not exist
00681         if ( !is_callable( $func ) && $this->mFile ) {
00682             require_once $this->mFile;
00683         }
00684         $this->outputHeader();
00685         call_user_func( $func, $subPage, $this );
00686     }
00687 
00696     function outputHeader( $summaryMessageKey = '' ) {
00697         global $wgContLang;
00698 
00699         if ( $summaryMessageKey == '' ) {
00700             $msg = $wgContLang->lc( $this->getName() ) . '-summary';
00701         } else {
00702             $msg = $summaryMessageKey;
00703         }
00704         if ( !$this->msg( $msg )->isDisabled() && !$this->including() ) {
00705             $this->getOutput()->wrapWikiMsg(
00706                 "<div class='mw-specialpage-summary'>\n$1\n</div>", $msg );
00707         }
00708 
00709     }
00710 
00721     function getDescription() {
00722         return $this->msg( strtolower( $this->mName ) )->text();
00723     }
00724 
00731     function getTitle( $subpage = false ) {
00732         return self::getTitleFor( $this->mName, $subpage );
00733     }
00734 
00741     public function setContext( $context ) {
00742         $this->mContext = $context;
00743     }
00744 
00751     public function getContext() {
00752         if ( $this->mContext instanceof IContextSource ) {
00753             return $this->mContext;
00754         } else {
00755             wfDebug( __METHOD__ . " called and \$mContext is null. " .
00756                 "Return RequestContext::getMain(); for sanity\n" );
00757             return RequestContext::getMain();
00758         }
00759     }
00760 
00767     public function getRequest() {
00768         return $this->getContext()->getRequest();
00769     }
00770 
00777     public function getOutput() {
00778         return $this->getContext()->getOutput();
00779     }
00780 
00787     public function getUser() {
00788         return $this->getContext()->getUser();
00789     }
00790 
00797     public function getSkin() {
00798         return $this->getContext()->getSkin();
00799     }
00800 
00808     public function getLang() {
00809         wfDeprecated( __METHOD__, '1.19' );
00810         return $this->getLanguage();
00811     }
00812 
00819     public function getLanguage() {
00820         return $this->getContext()->getLanguage();
00821     }
00822 
00829     public function getFullTitle() {
00830         return $this->getContext()->getTitle();
00831     }
00832 
00839     public function msg( /* $args */ ) {
00840         // Note: can't use func_get_args() directly as second or later item in
00841         // a parameter list until PHP 5.3 or you get a fatal error.
00842         // Works fine as the first parameter, which appears elsewhere in the
00843         // code base. Sighhhh.
00844         $args = func_get_args();
00845         $message = call_user_func_array( array( $this->getContext(), 'msg' ), $args );
00846         // RequestContext passes context to wfMessage, and the language is set from
00847         // the context, but setting the language for Message class removes the
00848         // interface message status, which breaks for example usernameless gender
00849         // invocations. Restore the flag when not including special page in content.
00850         if ( $this->including() ) {
00851             $message->setInterfaceMessageFlag( false );
00852         }
00853         return $message;
00854     }
00855 
00861     protected function addFeedLinks( $params ) {
00862         global $wgFeedClasses;
00863 
00864         $feedTemplate = wfScript( 'api' );
00865 
00866         foreach ( $wgFeedClasses as $format => $class ) {
00867             $theseParams = $params + array( 'feedformat' => $format );
00868             $url = wfAppendQuery( $feedTemplate, $theseParams );
00869             $this->getOutput()->addFeedLink( $format, $url );
00870         }
00871     }
00872 
00881     public function getFinalGroupName() {
00882         global $wgSpecialPageGroups;
00883         $name = $this->getName();
00884         $group = '-';
00885 
00886         // Allow overbidding the group from the wiki side
00887         $msg = $this->msg( 'specialpages-specialpagegroup-' . strtolower( $name ) )->inContentLanguage();
00888         if ( !$msg->isBlank() ) {
00889             $group = $msg->text();
00890         } else {
00891             // Than use the group from this object
00892             $group = $this->getGroupName();
00893 
00894             // Group '-' is used as default to have the chance to determine,
00895             // if the special pages overrides this method,
00896             // if not overridden, $wgSpecialPageGroups is checked for b/c
00897             if ( $group === '-' && isset( $wgSpecialPageGroups[$name] ) ) {
00898                 $group = $wgSpecialPageGroups[$name];
00899             }
00900         }
00901 
00902         // never give '-' back, change to 'other'
00903         if ( $group === '-' ) {
00904             $group = 'other';
00905         }
00906 
00907         return $group;
00908     }
00909 
00918     protected function getGroupName() {
00919         // '-' used here to determine, if this group is overridden or has a hardcoded 'other'
00920         // Needed for b/c in getFinalGroupName
00921         return '-';
00922     }
00923 }
00924 
00930 abstract class FormSpecialPage extends SpecialPage {
00935     protected $par = null;
00936 
00941     abstract protected function getFormFields();
00942 
00947     protected function preText() {
00948         return '';
00949     }
00950 
00955     protected function postText() {
00956         return '';
00957     }
00958 
00963     protected function alterForm( HTMLForm $form ) {
00964     }
00965 
00972     protected function getMessagePrefix() {
00973         return strtolower( $this->getName() );
00974     }
00975 
00980     protected function getForm() {
00981         $this->fields = $this->getFormFields();
00982 
00983         $form = new HTMLForm( $this->fields, $this->getContext(), $this->getMessagePrefix() );
00984         $form->setSubmitCallback( array( $this, 'onSubmit' ) );
00985         // If the form is a compact vertical form, then don't output this ugly
00986         // fieldset surrounding it.
00987         // XXX Special pages can setDisplayFormat to 'vform' in alterForm(), but that
00988         // is called after this.
00989         if ( !$form->isVForm() ) {
00990             $form->setWrapperLegendMsg( $this->getMessagePrefix() . '-legend' );
00991         }
00992 
00993         $headerMsg = $this->msg( $this->getMessagePrefix() . '-text' );
00994         if ( !$headerMsg->isDisabled() ) {
00995             $form->addHeaderText( $headerMsg->parseAsBlock() );
00996         }
00997 
00998         // Retain query parameters (uselang etc)
00999         $params = array_diff_key(
01000             $this->getRequest()->getQueryValues(), array( 'title' => null ) );
01001         $form->addHiddenField( 'redirectparams', wfArrayToCgi( $params ) );
01002 
01003         $form->addPreText( $this->preText() );
01004         $form->addPostText( $this->postText() );
01005         $this->alterForm( $form );
01006 
01007         // Give hooks a chance to alter the form, adding extra fields or text etc
01008         wfRunHooks( "Special{$this->getName()}BeforeFormDisplay", array( &$form ) );
01009 
01010         return $form;
01011     }
01012 
01018     abstract public function onSubmit( array $data );
01019 
01025     public function onSuccess() {
01026     }
01027 
01033     public function execute( $par ) {
01034         $this->setParameter( $par );
01035         $this->setHeaders();
01036 
01037         // This will throw exceptions if there's a problem
01038         $this->checkExecutePermissions( $this->getUser() );
01039 
01040         $form = $this->getForm();
01041         if ( $form->show() ) {
01042             $this->onSuccess();
01043         }
01044     }
01045 
01050     protected function setParameter( $par ) {
01051         $this->par = $par;
01052     }
01053 
01061     protected function checkExecutePermissions( User $user ) {
01062         $this->checkPermissions();
01063 
01064         if ( $this->requiresUnblock() && $user->isBlocked() ) {
01065             $block = $user->getBlock();
01066             throw new UserBlockedError( $block );
01067         }
01068 
01069         if ( $this->requiresWrite() ) {
01070             $this->checkReadOnly();
01071         }
01072 
01073         return true;
01074     }
01075 
01080     public function requiresWrite() {
01081         return true;
01082     }
01083 
01088     public function requiresUnblock() {
01089         return true;
01090     }
01091 }
01092 
01097 class UnlistedSpecialPage extends SpecialPage {
01098     function __construct( $name, $restriction = '', $function = false, $file = 'default' ) {
01099         parent::__construct( $name, $restriction, false, $function, $file );
01100     }
01101 
01102     public function isListed() {
01103         return false;
01104     }
01105 }
01106 
01111 class IncludableSpecialPage extends SpecialPage {
01112     function __construct(
01113         $name, $restriction = '', $listed = true, $function = false, $file = 'default'
01114     ) {
01115         parent::__construct( $name, $restriction, $listed, $function, $file, true );
01116     }
01117 
01118     public function isIncludable() {
01119         return true;
01120     }
01121 }
01122 
01127 abstract class RedirectSpecialPage extends UnlistedSpecialPage {
01128 
01129     // Query parameters that can be passed through redirects
01130     protected $mAllowedRedirectParams = array();
01131 
01132     // Query parameters added by redirects
01133     protected $mAddedRedirectParams = array();
01134 
01135     public function execute( $par ) {
01136         $redirect = $this->getRedirect( $par );
01137         $query = $this->getRedirectQuery();
01138         // Redirect to a page title with possible query parameters
01139         if ( $redirect instanceof Title ) {
01140             $url = $redirect->getFullURL( $query );
01141             $this->getOutput()->redirect( $url );
01142             return $redirect;
01143         } elseif ( $redirect === true ) {
01144             // Redirect to index.php with query parameters
01145             $url = wfAppendQuery( wfScript( 'index' ), $query );
01146             $this->getOutput()->redirect( $url );
01147             return $redirect;
01148         } else {
01149             $class = get_class( $this );
01150             throw new MWException( "RedirectSpecialPage $class doesn't redirect!" );
01151         }
01152     }
01153 
01161     abstract public function getRedirect( $par );
01162 
01169     public function getRedirectQuery() {
01170         $params = array();
01171 
01172         foreach ( $this->mAllowedRedirectParams as $arg ) {
01173             if ( $this->getRequest()->getVal( $arg, null ) !== null ) {
01174                 $params[$arg] = $this->getRequest()->getVal( $arg );
01175             }
01176         }
01177 
01178         foreach ( $this->mAddedRedirectParams as $arg => $val ) {
01179             $params[$arg] = $val;
01180         }
01181 
01182         return count( $params )
01183             ? $params
01184             : false;
01185     }
01186 }
01187 
01188 abstract class SpecialRedirectToSpecial extends RedirectSpecialPage {
01189     // @todo FIXME: Visibility must be declared
01190     var $redirName, $redirSubpage;
01191 
01192     function __construct(
01193         $name, $redirName, $redirSubpage = false,
01194         $allowedRedirectParams = array(), $addedRedirectParams = array()
01195     ) {
01196         parent::__construct( $name );
01197         $this->redirName = $redirName;
01198         $this->redirSubpage = $redirSubpage;
01199         $this->mAllowedRedirectParams = $allowedRedirectParams;
01200         $this->mAddedRedirectParams = $addedRedirectParams;
01201     }
01202 
01203     public function getRedirect( $subpage ) {
01204         if ( $this->redirSubpage === false ) {
01205             return SpecialPage::getTitleFor( $this->redirName, $subpage );
01206         } else {
01207             return SpecialPage::getTitleFor( $this->redirName, $this->redirSubpage );
01208         }
01209     }
01210 }
01211 
01215 class SpecialListAdmins extends SpecialRedirectToSpecial {
01216     function __construct() {
01217         parent::__construct( 'Listadmins', 'Listusers', 'sysop' );
01218     }
01219 }
01220 
01224 class SpecialListBots extends SpecialRedirectToSpecial {
01225     function __construct() {
01226         parent::__construct( 'Listbots', 'Listusers', 'bot' );
01227     }
01228 }
01229 
01234 class SpecialCreateAccount extends SpecialRedirectToSpecial {
01235     function __construct() {
01236         parent::__construct( 'CreateAccount', 'Userlogin', 'signup', array( 'returnto', 'returntoquery', 'uselang' ) );
01237     }
01238 
01239     // No reason to hide this link on Special:Specialpages
01240     public function isListed() {
01241         return true;
01242     }
01243 
01244     protected function getGroupName() {
01245         return 'login';
01246     }
01247 }
01322 abstract class RedirectSpecialArticle extends RedirectSpecialPage {
01323     function __construct( $name ) {
01324         parent::__construct( $name );
01325         $redirectParams = array(
01326             'action',
01327             'redirect', 'rdfrom',
01328             # Options for preloaded edits
01329             'preload', 'editintro', 'preloadtitle', 'summary', 'nosummary',
01330             # Options for overriding user settings
01331             'preview', 'internaledit', 'externaledit', 'mode', 'minor', 'watchthis',
01332             # Options for history/diffs
01333             'section', 'oldid', 'diff', 'dir',
01334             'limit', 'offset', 'feed',
01335             # Misc options
01336             'redlink', 'debug',
01337             # Options for action=raw; missing ctype can break JS or CSS in some browsers
01338             'ctype', 'maxage', 'smaxage',
01339         );
01340 
01341         wfRunHooks( "RedirectSpecialArticleRedirectParams", array( &$redirectParams ) );
01342         $this->mAllowedRedirectParams = $redirectParams;
01343     }
01344 }
01345 
01350 class SpecialMypage extends RedirectSpecialArticle {
01351     function __construct() {
01352         parent::__construct( 'Mypage' );
01353     }
01354 
01355     function getRedirect( $subpage ) {
01356         if ( strval( $subpage ) !== '' ) {
01357             return Title::makeTitle( NS_USER, $this->getUser()->getName() . '/' . $subpage );
01358         } else {
01359             return Title::makeTitle( NS_USER, $this->getUser()->getName() );
01360         }
01361     }
01362 }
01363 
01368 class SpecialMytalk extends RedirectSpecialArticle {
01369     function __construct() {
01370         parent::__construct( 'Mytalk' );
01371     }
01372 
01373     function getRedirect( $subpage ) {
01374         if ( strval( $subpage ) !== '' ) {
01375             return Title::makeTitle( NS_USER_TALK, $this->getUser()->getName() . '/' . $subpage );
01376         } else {
01377             return Title::makeTitle( NS_USER_TALK, $this->getUser()->getName() );
01378         }
01379     }
01380 }
01381 
01386 class SpecialMycontributions extends RedirectSpecialPage {
01387     function __construct() {
01388         parent::__construct( 'Mycontributions' );
01389         $this->mAllowedRedirectParams = array( 'limit', 'namespace', 'tagfilter',
01390             'offset', 'dir', 'year', 'month', 'feed' );
01391     }
01392 
01393     function getRedirect( $subpage ) {
01394         return SpecialPage::getTitleFor( 'Contributions', $this->getUser()->getName() );
01395     }
01396 }
01397 
01401 class SpecialMyuploads extends RedirectSpecialPage {
01402     function __construct() {
01403         parent::__construct( 'Myuploads' );
01404         $this->mAllowedRedirectParams = array( 'limit', 'ilshowall', 'ilsearch' );
01405     }
01406 
01407     function getRedirect( $subpage ) {
01408         return SpecialPage::getTitleFor( 'Listfiles', $this->getUser()->getName() );
01409     }
01410 }
01411 
01415 class SpecialAllMyUploads extends RedirectSpecialPage {
01416     function __construct() {
01417         parent::__construct( 'AllMyUploads' );
01418         $this->mAllowedRedirectParams = array( 'limit', 'ilsearch' );
01419     }
01420 
01421     function getRedirect( $subpage ) {
01422         $this->mAddedRedirectParams['ilshowall'] = 1;
01423         return SpecialPage::getTitleFor( 'Listfiles', $this->getUser()->getName() );
01424     }
01425 }
01426 
01427 
01431 class SpecialPermanentLink extends RedirectSpecialPage {
01432     function __construct() {
01433         parent::__construct( 'PermanentLink' );
01434         $this->mAllowedRedirectParams = array();
01435     }
01436 
01437     function getRedirect( $subpage ) {
01438         $subpage = intval( $subpage );
01439         if ( $subpage === 0 ) {
01440             # throw an error page when no subpage was given
01441             throw new ErrorPageError( 'nopagetitle', 'nopagetext' );
01442         }
01443         $this->mAddedRedirectParams['oldid'] = $subpage;
01444         return true;
01445     }
01446 }