Merge "Allow fragments in link= parameter in <gallery> tags."
[lhc/web/wiklou.git] / includes / parser / Parser.php
index d2a20df..61fd9cc 100644 (file)
@@ -167,7 +167,6 @@ class Parser {
        var $mLinkID;
        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
        var $mShowToc, $mForceTocPosition;
@@ -321,7 +320,7 @@ class Parser {
                $this->mStripState = new StripState( $this->mUniqPrefix );
 
                # Clear these on every parse, bug 4549
-               $this->mTplExpandCache = $this->mTplRedirCache = $this->mTplDomCache = array();
+               $this->mTplRedirCache = $this->mTplDomCache = array();
 
                $this->mShowToc = true;
                $this->mForceTocPosition = false;
@@ -618,13 +617,15 @@ class Parser {
        /**
         * Expand templates and variables in the text, producing valid, static wikitext.
         * Also removes comments.
+        * Do not call this function recursively.
         * @param string $text
         * @param Title $title
         * @param ParserOptions $options
         * @param int|null $revid
+        * @param bool|PPFrame $frame
         * @return mixed|string
         */
-       function preprocess( $text, Title $title = null, ParserOptions $options, $revid = null ) {
+       function preprocess( $text, Title $title = null, ParserOptions $options, $revid = null, $frame = false ) {
                wfProfileIn( __METHOD__ );
                $magicScopeVariable = $this->lock();
                $this->startParse( $title, $options, self::OT_PREPROCESS, true );
@@ -633,7 +634,7 @@ class Parser {
                }
                wfRunHooks( 'ParserBeforeStrip', array( &$this, &$text, &$this->mStripState ) );
                wfRunHooks( 'ParserAfterStrip', array( &$this, &$text, &$this->mStripState ) );
-               $text = $this->replaceVariables( $text );
+               $text = $this->replaceVariables( $text, $frame );
                $text = $this->mStripState->unstripBoth( $text );
                wfProfileOut( __METHOD__ );
                return $text;
@@ -1875,6 +1876,7 @@ class Parser {
         * @private
         */
        function replaceInternalLinks2( &$s ) {
+               global $wgExtraInterlanguageLinkPrefixes;
                wfProfileIn( __METHOD__ );
 
                wfProfileIn( __METHOD__ . '-setup' );
@@ -2095,11 +2097,12 @@ class Parser {
                        if ( $noforce ) {
                                # Interwikis
                                wfProfileIn( __METHOD__ . "-interwiki" );
-                               if ( $iw && $this->mOptions->getInterwikiMagic()
-                                       && $nottalk && Language::fetchLanguageName( $iw, null, 'mw' )
+                               if (
+                                       $iw && $this->mOptions->getInterwikiMagic() && $nottalk && (
+                                               Language::fetchLanguageName( $iw, null, 'mw' ) ||
+                                               in_array( $iw, $wgExtraInterlanguageLinkPrefixes )
+                                       )
                                ) {
-                                       // 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;
@@ -2327,13 +2330,13 @@ class Parser {
                $result = $this->closeParagraph();
 
                if ( '*' === $char ) {
-                       $result .= "<ul>\n<li>";
+                       $result .= "<ul><li>";
                } elseif ( '#' === $char ) {
-                       $result .= "<ol>\n<li>";
+                       $result .= "<ol><li>";
                } elseif ( ':' === $char ) {
-                       $result .= "<dl>\n<dd>";
+                       $result .= "<dl><dd>";
                } elseif ( ';' === $char ) {
-                       $result .= "<dl>\n<dt>";
+                       $result .= "<dl><dt>";
                        $this->mDTopen = true;
                } else {
                        $result = '<!-- ERR 1 -->';
@@ -2377,20 +2380,20 @@ class Parser {
         */
        function closeList( $char ) {
                if ( '*' === $char ) {
-                       $text = "</li>\n</ul>";
+                       $text = "</li></ul>";
                } elseif ( '#' === $char ) {
-                       $text = "</li>\n</ol>";
+                       $text = "</li></ol>";
                } elseif ( ':' === $char ) {
                        if ( $this->mDTopen ) {
                                $this->mDTopen = false;
-                               $text = "</dt>\n</dl>";
+                               $text = "</dt></dl>";
                        } else {
-                               $text = "</dd>\n</dl>";
+                               $text = "</dd></dl>";
                        }
                } else {
                        return '<!-- ERR 3 -->';
                }
-               return $text . "\n";
+               return $text;
        }
        /**#@-*/
 
@@ -2488,6 +2491,9 @@ class Parser {
                                }
 
                                # Open prefixes where appropriate.
+                               if (  $lastPrefix && $prefixLength > $commonPrefixLength ) {
+                                       $output .= "\n";
+                               }
                                while ( $prefixLength > $commonPrefixLength ) {
                                        $char = substr( $prefix, $commonPrefixLength, 1 );
                                        $output .= $this->openList( $char );
@@ -2501,6 +2507,9 @@ class Parser {
                                        }
                                        ++$commonPrefixLength;
                                }
+                               if ( !$prefixLength && $lastPrefix ) {
+                                       $output .= "\n";
+                               }
                                $lastPrefix = $prefix2;
                        }
 
@@ -2582,12 +2591,18 @@ class Parser {
                                $this->mInPre = false;
                        }
                        if ( $paragraphStack === false ) {
-                               $output .= $t . "\n";
+                               $output .= $t;
+                               if ( $prefixLength === 0 ) {
+                                       $output .= "\n";
+                               }
                        }
                }
                while ( $prefixLength ) {
                        $output .= $this->closeList( $prefix2[$prefixLength - 1] );
                        --$prefixLength;
+                       if ( !$prefixLength ) {
+                               $output .= "\n";
+                       }
                }
                if ( $this->mLastSection != '' ) {
                        $output .= '</' . $this->mLastSection . '>';
@@ -3562,12 +3577,7 @@ class Parser {
                                $text = $newFrame->expand( $text, PPFrame::RECOVER_ORIG );
                        } elseif ( $titleText !== false && $newFrame->isEmpty() ) {
                                # Expansion is eligible for the empty-frame cache
-                               if ( isset( $this->mTplExpandCache[$titleText] ) ) {
-                                       $text = $this->mTplExpandCache[$titleText];
-                               } else {
-                                       $text = $newFrame->expand( $text );
-                                       $this->mTplExpandCache[$titleText] = $text;
-                               }
+                               $text = $newFrame->cachedExpand( $titleText, $text );
                        } else {
                                # Uncached expansion
                                $text = $newFrame->expand( $text );
@@ -5329,7 +5339,7 @@ class Parser {
                                                        } else {
                                                                $localLinkTitle = Title::newFromText( $linkValue );
                                                                if ( $localLinkTitle !== null ) {
-                                                                       $link = $localLinkTitle->getLocalURL();
+                                                                       $link = $localLinkTitle->getLinkURL();
                                                                }
                                                        }
                                                        break;
@@ -5727,7 +5737,7 @@ class Parser {
         * External callers should use the getSection and replaceSection methods.
         *
         * @param string $text Page wikitext
-        * @param string $section A section identifier string of the form:
+        * @param string|number $sectionId A section identifier string of the form:
         *   "<flag1> - <flag2> - ... - <section number>"
         *
         * Currently the only recognised flag is "T", which means the target section number
@@ -5749,7 +5759,7 @@ class Parser {
         * @return string For "get", the extracted section text.
         *   for "replace", the whole page with the section replaced.
         */
-       private function extractSections( $text, $section, $mode, $newText = '' ) {
+       private function extractSections( $text, $sectionId, $mode, $newText = '' ) {
                global $wgTitle; # not generally used but removes an ugly failure mode
 
                $magicScopeVariable = $this->lock();
@@ -5759,7 +5769,7 @@ class Parser {
 
                # Process section extraction flags
                $flags = 0;
-               $sectionParts = explode( '-', $section );
+               $sectionParts = explode( '-', $sectionId );
                $sectionIndex = array_pop( $sectionParts );
                foreach ( $sectionParts as $part ) {
                        if ( $part === 'T' ) {
@@ -5868,12 +5878,14 @@ class Parser {
         * If a section contains subsections, these are also returned.
         *
         * @param string $text Text to look in
-        * @param string $section Section identifier
-        * @param string $deftext Default to return if section is not found
+        * @param string|number $sectionId Section identifier as a number or string
+        * (e.g. 0, 1 or 'T-1').
+        * @param string $defaultText Default to return if section is not found
+        *
         * @return string Text of the requested section
         */
-       public function getSection( $text, $section, $deftext = '' ) {
-               return $this->extractSections( $text, $section, "get", $deftext );
+       public function getSection( $text, $sectionId, $defaultText = '' ) {
+               return $this->extractSections( $text, $sectionId, 'get', $defaultText );
        }
 
        /**
@@ -5881,13 +5893,15 @@ class Parser {
         * specified by $section has been replaced with $text. If the target
         * section does not exist, $oldtext is returned unchanged.
         *
-        * @param string $oldtext Former text of the article
-        * @param int $section Section identifier
-        * @param string $text Replacing text
+        * @param string $oldText Former text of the article
+        * @param string|number $sectionId Section identifier as a number or string
+        * (e.g. 0, 1 or 'T-1').
+        * @param string $newText Replacing text
+        *
         * @return string Modified text
         */
-       public function replaceSection( $oldtext, $section, $text ) {
-               return $this->extractSections( $oldtext, $section, "replace", $text );
+       public function replaceSection( $oldText, $sectionId, $newText ) {
+               return $this->extractSections( $oldText, $sectionId, 'replace', $newText );
        }
 
        /**