Update docs for return and exception info
[lhc/web/wiklou.git] / includes / parser / Parser.php
index bcf030f..e1a2dd0 100644 (file)
@@ -163,7 +163,8 @@ class Parser {
        var $mLinkHolders;
 
        var $mLinkID;
-       var $mIncludeSizes, $mPPNodeCount, $mHighestExpansionDepth, $mDefaultSort;
+       var $mIncludeSizes, $mPPNodeCount, $mGeneratedPPNodeCount, $mHighestExpansionDepth;
+       var $mDefaultSort;
        var $mTplExpandCache; # empty-frame expansion cache
        var $mTplRedirCache, $mTplDomCache, $mHeadings, $mDoubleUnderscores;
        var $mExpensiveFunctionCount; # number of expensive parser function calls
@@ -199,6 +200,13 @@ class Parser {
         */
        var $mUniqPrefix;
 
+       /**
+        * @var Array with the language name of each language link (i.e. the
+        * interwiki prefix) in the key, value arbitrary. Used to avoid sending
+        * duplicate language links to the ParserOutput.
+        */
+       var $mLangLinkLanguages;
+
        /**
         * Constructor
         *
@@ -281,6 +289,7 @@ class Parser {
                        $this->mRevisionId = $this->mRevisionUser = null;
                $this->mVarCache = array();
                $this->mUser = null;
+               $this->mLangLinkLanguages = array();
 
                /**
                 * Prefix for temporary replacement strings for the multipass parser.
@@ -306,6 +315,7 @@ class Parser {
                        'arg' => 0,
                );
                $this->mPPNodeCount = 0;
+               $this->mGeneratedPPNodeCount = 0;
                $this->mHighestExpansionDepth = 0;
                $this->mDefaultSort = false;
                $this->mHeadings = array();
@@ -339,7 +349,7 @@ class Parser {
                 * to internalParse() which does all the real work.
                 */
 
-               global $wgUseTidy, $wgAlwaysUseTidy, $wgDisableLangConversion, $wgDisableTitleConversion;
+               global $wgUseTidy, $wgAlwaysUseTidy;
                $fname = __METHOD__.'-' . wfGetCaller();
                wfProfileIn( __METHOD__ );
                wfProfileIn( $fname );
@@ -392,9 +402,8 @@ class Parser {
                 * c) It's a conversion table
                 * d) it is an interface message (which is in the user language)
                 */
-               if ( !( $wgDisableLangConversion
-                               || isset( $this->mDoubleUnderscores['nocontentconvert'] )
-                               || $this->mTitle->isConversionTable() ) )
+               if ( !( $options->getDisableContentConversion()
+                               || isset( $this->mDoubleUnderscores['nocontentconvert'] ) ) )
                {
                        # Run convert unconditionally in 1.18-compatible mode
                        global $wgBug34832TransitionalRollback;
@@ -413,8 +422,7 @@ class Parser {
                 * {{DISPLAYTITLE:...}} is present. DISPLAYTITLE takes precedence over
                 * automatic link conversion.
                 */
-               if ( !( $wgDisableLangConversion
-                               || $wgDisableTitleConversion
+               if ( !( $options->getDisableTitleConversion()
                                || isset( $this->mDoubleUnderscores['nocontentconvert'] )
                                || isset( $this->mDoubleUnderscores['notitleconvert'] )
                                || $this->mOutput->getDisplayTitle() !== false ) )
@@ -482,13 +490,20 @@ class Parser {
                        $PFreport = "Expensive parser function count: {$this->mExpensiveFunctionCount}/{$this->mOptions->getExpensiveParserFunctionLimit()}\n";
                        $limitReport =
                                "NewPP limit report\n" .
-                               "Preprocessor node count: {$this->mPPNodeCount}/{$this->mOptions->getMaxPPNodeCount()}\n" .
+                               "Preprocessor visited node count: {$this->mPPNodeCount}/{$this->mOptions->getMaxPPNodeCount()}\n" .
+                               "Preprocessor generated node count: " .
+                                       "{$this->mGeneratedPPNodeCount}/{$this->mOptions->getMaxGeneratedPPNodeCount()}\n" .
                                "Post-expand include size: {$this->mIncludeSizes['post-expand']}/$max bytes\n" .
                                "Template argument size: {$this->mIncludeSizes['arg']}/$max bytes\n".
                                "Highest expansion depth: {$this->mHighestExpansionDepth}/{$this->mOptions->getMaxPPExpandDepth()}\n".
                                $PFreport;
                        wfRunHooks( 'ParserLimitReport', array( $this, &$limitReport ) );
                        $text .= "\n<!-- \n$limitReport-->\n";
+
+                       if ( $this->mGeneratedPPNodeCount > $this->mOptions->getMaxGeneratedPPNodeCount() / 10 ) {
+                               wfDebugLog( 'generated-pp-node-count', $this->mGeneratedPPNodeCount . ' ' .
+                                       $this->mTitle->getPrefixedDBkey() );
+                       }
                }
                $this->mOutput->setText( $text );
 
@@ -738,6 +753,7 @@ class Parser {
         *
         * @since 1.19
         *
+        * @throws MWException
         * @return Language|null
         */
        public function getTargetLanguage() {
@@ -1516,6 +1532,7 @@ class Parser {
         *
         * @param $text string
         *
+        * @throws MWException
         * @return string
         */
        function replaceExternalLinks( $text ) {
@@ -1719,6 +1736,8 @@ class Parser {
 
        /**
         * Process [[ ]] wikilinks (RIL)
+        * @param $s
+        * @throws MWException
         * @return LinkHolderArray
         *
         * @private
@@ -1946,8 +1965,14 @@ class Parser {
                                # Interwikis
                                wfProfileIn( __METHOD__."-interwiki" );
                                if ( $iw && $this->mOptions->getInterwikiMagic() && $nottalk && Language::fetchLanguageName( $iw, null, 'mw' ) ) {
-                                       // FIXME: the above check prevents links to sites with identifiers that are not language codes
-                                       $this->mOutput->addLanguageLink( $nt->getFullText() );
+                                       // XXX: the above check prevents links to sites with identifiers that are not language codes
+
+                                       # Bug 24502: filter duplicates
+                                       if ( !isset( $this->mLangLinkLanguages[$iw] ) ) {
+                                               $this->mLangLinkLanguages[$iw] = true;
+                                               $this->mOutput->addLanguageLink( $nt->getFullText() );
+                                       }
+
                                        $s = rtrim( $s . $prefix );
                                        $s .= trim( $trail, "\n" ) == '' ? '': $prefix . $trail;
                                        wfProfileOut( __METHOD__."-interwiki" );
@@ -2430,6 +2455,7 @@ class Parser {
         * @param $str String the string to split
         * @param &$before String set to everything before the ':'
         * @param &$after String set to everything after the ':'
+        * @throws MWException
         * @return String the position of the ':', or false if none found
         */
        function findColonNoLinks( $str, &$before, &$after ) {
@@ -2594,8 +2620,9 @@ class Parser {
         * @private
         *
         * @param $index integer
-        * @param $frame PPFrame
+        * @param bool|\PPFrame $frame
         *
+        * @throws MWException
         * @return string
         */
        function getVariableValue( $index, $frame = false ) {
@@ -3104,6 +3131,7 @@ class Parser {
         *  $piece['parts']: the parameter array
         *  $piece['lineStart']: whether the brace was at the start of a line
         * @param $frame PPFrame The current frame, contains template arguments
+        * @throws MWException
         * @return String: the text of the template
         * @private
         */
@@ -3700,8 +3728,13 @@ class Parser {
                        return $obj->tc_contents;
                }
 
-               $text = Http::get( $url );
-               if ( !$text ) {
+               $req = MWHttpRequest::factory( $url );
+               $status = $req->execute(); // Status object
+               if ( $status->isOK() ) {
+                       $text = $req->getContent();
+               } elseif ( $req->getStatus() != 200 ) { // Though we failed to fetch the content, this status is useless.
+                       return wfMessage( 'scarytranscludefailed-httpstatus', $url, $req->getStatus() /* HTTP status */ )->inContentLanguage()->text();
+               } else {
                        return wfMessage( 'scarytranscludefailed', $url )->inContentLanguage()->text();
                }
 
@@ -3776,6 +3809,7 @@ class Parser {
         *     noClose    Original text did not have a close tag
         * @param $frame PPFrame
         *
+        * @throws MWException
         * @return string
         */
        function extensionSubstitution( $params, $frame ) {
@@ -4145,10 +4179,16 @@ class Parser {
                        $safeHeadline = $this->mStripState->unstripBoth( $safeHeadline );
 
                        # Strip out HTML (first regex removes any tag not allowed)
-                       # Allowed tags are <sup> and <sub> (bug 8393), <i> (bug 26375) and <b> (r105284)
-                       # We strip any parameter from accepted tags (second regex)
+                       # Allowed tags are:
+                       # * <sup> and <sub> (bug 8393)
+                       # * <i> (bug 26375)
+                       # * <b> (r105284)
+                       # * <span dir="rtl"> and <span dir="ltr"> (bug 35167)
+                       #
+                       # We strip any parameter from accepted tags (second regex), except dir="rtl|ltr" from <span>,
+                       # to allow setting directionality in toc items.
                        $tocline = preg_replace(
-                               array( '#<(?!/?(sup|sub|i|b)(?: [^>]*)?>).*?'.'>#', '#<(/?(sup|sub|i|b))(?: .*?)?'.'>#' ),
+                               array( '#<(?!/?(span|sup|sub|i|b)(?: [^>]*)?>).*?'.'>#', '#<(/?(?:span(?: dir="(?:rtl|ltr)")?|sup|sub|i|b))(?: .*?)?'.'>#' ),
                                array( '',                          '<$1>' ),
                                $safeHeadline
                        );
@@ -4667,6 +4707,7 @@ class Parser {
         *
         * @param $tag Mixed: the tag to use, e.g. 'hook' for "<hook>"
         * @param $callback Mixed: the callback function (and object) to use for the tag
+        * @throws MWException
         * @return Mixed|null The old value of the mTagHooks array associated with the hook
         */
        public function setHook( $tag, $callback ) {
@@ -4697,6 +4738,7 @@ class Parser {
         *
         * @param $tag Mixed: the tag to use, e.g. 'hook' for "<hook>"
         * @param $callback Mixed: the callback function (and object) to use for the tag
+        * @throws MWException
         * @return Mixed|null The old value of the mTagHooks array associated with the hook
         */
        function setTransparentTagHook( $tag, $callback ) {
@@ -4759,6 +4801,7 @@ class Parser {
         *     Please read the documentation in includes/parser/Preprocessor.php for more information
         *     about the methods available in PPFrame and PPNode.
         *
+        * @throws MWException
         * @return string|callback The old callback function for this name, if any
         */
        public function setFunctionHook( $id, $callback, $flags = 0 ) {
@@ -4806,6 +4849,10 @@ class Parser {
         * Create a tag function, e.g. "<test>some stuff</test>".
         * Unlike tag hooks, tag functions are parsed at preprocessor level.
         * Unlike parser functions, their content is not preprocessed.
+        * @param $tag
+        * @param $callback
+        * @param $flags
+        * @throws MWException
         * @return null
         */
        function setFunctionTagHook( $tag, $callback, $flags ) {
@@ -5769,6 +5816,7 @@ class Parser {
         * check whether it is still valid, by calling isValidHalfParsedText().
         *
         * @param $data array Serialized data
+        * @throws MWException
         * @return String
         */
        function unserializeHalfParsedText( $data ) {