Merge "tests: Complete test coverage of HtmlArmor"
[lhc/web/wiklou.git] / includes / parser / Parser.php
index 7b2dc67..078de3c 100644 (file)
@@ -3114,10 +3114,29 @@ class Parser {
                                        throw $ex;
                                }
 
-                               # The interface for parser functions allows for extracting
-                               # flags into the local scope. Extract any forwarded flags
-                               # here.
-                               extract( $result );
+                               // Extract any forwarded flags
+                               if ( isset( $result['found'] ) ) {
+                                       $found = $result['found'];
+                               }
+                               if ( array_key_exists( 'text', $result ) ) {
+                                       // a string or null
+                                       $text = $result['text'];
+                               }
+                               if ( isset( $result['nowiki'] ) ) {
+                                       $nowiki = $result['nowiki'];
+                               }
+                               if ( isset( $result['isHTML'] ) ) {
+                                       $isHTML = $result['isHTML'];
+                               }
+                               if ( isset( $result['forceRawInterwiki'] ) ) {
+                                       $forceRawInterwiki = $result['forceRawInterwiki'];
+                               }
+                               if ( isset( $result['isChildObj'] ) ) {
+                                       $isChildObj = $result['isChildObj'];
+                               }
+                               if ( isset( $result['isLocalObj'] ) ) {
+                                       $isLocalObj = $result['isLocalObj'];
+                               }
                        }
                }
 
