From: daniel Date: Tue, 22 Jan 2013 11:59:23 +0000 (+0100) Subject: Better way for extensions to add to ParserOutput. X-Git-Tag: 1.31.0-rc.0~20861 X-Git-Url: http://git.cyclocoop.org/%24href?a=commitdiff_plain;h=40cb62d558102134fb2c8e7e3f61d9eae8dff1e7;p=lhc%2Fweb%2Fwiklou.git Better way for extensions to add to ParserOutput. Extensions sometimes need to stash information in the ParserOutput for later use. This change provides a clean way to do that. Change-Id: I8bc571d13c9a70bb71430862c2ab679ff1947126 --- diff --git a/includes/parser/ParserOutput.php b/includes/parser/ParserOutput.php index f32d5b6753..53b62938fb 100644 --- a/includes/parser/ParserOutput.php +++ b/includes/parser/ParserOutput.php @@ -51,6 +51,7 @@ class ParserOutput extends CacheTime { private $mIndexPolicy = ''; # 'index' or 'noindex'? Any other value will result in no change. private $mAccessedOptions = array(); # List of ParserOptions (stored in the keys) private $mSecondaryDataUpdates = array(); # List of DataUpdate, used to save info from the page somewhere else. + private $mExtensionData = array(); # extra data used by extensions const EDITSECTION_REGEX = '#<(?:mw:)?editsection page="(.*?)" section="(.*?)"(?:/>|>(.*?)())#'; @@ -370,15 +371,31 @@ class ParserOutput extends CacheTime { * Wikimedia Commons. * This is not actually implemented, yet but would be pretty cool. * - * Do not use setProperty() to set a property which is only used in a - * context where the ParserOutput object itself is already available, for - * example a normal page view. There is no need to save such a property + * @note: Do not use setProperty() to set a property which is only used + * in a context where the ParserOutput object itself is already available, + * for example a normal page view. There is no need to save such a property * in the database since it the text is already parsed. You can just hook * OutputPageParserOutput and get your data out of the ParserOutput object. * - * If you are writing an extension where you want to set - * a property in the parser which is used by an OutputPageParserOutput hook, - * just use a custom variable within the ParserOutput object: + * If you are writing an extension where you want to set a property in the + * parser which is used by an OutputPageParserOutput hook, you have to + * associate the extension data directly with the ParserOutput object. + * Since MediaWiki 1.21, you can use setExtensionData() to do this: + * + * @par Example: + * @code + * $parser->getOutput()->setExtensionData( 'my_ext_foo', '...' ); + * @endcode + * + * And then later, in OutputPageParserOutput or similar: + * + * @par Example: + * @code + * $output->getExtensionData( 'my_ext_foo' ); + * @endcode + * + * In MediaWiki 1.20 and older, you have to use a custom member variable + * within the ParserOutput object: * * @par Example: * @code @@ -460,4 +477,72 @@ class ParserOutput extends CacheTime { return array_merge( $this->mSecondaryDataUpdates, array( $linksUpdate ) ); } + /** + * Attaches arbitrary data to this ParserObject. This can be used to store some information in + * the ParserOutput object for later use during page output. The data will be cached along with + * the ParserOutput object, but unlike data set using setProperty(), it is not recorded in the + * database. + * + * This method is provided to overcome the unsafe practice of attaching extra information to a + * ParserObject by directly assigning member variables. + * + * To use setExtensionData() to pass extension information from a hook inside the parser to a + * hook in the page output, use this in the parser hook: + * + * @par Example: + * @code + * $parser->getOutput()->setExtensionData( 'my_ext_foo', '...' ); + * @endcode + * + * And then later, in OutputPageParserOutput or similar: + * + * @par Example: + * @code + * $output->getExtensionData( 'my_ext_foo' ); + * @endcode + * + * In MediaWiki 1.20 and older, you have to use a custom member variable + * within the ParserOutput object: + * + * @par Example: + * @code + * $parser->getOutput()->my_ext_foo = '...'; + * @endcode + * + * @since 1.21 + * + * @param string $key The key for accessing the data. Extensions should take care to avoid + * conflicts in naming keys. It is suggested to use the extension's name as a + * prefix. + * + * @param mixed $value The value to set. Setting a value to null is equivalent to removing + * the value. + */ + public function setExtensionData( $key, $value ) { + if ( $value === null ) { + unset( $this->mExtensionData[$key] ); + } else { + $this->mExtensionData[$key] = $value; + } + } + + /** + * Gets extensions data previously attached to this ParserOutput using setExtensionData(). + * Typically, such data would be set while parsing the page, e.g. by a parser function. + * + * @since 1.21 + * + * @param string $key The key to look up. + * + * @return mixed The value previously set for the given key using setExtensionData( $key ), + * or null if no value was set for this key. + */ + public function getExtensionData( $key ) { + if ( isset( $this->mExtensionData[$key] ) ) { + return $this->mExtensionData[$key]; + } + + return null; + } + } diff --git a/tests/phpunit/includes/parser/ParserOutputTest.php b/tests/phpunit/includes/parser/ParserOutputTest.php index 2244fdb932..68f77ab537 100644 --- a/tests/phpunit/includes/parser/ParserOutputTest.php +++ b/tests/phpunit/includes/parser/ParserOutputTest.php @@ -35,4 +35,21 @@ class ParserOutputTest extends MediaWikiTestCase { $this->assertEquals( $shouldMatch, ParserOutput::isLinkInternal( $server, $url ) ); } + + public function testExtensionData() { + $po = new ParserOutput(); + + $po->setExtensionData( "one", "Foo" ); + + $this->assertEquals( "Foo", $po->getExtensionData( "one" ) ); + $this->assertNull( $po->getExtensionData( "spam" ) ); + + $po->setExtensionData( "two", "Bar" ); + $this->assertEquals( "Foo", $po->getExtensionData( "one" ) ); + $this->assertEquals( "Bar", $po->getExtensionData( "two" ) ); + + $po->setExtensionData( "one", null ); + $this->assertNull( $po->getExtensionData( "one" ) ); + $this->assertEquals( "Bar", $po->getExtensionData( "two" ) ); + } }