* Made generateReason() skip deleted user names
[lhc/web/wiklou.git] / includes / SpecialPage.php
index d65cae8..31b4383 100644 (file)
  * SpecialPage::$mList. To remove a core static special page at runtime, use
  * a SpecialPage_initList hook.
  *
- * @addtogroup SpecialPage
+ * @file
+ * @ingroup SpecialPage
+ * @defgroup SpecialPage SpecialPage
  */
 
 /**
  * Parent special page class, also static functions for handling the special
  * page list.
- * @addtogroup SpecialPage
+ * @ingroup SpecialPage
  */
 class SpecialPage
 {
@@ -78,181 +80,116 @@ class SpecialPage
         ** array( 'SpecialRedirectToSpecial', name, page to redirect to, special page param, ... )
         */
        static public $mList = array(
-               'DoubleRedirects'           => array( 'SpecialPage', 'DoubleRedirects' ),
+               # Maintenance Reports
                'BrokenRedirects'           => array( 'SpecialPage', 'BrokenRedirects' ),
+               'Deadendpages'              => array( 'SpecialPage', 'Deadendpages' ),
+               'DoubleRedirects'           => array( 'SpecialPage', 'DoubleRedirects' ),
+               'Longpages'                 => array( 'SpecialPage', 'Longpages' ),
+               'Ancientpages'              => array( 'SpecialPage', 'Ancientpages' ),
+               'Lonelypages'               => array( 'SpecialPage', 'Lonelypages' ),
+               'Fewestrevisions'           => array( 'SpecialPage', 'Fewestrevisions' ),
+               'Withoutinterwiki'          => array( 'SpecialPage', 'Withoutinterwiki' ),
+               'Protectedpages'            => array( 'SpecialPage', 'Protectedpages' ),
+               'Protectedtitles'           => array( 'SpecialPage', 'Protectedtitles' ),       
+               'Shortpages'                => array( 'SpecialPage', 'Shortpages' ),    
+               'Uncategorizedcategories'   => array( 'SpecialPage', 'Uncategorizedcategories' ),       
+               'Uncategorizedimages'       => array( 'SpecialPage', 'Uncategorizedimages' ),   
+               'Uncategorizedpages'        => array( 'SpecialPage', 'Uncategorizedpages' ),    
+               'Uncategorizedtemplates'    => array( 'SpecialPage', 'Uncategorizedtemplates' ),
+               'Unusedcategories'          => array( 'SpecialPage', 'Unusedcategories' ),
+               'Unusedimages'              => array( 'SpecialPage', 'Unusedimages' ),          
+               'Unusedtemplates'           => array( 'SpecialPage', 'Unusedtemplates' ),
+               'Unwatchedpages'            => array( 'SpecialPage', 'Unwatchedpages', 'unwatchedpages' ),      
+               'Wantedcategories'          => array( 'SpecialPage', 'Wantedcategories' ),
+               'Wantedfiles'               => array( 'SpecialPage', 'Wantedfiles' ),
+               'Wantedpages'               => array( 'IncludableSpecialPage', 'Wantedpages' ),
+               'Wantedtemplates'           => array( 'SpecialPage', 'Wantedtemplates' ),
+
+               # List of pages
+               'Allpages'                  => 'SpecialAllpages',               
+               'Prefixindex'               => 'SpecialPrefixindex',            
+               'Categories'                => array( 'SpecialPage', 'Categories' ),
                'Disambiguations'           => array( 'SpecialPage', 'Disambiguations' ),
+               'Listredirects'             => array( 'SpecialPage', 'Listredirects' ), 
 
-               'Userlogin'                 => array( 'SpecialPage', 'Userlogin' ),
-               'Userlogout'                => array( 'UnlistedSpecialPage', 'Userlogout' ),
+               # Login/create account
+               'Userlogin'                 => array( 'SpecialPage', 'Userlogin' ),             
                'CreateAccount'             => array( 'SpecialRedirectToSpecial', 'CreateAccount', 'Userlogin', 'signup', array( 'uselang' ) ),
-               'Preferences'               => array( 'SpecialPage', 'Preferences' ),
+
+               # Users and rights
+               'Blockip'                   => array( 'SpecialPage', 'Blockip', 'block' ),
+               'Ipblocklist'               => array( 'SpecialPage', 'Ipblocklist' ),
+               'Resetpass'                 => 'SpecialResetpass',
+               'DeletedContributions'      => 'DeletedContributionsPage',
+               'Preferences'               => array( 'SpecialPage', 'Preferences' ),   
+               'Contributions'             => 'SpecialContributions',  
+               'Listgrouprights'           => 'SpecialListGroupRights',
+               'Listusers'                 => array( 'SpecialPage', 'Listusers' ),     
+               'Userrights'                => 'UserrightsPage',
+
+               # Recent changes and logs
+               'Newimages'                 => array( 'IncludableSpecialPage', 'Newimages' ),   
+               'Log'                       => array( 'SpecialPage', 'Log' ),
                'Watchlist'                 => array( 'SpecialPage', 'Watchlist' ),
+               'Newpages'                  => 'SpecialNewpages',
+               'Recentchanges'             => 'SpecialRecentchanges',
+               'Recentchangeslinked'       => 'SpecialRecentchangeslinked',
+               'Tags'                      => 'SpecialTags',
 
-               'Recentchanges'             => array( 'IncludableSpecialPage', 'Recentchanges' ),
+               # Media reports and uploads
+               'Listfiles'                 => array( 'SpecialPage', 'Listfiles' ),
+               'Filepath'                  => array( 'SpecialPage', 'Filepath' ),
+               'MIMEsearch'                => array( 'SpecialPage', 'MIMEsearch' ),
+               'FileDuplicateSearch'       => array( 'SpecialPage', 'FileDuplicateSearch' ),
                'Upload'                    => array( 'SpecialPage', 'Upload' ),
-               'Imagelist'                 => array( 'SpecialPage', 'Imagelist' ),
-               'Newimages'                 => array( 'IncludableSpecialPage', 'Newimages' ),
-               'Listusers'                 => array( 'SpecialPage', 'Listusers' ),
-               'Listgrouprights'           => 'SpecialListGroupRights',
-               'Statistics'                => array( 'SpecialPage', 'Statistics' ),
+
+               # Wiki data and tools
+               'Statistics'                            => 'SpecialStatistics',
+               'Allmessages'               => array( 'SpecialPage', 'Allmessages' ),
+               'Version'                   => 'SpecialVersion',
+               'Lockdb'                    => array( 'SpecialPage', 'Lockdb', 'siteadmin' ),
+               'Unlockdb'                  => array( 'SpecialPage', 'Unlockdb', 'siteadmin' ),
+
+               # Redirecting special pages
+               'LinkSearch'                => array( 'SpecialPage', 'LinkSearch' ),
                'Randompage'                => 'Randompage',
-               'Lonelypages'               => array( 'SpecialPage', 'Lonelypages' ),
-               'Uncategorizedpages'        => array( 'SpecialPage', 'Uncategorizedpages' ),
-               'Uncategorizedcategories'   => array( 'SpecialPage', 'Uncategorizedcategories' ),
-               'Uncategorizedimages'       => array( 'SpecialPage', 'Uncategorizedimages' ),
-               'Uncategorizedtemplates'    => array( 'SpecialPage', 'Uncategorizedtemplates' ),
-               'Unusedcategories'          => array( 'SpecialPage', 'Unusedcategories' ),
-               'Unusedimages'              => array( 'SpecialPage', 'Unusedimages' ),
-               'Wantedpages'               => array( 'IncludableSpecialPage', 'Wantedpages' ),
-               'Wantedcategories'          => array( 'SpecialPage', 'Wantedcategories' ),
-               'Mostlinked'                => array( 'SpecialPage', 'Mostlinked' ),
+               'Randomredirect'            => 'SpecialRandomredirect',
+
+               # High use pages
                'Mostlinkedcategories'      => array( 'SpecialPage', 'Mostlinkedcategories' ),
+               'Mostimages'                => array( 'SpecialPage', 'Mostimages' ),
+               'Mostlinked'                => array( 'SpecialPage', 'Mostlinked' ),
                'Mostlinkedtemplates'       => array( 'SpecialPage', 'Mostlinkedtemplates' ),
                'Mostcategories'            => array( 'SpecialPage', 'Mostcategories' ),
-               'Mostimages'                => array( 'SpecialPage', 'Mostimages' ),
                'Mostrevisions'             => array( 'SpecialPage', 'Mostrevisions' ),
-               'Fewestrevisions'           => array( 'SpecialPage', 'Fewestrevisions' ),
-               'Shortpages'                => array( 'SpecialPage', 'Shortpages' ),
-               'Longpages'                 => array( 'SpecialPage', 'Longpages' ),
-               'Newpages'                  => array( 'IncludableSpecialPage', 'Newpages' ),
-               'Ancientpages'              => array( 'SpecialPage', 'Ancientpages' ),
-               'Deadendpages'              => array( 'SpecialPage', 'Deadendpages' ),
-               'Protectedpages'            => array( 'SpecialPage', 'Protectedpages' ),
-               'Protectedtitles'           => array( 'SpecialPage', 'Protectedtitles' ),
-               'Allpages'                  => array( 'IncludableSpecialPage', 'Allpages' ),
-               'Prefixindex'               => array( 'IncludableSpecialPage', 'Prefixindex' ) ,
-               'Ipblocklist'               => array( 'SpecialPage', 'Ipblocklist' ),
-               'Specialpages'              => array( 'UnlistedSpecialPage', 'Specialpages' ),
-               'Contributions'             => array( 'SpecialPage', 'Contributions' ),
-               'Emailuser'                 => array( 'UnlistedSpecialPage', 'Emailuser' ),
+
+               # Page tools
+               'Export'                    => 'SpecialExport',
+               'Import'                    => 'SpecialImport',
+               'Undelete'                  => array( 'SpecialPage', 'Undelete', 'deletedhistory' ),
                'Whatlinkshere'             => array( 'SpecialPage', 'Whatlinkshere' ),
-               'Recentchangeslinked'       => array( 'SpecialPage', 'Recentchangeslinked' ),
-               'Movepage'                  => array( 'UnlistedSpecialPage', 'Movepage' ),
-               'Blockme'                   => array( 'UnlistedSpecialPage', 'Blockme' ),
-               'Resetpass'                 => array( 'UnlistedSpecialPage', 'Resetpass' ),
+               'MergeHistory'              => array( 'SpecialPage', 'MergeHistory', 'mergehistory' ),  
+               
+               # Other
                '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'                => 'UserrightsPage',
-               'MIMEsearch'                => array( 'SpecialPage', 'MIMEsearch' ),
-               'FileDuplicateSearch'       => array( 'SpecialPage', 'FileDuplicateSearch' ),
-               'Unwatchedpages'            => array( 'SpecialPage', 'Unwatchedpages', 'unwatchedpages' ),
-               'Listredirects'             => array( 'SpecialPage', 'Listredirects' ),
-               'Revisiondelete'            => array( 'UnlistedSpecialPage', 'Revisiondelete', 'deleterevision' ),
-               'Unusedtemplates'           => array( 'SpecialPage', 'Unusedtemplates' ),
-               'Randomredirect'            => 'SpecialRandomredirect',
-               'Withoutinterwiki'          => array( 'SpecialPage', 'Withoutinterwiki' ),
-               'Filepath'                  => array( 'SpecialPage', 'Filepath' ),
-
-               'Mypage'                    => array( 'SpecialMypage' ),
-               'Mytalk'                    => array( 'SpecialMytalk' ),
-               'Mycontributions'           => array( 'SpecialMycontributions' ),
+               
+               # Unlisted / redirects
+               'Blankpage'                 => array( 'UnlistedSpecialPage', 'Blankpage' ),
+               'Blockme'                   => array( 'UnlistedSpecialPage', 'Blockme' ),       
+               'Emailuser'                 => array( 'UnlistedSpecialPage', 'Emailuser' ),
                'Listadmins'                => array( 'SpecialRedirectToSpecial', 'Listadmins', 'Listusers', 'sysop' ),
-               'MergeHistory'              => array( 'SpecialPage', 'MergeHistory', 'mergehistory' ),
                'Listbots'                  => array( 'SpecialRedirectToSpecial', 'Listbots', 'Listusers', 'bot' ),
+               'Movepage'                  => array( 'UnlistedSpecialPage', 'Movepage' ),
+               'Mycontributions'           => array( 'SpecialMycontributions' ),
+               'Mypage'                    => array( 'SpecialMypage' ),
+               'Mytalk'                    => array( 'SpecialMytalk' ),
+               'Revisiondelete'            => 'SpecialRevisionDelete',
+               'Specialpages'              => array( 'UnlistedSpecialPage', 'Specialpages' ),
+               'Userlogout'                => array( 'UnlistedSpecialPage', 'Userlogout' ),
        );
 
        static public $mAliases;
        static public $mListInitialised = false;
-       /**
-        * List of special pages, followed by what subtitle they should go under
-        * at Special:SpecialPages
-        */
-       static public $mGroupsList = array(
-               'DoubleRedirects'           => 'maintenance',
-               'BrokenRedirects'           => 'maintenance',
-               'Lonelypages'               => 'maintenance',
-               'Uncategorizedpages'        => 'maintenance',
-               'Uncategorizedcategories'   => 'maintenance',
-               'Uncategorizedimages'       => 'maintenance',
-               'Uncategorizedtemplates'    => 'maintenance',
-               'Unusedcategories'          => 'maintenance',
-               'Unusedimages'              => 'maintenance',
-               'Protectedpages'            => 'maintenance',
-               'Protectedtitles'           => 'maintenance',
-               'Unusedtemplates'           => 'maintenance',
-               'Withoutinterwiki'          => 'maintenance',
-               'Longpages'                 => 'maintenance',
-
-               'Userlogin'                 => 'login',
-               'Userlogout'                => 'login',
-               'CreateAccount'             => 'login',
-
-               'Recentchanges'             => 'changes',
-               'Recentchangeslinked'       => 'changes',
-               'Watchlist'                 => 'changes',
-               'Newimages'                 => 'changes',
-               'Newpages'                  => 'changes',
-               'Log'                       => 'changes',
-
-               'Upload'                    => 'media',
-               'Imagelist'                 => 'media',
-               'MIMEsearch'                => 'media',
-               'FileDuplicateSearch'       => 'media',
-               'Filepath'                  => 'media',
-
-               'Listusers'                 => 'users',
-               'Listgrouprights'           => 'users',
-               'Ipblocklist'               => 'users',
-               'Contributions'             => 'users',
-               'Emailuser'                 => 'users',
-               'Listadmins'                => 'users',
-               'Listbots'                  => 'users',
-
-               'Wantedpages'               => 'needy',
-               'Wantedcategories'          => 'needy',
-               'Shortpages'                => 'needy',
-               'Ancientpages'              => 'needy',
-               'Deadendpages'              => 'needy',
-
-               'Mostlinked'                => 'highuse',
-               'Mostlinkedcategories'      => 'highuse',
-               'Mostlinkedtemplates'       => 'highuse',
-               'Mostcategories'            => 'highuse',
-               'Mostimages'                => 'highuse',
-               'Mostrevisions'             => 'highuse',
-
-               'Userrights'                => 'permissions',
-               'Blockip'                   => 'permissions',
-
-               'Statistics'                => 'other',
-               'Fewestrevisions'           => 'other',
-               'Randompage'                => 'other',
-               'Disambiguations'           => 'other',
-               'Specialpages'              => 'other',
-               'Blockme'                   => 'other',
-               'Movepage'                  => 'other',
-               'MergeHistory'              => 'other',
-               'Lockdb'                    => 'other',
-               'Unlockdb'                  => 'other',
-               'Version'                   => 'other',
-               'Whatlinkshere'             => 'other',
-               'Booksources'               => 'other',
-               'Revisiondelete'            => 'other',
-               'Export'                    => 'other',
-               'Categories'                => 'other',
-               'Undelete'                  => 'other',
-               'Import'                    => 'other',
-               'Unwatchedpages'            => 'other',
-               'Randomredirect'            => 'other',
-               'Allpages'                  => 'other',
-               'Allmessages'               => 'other',
-               'Prefixindex'               => 'other',
-               'Listredirects'             => 'other',
-               'Preferences'               => 'other',
-               'Resetpass'                 => 'other',
-               'Mypage'                    => 'other',
-               'Mytalk'                    => 'other',
-               'Mycontributions'           => 'other',
-       );
 
        /**#@-*/
 
@@ -365,15 +302,14 @@ class SpecialPage
        /**
         * Add a page to a certain display group for Special:SpecialPages
         *
-        * @param SpecialPage $page
+        * @param mixed $page (SpecialPage or string)
         * @param string $group
         * @static
         */
-       static function setGroup( &$page, $group ) {
-               if ( !self::$mListInitialised ) {
-                       self::initList();
-               }
-               self::$mGroupsList[$page->mName] = $group;
+       static function setGroup( $page, $group ) {
+               global $wgSpecialPageGroups;
+               $name = is_object($page) ? $page->mName : $page;
+               $wgSpecialPageGroups[$name] = $group;
        }
 
        /**
@@ -383,11 +319,20 @@ class SpecialPage
         * @static
         */
        static function getGroup( &$page ) {
-               if ( !self::$mListInitialised ) {
-                       self::initList();
-               }
-               $group = isset(self::$mGroupsList[$page->mName]) ?
-                       self::$mGroupsList[$page->mName] : 'other';
+               global $wgSpecialPageGroups;
+               static $specialPageGroupsCache = array();
+               if( isset($specialPageGroupsCache[$page->mName]) ) {
+                       return $specialPageGroupsCache[$page->mName];
+               }
+               $group = wfMsg('specialpages-specialpagegroup-'.strtolower($page->mName));
+               if( $group == ''
+                || wfEmptyMsg('specialpages-specialpagegroup-'.strtolower($page->mName), $group ) ) {
+                       $group = isset($wgSpecialPageGroups[$page->mName])
+                               ? $wgSpecialPageGroups[$page->mName]
+                               : '-';
+               }
+               if( $group == '-' ) $group = 'other';
+               $specialPageGroupsCache[$page->mName] = $group;
                return $group;
        }
 
@@ -466,6 +411,32 @@ class SpecialPage
                }
        }
 
