From bba2bc6ca01de21114328f61c5c8cb16c25f70e0 Mon Sep 17 00:00:00 2001 From: Brad Jorsch Date: Fri, 2 May 2014 16:16:51 -0400 Subject: [PATCH] Record redirect target in ParserOptions Since Id44d566a, the text passed to the parser when parsing a &redirect=no page no longer contains the #REDIRECT directive. For the benefit of extensions that want to know the redirect target from various parser hooks, record the target on the ParserOptions object associated with the parse. Bug: 62856 Change-Id: Icd1da9911a43eabacbd9e9a369a8326f67f270ff --- includes/content/AbstractContent.php | 5 ++ includes/content/WikitextContent.php | 19 ++++++-- includes/parser/ParserOptions.php | 31 +++++++++++++ .../includes/content/WikitextContentTest.php | 46 +++++++++++++++++++ 4 files changed, 97 insertions(+), 4 deletions(-) diff --git a/includes/content/AbstractContent.php b/includes/content/AbstractContent.php index 683c9596be..9d257a6a6a 100644 --- a/includes/content/AbstractContent.php +++ b/includes/content/AbstractContent.php @@ -483,7 +483,12 @@ abstract class AbstractContent implements Content { if ( wfRunHooks( 'ContentGetParserOutput', array( $this, $title, $revId, $options, $generateHtml, &$po ) ) ) { + // Save and restore the old value, just in case something is reusing + // the ParserOptions object in some weird way. + $oldRedir = $options->getRedirectTarget(); + $options->setRedirectTarget( $this->getRedirectTarget() ); $this->fillParserOutput( $title, $revId, $options, $generateHtml, $po ); + $options->setRedirectTarget( $oldRedir ); } return $po; diff --git a/includes/content/WikitextContent.php b/includes/content/WikitextContent.php index 3ab6a6dbea..9a8ab3a6c4 100644 --- a/includes/content/WikitextContent.php +++ b/includes/content/WikitextContent.php @@ -31,6 +31,7 @@ * @ingroup Content */ class WikitextContent extends TextContent { + private $redirectTargetAndText = null; public function __construct( $text ) { parent::__construct( $text, CONTENT_MODEL_WIKITEXT ); @@ -178,10 +179,17 @@ class WikitextContent extends TextContent { */ protected function getRedirectTargetAndText() { global $wgMaxRedirects; + + if ( $this->redirectTargetAndText !== null ) { + return $this->redirectTargetAndText; + } + if ( $wgMaxRedirects < 1 ) { // redirects are disabled, so quit early - return array( null, $this->getNativeData() ); + $this->redirectTargetAndText = array( null, $this->getNativeData() ); + return $this->redirectTargetAndText; } + $redir = MagicWord::get( 'redirect' ); $text = ltrim( $this->getNativeData() ); if ( $redir->matchStartAndRemove( $text ) ) { @@ -199,14 +207,17 @@ class WikitextContent extends TextContent { $title = Title::newFromText( $m[1] ); // If the title is a redirect to bad special pages or is invalid, return null if ( !$title instanceof Title || !$title->isValidRedirectTarget() ) { - return array( null, $this->getNativeData() ); + $this->redirectTargetAndText = array( null, $this->getNativeData() ); + return $this->redirectTargetAndText; } - return array( $title, substr( $text, strlen( $m[0] ) ) ); + $this->redirectTargetAndText = array( $title, substr( $text, strlen( $m[0] ) ) ); + return $this->redirectTargetAndText; } } - return array( null, $this->getNativeData() ); + $this->redirectTargetAndText = array( null, $this->getNativeData() ); + return $this->redirectTargetAndText; } /** diff --git a/includes/parser/ParserOptions.php b/includes/parser/ParserOptions.php index 2ca9d505bb..7e4059b88f 100644 --- a/includes/parser/ParserOptions.php +++ b/includes/parser/ParserOptions.php @@ -211,6 +211,13 @@ class ParserOptions { */ protected $onAccessCallback = null; + /** + * If the page being parsed is a redirect, this should hold the redirect + * target. + * @var Title|null + */ + private $redirectTarget = null; + public function getInterwikiMagic() { return $this->mInterwikiMagic; } @@ -515,6 +522,30 @@ class ParserOptions { return wfSetVar( $this->mIsPrintable, $x ); } + /** + * Set the redirect target. + * + * Note that setting or changing this does not *make* the page a redirect + * or change its target, it merely records the information for reference + * during the parse. + * + * @since 1.24 + * @param Title|null $title + */ + function setRedirectTarget( $title ) { + $this->redirectTarget = $title; + } + + /** + * Get the previously-set redirect target. + * + * @since 1.24 + * @return Title|null + */ + function getRedirectTarget() { + return $this->redirectTarget; + } + /** * Extra key that should be present in the parser cache key. * @param string $key diff --git a/tests/phpunit/includes/content/WikitextContentTest.php b/tests/phpunit/includes/content/WikitextContentTest.php index bd4ae35d08..7becd6f434 100644 --- a/tests/phpunit/includes/content/WikitextContentTest.php +++ b/tests/phpunit/includes/content/WikitextContentTest.php @@ -361,6 +361,52 @@ just a test" $this->assertEquals( CONTENT_MODEL_WIKITEXT, $content->getContentHandler()->getModelID() ); } + public function testRedirectParserOption() { + $title = Title::newFromText( 'testRedirectParserOption' ); + + // Set up hook and its reporting variables + $wikitext = null; + $redirectTarget = null; + $this->mergeMwGlobalArrayValue( 'wgHooks', array( + 'InternalParseBeforeLinks' => array( + function ( &$parser, &$text, &$stripState ) use ( &$wikitext, &$redirectTarget ) { + $wikitext = $text; + $redirectTarget = $parser->getOptions()->getRedirectTarget(); + } + ) + ) ); + + // Test with non-redirect page + $wikitext = false; + $redirectTarget = false; + $content = $this->newContent( 'hello world.' ); + $options = $content->getContentHandler()->makeParserOptions( 'canonical' ); + $options->setRedirectTarget( $title ); + $content->getParserOutput( $title, null, $options ); + $this->assertEquals( 'hello world.', $wikitext, + 'Wikitext passed to hook was not as expected' + ); + $this->assertEquals( null, $redirectTarget, 'Redirect seen in hook was not null' ); + $this->assertEquals( $title, $options->getRedirectTarget(), + 'ParserOptions\' redirectTarget was changed' + ); + + // Test with a redirect page + $wikitext = false; + $redirectTarget = false; + $content = $this->newContent( "#REDIRECT [[TestRedirectParserOption/redir]]\nhello redirect." ); + $options = $content->getContentHandler()->makeParserOptions( 'canonical' ); + $content->getParserOutput( $title, null, $options ); + $this->assertEquals( 'hello redirect.', $wikitext, 'Wikitext passed to hook was not as expected' ); + $this->assertNotEquals( null, $redirectTarget, 'Redirect seen in hook was null' ); + $this->assertEquals( 'TestRedirectParserOption/redir', $redirectTarget->getFullText(), + 'Redirect seen in hook was not the expected title' + ); + $this->assertEquals( null, $options->getRedirectTarget(), + 'ParserOptions\' redirectTarget was changed' + ); + } + public static function dataEquals() { return array( array( new WikitextContent( "hallo" ), null, false ), -- 2.20.1