Merge "Remove unused job ID parameter from jobs"
[mediawiki.git] / includes / specialpage / SpecialPage.php
blobe874b3e2dfcebb91ce978d355ae5e3504a85fbe0
1 <?php
2 /**
3 * Parent class for all special pages.
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 * http://www.gnu.org/copyleft/gpl.html
20 * @file
21 * @ingroup SpecialPage
24 /**
25 * Parent class for all special pages.
27 * Includes some static functions for handling the special page list deprecated
28 * in favor of SpecialPageFactory.
30 * @ingroup SpecialPage
32 class SpecialPage {
33 // The canonical name of this special page
34 // Also used for the default <h1> heading, @see getDescription()
35 protected $mName;
37 // The local name of this special page
38 private $mLocalName;
40 // Minimum user level required to access this page, or "" for anyone.
41 // Also used to categorise the pages in Special:Specialpages
42 private $mRestriction;
44 // Listed in Special:Specialpages?
45 private $mListed;
47 // Function name called by the default execute()
48 private $mFunction;
50 // File which needs to be included before the function above can be called
51 private $mFile;
53 // Whether or not this special page is being included from an article
54 protected $mIncluding;
56 // Whether the special page can be included in an article
57 protected $mIncludable;
59 /**
60 * Current request context
61 * @var IContextSource
63 protected $mContext;
65 /**
66 * Initialise the special page list
67 * This must be called before accessing SpecialPage::$mList
68 * @deprecated since 1.18
70 static function initList() {
71 wfDeprecated( __METHOD__, '1.18' );
72 // Noop
75 /**
76 * @deprecated since 1.18
78 static function initAliasList() {
79 wfDeprecated( __METHOD__, '1.18' );
80 // Noop
83 /**
84 * Given a special page alias, return the special page name.
85 * Returns false if there is no such alias.
87 * @param $alias String
88 * @return String or false
89 * @deprecated since 1.18 call SpecialPageFactory method directly
91 static function resolveAlias( $alias ) {
92 wfDeprecated( __METHOD__, '1.18' );
93 list( $name, /*...*/ ) = SpecialPageFactory::resolveAlias( $alias );
94 return $name;
97 /**
98 * Given a special page name with a possible subpage, return an array
99 * where the first element is the special page name and the second is the
100 * subpage.
102 * @param $alias String
103 * @return Array
104 * @deprecated since 1.18 call SpecialPageFactory method directly
106 static function resolveAliasWithSubpage( $alias ) {
107 return SpecialPageFactory::resolveAlias( $alias );
111 * Add a page to a certain display group for Special:SpecialPages
113 * @param $page Mixed: SpecialPage or string
114 * @param $group String
115 * @deprecated since 1.18 call SpecialPageFactory method directly
117 static function setGroup( $page, $group ) {
118 wfDeprecated( __METHOD__, '1.18' );
119 SpecialPageFactory::setGroup( $page, $group );
123 * Get the group that the special page belongs in on Special:SpecialPage
125 * @param $page SpecialPage
126 * @return string
127 * @deprecated since 1.18 call SpecialPageFactory method directly
129 static function getGroup( &$page ) {
130 wfDeprecated( __METHOD__, '1.18' );
131 return SpecialPageFactory::getGroup( $page );
135 * Remove a special page from the list
136 * Formerly used to disable expensive or dangerous special pages. The
137 * preferred method is now to add a SpecialPage_initList hook.
138 * @deprecated since 1.18
140 * @param string $name the page to remove
142 static function removePage( $name ) {
143 wfDeprecated( __METHOD__, '1.18' );
144 unset( SpecialPageFactory::getList()->$name );
148 * Check if a given name exist as a special page or as a special page alias
150 * @param string $name name of a special page
151 * @return Boolean: true if a special page exists with this name
152 * @deprecated since 1.18 call SpecialPageFactory method directly
154 static function exists( $name ) {
155 wfDeprecated( __METHOD__, '1.18' );
156 return SpecialPageFactory::exists( $name );
160 * Find the object with a given name and return it (or NULL)
162 * @param $name String
163 * @return SpecialPage object or null if the page doesn't exist
164 * @deprecated since 1.18 call SpecialPageFactory method directly
166 static function getPage( $name ) {
167 wfDeprecated( __METHOD__, '1.18' );
168 return SpecialPageFactory::getPage( $name );
172 * Get a special page with a given localised name, or NULL if there
173 * is no such special page.
175 * @param $alias String
176 * @return SpecialPage object or null if the page doesn't exist
177 * @deprecated since 1.18 call SpecialPageFactory method directly
179 static function getPageByAlias( $alias ) {
180 wfDeprecated( __METHOD__, '1.18' );
181 return SpecialPageFactory::getPage( $alias );
185 * Return categorised listable special pages which are available
186 * for the current user, and everyone.
188 * @param $user User object to check permissions, $wgUser will be used
189 * if not provided
190 * @return array Associative array mapping page's name to its SpecialPage object
191 * @deprecated since 1.18 call SpecialPageFactory method directly
193 static function getUsablePages( User $user = null ) {
194 wfDeprecated( __METHOD__, '1.18' );
195 return SpecialPageFactory::getUsablePages( $user );
199 * Return categorised listable special pages for all users
201 * @return array Associative array mapping page's name to its SpecialPage object
202 * @deprecated since 1.18 call SpecialPageFactory method directly
204 static function getRegularPages() {
205 wfDeprecated( __METHOD__, '1.18' );
206 return SpecialPageFactory::getRegularPages();
210 * Return categorised listable special pages which are available
211 * for the current user, but not for everyone
213 * @return array Associative array mapping page's name to its SpecialPage object
214 * @deprecated since 1.18 call SpecialPageFactory method directly
216 static function getRestrictedPages() {
217 wfDeprecated( __METHOD__, '1.18' );
218 return SpecialPageFactory::getRestrictedPages();
222 * Execute a special page path.
223 * The path may contain parameters, e.g. Special:Name/Params
224 * Extracts the special page name and call the execute method, passing the parameters
226 * Returns a title object if the page is redirected, false if there was no such special
227 * page, and true if it was successful.
229 * @param $title Title object
230 * @param $context IContextSource
231 * @param $including Bool output is being captured for use in {{special:whatever}}
232 * @return Bool
233 * @deprecated since 1.18 call SpecialPageFactory method directly
235 public static function executePath( &$title, IContextSource &$context, $including = false ) {
236 wfDeprecated( __METHOD__, '1.18' );
237 return SpecialPageFactory::executePath( $title, $context, $including );
241 * Get the local name for a specified canonical name
243 * @param $name String
244 * @param $subpage Mixed: boolean false, or string
246 * @return String
247 * @deprecated since 1.18 call SpecialPageFactory method directly
249 static function getLocalNameFor( $name, $subpage = false ) {
250 wfDeprecated( __METHOD__, '1.18' );
251 return SpecialPageFactory::getLocalNameFor( $name, $subpage );
255 * Get a localised Title object for a specified special page name
257 * @param $name String
258 * @param string|Bool $subpage subpage string, or false to not use a subpage
259 * @param string $fragment the link fragment (after the "#")
260 * @throws MWException
261 * @return Title object
263 public static function getTitleFor( $name, $subpage = false, $fragment = '' ) {
264 $name = SpecialPageFactory::getLocalNameFor( $name, $subpage );
265 return Title::makeTitle( NS_SPECIAL, $name, $fragment );
269 * Get a localised Title object for a page name with a possibly unvalidated subpage
271 * @param $name String
272 * @param string|Bool $subpage subpage string, or false to not use a subpage
273 * @return Title object or null if the page doesn't exist
275 public static function getSafeTitleFor( $name, $subpage = false ) {
276 $name = SpecialPageFactory::getLocalNameFor( $name, $subpage );
277 if ( $name ) {
278 return Title::makeTitleSafe( NS_SPECIAL, $name );
279 } else {
280 return null;
285 * Get a title for a given alias
287 * @param $alias String
288 * @return Title or null if there is no such alias
289 * @deprecated since 1.18 call SpecialPageFactory method directly
291 static function getTitleForAlias( $alias ) {
292 wfDeprecated( __METHOD__, '1.18' );
293 return SpecialPageFactory::getTitleForAlias( $alias );
297 * Default constructor for special pages
298 * Derivative classes should call this from their constructor
299 * Note that if the user does not have the required level, an error message will
300 * be displayed by the default execute() method, without the global function ever
301 * being called.
303 * If you override execute(), you can recover the default behavior with userCanExecute()
304 * and displayRestrictionError()
306 * @param string $name Name of the special page, as seen in links and URLs
307 * @param string $restriction User right required, e.g. "block" or "delete"
308 * @param bool $listed Whether the page is listed in Special:Specialpages
309 * @param Callback|Bool $function Function called by execute(). By default
310 * it is constructed from $name
311 * @param string $file File which is included by execute(). It is also
312 * constructed from $name by default
313 * @param bool $includable Whether the page can be included in normal pages
315 public function __construct(
316 $name = '', $restriction = '', $listed = true,
317 $function = false, $file = 'default', $includable = false
319 $this->init( $name, $restriction, $listed, $function, $file, $includable );
323 * Do the real work for the constructor, mainly so __call() can intercept
324 * calls to SpecialPage()
325 * @param string $name Name of the special page, as seen in links and URLs
326 * @param string $restriction User right required, e.g. "block" or "delete"
327 * @param bool $listed Whether the page is listed in Special:Specialpages
328 * @param Callback|Bool $function Function called by execute(). By default
329 * it is constructed from $name
330 * @param string $file File which is included by execute(). It is also
331 * constructed from $name by default
332 * @param bool $includable Whether the page can be included in normal pages
334 private function init( $name, $restriction, $listed, $function, $file, $includable ) {
335 $this->mName = $name;
336 $this->mRestriction = $restriction;
337 $this->mListed = $listed;
338 $this->mIncludable = $includable;
339 if ( !$function ) {
340 $this->mFunction = 'wfSpecial' . $name;
341 } else {
342 $this->mFunction = $function;
344 if ( $file === 'default' ) {
345 $this->mFile = __DIR__ . "/specials/Special$name.php";
346 } else {
347 $this->mFile = $file;
352 * Use PHP's magic __call handler to get calls to the old PHP4 constructor
353 * because PHP E_STRICT yells at you for having __construct() and SpecialPage()
355 * @param string $fName Name of called method
356 * @param array $a Arguments to the method
357 * @throws MWException
358 * @deprecated since 1.17, call parent::__construct()
360 public function __call( $fName, $a ) {
361 // Deprecated messages now, remove in 1.19 or 1.20?
362 wfDeprecated( __METHOD__, '1.17' );
364 // Sometimes $fName is SpecialPage, sometimes it's specialpage. <3 PHP
365 if ( strtolower( $fName ) == 'specialpage' ) {
366 $name = isset( $a[0] ) ? $a[0] : '';
367 $restriction = isset( $a[1] ) ? $a[1] : '';
368 $listed = isset( $a[2] ) ? $a[2] : true;
369 $function = isset( $a[3] ) ? $a[3] : false;
370 $file = isset( $a[4] ) ? $a[4] : 'default';
371 $includable = isset( $a[5] ) ? $a[5] : false;
372 $this->init( $name, $restriction, $listed, $function, $file, $includable );
373 } else {
374 $className = get_class( $this );
375 throw new MWException( "Call to undefined method $className::$fName" );
380 * Get the name of this Special Page.
381 * @return String
383 function getName() {
384 return $this->mName;
388 * Get the permission that a user must have to execute this page
389 * @return String
391 function getRestriction() {
392 return $this->mRestriction;
396 * Get the file which will be included by SpecialPage::execute() if your extension is
397 * still stuck in the past and hasn't overridden the execute() method. No modern code
398 * should want or need to know this.
399 * @return String
400 * @deprecated since 1.18
402 function getFile() {
403 wfDeprecated( __METHOD__, '1.18' );
404 return $this->mFile;
407 // @todo FIXME: Decide which syntax to use for this, and stick to it
409 * Whether this special page is listed in Special:SpecialPages
410 * @since r3583 (v1.3)
411 * @return Bool
413 function isListed() {
414 return $this->mListed;
417 * Set whether this page is listed in Special:Specialpages, at run-time
418 * @since r3583 (v1.3)
419 * @param $listed Bool
420 * @return Bool
422 function setListed( $listed ) {
423 return wfSetVar( $this->mListed, $listed );
426 * Get or set whether this special page is listed in Special:SpecialPages
427 * @since r11308 (v1.6)
428 * @param $x Bool
429 * @return Bool
431 function listed( $x = null ) {
432 return wfSetVar( $this->mListed, $x );
436 * Whether it's allowed to transclude the special page via {{Special:Foo/params}}
437 * @return Bool
439 public function isIncludable() {
440 return $this->mIncludable;
444 * These mutators are very evil, as the relevant variables should not mutate. So
445 * don't use them.
446 * @param $x Mixed
447 * @return Mixed
448 * @deprecated since 1.18
450 function name( $x = null ) {
451 wfDeprecated( __METHOD__, '1.18' );
452 return wfSetVar( $this->mName, $x );
456 * These mutators are very evil, as the relevant variables should not mutate. So
457 * don't use them.
458 * @param $x Mixed
459 * @return Mixed
460 * @deprecated since 1.18
462 function restriction( $x = null ) {
463 wfDeprecated( __METHOD__, '1.18' );
464 return wfSetVar( $this->mRestriction, $x );
468 * These mutators are very evil, as the relevant variables should not mutate. So
469 * don't use them.
470 * @param $x Mixed
471 * @return Mixed
472 * @deprecated since 1.18
474 function func( $x = null ) {
475 wfDeprecated( __METHOD__, '1.18' );
476 return wfSetVar( $this->mFunction, $x );
480 * These mutators are very evil, as the relevant variables should not mutate. So
481 * don't use them.
482 * @param $x Mixed
483 * @return Mixed
484 * @deprecated since 1.18
486 function file( $x = null ) {
487 wfDeprecated( __METHOD__, '1.18' );
488 return wfSetVar( $this->mFile, $x );
492 * These mutators are very evil, as the relevant variables should not mutate. So
493 * don't use them.
494 * @param $x Mixed
495 * @return Mixed
496 * @deprecated since 1.18
498 function includable( $x = null ) {
499 wfDeprecated( __METHOD__, '1.18' );
500 return wfSetVar( $this->mIncludable, $x );
504 * Whether the special page is being evaluated via transclusion
505 * @param $x Bool
506 * @return Bool
508 function including( $x = null ) {
509 return wfSetVar( $this->mIncluding, $x );
513 * Get the localised name of the special page
515 function getLocalName() {
516 if ( !isset( $this->mLocalName ) ) {
517 $this->mLocalName = SpecialPageFactory::getLocalNameFor( $this->mName );
519 return $this->mLocalName;
523 * Is this page expensive (for some definition of expensive)?
524 * Expensive pages are disabled or cached in miser mode. Originally used
525 * (and still overridden) by QueryPage and subclasses, moved here so that
526 * Special:SpecialPages can safely call it for all special pages.
528 * @return Boolean
530 public function isExpensive() {
531 return false;
535 * Is this page cached?
536 * Expensive pages are cached or disabled in miser mode.
537 * Used by QueryPage and subclasses, moved here so that
538 * Special:SpecialPages can safely call it for all special pages.
540 * @return Boolean
541 * @since 1.21
543 public function isCached() {
544 return false;
548 * Can be overridden by subclasses with more complicated permissions
549 * schemes.
551 * @return Boolean: should the page be displayed with the restricted-access
552 * pages?
554 public function isRestricted() {
555 // DWIM: If anons can do something, then it is not restricted
556 return $this->mRestriction != '' && !User::groupHasPermission( '*', $this->mRestriction );
560 * Checks if the given user (identified by an object) can execute this
561 * special page (as defined by $mRestriction). Can be overridden by sub-
562 * classes with more complicated permissions schemes.
564 * @param $user User: the user to check
565 * @return Boolean: does the user have permission to view the page?
567 public function userCanExecute( User $user ) {
568 return $user->isAllowed( $this->mRestriction );
572 * Output an error message telling the user what access level they have to have
574 function displayRestrictionError() {
575 throw new PermissionsError( $this->mRestriction );
579 * Checks if userCanExecute, and if not throws a PermissionsError
581 * @since 1.19
583 public function checkPermissions() {
584 if ( !$this->userCanExecute( $this->getUser() ) ) {
585 $this->displayRestrictionError();
590 * If the wiki is currently in readonly mode, throws a ReadOnlyError
592 * @since 1.19
593 * @throws ReadOnlyError
595 public function checkReadOnly() {
596 if ( wfReadOnly() ) {
597 throw new ReadOnlyError;
602 * If the user is not logged in, throws UserNotLoggedIn error.
604 * Default error message includes a link to Special:Userlogin with properly set 'returnto' query
605 * parameter.
607 * @since 1.23
608 * @param string|Message $reasonMsg [optional] Passed on to UserNotLoggedIn constructor. Strings
609 * will be used as message keys. If a string is given, the message will also receive a
610 * formatted login link (generated using the 'loginreqlink' message) as first parameter. If a
611 * Message is given, it will be passed on verbatim.
612 * @param string|Message $titleMsg [optional] Passed on to UserNotLoggedIn constructor. Strings
613 * will be used as message keys.
614 * @throws UserNotLoggedIn
616 public function requireLogin( $reasonMsg = null, $titleMsg = null ) {
617 if ( $this->getUser()->isAnon() ) {
618 // Use default messages if not given or explicit null passed
619 if ( !$reasonMsg ) {
620 $reasonMsg = 'exception-nologin-text-manual';
622 if ( !$titleMsg ) {
623 $titleMsg = 'exception-nologin';
626 // Convert to Messages with current context
627 if ( is_string( $reasonMsg ) ) {
628 $loginreqlink = Linker::linkKnown(
629 SpecialPage::getTitleFor( 'Userlogin' ),
630 $this->msg( 'loginreqlink' )->escaped(),
631 array(),
632 array( 'returnto' => $this->getTitle()->getPrefixedText() )
634 $reasonMsg = $this->msg( $reasonMsg )->rawParams( $loginreqlink );
636 if ( is_string( $titleMsg ) ) {
637 $titleMsg = $this->msg( $titleMsg );
640 throw new UserNotLoggedIn( $reasonMsg, $titleMsg );
645 * Sets headers - this should be called from the execute() method of all derived classes!
647 function setHeaders() {
648 $out = $this->getOutput();
649 $out->setArticleRelated( false );
650 $out->setRobotPolicy( "noindex,nofollow" );
651 $out->setPageTitle( $this->getDescription() );
655 * Entry point.
657 * @since 1.20
659 * @param $subPage string|null
661 final public function run( $subPage ) {
663 * Gets called before @see SpecialPage::execute.
665 * @since 1.20
667 * @param $special SpecialPage
668 * @param $subPage string|null
670 wfRunHooks( 'SpecialPageBeforeExecute', array( $this, $subPage ) );
672 $this->beforeExecute( $subPage );
673 $this->execute( $subPage );
674 $this->afterExecute( $subPage );
677 * Gets called after @see SpecialPage::execute.
679 * @since 1.20
681 * @param $special SpecialPage
682 * @param $subPage string|null
684 wfRunHooks( 'SpecialPageAfterExecute', array( $this, $subPage ) );
688 * Gets called before @see SpecialPage::execute.
690 * @since 1.20
692 * @param $subPage string|null
694 protected function beforeExecute( $subPage ) {
695 // No-op
699 * Gets called after @see SpecialPage::execute.
701 * @since 1.20
703 * @param $subPage string|null
705 protected function afterExecute( $subPage ) {
706 // No-op
710 * Default execute method
711 * Checks user permissions, calls the function given in mFunction
713 * This must be overridden by subclasses; it will be made abstract in a future version
715 * @param $subPage string|null
717 public function execute( $subPage ) {
718 $this->setHeaders();
719 $this->checkPermissions();
721 $func = $this->mFunction;
722 // only load file if the function does not exist
723 if ( !is_callable( $func ) && $this->mFile ) {
724 require_once $this->mFile;
726 $this->outputHeader();
727 call_user_func( $func, $subPage, $this );
731 * Outputs a summary message on top of special pages
732 * Per default the message key is the canonical name of the special page
733 * May be overridden, i.e. by extensions to stick with the naming conventions
734 * for message keys: 'extensionname-xxx'
736 * @param string $summaryMessageKey message key of the summary
738 function outputHeader( $summaryMessageKey = '' ) {
739 global $wgContLang;
741 if ( $summaryMessageKey == '' ) {
742 $msg = $wgContLang->lc( $this->getName() ) . '-summary';
743 } else {
744 $msg = $summaryMessageKey;
746 if ( !$this->msg( $msg )->isDisabled() && !$this->including() ) {
747 $this->getOutput()->wrapWikiMsg(
748 "<div class='mw-specialpage-summary'>\n$1\n</div>", $msg );
754 * Returns the name that goes in the \<h1\> in the special page itself, and
755 * also the name that will be listed in Special:Specialpages
757 * Derived classes can override this, but usually it is easier to keep the
758 * default behavior. Messages can be added at run-time, see
759 * MessageCache.php.
761 * @return String
763 function getDescription() {
764 return $this->msg( strtolower( $this->mName ) )->text();
768 * Get a self-referential title object
770 * @param $subpage String|Bool
771 * @return Title object
773 function getTitle( $subpage = false ) {
774 return self::getTitleFor( $this->mName, $subpage );
778 * Sets the context this SpecialPage is executed in
780 * @param $context IContextSource
781 * @since 1.18
783 public function setContext( $context ) {
784 $this->mContext = $context;
788 * Gets the context this SpecialPage is executed in
790 * @return IContextSource|RequestContext
791 * @since 1.18
793 public function getContext() {
794 if ( $this->mContext instanceof IContextSource ) {
795 return $this->mContext;
796 } else {
797 wfDebug( __METHOD__ . " called and \$mContext is null. " .
798 "Return RequestContext::getMain(); for sanity\n" );
799 return RequestContext::getMain();
804 * Get the WebRequest being used for this instance
806 * @return WebRequest
807 * @since 1.18
809 public function getRequest() {
810 return $this->getContext()->getRequest();
814 * Get the OutputPage being used for this instance
816 * @return OutputPage
817 * @since 1.18
819 public function getOutput() {
820 return $this->getContext()->getOutput();
824 * Shortcut to get the User executing this instance
826 * @return User
827 * @since 1.18
829 public function getUser() {
830 return $this->getContext()->getUser();
834 * Shortcut to get the skin being used for this instance
836 * @return Skin
837 * @since 1.18
839 public function getSkin() {
840 return $this->getContext()->getSkin();
844 * Shortcut to get user's language
846 * @deprecated since 1.19 Use getLanguage instead
847 * @return Language
848 * @since 1.18
850 public function getLang() {
851 wfDeprecated( __METHOD__, '1.19' );
852 return $this->getLanguage();
856 * Shortcut to get user's language
858 * @return Language
859 * @since 1.19
861 public function getLanguage() {
862 return $this->getContext()->getLanguage();
866 * Return the full title, including $par
868 * @return Title
869 * @since 1.18
871 public function getFullTitle() {
872 return $this->getContext()->getTitle();
876 * Wrapper around wfMessage that sets the current context.
878 * @return Message
879 * @see wfMessage
881 public function msg( /* $args */ ) {
882 $message = call_user_func_array(
883 array( $this->getContext(), 'msg' ),
884 func_get_args()
886 // RequestContext passes context to wfMessage, and the language is set from
887 // the context, but setting the language for Message class removes the
888 // interface message status, which breaks for example usernameless gender
889 // invocations. Restore the flag when not including special page in content.
890 if ( $this->including() ) {
891 $message->setInterfaceMessageFlag( false );
893 return $message;
897 * Adds RSS/atom links
899 * @param $params array
901 protected function addFeedLinks( $params ) {
902 global $wgFeedClasses;
904 $feedTemplate = wfScript( 'api' );
906 foreach ( $wgFeedClasses as $format => $class ) {
907 $theseParams = $params + array( 'feedformat' => $format );
908 $url = wfAppendQuery( $feedTemplate, $theseParams );
909 $this->getOutput()->addFeedLink( $format, $url );
914 * Get the group that the special page belongs in on Special:SpecialPage
915 * Use this method, instead of getGroupName to allow customization
916 * of the group name from the wiki side
918 * @return string Group of this special page
919 * @since 1.21
921 public function getFinalGroupName() {
922 global $wgSpecialPageGroups;
923 $name = $this->getName();
925 // Allow overbidding the group from the wiki side
926 $msg = $this->msg( 'specialpages-specialpagegroup-' . strtolower( $name ) )->inContentLanguage();
927 if ( !$msg->isBlank() ) {
928 $group = $msg->text();
929 } else {
930 // Than use the group from this object
931 $group = $this->getGroupName();
933 // Group '-' is used as default to have the chance to determine,
934 // if the special pages overrides this method,
935 // if not overridden, $wgSpecialPageGroups is checked for b/c
936 if ( $group === '-' && isset( $wgSpecialPageGroups[$name] ) ) {
937 $group = $wgSpecialPageGroups[$name];
941 // never give '-' back, change to 'other'
942 if ( $group === '-' ) {
943 $group = 'other';
946 return $group;
950 * Under which header this special page is listed in Special:SpecialPages
951 * See messages 'specialpages-group-*' for valid names
952 * This method defaults to group 'other'
954 * @return string
955 * @since 1.21
957 protected function getGroupName() {
958 // '-' used here to determine, if this group is overridden or has a hardcoded 'other'
959 // Needed for b/c in getFinalGroupName
960 return '-';