+       /**
+        * Return categorised listable special pages which are available
+        * for the current user, and everyone.
+        * @static
+        */
+       static function getUsablePages() {
+               global $wgUser;
+               if ( !self::$mListInitialised ) {
+                       self::initList();
+               }
+               $pages = array();
+
+               foreach ( self::$mList as $name => $rec ) {
+                       $page = self::getPage( $name );
+                       if ( $page->isListed()
+                               && (
+                                       !$page->isRestricted()
+                                       || $page->userCanExecute( $wgUser )
+                               )
+                       ) {
+                               $pages[$name] = $page;
+                       }
+               }
+               return $pages;
+       }
+
        /**
         * Return categorised listable special pages for all users
         * @static
@@ -492,17 +463,17 @@ class SpecialPage
         */
        static function getRestrictedPages() {
                global $wgUser;
-               if ( !self::$mListInitialised ) {
+               if( !self::$mListInitialised ) {
                        self::initList();
                }
                $pages = array();
 
-               foreach ( self::$mList as $name => $rec ) {
+               foreach( self::$mList as $name => $rec ) {
                        $page = self::getPage( $name );
-                       if (
+                       if(
                                $page->isListed()
-                               and $page->isRestricted()
-                               and $page->userCanExecute( $wgUser )
+                               && $page->isRestricted()
+                               && $page->userCanExecute( $wgUser )
                        ) {
                                $pages[$name] = $page;
                        }
@@ -538,7 +509,7 @@ class SpecialPage
                if ( !$page ) {
                        if ( !$including ) {
                                $wgOut->setArticleRelated( false );
-                               $wgOut->setRobotpolicy( 'noindex,nofollow' );
+                               $wgOut->setRobotPolicy( 'noindex,nofollow' );
                                $wgOut->setStatusCode( 404 );
                                $wgOut->showErrorPage( 'nosuchspecialpage', 'nospecialpagetext' );
                        }
@@ -630,7 +601,7 @@ class SpecialPage
                if ( $subpage !== false && !is_null( $subpage ) ) {
                        $name = "$name/$subpage";
                }
-               return $name;
+               return ucfirst( $name );
        }
 
        /**
@@ -697,7 +668,7 @@ class SpecialPage
                        $this->mFunction = $function;
                }
                if ( $file === 'default' ) {
-                       $this->mFile = dirname(__FILE__) . "/Special{$name}.php";
+                       $this->mFile = dirname(__FILE__) . "/specials/Special$name.php";
                } else {
                        $this->mFile = $file;
                }
@@ -744,7 +715,9 @@ class SpecialPage
         *   pages?
         */
        public function isRestricted() {
-               return $this->mRestriction != '';
+               global $wgGroupPermissions;
+               // DWIM: If all anons can do something, then it is not restricted
+               return $this->mRestriction != '' && empty($wgGroupPermissions['*'][$this->mRestriction]);
        }
 
        /**
@@ -794,26 +767,32 @@ class SpecialPage
                        if(!is_callable($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 ) ) )
-                               return;
+                       $this->outputHeader();
                        call_user_func( $func, $par, $this );
-                       if ( ! wfRunHooks( 'SpecialPageExecuteAfterPage', array( &$this, &$par, &$func ) ) )
-                               return;
                } else {
                        $this->displayRestrictionError();
                }
        }
 
-       function outputHeader() {
+       /**
+        * Outputs a summary message on top of special pages
+        * Per default the message key is the canonical name of the special page
+        * May be overriden, i.e. by extensions to stick with the naming conventions
+        * for message keys: 'extensionname-xxx' 
+        *
+        * @param string message key of the summary
+        */
+       function outputHeader( $summaryMessageKey = '' ) {
                global $wgOut, $wgContLang;
 
-               $msg = $wgContLang->lc( $this->name() ) . '-summary';
+               if( $summaryMessageKey == '' ) {
+                       $msg = $wgContLang->lc( $this->name() ) . '-summary';
+               } else {
+                       $msg = $summaryMessageKey;
+               }
                $out = wfMsgNoTrans( $msg );
                if ( ! wfEmptyMsg( $msg, $out ) and  $out !== '' and ! $this->including() ) {
-                       $wgOut->addWikiText( $out );
+                       $wgOut->wrapWikiMsg( "<div class='mw-specialpage-summary'>\n$1</div>", $msg );
                }
 
        }
@@ -869,7 +848,7 @@ class SpecialPage
 
 /**
  * Shortcut to construct a special page which is unlisted by default
- * @addtogroup SpecialPage
+ * @ingroup SpecialPage
  */
 class UnlistedSpecialPage extends SpecialPage
 {
@@ -880,7 +859,7 @@ class UnlistedSpecialPage extends SpecialPage
 
 /**
  * Shortcut to construct an includable special  page
- * @addtogroup SpecialPage
+ * @ingroup SpecialPage
  */
 class IncludableSpecialPage extends SpecialPage
 {
@@ -891,7 +870,7 @@ class IncludableSpecialPage extends SpecialPage
 
 /**
  * Shortcut to construct a special page alias.
- * @addtogroup SpecialPage
+ * @ingroup SpecialPage
  */
 class SpecialRedirectToSpecial extends UnlistedSpecialPage {
        var $redirName, $redirSubpage;
@@ -921,7 +900,7 @@ class SpecialRedirectToSpecial extends UnlistedSpecialPage {
 
 /**
  * Shortcut to construct a special page pointing to current user user's page.
- * @addtogroup SpecialPage
+ * @ingroup SpecialPage
  */
 class SpecialMypage extends UnlistedSpecialPage {
        function __construct() {
@@ -941,7 +920,7 @@ class SpecialMypage extends UnlistedSpecialPage {
 
 /**
  * Shortcut to construct a special page pointing to current user talk page.
- * @addtogroup SpecialPage
+ * @ingroup SpecialPage
  */
 class SpecialMytalk extends UnlistedSpecialPage {
        function __construct() {
@@ -961,7 +940,7 @@ class SpecialMytalk extends UnlistedSpecialPage {
 
 /**
  * Shortcut to construct a special page pointing to current user contributions.
- * @addtogroup SpecialPage
+ * @ingroup SpecialPage
  */
 class SpecialMycontributions extends UnlistedSpecialPage {
        function __construct() {