X-Git-Url: http://git.heureux-cyclage.org/?p=lhc%2Fweb%2Fwiklou.git;a=blobdiff_plain;f=includes%2Fparser%2FParser.php;h=c5dd811c8a78fd42a1802a224003b036a5013d37;hp=ec1628f8d0f54b592aa441dc6bef42ad00e7b9c7;hb=0974c515c10806f37d9e8e388740ad3a83bd8f5b;hpb=60882bb6b07aa0a9cbf0f8a2224cc94e2575dc11 diff --git a/includes/parser/Parser.php b/includes/parser/Parser.php index ec1628f8d0..c5dd811c8a 100644 --- a/includes/parser/Parser.php +++ b/includes/parser/Parser.php @@ -162,7 +162,7 @@ class Parser { */ public $mFirstCall = true; - # Initialised by initialiseVariables() + # Initialised by initializeVariables() /** * @var MagicWordArray @@ -228,7 +228,11 @@ class Parser { public $mOptions; /** - * @var Title + * Since 1.34, leaving `mTitle` uninitialized or setting `mTitle` to + * `null` is deprecated. + * + * @internal + * @var Title|null */ public $mTitle; # Title context, used for self-link rendering and similar things public $mOutputType; # Output type, one of the OT_xxx constants @@ -465,7 +469,7 @@ class Parser { CoreParserFunctions::register( $this ); CoreTagHooks::register( $this ); - $this->initialiseVariables(); + $this->initializeVariables(); // Avoid PHP 7.1 warning from passing $this by reference $parser = $this; @@ -906,11 +910,11 @@ class Parser { /** * Set the context title * - * @param Title $t + * @param Title|null $t */ - public function setTitle( $t ) { + public function setTitle( Title $t = null ) { if ( !$t ) { - $t = Title::newFromText( 'NO TITLE' ); + $t = Title::makeTitle( NS_SPECIAL, 'Badtitle/Parser' ); } if ( $t->hasFragment() ) { @@ -924,9 +928,14 @@ class Parser { /** * Accessor for the Title object * + * Since 1.34, leaving `mTitle` uninitialized as `null` is deprecated. + * * @return Title|null */ - public function getTitle() { + public function getTitle() : ?Title { + if ( $this->mTitle === null ) { + wfDeprecated( 'Parser title should never be null', '1.34' ); + } return $this->mTitle; } @@ -934,9 +943,9 @@ class Parser { * Accessor/mutator for the Title object * * @param Title|null $x Title object or null to just get the current one - * @return Title + * @return Title|null */ - public function Title( $x = null ) { + public function Title( Title $x = null ) : ?Title { return wfSetVar( $this->mTitle, $x ); } @@ -1224,13 +1233,25 @@ class Parser { } /** - * parse the wiki syntax used to render tables + * Parse the wiki syntax used to render tables. * * @private * @param string $text * @return string + * @deprecated since 1.34; should not be used outside parser class. */ public function doTableStuff( $text ) { + wfDeprecated( __METHOD__, '1.34' ); + return $this->handleTables( $text ); + } + + /** + * Parse the wiki syntax used to render tables. + * + * @param string $text + * @return string + */ + private function handleTables( $text ) { $lines = StringUtils::explode( "\n", $text ); $out = ''; $td_history = []; # Is currently a td tag open? @@ -1482,23 +1503,23 @@ class Parser { # properly; putting them before other transformations should keep # exciting things like link expansions from showing up in surprising # places. - $text = $this->doTableStuff( $text ); + $text = $this->handleTables( $text ); $text = preg_replace( '/(^|\n)-----*/', '\\1
', $text ); - $text = $this->doDoubleUnderscore( $text ); + $text = $this->handleDoubleUnderscore( $text ); - $text = $this->doHeadings( $text ); - $text = $this->replaceInternalLinks( $text ); - $text = $this->doAllQuotes( $text ); - $text = $this->replaceExternalLinks( $text ); + $text = $this->handleHeadings( $text ); + $text = $this->handleInternalLinks( $text ); + $text = $this->handleAllQuotes( $text ); + $text = $this->handleExternalLinks( $text ); - # replaceInternalLinks may sometimes leave behind - # absolute URLs, which have to be masked to hide them from replaceExternalLinks + # handleInternalLinks may sometimes leave behind + # absolute URLs, which have to be masked to hide them from handleExternalLinks $text = str_replace( self::MARKER_PREFIX . 'NOPARSE', '', $text ); - $text = $this->doMagicLinks( $text ); - $text = $this->formatHeadings( $text, $origText, $isMain ); + $text = $this->handleMagicLinks( $text ); + $text = $this->finalizeHeadings( $text, $origText, $isMain ); return $text; } @@ -1604,12 +1625,26 @@ class Parser { * * DML * @private + * @param string $text + * @return string + * @deprecated since 1.34; should not be used outside parser class. + */ + public function doMagicLinks( $text ) { + wfDeprecated( __METHOD__, '1.34' ); + return $this->handleMagicLinks( $text ); + } + + /** + * Replace special strings like "ISBN xxx" and "RFC xxx" with + * magic external links. + * + * DML * * @param string $text * * @return string */ - public function doMagicLinks( $text ) { + private function handleMagicLinks( $text ) { $prots = wfUrlProtocolsWithoutProtRel(); $urlChar = self::EXT_LINK_URL_CLASS; $addr = self::EXT_LINK_ADDR; @@ -1779,15 +1814,25 @@ class Parser { } /** - * Parse headers and return html + * Parse headers and return html. * * @private - * * @param string $text - * * @return string + * @deprecated since 1.34; should not be used outside parser class. */ public function doHeadings( $text ) { + wfDeprecated( __METHOD__, '1.34' ); + return $this->handleHeadings( $text ); + } + + /** + * Parse headers and return html + * + * @param string $text + * @return string + */ + private function handleHeadings( $text ) { for ( $i = 6; $i >= 1; --$i ) { $h = str_repeat( '=', $i ); // Trim non-newline whitespace from headings @@ -1804,8 +1849,21 @@ class Parser { * @param string $text * * @return string The altered text + * @deprecated since 1.34; should not be used outside parser class. */ public function doAllQuotes( $text ) { + wfDeprecated( __METHOD__, '1.34' ); + return $this->handleAllQuotes( $text ); + } + + /** + * Replace single quotes with HTML markup + * + * @param string $text + * + * @return string The altered text + */ + private function handleAllQuotes( $text ) { $outtext = ''; $lines = StringUtils::explode( "\n", $text ); foreach ( $lines as $line ) { @@ -1821,6 +1879,7 @@ class Parser { * @param string $text * * @return string + * @internal */ public function doQuotes( $text ) { $arr = preg_split( "/(''+)/", $text, -1, PREG_SPLIT_DELIM_CAPTURE ); @@ -2009,6 +2068,21 @@ class Parser { * @return string */ public function replaceExternalLinks( $text ) { + wfDeprecated( __METHOD__, '1.34' ); + return $this->handleExternalLinks( $text ); + } + + /** + * Replace external links (REL) + * + * Note: this is all very hackish and the order of execution matters a lot. + * Make sure to run tests/parser/parserTests.php if you change this code. + * + * @param string $text + * @throws MWException + * @return string + */ + private function handleExternalLinks( $text ) { $bits = preg_split( $this->mExtLinkBracketedRegex, $text, -1, PREG_SPLIT_DELIM_CAPTURE ); // @phan-suppress-next-line PhanTypeComparisonFromArray See phan issue #3161 if ( $bits === false ) { @@ -2082,6 +2156,7 @@ class Parser { * Get the rel attribute for a particular external link. * * @since 1.21 + * @internal * @param string|bool $url Optional URL, to extract the domain from for rel => * nofollow if appropriate * @param LinkTarget|null $title Optional LinkTarget, for wgNoFollowNsExceptions lookups @@ -2104,6 +2179,7 @@ class Parser { * (depending on configuration, namespace, and the URL's domain) and/or a * target attribute (depending on configuration). * + * @internal * @param string $url URL to extract the domain from for rel => * nofollow if appropriate * @return array Associative array of HTML attributes @@ -2135,6 +2211,7 @@ class Parser { * This generally follows the syntax defined in RFC 3986, with special * consideration for HTTP query strings. * + * @internal * @param string $url * @return string */ @@ -2272,26 +2349,51 @@ class Parser { /** * Process [[ ]] wikilinks * - * @param string $s + * @param string $text * * @return string Processed text * * @private + * @deprecated since 1.34; should not be used outside parser class. */ - public function replaceInternalLinks( $s ) { - $this->mLinkHolders->merge( $this->replaceInternalLinks2( $s ) ); - return $s; + public function replaceInternalLinks( $text ) { + wfDeprecated( __METHOD__, '1.34' ); + return $this->handleInternalLinks( $text ); + } + + /** + * Process [[ ]] wikilinks + * + * @param string $text + * + * @return string Processed text + */ + private function handleInternalLinks( $text ) { + $this->mLinkHolders->merge( $this->handleInternalLinks2( $text ) ); + return $text; } /** * Process [[ ]] wikilinks (RIL) - * @param string &$s + * @param string &$text * @throws MWException * @return LinkHolderArray * * @private + * @deprecated since 1.34; should not be used outside parser class. + */ + public function replaceInternalLinks2( &$text ) { + wfDeprecated( __METHOD__, '1.34' ); + return $this->handleInternalLinks2( $text ); + } + + /** + * Process [[ ]] wikilinks (RIL) + * @param string &$s + * @throws MWException + * @return LinkHolderArray */ - public function replaceInternalLinks2( &$s ) { + private function handleInternalLinks2( &$s ) { static $tc = false, $e1, $e1_img; # the % is needed to support urlencoded titles as well if ( !$tc ) { @@ -2334,7 +2436,10 @@ class Parser { $prefix = ''; } - $useSubpages = $this->areSubpagesAllowed(); + # Some namespaces don't allow subpages + $useSubpages = $this->nsInfo->hasSubpages( + $this->mTitle->getNamespace() + ); # Loop for each link for ( ; $line !== false && $line !== null; $a->next(), $line = $a->current() ) { @@ -2373,7 +2478,7 @@ class Parser { && substr( $m[3], 0, 1 ) === ']' && strpos( $text, '[' ) !== false ) { - $text .= ']'; # so that replaceExternalLinks($text) works later + $text .= ']'; # so that handleExternalLinks($text) works later $m[3] = substr( $m[3], 1 ); } # fix up urlencoded title texts @@ -2407,7 +2512,9 @@ class Parser { # Make subpage if necessary if ( $useSubpages ) { - $link = $this->maybeDoSubpageLink( $origLink, $text ); + $link = Linker::normalizeSubpageLink( + $this->mTitle, $origLink, $text + ); } else { $link = $origLink; } @@ -2459,7 +2566,7 @@ class Parser { if ( !$found ) { # we couldn't find the end of this imageLink, so output it raw # but don't ignore what might be perfectly normal links in the text we've examined - $holders->merge( $this->replaceInternalLinks2( $text ) ); + $holders->merge( $this->handleInternalLinks2( $text ) ); $s .= "{$prefix}[[$link|$text"; # note: no $trail, because without an end, there *is* no trail continue; @@ -2520,10 +2627,10 @@ class Parser { # recursively parse links inside the image caption # actually, this will parse them in any other parameters, too, # but it might be hard to fix that, and it doesn't matter ATM - $text = $this->replaceExternalLinks( $text ); - $holders->merge( $this->replaceInternalLinks2( $text ) ); + $text = $this->handleExternalLinks( $text ); + $holders->merge( $this->handleInternalLinks2( $text ) ); } - # cloak any absolute URLs inside the image markup, so replaceExternalLinks() won't touch them + # cloak any absolute URLs inside the image markup, so handleExternalLinks() won't touch them $s .= $prefix . $this->armorLinks( $this->makeImage( $nt, $text, $holders ) ) . $trail; continue; @@ -2566,7 +2673,7 @@ class Parser { [ $this, $nt, &$options, &$descQuery ] ); # Fetch and register the file (file title may be different via hooks) list( $file, $nt ) = $this->fetchFileAndTitle( $nt, $options ); - # Cloak with NOPARSE to avoid replacement in replaceExternalLinks + # Cloak with NOPARSE to avoid replacement in handleExternalLinks $s .= $prefix . $this->armorLinks( Linker::makeMediaLinkFile( $nt, $file, $text ) ) . $trail; continue; @@ -2632,9 +2739,11 @@ class Parser { /** * Return true if subpage links should be expanded on this page. * @return bool + * @deprecated since 1.34; should not be used outside parser class. */ public function areSubpagesAllowed() { # Some namespaces don't allow subpages + wfDeprecated( __METHOD__, '1.34' ); return $this->nsInfo->hasSubpages( $this->mTitle->getNamespace() ); } @@ -2645,8 +2754,10 @@ class Parser { * @param string &$text The link text, modified as necessary * @return string The full name of the link * @private + * @deprecated since 1.34; should not be used outside parser class. */ public function maybeDoSubpageLink( $target, &$text ) { + wfDeprecated( __METHOD__, '1.34' ); return Linker::normalizeSubpageLink( $this->mTitle, $target, $text ); } @@ -2672,8 +2783,25 @@ class Parser { * * @throws MWException * @return string + * @deprecated since 1.34; should not be used outside parser class. */ public function getVariableValue( $index, $frame = false ) { + wfDeprecated( __METHOD__, '1.34' ); + return $this->expandMagicVariable( $index, $frame ); + } + + /** + * Return value of a magic variable (like PAGENAME) + * + * @param string $index Magic variable identifier as mapped in MagicWordFactory::$mVariableIDs + * @param bool|PPFrame $frame + * + * @throws MWException + * @return string + */ + private function expandMagicVariable( $index, $frame = false ) { + // XXX This function should be moved out of Parser class for + // reuse by Parsoid/etc. if ( is_null( $this->mTitle ) ) { // If no title set, bad things are going to happen // later. Title should always be set since this @@ -3056,8 +3184,18 @@ class Parser { * initialise the magic variables (like CURRENTMONTHNAME) and substitution modifiers * * @private + * @deprecated since 1.34; should not be used outside parser class. */ public function initialiseVariables() { + wfDeprecated( __METHOD__, '1.34' ); + $this->initializeVariables(); + } + + /** + * Initialize the magic variables (like CURRENTMONTHNAME) and + * substitution modifiers. + */ + private function initializeVariables() { $variableIDs = $this->magicWordFactory->getVariableIDs(); $substIDs = $this->magicWordFactory->getSubstIDs(); @@ -3232,6 +3370,7 @@ class Parser { * @param PPFrame $frame The current frame, contains template arguments * @throws Exception * @return string|array The text of the template + * @internal */ public function braceSubstitution( $piece, $frame ) { // Flags @@ -3298,7 +3437,7 @@ class Parser { if ( !$found && $args->getLength() == 0 ) { $id = $this->mVariables->matchStartToEnd( $part1 ); if ( $id !== false ) { - $text = $this->getVariableValue( $id, $frame ); + $text = $this->expandMagicVariable( $id, $frame ); if ( $this->magicWordFactory->getCacheTTL( $id ) > -1 ) { $this->mOutput->updateCacheExpiry( $this->magicWordFactory->getCacheTTL( $id ) ); @@ -3374,7 +3513,9 @@ class Parser { $ns = NS_TEMPLATE; # Split the title into page and subpage $subpage = ''; - $relative = $this->maybeDoSubpageLink( $part1, $subpage ); + $relative = Linker::normalizeSubpageLink( + $this->mTitle, $part1, $subpage + ); if ( $part1 !== $relative ) { $part1 = $relative; $ns = $this->mTitle->getNamespace(); @@ -4008,7 +4149,7 @@ class Parser { /** * Triple brace replacement -- used for template arguments - * @private + * @internal * * @param array $piece * @param PPFrame $frame @@ -4066,6 +4207,7 @@ class Parser { * * @throws MWException * @return string + * @internal */ public function extensionSubstitution( $params, $frame ) { static $errorStr = ''; @@ -4193,10 +4335,22 @@ class Parser { * Fills $this->mDoubleUnderscores, returns the modified text * * @param string $text - * * @return string + * @deprecated since 1.34; should not be used outside parser class. */ public function doDoubleUnderscore( $text ) { + wfDeprecated( __METHOD__, '1.34' ); + return $this->handleDoubleUnderscore( $text ); + } + + /** + * Strip double-underscore items like __NOGALLERY__ and __NOTOC__ + * Fills $this->mDoubleUnderscores, returns the modified text + * + * @param string $text + * @return string + */ + private function handleDoubleUnderscore( $text ) { # The position of __TOC__ needs to be recorded $mw = $this->magicWordFactory->get( 'toc' ); if ( $mw->match( $text ) ) { @@ -4268,8 +4422,29 @@ class Parser { * @param bool $isMain * @return mixed|string * @private + * @deprecated since 1.34; should not be used outside parser class. */ public function formatHeadings( $text, $origText, $isMain = true ) { + wfDeprecated( __METHOD__, '1.34' ); + return $this->finalizeHeadings( $text, $origText, $isMain ); + } + + /** + * This function accomplishes several tasks: + * 1) Auto-number headings if that option is enabled + * 2) Add an [edit] link to sections for users who have enabled the option and can edit the page + * 3) Add a Table of contents on the top for users who have enabled the option + * 4) Auto-anchor headings + * + * It loops through all headlines, collects the necessary data, then splits up the + * string and re-inserts the newly formatted headlines. + * + * @param string $text + * @param string $origText Original, untouched wikitext + * @param bool $isMain + * @return mixed|string + */ + private function finalizeHeadings( $text, $origText, $isMain = true ) { # Inhibit editsection links if requested in the page if ( isset( $this->mDoubleUnderscores['noeditsection'] ) ) { $maybeShowEditLink = false; @@ -4279,7 +4454,7 @@ class Parser { # Get all headlines for numbering them and adding funky stuff like [edit] # links - this is for later, but we need the number of headlines right now - # NOTE: white space in headings have been trimmed in doHeadings. They shouldn't + # NOTE: white space in headings have been trimmed in handleHeadings. They shouldn't # be trimmed here since whitespace in HTML headings is significant. $matches = []; $numMatches = preg_match_all( @@ -5637,7 +5812,7 @@ class Parser { protected function stripAltText( $caption, $holders ) { # Strip bad stuff out of the title (tooltip). We can't just use # replaceLinkHoldersText() here, because if this function is called - # from replaceInternalLinks2(), mLinkHolders won't be up-to-date. + # from handleInternalLinks2(), mLinkHolders won't be up-to-date. if ( $holders ) { $tooltip = $holders->replaceText( $caption ); } else { @@ -6241,9 +6416,27 @@ class Parser { * @param int $outputType * * @return string + * @deprecated since 1.34; should not be used outside parser class. */ public function testSrvus( $text, Title $title, ParserOptions $options, $outputType = self::OT_HTML + ) { + wfDeprecated( __METHOD__, '1.34' ); + return $this->fuzzTestSrvus( $text, $title, $options, $outputType ); + } + + /** + * Strip/replaceVariables/unstrip for preprocessor regression testing + * + * @param string $text + * @param Title $title + * @param ParserOptions $options + * @param int $outputType + * + * @return string + */ + private function fuzzTestSrvus( $text, Title $title, ParserOptions $options, + $outputType = self::OT_HTML ) { $magicScopeVariable = $this->lock(); $this->startParse( $title, $options, $outputType, true ); @@ -6259,8 +6452,20 @@ class Parser { * @param Title $title * @param ParserOptions $options * @return string + * @deprecated since 1.34; should not be used outside parser class. */ public function testPst( $text, Title $title, ParserOptions $options ) { + wfDeprecated( __METHOD__, '1.34' ); + return $this->fuzzTestPst( $text, $title, $options ); + } + + /** + * @param string $text + * @param Title $title + * @param ParserOptions $options + * @return string + */ + private function fuzzTestPst( $text, Title $title, ParserOptions $options ) { return $this->preSaveTransform( $text, $title, $options->getUser(), $options ); } @@ -6269,9 +6474,21 @@ class Parser { * @param Title $title * @param ParserOptions $options * @return string + * @deprecated since 1.34; should not be used outside parser class. */ public function testPreprocess( $text, Title $title, ParserOptions $options ) { - return $this->testSrvus( $text, $title, $options, self::OT_PREPROCESS ); + wfDeprecated( __METHOD__, '1.34' ); + return $this->fuzzTestPreprocess( $text, $title, $options ); + } + + /** + * @param string $text + * @param Title $title + * @param ParserOptions $options + * @return string + */ + private function fuzzTestPreprocess( $text, Title $title, ParserOptions $options ) { + return $this->fuzzTestSrvus( $text, $title, $options, self::OT_PREPROCESS ); } /**