X-Git-Url: https://git.heureux-cyclage.org/?a=blobdiff_plain;f=includes%2FSpecialPage.php;h=c184c06dd082820763ba4a2a52b9d38cea049cd9;hb=3de6fd8c819d21bb3814a6f97d429c1912f5c048;hp=bf6c74582ee08e501766065b1360195c729ab76c;hpb=7ebdb6de899ca4a7673b48f4c98a477d5631db7e;p=lhc%2Fweb%2Fwiklou.git diff --git a/includes/SpecialPage.php b/includes/SpecialPage.php index bf6c74582e..c184c06dd0 100644 --- a/includes/SpecialPage.php +++ b/includes/SpecialPage.php @@ -1,104 +1,32 @@ new SpecialPage ( 'DoubleRedirects' ), - 'BrokenRedirects' => new SpecialPage ( 'BrokenRedirects' ), - 'Disambiguations' => new SpecialPage ( 'Disambiguations' ), - - 'Userlogin' => new SpecialPage( 'Userlogin' ), - 'Userlogout' => new UnlistedSpecialPage( 'Userlogout' ), - 'Preferences' => new SpecialPage( 'Preferences' ), - 'Watchlist' => new SpecialPage( 'Watchlist' ), - - 'Recentchanges' => new IncludableSpecialPage( 'Recentchanges' ), - 'Upload' => new SpecialPage( 'Upload' ), - 'Imagelist' => new SpecialPage( 'Imagelist' ), - 'Newimages' => new IncludableSpecialPage( 'Newimages' ), - 'Listusers' => new SpecialPage( 'Listusers' ), - 'Statistics' => new SpecialPage( 'Statistics' ), - 'Random' => new SpecialPage( 'Randompage' ), - 'Lonelypages' => new SpecialPage( 'Lonelypages' ), - 'Uncategorizedpages'=> new SpecialPage( 'Uncategorizedpages' ), - 'Uncategorizedcategories'=> new SpecialPage( 'Uncategorizedcategories' ), - 'Unusedcategories' => new SpecialPage( 'Unusedcategories' ), - 'Unusedimages' => new SpecialPage( 'Unusedimages' ), - 'Wantedpages' => new IncludableSpecialPage( 'Wantedpages' ), - 'Wantedcategories' => new SpecialPage( 'Wantedcategories' ), - 'Mostlinked' => new SpecialPage( 'Mostlinked' ), - 'Mostlinkedcategories' => new SpecialPage( 'Mostlinkedcategories' ), - 'Mostcategories' => new SpecialPage( 'Mostcategories' ), - 'Mostimages' => new SpecialPage( 'Mostimages' ), - 'Mostrevisions' => new SpecialPage( 'Mostrevisions' ), - 'Shortpages' => new SpecialPage( 'Shortpages' ), - 'Longpages' => new SpecialPage( 'Longpages' ), - 'Newpages' => new IncludableSpecialPage( 'Newpages' ), - 'Ancientpages' => new SpecialPage( 'Ancientpages' ), - 'Deadendpages' => new SpecialPage( 'Deadendpages' ), - 'Allpages' => new IncludableSpecialPage( 'Allpages' ), - 'Prefixindex' => new IncludableSpecialPage( 'Prefixindex' ) , - 'Ipblocklist' => new SpecialPage( 'Ipblocklist' ), - 'Specialpages' => new UnlistedSpecialPage( 'Specialpages' ), - 'Contributions' => new UnlistedSpecialPage( 'Contributions' ), - 'Emailuser' => new UnlistedSpecialPage( 'Emailuser' ), - 'Whatlinkshere' => new UnlistedSpecialPage( 'Whatlinkshere' ), - 'Recentchangeslinked' => new UnlistedSpecialPage( 'Recentchangeslinked' ), - 'Movepage' => new UnlistedSpecialPage( 'Movepage' ), - 'Blockme' => new UnlistedSpecialPage( 'Blockme' ), - 'Booksources' => new SpecialPage( 'Booksources' ), - 'Categories' => new SpecialPage( 'Categories' ), - 'Export' => new SpecialPage( 'Export' ), - 'Version' => new SpecialPage( 'Version' ), - 'Allmessages' => new SpecialPage( 'Allmessages' ), - 'Log' => new SpecialPage( 'Log' ), - 'Blockip' => new SpecialPage( 'Blockip', 'block' ), - 'Undelete' => new SpecialPage( 'Undelete', 'deletedhistory' ), - "Import" => new SpecialPage( "Import", 'import' ), - 'Lockdb' => new SpecialPage( 'Lockdb', 'siteadmin' ), - 'Unlockdb' => new SpecialPage( 'Unlockdb', 'siteadmin' ), - 'Userrights' => new SpecialPage( 'Userrights', 'userrights' ), - 'MIMEsearch' => new SpecialPage( 'MIMEsearch' ), - 'Unwatchedpages' => new SpecialPage( 'Unwatchedpages', 'unwatchedpages' ), - 'Listredirects' => new SpecialPage( 'Listredirects' ), - 'Revisiondelete' => new SpecialPage( 'Revisiondelete', 'deleterevision' ), - 'Unusedtemplates' => new SpecialPage( 'Unusedtemplates' ), - 'Randomredirect' => new SpecialPage( 'Randomredirect' ), -); - -if( !$wgDisableCounters ) { - $wgSpecialPages['Popularpages'] = new SpecialPage( 'Popularpages' ); -} - -if( !$wgDisableInternalSearch ) { - $wgSpecialPages['Search'] = new SpecialPage( 'Search' ); -} - -if( $wgEmailAuthentication ) { - $wgSpecialPages['Confirmemail'] = new UnlistedSpecialPage( 'Confirmemail' ); -} /** * Parent special page class, also static functions for handling the special * page list - * @package MediaWiki */ class SpecialPage { @@ -106,10 +34,14 @@ class SpecialPage * @access private */ /** - * The name of the class, used in the URL. + * The canonical name of this special page * Also used for the default