@@ -3498,13 +3517,7 @@ class Parser {
         * @return Revision|bool False if missing
         */
        public static function statelessFetchRevision( Title $title, $parser = false ) {
-               $pageId = $title->getArticleID();
-               $revId = $title->getLatestRevID();
-
-               $rev = Revision::newKnownCurrent( wfGetDB( DB_REPLICA ), $pageId, $revId );
-               if ( $rev ) {
-                       $rev->setTitle( $title );
-               }
+               $rev = Revision::newKnownCurrent( wfGetDB( DB_REPLICA ), $title );
 
                return $rev;
        }
@@ -3868,11 +3881,12 @@ class Parser {
                        }
 
                        if ( is_array( $output ) ) {
-                               # Extract flags to local scope (to override $markerType)
+                               // Extract flags
                                $flags = $output;
                                $output = $flags[0];
-                               unset( $flags[0] );
-                               extract( $flags );
+                               if ( isset( $flags['markerType'] ) ) {
+                                       $markerType = $flags['markerType'];
+                               }
                        }
                } else {
                        if ( is_null( $attrText ) ) {
@@ -3950,7 +3964,7 @@ class Parser {
                        $this->mForceTocPosition = true;
 
                        # Set a placeholder. At the end we'll fill it in with the TOC.
-                       $text = $mw->replace( '<!--MWTOC-->', $text, 1 );
+                       $text = $mw->replace( '<!--MWTOC\'"-->', $text, 1 );
 
                        # Only keep the first one.
                        $text = $mw->replace( '', $text );
@@ -4213,7 +4227,7 @@ class Parser {
                        # Decode HTML entities
                        $safeHeadline = Sanitizer::decodeCharReferences( $safeHeadline );
 
-                       $safeHeadline = $this->normalizeSectionName( $safeHeadline );
+                       $safeHeadline = self::normalizeSectionName( $safeHeadline );
 
                        $fallbackHeadline = Sanitizer::escapeIdForAttribute( $safeHeadline, Sanitizer::ID_FALLBACK );
                        $linkAnchor = Sanitizer::escapeIdForLink( $safeHeadline );
@@ -4396,7 +4410,7 @@ class Parser {
                $full .= implode( '', $sections );
 
                if ( $this->mForceTocPosition ) {
-                       return str_replace( '<!--MWTOC-->', $toc, $full );
+                       return str_replace( '<!--MWTOC\'"-->', $toc, $full );
                } else {
                        return $full;
                }
@@ -5028,40 +5042,40 @@ class Parser {
                                                $paramName = $paramMap[$magicName];
 
                                                switch ( $paramName ) {
-                                               case 'gallery-internal-alt':
-                                                       $alt = $this->stripAltText( $match, false );
-                                                       break;
-                                               case 'gallery-internal-link':
-                                                       $linkValue = strip_tags( $this->replaceLinkHoldersText( $match ) );
-                                                       $chars = self::EXT_LINK_URL_CLASS;
-                                                       $addr = self::EXT_LINK_ADDR;
-                                                       $prots = $this->mUrlProtocols;
-                                                       // check to see if link matches an absolute url, if not then it must be a wiki link.
-                                                       if ( preg_match( '/^-{R|(.*)}-$/', $linkValue ) ) {
-                                                               // Result of LanguageConverter::markNoConversion
-                                                               // invoked on an external link.
-                                                               $linkValue = substr( $linkValue, 4, -2 );
-                                                       }
-                                                       if ( preg_match( "/^($prots)$addr$chars*$/u", $linkValue ) ) {
-                                                               $link = $linkValue;
-                                                               $this->mOutput->addExternalLink( $link );
-                                                       } else {
-                                                               $localLinkTitle = Title::newFromText( $linkValue );
-                                                               if ( $localLinkTitle !== null ) {
-                                                                       $this->mOutput->addLink( $localLinkTitle );
-                                                                       $link = $localLinkTitle->getLinkURL();
+                                                       case 'gallery-internal-alt':
+                                                               $alt = $this->stripAltText( $match, false );
+                                                               break;
+                                                       case 'gallery-internal-link':
+                                                               $linkValue = strip_tags( $this->replaceLinkHoldersText( $match ) );
+                                                               $chars = self::EXT_LINK_URL_CLASS;
+                                                               $addr = self::EXT_LINK_ADDR;
+                                                               $prots = $this->mUrlProtocols;
+                                                               // check to see if link matches an absolute url, if not then it must be a wiki link.
+                                                               if ( preg_match( '/^-{R|(.*)}-$/', $linkValue ) ) {
+                                                                       // Result of LanguageConverter::markNoConversion
+                                                                       // invoked on an external link.
+                                                                       $linkValue = substr( $linkValue, 4, -2 );
+                                                               }
+                                                               if ( preg_match( "/^($prots)$addr$chars*$/u", $linkValue ) ) {
+                                                                       $link = $linkValue;
+                                                                       $this->mOutput->addExternalLink( $link );
+                                                               } else {
+                                                                       $localLinkTitle = Title::newFromText( $linkValue );
+                                                                       if ( $localLinkTitle !== null ) {
+                                                                               $this->mOutput->addLink( $localLinkTitle );
+                                                                               $link = $localLinkTitle->getLinkURL();
+                                                                       }
+                                                               }
+                                                               break;
+                                                       default:
+                                                               // Must be a handler specific parameter.
+                                                               if ( $handler->validateParam( $paramName, $match ) ) {
+                                                                       $handlerOptions[$paramName] = $match;
+                                                               } else {
+                                                                       // Guess not, consider it as caption.
+                                                                       wfDebug( "$parameterMatch failed parameter validation\n" );
+                                                                       $label = '|' . $parameterMatch;
                                                                }
-                                                       }
-                                                       break;
-                                               default:
-                                                       // Must be a handler specific parameter.
-                                                       if ( $handler->validateParam( $paramName, $match ) ) {
-                                                               $handlerOptions[$paramName] = $match;
-                                                       } else {
-                                                               // Guess not, consider it as caption.
-                                                               wfDebug( "$parameterMatch failed parameter validation\n" );
-                                                               $label = '|' . $parameterMatch;
-                                                       }
                                                }
 
                                        } else {
@@ -5223,52 +5237,52 @@ class Parser {
                                        } else {
                                                # Validate internal parameters
                                                switch ( $paramName ) {
-                                               case 'manualthumb':
-                                               case 'alt':
-                                               case 'class':
-                                                       # @todo FIXME: Possibly check validity here for
-                                                       # manualthumb? downstream behavior seems odd with
-                                                       # missing manual thumbs.
-                                                       $validated = true;
-                                                       $value = $this->stripAltText( $value, $holders );
-                                                       break;
-                                               case 'link':
-                                                       $chars = self::EXT_LINK_URL_CLASS;
-                                                       $addr = self::EXT_LINK_ADDR;
-                                                       $prots = $this->mUrlProtocols;
-                                                       if ( $value === '' ) {
-                                                               $paramName = 'no-link';
-                                                               $value = true;
+                                                       case 'manualthumb':
+                                                       case 'alt':
+                                                       case 'class':
+                                                               # @todo FIXME: Possibly check validity here for
+                                                               # manualthumb? downstream behavior seems odd with
+                                                               # missing manual thumbs.
                                                                $validated = true;
-                                                       } elseif ( preg_match( "/^((?i)$prots)/", $value ) ) {
-                                                               if ( preg_match( "/^((?i)$prots)$addr$chars*$/u", $value, $m ) ) {
-                                                                       $paramName = 'link-url';
-                                                                       $this->mOutput->addExternalLink( $value );
-                                                                       if ( $this->mOptions->getExternalLinkTarget() ) {
-                                                                               $params[$type]['link-target'] = $this->mOptions->getExternalLinkTarget();
-                                                                       }
-                                                                       $validated = true;
-                                                               }
-                                                       } else {
-                                                               $linkTitle = Title::newFromText( $value );
-                                                               if ( $linkTitle ) {
-                                                                       $paramName = 'link-title';
-                                                                       $value = $linkTitle;
-                                                                       $this->mOutput->addLink( $linkTitle );
+                                                               $value = $this->stripAltText( $value, $holders );
+                                                               break;
+                                                       case 'link':
+                                                               $chars = self::EXT_LINK_URL_CLASS;
+                                                               $addr = self::EXT_LINK_ADDR;
+                                                               $prots = $this->mUrlProtocols;
+                                                               if ( $value === '' ) {
+                                                                       $paramName = 'no-link';
+                                                                       $value = true;
                                                                        $validated = true;
+                                                               } elseif ( preg_match( "/^((?i)$prots)/", $value ) ) {
+                                                                       if ( preg_match( "/^((?i)$prots)$addr$chars*$/u", $value, $m ) ) {
+                                                                               $paramName = 'link-url';
+                                                                               $this->mOutput->addExternalLink( $value );
+                                                                               if ( $this->mOptions->getExternalLinkTarget() ) {
+                                                                                       $params[$type]['link-target'] = $this->mOptions->getExternalLinkTarget();
+                                                                               }
+                                                                               $validated = true;
+                                                                       }
+                                                               } else {
+                                                                       $linkTitle = Title::newFromText( $value );
+                                                                       if ( $linkTitle ) {
+                                                                               $paramName = 'link-title';
+                                                                               $value = $linkTitle;
+                                                                               $this->mOutput->addLink( $linkTitle );
+                                                                               $validated = true;
+                                                                       }
                                                                }
-                                                       }
-                                                       break;
-                                               case 'frameless':
-                                               case 'framed':
-                                               case 'thumbnail':
-                                                       // use first appearing option, discard others.
-                                                       $validated = !$seenformat;
-                                                       $seenformat = true;
-                                                       break;
-                                               default:
-                                                       # Most other things appear to be empty or numeric...
-                                                       $validated = ( $value === false || is_numeric( trim( $value ) ) );
+                                                               break;
+                                                       case 'frameless':
+                                                       case 'framed':
+                                                       case 'thumbnail':
+                                                               // use first appearing option, discard others.
+                                                               $validated = !$seenformat;
+                                                               $seenformat = true;
+                                                               break;
+                                                       default:
+                                                               # Most other things appear to be empty or numeric...
+                                                               $validated = ( $value === false || is_numeric( trim( $value ) ) );
                                                }
                                        }
 
@@ -5762,23 +5776,42 @@ class Parser {
                return $this->mDefaultSort;
        }
 
+       private static function getSectionNameFromStrippedText( $text ) {
+               $text = Sanitizer::normalizeSectionNameWhitespace( $text );
+               $text = Sanitizer::decodeCharReferences( $text );
+               $text = self::normalizeSectionName( $text );
+               return $text;
+       }
+
+       private static function makeAnchor( $sectionName ) {
+               return '#' . Sanitizer::escapeIdForLink( $sectionName );
+       }
+
+       private static function makeLegacyAnchor( $sectionName ) {
+               global $wgFragmentMode;
+               if ( isset( $wgFragmentMode[1] ) && $wgFragmentMode[1] === 'legacy' ) {
+                       // ForAttribute() and ForLink() are the same for legacy encoding
+                       $id = Sanitizer::escapeIdForAttribute( $text, Sanitizer::ID_FALLBACK );
+               } else {
+                       $id = Sanitizer::escapeIdForLink( $text );
+               }
+
+               return "#$id";
+       }
+
        /**
         * Try to guess the section anchor name based on a wikitext fragment
         * presumably extracted from a heading, for example "Header" from
         * "== Header ==".
         *
         * @param string $text
-        *
-        * @return string
+        * @return string Anchor (starting with '#')
         */
        public function guessSectionNameFromWikiText( $text ) {
                # Strip out wikitext links(they break the anchor)
                $text = $this->stripSectionName( $text );
-               $text = Sanitizer::normalizeSectionNameWhitespace( $text );
-               $text = Sanitizer::decodeCharReferences( $text );
-               $text = $this->normalizeSectionName( $text );
-
-               return '#' . Sanitizer::escapeIdForLink( $text );
+               $sectionName = self::getSectionNameFromStrippedText( $text );
+               return self::makeAnchor( $sectionName );
        }
 
        /**
@@ -5788,25 +5821,23 @@ class Parser {
         * than UTF-8, resulting in breakage.
         *
         * @param string $text The section name
-        * @return string An anchor
+        * @return string Anchor (starting with '#')
         */
        public function guessLegacySectionNameFromWikiText( $text ) {
-               global $wgFragmentMode;
-
                # Strip out wikitext links(they break the anchor)
                $text = $this->stripSectionName( $text );
-               $text = Sanitizer::normalizeSectionNameWhitespace( $text );
-               $text = Sanitizer::decodeCharReferences( $text );
-               $text = $this->normalizeSectionName( $text );
-
-               if ( isset( $wgFragmentMode[1] ) && $wgFragmentMode[1] === 'legacy' ) {
-                       // ForAttribute() and ForLink() are the same for legacy encoding
-                       $id = Sanitizer::escapeIdForAttribute( $text, Sanitizer::ID_FALLBACK );
-               } else {
-                       $id = Sanitizer::escapeIdForLink( $text );
-               }
+               $sectionName = self::getSectionNameFromStrippedText( $text );
+               return self::makeLegacyAnchor( $sectionName );
+       }
 
-               return "#$id";
+       /**
+        * Like guessSectionNameFromWikiText(), but takes already-stripped text as input.
+        * @param string $text Section name (plain text)
+        * @return string Anchor (starting with '#')
+        */
+       public static function guessSectionNameFromStrippedText( $text ) {
+               $sectionName = self::getSectionNameFromStrippedText( $text );
+               return self::makeAnchor( $sectionName );
        }
 
        /**
@@ -5815,7 +5846,7 @@ class Parser {
         * @param string $text
         * @return string
         */
-       private function normalizeSectionName( $text ) {
+       private static function normalizeSectionName( $text ) {
                # T90902: ensure the same normalization is applied for IDs as to links
                $titleParser = MediaWikiServices::getInstance()->getTitleParser();
                try {