Merge "registration: Ignore attributes that start with @"
[lhc/web/wiklou.git] / includes / Title.php
index 638da08..2d0cfda 100644 (file)
@@ -614,28 +614,13 @@ class Title {
         * Note that this doesn't pick up many things that could be wrong with titles, but that
         * replacing this regex with something valid will make many titles valid.
         *
-        * @todo move this into MediaWikiTitleCodec
+        * @deprecated since 1.25, use MediaWikiTitleCodec::getTitleInvalidRegex() instead
         *
         * @return string Regex string
         */
        static function getTitleInvalidRegex() {
-               static $rxTc = false;
-               if ( !$rxTc ) {
-                       # Matching titles will be held as illegal.
-                       $rxTc = '/' .
-                               # Any character not allowed is forbidden...
-                               '[^' . self::legalChars() . ']' .
-                               # URL percent encoding sequences interfere with the ability
-                               # to round-trip titles -- you can't link to them consistently.
-                               '|%[0-9A-Fa-f]{2}' .
-                               # XML/HTML character references produce similar issues.
-                               '|&[A-Za-z0-9\x80-\xff]+;' .
-                               '|&#[0-9]+;' .
-                               '|&#x[0-9A-Fa-f]+;' .
-                               '/S';
-               }
-
-               return $rxTc;
+               wfDeprecated( __METHOD__, '1.25' );
+               return MediaWikiTitleCodec::getTitleInvalidRegex();
        }
 
        /**
@@ -747,7 +732,7 @@ class Title {
         * @param string $title The DB key form the title
         * @param string $fragment The link fragment (after the "#")
         * @param string $interwiki The interwiki prefix
-        * @param boolean $canoncialNamespace If true, use the canonical name for
+        * @param bool $canoncialNamespace If true, use the canonical name for
         *   $ns instead of the localized version.
         * @return string The prefixed form of the title
         */
@@ -1044,7 +1029,6 @@ class Title {
         * Is this in a namespace that allows actual pages?
         *
         * @return bool
-        * @internal note -- uses hardcoded namespace index instead of constants
         */
        public function canExist() {
                return $this->mNamespace >= NS_MAIN;
@@ -1180,7 +1164,7 @@ class Title {
                }
 
                $result = true;
-               wfRunHooks( 'TitleIsMovable', array( $this, &$result ) );
+               Hooks::run( 'TitleIsMovable', array( $this, &$result ) );
                return $result;
        }
 
@@ -1252,7 +1236,7 @@ class Title {
                #   It's called here again to make sure hook functions can force this
                #   method to return true even outside the MediaWiki namespace.
 
-               wfRunHooks( 'TitleIsCssOrJsPage', array( $this, &$isCssOrJsPage ), '1.25' );
+               Hooks::run( 'TitleIsCssOrJsPage', array( $this, &$isCssOrJsPage ), '1.25' );
 
                return $isCssOrJsPage;
        }
@@ -1335,6 +1319,25 @@ class Title {
                return Title::makeTitle( $subjectNS, $this->getDBkey() );
        }
 
+       /**
+        * Get the other title for this page, if this is a subject page
+        * get the talk page, if it is a subject page get the talk page
+        *
+        * @since 1.25
+        * @throws MWException
+        * @return Title
+        */
+       public function getOtherPage() {
+               if ( $this->isSpecialPage() ) {
+                       throw new MWException( 'Special pages cannot have other pages' );
+               }
+               if ( $this->isTalkPage() ) {
+                       return $this->getSubjectPage();
+               } else {
+                       return $this->getTalkPage();
+               }
+       }
+
        /**
         * Get the default namespace index, for when there is no namespace
         *
@@ -1659,7 +1662,7 @@ class Title {
                # Finally, add the fragment.
                $url .= $this->getFragmentForURL();
 
-               wfRunHooks( 'GetFullURL', array( &$this, &$url, $query ) );
+               Hooks::run( 'GetFullURL', array( &$this, &$url, $query ) );
                return $url;
        }
 
@@ -1705,7 +1708,7 @@ class Title {
                        $dbkey = wfUrlencode( $this->getPrefixedDBkey() );
                        if ( $query == '' ) {
                                $url = str_replace( '$1', $dbkey, $wgArticlePath );
-                               wfRunHooks( 'GetLocalURL::Article', array( &$this, &$url ) );
+                               Hooks::run( 'GetLocalURL::Article', array( &$this, &$url ) );
                        } else {
                                global $wgVariantArticlePath, $wgActionPaths, $wgContLang;
                                $url = false;
@@ -1750,7 +1753,7 @@ class Title {
                                }
                        }
 
-                       wfRunHooks( 'GetLocalURL::Internal', array( &$this, &$url, $query ) );
+                       Hooks::run( 'GetLocalURL::Internal', array( &$this, &$url, $query ) );
 
                        // @todo FIXME: This causes breakage in various places when we
                        // actually expected a local URL and end up with dupe prefixes.
@@ -1758,7 +1761,7 @@ class Title {
                                $url = $wgServer . $url;
                        }
                }
-               wfRunHooks( 'GetLocalURL', array( &$this, &$url, $query ) );
+               Hooks::run( 'GetLocalURL', array( &$this, &$url, $query ) );
                return $url;
        }
 
@@ -1779,7 +1782,6 @@ class Title {
         * @return string The URL
         */
        public function getLinkURL( $query = '', $query2 = false, $proto = PROTO_RELATIVE ) {
-               wfProfileIn( __METHOD__ );
                if ( $this->isExternal() || $proto !== PROTO_RELATIVE ) {
                        $ret = $this->getFullURL( $query, $query2, $proto );
                } elseif ( $this->getPrefixedText() === '' && $this->hasFragment() ) {
@@ -1787,7 +1789,6 @@ class Title {
                } else {
                        $ret = $this->getLocalURL( $query, $query2 ) . $this->getFragmentForURL();
                }
-               wfProfileOut( __METHOD__ );
                return $ret;
        }
 
@@ -1808,7 +1809,7 @@ class Title {
                $query = self::fixUrlQueryArgs( $query, $query2 );
                $server = $wgInternalServer !== false ? $wgInternalServer : $wgServer;
                $url = wfExpandUrl( $server . $this->getLocalURL( $query ), PROTO_HTTP );
-               wfRunHooks( 'GetInternalURL', array( &$this, &$url, $query ) );
+               Hooks::run( 'GetInternalURL', array( &$this, &$url, $query ) );
                return $url;
        }
 
@@ -1826,7 +1827,7 @@ class Title {
        public function getCanonicalURL( $query = '', $query2 = false ) {
                $query = self::fixUrlQueryArgs( $query, $query2 );
                $url = wfExpandUrl( $this->getLocalURL( $query ) . $this->getFragmentForURL(), PROTO_CANONICAL );
-               wfRunHooks( 'GetCanonicalURL', array( &$this, &$url, $query ) );
+               Hooks::run( 'GetCanonicalURL', array( &$this, &$url, $query ) );
                return $url;
        }
 
@@ -1945,7 +1946,7 @@ class Title {
        private function checkQuickPermissions( $action, $user, $errors,
                $doExpensiveQueries, $short
        ) {
-               if ( !wfRunHooks( 'TitleQuickPermissions',
+               if ( !Hooks::run( 'TitleQuickPermissions',
                        array( $this, $user, $action, &$errors, $doExpensiveQueries, $short ) )
                ) {
                        return $errors;
@@ -2045,18 +2046,18 @@ class Title {
        private function checkPermissionHooks( $action, $user, $errors, $doExpensiveQueries, $short ) {
                // Use getUserPermissionsErrors instead
                $result = '';
-               if ( !wfRunHooks( 'userCan', array( &$this, &$user, $action, &$result ) ) ) {
+               if ( !Hooks::run( 'userCan', array( &$this, &$user, $action, &$result ) ) ) {
                        return $result ? array() : array( array( 'badaccess-group0' ) );
                }
                // Check getUserPermissionsErrors hook
-               if ( !wfRunHooks( 'getUserPermissionsErrors', array( &$this, &$user, $action, &$result ) ) ) {
+               if ( !Hooks::run( 'getUserPermissionsErrors', array( &$this, &$user, $action, &$result ) ) ) {
                        $errors = $this->resultToError( $errors, $result );
                }
                // Check getUserPermissionsErrorsExpensive hook
                if (
                        $doExpensiveQueries
                        && !( $short && count( $errors ) > 0 )
-                       && !wfRunHooks( 'getUserPermissionsErrorsExpensive', array( &$this, &$user, $action, &$result ) )
+                       && !Hooks::run( 'getUserPermissionsErrorsExpensive', array( &$this, &$user, $action, &$result ) )
                ) {
                        $errors = $this->resultToError( $errors, $result );
                }
@@ -2389,7 +2390,7 @@ class Title {
 
                if ( !$whitelisted ) {
                        # If the title is not whitelisted, give extensions a chance to do so...
-                       wfRunHooks( 'TitleReadWhitelist', array( $this, $user, &$whitelisted ) );
+                       Hooks::run( 'TitleReadWhitelist', array( $this, $user, &$whitelisted ) );
                        if ( !$whitelisted ) {
                                $errors[] = $this->missingPermissionError( $action, $short );
                        }
@@ -2441,7 +2442,6 @@ class Title {
        protected function getUserPermissionsErrorsInternal( $action, $user,
                $doExpensiveQueries = true, $short = false
        ) {
-               wfProfileIn( __METHOD__ );
 
                # Read has special handling
                if ( $action == 'read' ) {
@@ -2482,7 +2482,6 @@ class Title {
                        $errors = $this->$method( $action, $user, $errors, $doExpensiveQueries, $short );
                }
 
-               wfProfileOut( __METHOD__ );
                return $errors;
        }
 
@@ -2523,7 +2522,7 @@ class Title {
                        $types = array_diff( $types, array( 'upload' ) );
                }
 
-               wfRunHooks( 'TitleGetRestrictionTypes', array( $this, &$types ) );
+               Hooks::run( 'TitleGetRestrictionTypes', array( $this, &$types ) );
 
                wfDebug( __METHOD__ . ': applicable restrictions to [[' .
                        $this->getPrefixedText() . ']] are {' . implode( ',', $types ) . "}\n" );
@@ -2718,8 +2717,6 @@ class Title {
                        return array( $this->mHasCascadingRestrictions, $pagerestrictions );
                }
 
-               wfProfileIn( __METHOD__ );
-
                $dbr = wfGetDB( DB_SLAVE );
 
                if ( $this->getNamespace() == NS_FILE ) {
@@ -2794,7 +2791,6 @@ class Title {
                        $this->mHasCascadingRestrictions = $sources;
                }
 
-               wfProfileOut( __METHOD__ );
                return array( $sources, $pagerestrictions );
        }
 
@@ -2813,8 +2809,10 @@ class Title {
         * Accessor/initialisation for mRestrictions
         *
         * @param string $action Action that permission needs to be checked for
-        * @return array Restriction levels needed to take the action. All levels
-        *     are required.
+        * @return array Restriction levels needed to take the action. All levels are
+        *     required. Note that restriction levels are normally user rights, but 'sysop'
+        *     and 'autoconfirmed' are also allowed for backwards compatibility. These should
+        *     be mapped to 'editprotected' and 'editsemiprotected' respectively.
         */
        public function getRestrictions( $action ) {
                if ( !$this->mRestrictionsLoaded ) {
@@ -3576,7 +3574,7 @@ class Title {
                        $urls[] = $this->getInternalUrl( 'action=raw&ctype=text/css' );
                }
 
-               wfRunHooks( 'TitleSquidURLs', array( $this, &$urls ) );
+               Hooks::run( 'TitleSquidURLs', array( $this, &$urls ) );
                return $urls;
        }
 
@@ -4041,7 +4039,7 @@ class Title {
                if ( $this->mIsBigDeletion === null ) {
                        $dbr = wfGetDB( DB_SLAVE );
 
-                       $innerQuery = $dbr->selectSQLText(
+                       $revCount = $dbr->selectRowCount(
                                'revision',
                                '1',
                                array( 'rev_page' => $this->getArticleID() ),
@@ -4049,13 +4047,6 @@ class Title {
                                array( 'LIMIT' => $wgDeleteRevisionsLimit + 1 )
                        );
 
-                       $revCount = $dbr->query(
-                               'SELECT COUNT(*) FROM (' . $innerQuery . ') AS innerQuery',
-                               __METHOD__
-                       );
-                       $revCount = $revCount->fetchRow();
-                       $revCount = $revCount['COUNT(*)'];
-
                        $this->mIsBigDeletion = $revCount > $wgDeleteRevisionsLimit;
                }
 
@@ -4107,12 +4098,11 @@ class Title {
                        'rev_timestamp < ' . $dbr->addQuotes( $dbr->timestamp( $new->getTimestamp() ) )
                );
                if ( $max !== null ) {
-                       $res = $dbr->select( 'revision', '1',
+                       return $dbr->selectRowCount( 'revision', '1',
                                $conds,
                                __METHOD__,
                                array( 'LIMIT' => $max + 1 ) // extra to detect truncation
                        );
-                       return $res->numRows();
                } else {
                        return (int)$dbr->selectField( 'revision', 'count(*)', $conds, __METHOD__ );
                }
@@ -4163,17 +4153,19 @@ class Title {
                }
                // No DB query needed if $old and $new are the same or successive revisions:
                if ( $old->getId() === $new->getId() ) {
-                       return ( $old_cmp === '>' && $new_cmp === '<' ) ? array() : array( $old->getRawUserText() );
+                       return ( $old_cmp === '>' && $new_cmp === '<' ) ?
+                               array() :
+                               array( $old->getUserText( Revision::RAW ) );
                } elseif ( $old->getId() === $new->getParentId() ) {
                        if ( $old_cmp === '>=' && $new_cmp === '<=' ) {
-                               $authors[] = $old->getRawUserText();
-                               if ( $old->getRawUserText() != $new->getRawUserText() ) {
-                                       $authors[] = $new->getRawUserText();
+                               $authors[] = $old->getUserText( Revision::RAW );
+                               if ( $old->getUserText( Revision::RAW ) != $new->getUserText( Revision::RAW ) ) {
+                                       $authors[] = $new->getUserText( Revision::RAW );
                                }
                        } elseif ( $old_cmp === '>=' ) {
-                               $authors[] = $old->getRawUserText();
+                               $authors[] = $old->getUserText( Revision::RAW );
                        } elseif ( $new_cmp === '<=' ) {
-                               $authors[] = $new->getRawUserText();
+                               $authors[] = $new->getUserText( Revision::RAW );
                        }
                        return $authors;
                }
@@ -4247,7 +4239,7 @@ class Title {
         */
        public function exists() {
                $exists = $this->getArticleID() != 0;
-               wfRunHooks( 'TitleExists', array( $this, &$exists ) );
+               Hooks::run( 'TitleExists', array( $this, &$exists ) );
                return $exists;
        }
 
@@ -4280,7 +4272,7 @@ class Title {
                 * @param Title $title
                 * @param bool|null $isKnown
                 */
-               wfRunHooks( 'TitleIsAlwaysKnown', array( $this, &$isKnown ) );
+               Hooks::run( 'TitleIsAlwaysKnown', array( $this, &$isKnown ) );
 
                if ( !is_null( $isKnown ) ) {
                        return $isKnown;
@@ -4603,7 +4595,7 @@ class Title {
                // on the Title object passed in, and should probably
                // tell the users to run updateCollations.php --force
                // in order to re-sort existing category relations.
-               wfRunHooks( 'GetDefaultSortkey', array( $this, &$unprefixed ) );
+               Hooks::run( 'GetDefaultSortkey', array( $this, &$unprefixed ) );
                if ( $prefix !== '' ) {
                        # Separate with a line feed, so the unprefixed part is only used as
                        # a tiebreaker when two pages have the exact same prefix.
@@ -4625,16 +4617,13 @@ class Title {
         */
        public function getPageLanguage() {
                global $wgLang, $wgLanguageCode;
-               wfProfileIn( __METHOD__ );
                if ( $this->isSpecialPage() ) {
                        // special pages are in the user language
-                       wfProfileOut( __METHOD__ );
                        return $wgLang;
                }
 
                // Checking if DB language is set
                if ( $this->mDbPageLanguage ) {
-                       wfProfileOut( __METHOD__ );
                        return wfGetLangObj( $this->mDbPageLanguage );
                }
 
@@ -4652,7 +4641,6 @@ class Title {
                        $langObj = wfGetLangObj( $this->mPageLanguage[0] );
                }
 
-               wfProfileOut( __METHOD__ );
                return $langObj;
        }
 
@@ -4703,7 +4691,9 @@ class Title {
                $editnotice_ns = 'editnotice-' . $this->getNamespace();
                $editnotice_ns_message = wfMessage( $editnotice_ns );
                if ( $editnotice_ns_message->exists() ) {
-                       $notices[$editnotice_ns] = $editnotice_ns_message->parseAsBlock();
+                       $notices[$editnotice_ns] = '<div class="mw-editnotice mw-editnotice-namespace ' .
+                               Sanitizer::escapeClass( "mw-$editnotice_ns" ) . '">' .
+                               $editnotice_ns_message->parseAsBlock() . '</div>';
                }
                if ( MWNamespace::hasSubpages( $this->getNamespace() ) ) {
                        $parts = explode( '/', $this->getDBkey() );
@@ -4712,7 +4702,9 @@ class Title {
                                $editnotice_base .= '-' . array_shift( $parts );
                                $editnotice_base_msg = wfMessage( $editnotice_base );
                                if ( $editnotice_base_msg->exists() ) {
-                                       $notices[$editnotice_base] = $editnotice_base_msg->parseAsBlock();
+                                       $notices[$editnotice_base] = '<div class="mw-editnotice mw-editnotice-base ' .
+                                               Sanitizer::escapeClass( "mw-$editnotice_base" ) . '">' .
+                                               $editnotice_base_msg->parseAsBlock() . '</div>';
                                }
                        }
                } else {
@@ -4720,11 +4712,13 @@ class Title {
                        $editnoticeText = $editnotice_ns . '-' . str_replace( '/', '-', $this->getDBkey() );
                        $editnoticeMsg = wfMessage( $editnoticeText );
                        if ( $editnoticeMsg->exists() ) {
-                               $notices[$editnoticeText] = $editnoticeMsg->parseAsBlock();
+                               $notices[$editnoticeText] = '<div class="mw-editnotice mw-editnotice-page ' .
+                                       Sanitizer::escapeClass( "mw-$editnoticeText" ) . '">' .
+                                       $editnoticeMsg->parseAsBlock() . '</div>';
                        }
                }
 
-               wfRunHooks( 'TitleGetEditNotices', array( $this, $oldid, &$notices ) );
+               Hooks::run( 'TitleGetEditNotices', array( $this, $oldid, &$notices ) );
                return $notices;
        }
 }