heading, @see getDescription() */ var $mName; + /** + * The local name of this special page + */ + var $mLocalName; /** * Minimum user level required to access this page, or "" for anyone. * Also used to categorise the pages in Special:Specialpages @@ -135,30 +67,208 @@ class SpecialPage * Whether the special page can be included in an article */ var $mIncludable; - + /** + * Query parameters that can be passed through redirects + */ + var $mAllowedRedirectParams = array(); + + static public $mList = array( + 'DoubleRedirects' => array( 'SpecialPage', 'DoubleRedirects' ), + 'BrokenRedirects' => array( 'SpecialPage', 'BrokenRedirects' ), + 'Disambiguations' => array( 'SpecialPage', 'Disambiguations' ), + + 'Userlogin' => array( 'SpecialPage', 'Userlogin' ), + 'Userlogout' => array( 'UnlistedSpecialPage', 'Userlogout' ), + 'Preferences' => array( 'SpecialPage', 'Preferences' ), + 'Watchlist' => array( 'SpecialPage', 'Watchlist' ), + + 'Recentchanges' => array( 'IncludableSpecialPage', 'Recentchanges' ), + 'Upload' => array( 'SpecialPage', 'Upload' ), + 'Imagelist' => array( 'SpecialPage', 'Imagelist' ), + 'Newimages' => array( 'IncludableSpecialPage', 'Newimages' ), + 'Listusers' => array( 'SpecialPage', 'Listusers' ), + 'Statistics' => array( 'SpecialPage', 'Statistics' ), + 'Randompage' => array( 'SpecialPage', 'Randompage' ), + 'Lonelypages' => array( 'SpecialPage', 'Lonelypages' ), + 'Uncategorizedpages' => array( 'SpecialPage', 'Uncategorizedpages' ), + 'Uncategorizedcategories' => array( 'SpecialPage', 'Uncategorizedcategories' ), + 'Uncategorizedimages' => array( 'SpecialPage', 'Uncategorizedimages' ), + 'Unusedcategories' => array( 'SpecialPage', 'Unusedcategories' ), + 'Unusedimages' => array( 'SpecialPage', 'Unusedimages' ), + 'Wantedpages' => array( 'IncludableSpecialPage', 'Wantedpages' ), + 'Wantedcategories' => array( 'SpecialPage', 'Wantedcategories' ), + 'Mostlinked' => array( 'SpecialPage', 'Mostlinked' ), + 'Mostlinkedcategories' => array( 'SpecialPage', 'Mostlinkedcategories' ), + 'Mostcategories' => array( 'SpecialPage', 'Mostcategories' ), + 'Mostimages' => array( 'SpecialPage', 'Mostimages' ), + 'Mostrevisions' => array( 'SpecialPage', 'Mostrevisions' ), + 'Shortpages' => array( 'SpecialPage', 'Shortpages' ), + 'Longpages' => array( 'SpecialPage', 'Longpages' ), + 'Newpages' => array( 'IncludableSpecialPage', 'Newpages' ), + 'Ancientpages' => array( 'SpecialPage', 'Ancientpages' ), + 'Deadendpages' => array( 'SpecialPage', 'Deadendpages' ), + 'Protectedpages' => array( 'SpecialPage', 'Protectedpages' ), + 'Allpages' => array( 'IncludableSpecialPage', 'Allpages' ), + 'Prefixindex' => array( 'IncludableSpecialPage', 'Prefixindex' ) , + 'Ipblocklist' => array( 'SpecialPage', 'Ipblocklist' ), + 'Specialpages' => array( 'UnlistedSpecialPage', 'Specialpages' ), + 'Contributions' => array( 'UnlistedSpecialPage', 'Contributions' ), + 'Emailuser' => array( 'UnlistedSpecialPage', 'Emailuser' ), + 'Whatlinkshere' => array( 'UnlistedSpecialPage', 'Whatlinkshere' ), + 'Recentchangeslinked' => array( 'UnlistedSpecialPage', 'Recentchangeslinked' ), + 'Movepage' => array( 'UnlistedSpecialPage', 'Movepage' ), + 'Blockme' => array( 'UnlistedSpecialPage', 'Blockme' ), + 'Resetpass' => array( 'UnlistedSpecialPage', 'Resetpass' ), + 'Booksources' => 'SpecialBookSources', + 'Categories' => array( 'SpecialPage', 'Categories' ), + 'Export' => array( 'SpecialPage', 'Export' ), + 'Version' => array( 'SpecialPage', 'Version' ), + 'Allmessages' => array( 'SpecialPage', 'Allmessages' ), + 'Log' => array( 'SpecialPage', 'Log' ), + 'Blockip' => array( 'SpecialPage', 'Blockip', 'block' ), + 'Undelete' => array( 'SpecialPage', 'Undelete', 'deletedhistory' ), + 'Import' => array( 'SpecialPage', "Import", 'import' ), + 'Lockdb' => array( 'SpecialPage', 'Lockdb', 'siteadmin' ), + 'Unlockdb' => array( 'SpecialPage', 'Unlockdb', 'siteadmin' ), + 'Userrights' => array( 'SpecialPage', 'Userrights', 'userrights' ), + 'MIMEsearch' => array( 'SpecialPage', 'MIMEsearch' ), + 'Unwatchedpages' => array( 'SpecialPage', 'Unwatchedpages', 'unwatchedpages' ), + 'Listredirects' => array( 'SpecialPage', 'Listredirects' ), + 'Revisiondelete' => array( 'SpecialPage', 'Revisiondelete', 'deleterevision' ), + 'Unusedtemplates' => array( 'SpecialPage', 'Unusedtemplates' ), + 'Randomredirect' => array( 'SpecialPage', 'Randomredirect' ), + + 'Mypage' => array( 'SpecialMypage' ), + 'Mytalk' => array( 'SpecialMytalk' ), + 'Mycontributions' => array( 'SpecialMycontributions' ), + 'Listadmins' => array( 'SpecialRedirectToSpecial', 'Listadmins', 'Listusers', 'sysop' ), + ); + + static public $mAliases; + static public $mListInitialised = false; /**#@-*/ + /** + * Initialise the special page list + * This must be called before accessing SpecialPage::$mList + */ + static function initList() { + global $wgSpecialPages; + global $wgDisableCounters, $wgDisableInternalSearch, $wgEmailAuthentication; + + if ( self::$mListInitialised ) { + return; + } + wfProfileIn( __METHOD__ ); + + # Better to set this now, to avoid infinite recursion in carelessly written hooks + self::$mListInitialised = true; + + if( !$wgDisableCounters ) { + self::$mList['Popularpages'] = array( 'SpecialPage', 'Popularpages' ); + } + + if( !$wgDisableInternalSearch ) { + self::$mList['Search'] = array( 'SpecialPage', 'Search' ); + } + + if( $wgEmailAuthentication ) { + self::$mList['Confirmemail'] = array( 'UnlistedSpecialPage', 'Confirmemail' ); + } + + # Add extension special pages + self::$mList = array_merge( self::$mList, $wgSpecialPages ); + + # Run hooks + # This hook can be used to remove undesired built-in special pages + wfRunHooks( 'SpecialPage_initList', array( &self::$mList ) ); + wfProfileOut( __METHOD__ ); + } + + static function initAliasList() { + if ( !is_null( self::$mAliases ) ) { + return; + } + + global $wgContLang; + $aliases = $wgContLang->getSpecialPageAliases(); + $missingPages = self::$mList; + self::$mAliases = array(); + foreach ( $aliases as $realName => $aliasList ) { + foreach ( $aliasList as $alias ) { + self::$mAliases[$wgContLang->caseFold( $alias )] = $realName; + } + unset( $missingPages[$realName] ); + } + foreach ( $missingPages as $name => $stuff ) { + self::$mAliases[$wgContLang->caseFold( $name )] = $name; + } + } + + /** + * Given a special page alias, return the special page name. + * Returns false if there is no such alias. + */ + static function resolveAlias( $alias ) { + global $wgContLang; + + if ( !self::$mListInitialised ) self::initList(); + if ( is_null( self::$mAliases ) ) self::initAliasList(); + $caseFoldedAlias = $wgContLang->caseFold( $alias ); + if ( isset( self::$mAliases[$caseFoldedAlias] ) ) { + return self::$mAliases[$caseFoldedAlias]; + } else { + return false; + } + } + + /** + * Given a special page name with a possible subpage, return an array + * where the first element is the special page name and the second is the + * subpage. + */ + static function resolveAliasWithSubpage( $alias ) { + $bits = explode( '/', $alias, 2 ); + $name = self::resolveAlias( $bits[0] ); + if( !isset( $bits[1] ) ) { // bug 2087 + $par = NULL; + } else { + $par = $bits[1]; + } + return array( $name, $par ); + } /** - * Add a page to the list of valid special pages - * $obj->execute() must send HTML to $wgOut then return - * Use this for a special page extension + * Add a page to the list of valid special pages. This used to be the preferred + * method for adding special pages in extensions. It's now suggested that you add + * an associative record to $wgSpecialPages. This avoids autoloading SpecialPage. + * + * @param mixed $page Must either be an array specifying a class name and + * constructor parameters, or an object. The object, + * when constructed, must have an execute() method which + * sends HTML to $wgOut. * @static */ - function addPage( &$obj ) { - global $wgSpecialPages; - $wgSpecialPages[$obj->mName] = $obj; + static function addPage( &$page ) { + if ( !self::$mListInitialised ) { + self::initList(); + } + self::$mList[$page->mName] = $page; } /** * Remove a special page from the list - * Occasionally used to disable expensive or dangerous special pages + * Formerly used to disable expensive or dangerous special pages. The + * preferred method is now to add a SpecialPage_initList hook. + * * @static */ - function removePage( $name ) { - global $wgSpecialPages; - unset( $wgSpecialPages[$name] ); + static function removePage( $name ) { + if ( !self::$mListInitialised ) { + self::initList(); + } + unset( self::$mList[$name] ); } /** @@ -166,79 +276,76 @@ class SpecialPage * @static * @param string $name */ - function getPage( $name ) { - global $wgSpecialPages; - if ( array_key_exists( $name, $wgSpecialPages ) ) { - return $wgSpecialPages[$name]; + static function getPage( $name ) { + if ( !self::$mListInitialised ) { + self::initList(); + } + if ( array_key_exists( $name, self::$mList ) ) { + $rec = self::$mList[$name]; + if ( is_string( $rec ) ) { + $className = $rec; + self::$mList[$name] = new $className; + } elseif ( is_array( $rec ) ) { + $className = array_shift( $rec ); + self::$mList[$name] = wfCreateObject( $className, $rec ); + } + return self::$mList[$name]; } else { return NULL; } } /** - * @static - * @param string $name - * @return mixed Title object if the redirect exists, otherwise NULL + * Get a special page with a given localised name, or NULL if there + * is no such special page. */ - function getRedirect( $name ) { - global $wgUser; - - $redirects = array( - 'Mypage' => Title::makeTitle( NS_USER, $wgUser->getName() ), - 'Mytalk' => Title::makeTitle( NS_USER_TALK, $wgUser->getName() ), - 'Mycontributions' => Title::makeTitle( NS_SPECIAL, 'Contributions/' . $wgUser->getName() ), - 'Listadmins' => Title::makeTitle( NS_SPECIAL, 'Listusers/sysop' ), # @bug 2832 - 'Randompage' => Title::makeTitle( NS_SPECIAL, 'Random' ), - 'Userlist' => Title::makeTitle( NS_SPECIAL, 'Listusers' ) - ); - wfRunHooks( 'SpecialPageGetRedirect', array( &$redirects ) ); - - return isset( $redirects[$name] ) ? $redirects[$name] : null; + static function getPageByAlias( $alias ) { + $realName = self::resolveAlias( $alias ); + if ( $realName ) { + return self::getPage( $realName ); + } else { + return NULL; + } } /** - * Return part of the request string for a special redirect page - * This allows passing, e.g. action=history to Special:Mypage, etc. - * - * @param $name Name of the redirect page - * @return string + * Return categorised listable special pages for all users + * @static */ - function getRedirectParams( $name ) { - global $wgRequest; - - $args = array(); - switch( $name ) { - case 'Mypage': - case 'Mytalk': - case 'Randompage': - $args = array( 'action' ); + static function getRegularPages() { + if ( !self::$mListInitialised ) { + self::initList(); } - - $params = array(); - foreach( $args as $arg ) { - if( $val = $wgRequest->getVal( $arg, false ) ) - $params[] = $arg . '=' . $val; + $pages = array(); + + foreach ( self::$mList as $name => $rec ) { + $page = self::getPage( $name ); + if ( $page->isListed() && $page->getRestriction() == '' ) { + $pages[$name] = $page; + } } - - return count( $params ) ? implode( '&', $params ) : false; - } + return $pages; + } /** - * Return categorised listable special pages - * Returns a 2d array where the first index is the restriction name + * Return categorised listable special pages which are available + * for the current user, but not for everyone * @static */ - function getPages() { - global $wgSpecialPages; - $pages = array( - '' => array(), - 'sysop' => array(), - 'developer' => array() - ); + static function getRestrictedPages() { + global $wgUser; + if ( !self::$mListInitialised ) { + self::initList(); + } + $pages = array(); - foreach ( $wgSpecialPages as $name => $page ) { + foreach ( self::$mList as $name => $rec ) { + $page = self::getPage( $name ); if ( $page->isListed() ) { - $pages[$page->getRestriction()][$page->getName()] =& $wgSpecialPages[$name]; + $restriction = $page->getRestriction(); + if ( $restriction != '' && $wgUser->isAllowed( $restriction ) ) { + $pages[$name] = $page; + } } } return $pages; @@ -255,68 +362,75 @@ class SpecialPage * @param $title a title object * @param $including output is being captured for use in {{special:whatever}} */ - function executePath( &$title, $including = false ) { - global $wgOut, $wgTitle; - $fname = 'SpecialPage::executePath'; - wfProfileIn( $fname ); + static function executePath( &$title, $including = false ) { + global $wgOut, $wgTitle, $wgRequest; + wfProfileIn( __METHOD__ ); - $bits = split( "/", $title->getDBkey(), 2 ); + # FIXME: redirects broken due to this call + $bits = explode( '/', $title->getDBkey(), 2 ); $name = $bits[0]; if( !isset( $bits[1] ) ) { // bug 2087 $par = NULL; } else { $par = $bits[1]; } - - $page = SpecialPage::getPage( $name ); - if ( is_null( $page ) ) { - if ( $including ) { - wfProfileOut( $fname ); - return false; - } else { - $redir = SpecialPage::getRedirect( $name ); - if ( isset( $redir ) ) { - if( $par ) - $redir = Title::makeTitle( $redir->getNamespace(), $redir->getText() . '/' . $par ); - $params = SpecialPage::getRedirectParams( $name ); - if( $params ) { - $url = $redir->getFullUrl( $params ); - } else { - $url = $redir->getFullUrl(); - } - $wgOut->redirect( $url ); - $retVal = $redir; - $wgOut->redirect( $url ); - $retVal = $redir; - } else { - $wgOut->setArticleRelated( false ); - $wgOut->setRobotpolicy( 'noindex,follow' ); - $wgOut->setStatusCode( 404 ); - $wgOut->errorpage( 'nosuchspecialpage', 'nospecialpagetext' ); - $retVal = false; - } + $page = SpecialPage::getPageByAlias( $name ); + + # Nonexistent? + if ( !$page ) { + if ( !$including ) { + $wgOut->setArticleRelated( false ); + $wgOut->setRobotpolicy( 'noindex,nofollow' ); + $wgOut->setStatusCode( 404 ); + $wgOut->showErrorPage( 'nosuchspecialpage', 'nospecialpagetext' ); } - } else { - if ( $including && !$page->includable() ) { - wfProfileOut( $fname ); - return false; - } elseif ( !$including ) { - if($par !== NULL) { - $wgTitle = Title::makeTitle( NS_SPECIAL, $name ); - } else { - $wgTitle = $title; - } + wfProfileOut( __METHOD__ ); + return false; + } + + # Check for redirect + if ( !$including ) { + $redirect = $page->getRedirect( $par ); + if ( $redirect ) { + $query = $page->getRedirectQuery(); + $url = $redirect->getFullUrl( $query ); + $wgOut->redirect( $url ); + wfProfileOut( __METHOD__ ); + return $redirect; } - $page->including( $including ); + } + + # Redirect to canonical alias for GET commands + # Not for POST, we'd lose the post data, so it's best to just distribute + # the request. Such POST requests are possible for old extensions that + # generate self-links without being aware that their default name has + # changed. + if ( !$including && $name != $page->getLocalName() && !$wgRequest->wasPosted() ) { + $query = $_GET; + unset( $query['title'] ); + $query = wfArrayToCGI( $query ); + $title = $page->getTitle( $par ); + $url = $title->getFullUrl( $query ); + $wgOut->redirect( $url ); + wfProfileOut( __METHOD__ ); + return $redirect; + } - $profName = 'Special:' . $page->getName(); - wfProfileIn( $profName ); - $page->execute( $par ); - wfProfileOut( $profName ); - $retVal = true; + if ( $including && !$page->includable() ) { + wfProfileOut( __METHOD__ ); + return false; + } elseif ( !$including ) { + $wgTitle = $page->getTitle(); } - wfProfileOut( $fname ); - return $retVal; + $page->including( $including ); + + // Execute special page + $profName = 'Special:' . $page->getName(); + wfProfileIn( $profName ); + $page->execute( $par ); + wfProfileOut( $profName ); + wfProfileOut( __METHOD__ ); + return true; } /** @@ -325,7 +439,7 @@ class SpecialPage * a redirect. * @static */ - function capturePath( &$title ) { + static function capturePath( &$title ) { global $wgOut, $wgTitle; $oldTitle = $wgTitle; @@ -341,6 +455,58 @@ class SpecialPage return $ret; } + /** + * Get the local name for a specified canonical name + */ + static function getLocalNameFor( $name, $subpage = false ) { + global $wgContLang; + $aliases = $wgContLang->getSpecialPageAliases(); + if ( isset( $aliases[$name][0] ) ) { + $name = $aliases[$name][0]; + } + if ( $subpage !== false && !is_null( $subpage ) ) { + $name = "$name/$subpage"; + } + return $name; + } + + /** + * Get a localised Title object for a specified special page name + */ + static function getTitleFor( $name, $subpage = false ) { + $name = self::getLocalNameFor( $name, $subpage ); + if ( $name ) { + return Title::makeTitle( NS_SPECIAL, $name ); + } else { + throw new MWException( "Invalid special page name \"$name\"" ); + } + } + + /** + * Get a localised Title object for a page name with a possibly unvalidated subpage + */ + static function getSafeTitleFor( $name, $subpage = false ) { + $name = self::getLocalNameFor( $name, $subpage ); + if ( $name ) { + return Title::makeTitleSafe( NS_SPECIAL, $name ); + } else { + return null; + } + } + + /** + * Get a title for a given alias + * @return Title or null if there is no such alias + */ + static function getTitleForAlias( $alias ) { + $name = self::resolveAlias( $alias ); + if ( $name ) { + return self::getTitleFor( $name ); + } else { + return null; + } + } + /** * Default constructor for special pages * Derivative classes should call this from their constructor @@ -352,7 +518,7 @@ class SpecialPage * and displayRestrictionError() * * @param string $name Name of the special page, as seen in links and URLs - * @param string $restriction Minimum user level required, e.g. "sysop" or "developer". + * @param string $restriction User right required, e.g. "block" or "delete" * @param boolean $listed Whether the page is listed in Special:Specialpages * @param string $function Function called by execute(). By default it is constructed from $name * @param string $file File which is included by execute(). It is also constructed from $name by default @@ -368,7 +534,7 @@ class SpecialPage $this->mFunction = $function; } if ( $file === 'default' ) { - $this->mFile = "Special{$name}.php"; + $this->mFile = dirname(__FILE__) . "/Special{$name}.php"; } else { $this->mFile = $file; } @@ -397,20 +563,22 @@ class SpecialPage function including( $x = NULL ) { return wfSetVar( $this->mIncluding, $x ); } /**#@-*/ + /** + * Get the localised name of the special page + */ + function getLocalName() { + if ( !isset( $this->mLocalName ) ) { + $this->mLocalName = self::getLocalNameFor( $this->mName ); + } + return $this->mLocalName; + } + /** * Checks if the given user (identified by an object) can execute this * special page (as defined by $mRestriction) */ function userCanExecute( &$user ) { - if ( $this->mRestriction == "" ) { - return true; - } else { - if ( in_array( $this->mRestriction, $user->getRights() ) ) { - return true; - } else { - return false; - } - } + return $user->isAllowed( $this->mRestriction ); } /** @@ -427,13 +595,15 @@ class SpecialPage function setHeaders() { global $wgOut; $wgOut->setArticleRelated( false ); - $wgOut->setRobotPolicy( "noindex,follow" ); + $wgOut->setRobotPolicy( "noindex,nofollow" ); $wgOut->setPageTitle( $this->getDescription() ); } /** * Default execute method * Checks user permissions, calls the function given in mFunction + * + * This may be overridden by subclasses. */ function execute( $par ) { global $wgUser; @@ -446,6 +616,7 @@ class SpecialPage if(!function_exists($func) and $this->mFile) { require_once( $this->mFile ); } + # FIXME: these hooks are broken for extensions and anything else that subclasses SpecialPage. if ( wfRunHooks( 'SpecialPageExecuteBeforeHeader', array( &$this, &$par, &$func ) ) ) $this->outputHeader(); if ( ! wfRunHooks( 'SpecialPageExecuteBeforePage', array( &$this, &$par, &$func ) ) ) @@ -480,8 +651,8 @@ class SpecialPage /** * Get a self-referential title object */ - function getTitle() { - return Title::makeTitle( NS_SPECIAL, $this->mName ); + function getTitle( $subpage = false) { + return self::getTitleFor( $this->mName, $subpage ); } /** @@ -491,11 +662,34 @@ class SpecialPage return wfSetVar( $this->mListed, $listed ); } + /** + * If the special page is a redirect, then get the Title object it redirects to. + * False otherwise. + */ + function getRedirect( $subpage ) { + return false; + } + + /** + * Return part of the request string for a special redirect page + * This allows passing, e.g. action=history to Special:Mypage, etc. + * + * @return string + */ + function getRedirectQuery() { + global $wgRequest; + $params = array(); + foreach( $this->mAllowedRedirectParams as $arg ) { + if( $val = $wgRequest->getVal( $arg, false ) ) + $params[] = $arg . '=' . $val; + } + + return count( $params ) ? implode( '&', $params ) : false; + } } /** * Shortcut to construct a special page which is unlisted by default - * @package MediaWiki */ class UnlistedSpecialPage extends SpecialPage { @@ -506,7 +700,6 @@ class UnlistedSpecialPage extends SpecialPage /** * Shortcut to construct an includable special page - * @package MediaWiki */ class IncludableSpecialPage extends SpecialPage { @@ -514,4 +707,67 @@ class IncludableSpecialPage extends SpecialPage SpecialPage::SpecialPage( $name, $restriction, $listed, $function, $file, true ); } } + +class SpecialRedirectToSpecial extends UnlistedSpecialPage { + var $redirName, $redirSubpage; + + function __construct( $name, $redirName, $redirSubpage = false, $redirectParams = array() ) { + parent::__construct( $name ); + $this->redirName = $redirName; + $this->redirSubpage = $redirSubpage; + $this->mAllowedRedirectParams = $redirectParams; + } + + function getRedirect( $subpage ) { + if ( $this->redirSubpage === false ) { + return SpecialPage::getTitleFor( $this->redirName, $subpage ); + } else { + return SpecialPage::getTitleFor( $this->redirName, $this->redirSubpage ); + } + } +} + +class SpecialMypage extends UnlistedSpecialPage { + function __construct() { + parent::__construct( 'Mypage' ); + $this->mAllowedRedirectParams = array( 'action' ); + } + + function getRedirect( $subpage ) { + global $wgUser; + if ( strval( $subpage ) !== '' ) { + return Title::makeTitle( NS_USER, $wgUser->getName() . '/' . $subpage ); + } else { + return Title::makeTitle( NS_USER, $wgUser->getName() ); + } + } +} + +class SpecialMytalk extends UnlistedSpecialPage { + function __construct() { + parent::__construct( 'Mytalk' ); + $this->mAllowedRedirectParams = array( 'action' ); + } + + function getRedirect( $subpage ) { + global $wgUser; + if ( strval( $subpage ) !== '' ) { + return Title::makeTitle( NS_USER_TALK, $wgUser->getName() . '/' . $subpage ); + } else { + return Title::makeTitle( NS_USER_TALK, $wgUser->getName() ); + } + } +} + +class SpecialMycontributions extends UnlistedSpecialPage { + function __construct() { + parent::__construct( 'Mycontributions' ); + } + + function getRedirect( $subpage ) { + global $wgUser; + return SpecialPage::getTitleFor( 'Contributions', $wgUser->getName() ); + } +} + ?>