From 8d280dde9b405880d9d4a3a724c6b0872ef03dc1 Mon Sep 17 00:00:00 2001 From: daniel Date: Mon, 23 Jul 2012 23:52:34 +0200 Subject: [PATCH] Moved getParserOutput to Content interface. On Tim's request, this change moved getParserOutput() and getSecondaryDataUpdates() from the ContentHandler to the Content interface. Change-Id: Ia654aa8710a242ba5fe7a4eb528e6a6449035f59 --- includes/Content.php | 215 ++++++++++++++++-- includes/ContentHandler.php | 186 --------------- includes/WikiPage.php | 3 +- includes/api/ApiPurge.php | 2 +- includes/job/RefreshLinksJob.php | 4 +- maintenance/refreshLinks.php | 3 +- tests/phpunit/includes/ContentHandlerTest.php | 96 ++------ tests/phpunit/includes/CssContentTest.php | 2 +- .../includes/JavascriptContentTest.php | 2 +- .../phpunit/includes/WikitextContentTest.php | 57 ++++- 10 files changed, 270 insertions(+), 300 deletions(-) diff --git a/includes/Content.php b/includes/Content.php index 0f2fa0b0ec..54d8110cdb 100644 --- a/includes/Content.php +++ b/includes/Content.php @@ -221,26 +221,62 @@ interface Content { */ public function isCountable( $hasLinks = null ) ; + /** - * Convenience method, shorthand for - * $this->getContentHandler()->getParserOutput( $this, $title, $revId, $options, $generateHtml ) - * - * @note: subclasses should NOT override this to provide custom rendering. - * Override ContentHandler::getParserOutput() instead! + * Parse the Content object and generate a ParserOutput from the result. + * $result->getText() can be used to obtain the generated HTML. If no HTML + * is needed, $generateHtml can be set to false; in that case, + * $result->getText() may return null. * - * @param $title Title - * @param $revId null - * @param $options null|ParserOptions - * @param $generateHtml Boolean Whether to generate HTML (default: true). - * If false, the result of calling getText() on the ParserOutput object - * returned by this method is undefined. + * @param $title Title The page title to use as a context for rendering + * @param $revId null|int The revision being rendered (optional) + * @param $options null|ParserOptions Any parser options + * @param $generateHtml Boolean Whether to generate HTML (default: true). If false, + * the result of calling getText() on the ParserOutput object returned by + * this method is undefined. * * @since WD.1 * * @return ParserOutput */ - public function getParserOutput( Title $title, $revId = null, ParserOptions $options = null, - $generateHtml = true ); + public function getParserOutput( Title $title, + $revId = null, + ParserOptions $options = null, $generateHtml = true ); + # TODO: make RenderOutput and RenderOptions base classes + + /** + * Returns a list of DataUpdate objects for recording information about this + * Content in some secondary data store. If the optional second argument, + * $old, is given, the updates may model only the changes that need to be + * made to replace information about the old content with information about + * the new content. + * + * This default implementation calls + * $this->getParserOutput( $content, $title, null, null, false ), + * and then calls getSecondaryDataUpdates( $title, $recursive ) on the + * resulting ParserOutput object. + * + * Subclasses may implement this to determine the necessary updates more + * efficiently, or make use of information about the old content. + * + * @param $title Title The context for determining the necessary updates + * @param $old Content|null An optional Content object representing the + * previous content, i.e. the content being replaced by this Content + * object. + * @param $recursive boolean Whether to include recursive updates (default: + * false). + * @param $parserOutput ParserOutput|null Optional ParserOutput object. + * Provide if you have one handy, to avoid re-parsing of the content. + * + * @return Array. A list of DataUpdate objects for putting information + * about this content object somewhere. + * + * @since WD.1 + */ + public function getSecondaryDataUpdates( Title $title, + Content $old = null, + $recursive = true, ParserOutput $parserOutput = null + ); /** * Construct the redirect destination from this content and return an @@ -549,16 +585,47 @@ abstract class AbstractContent implements Content { return $this->getNativeData() === $that->getNativeData(); } + /** - * @see Content::getParserOutput() + * Returns a list of DataUpdate objects for recording information about this + * Content in some secondary data store. + * + * This default implementation calls + * $this->getParserOutput( $content, $title, null, null, false ), + * and then calls getSecondaryDataUpdates( $title, $recursive ) on the + * resulting ParserOutput object. + * + * Subclasses may override this to determine the secondary data updates more + * efficiently, preferrably without the need to generate a parser output object. + * + * @see Content::getSecondaryDataUpdates() + * + * @param $title Title The context for determining the necessary updates + * @param $old Content|null An optional Content object representing the + * previous content, i.e. the content being replaced by this Content + * object. + * @param $recursive boolean Whether to include recursive updates (default: + * false). + * @param $parserOutput ParserOutput|null Optional ParserOutput object. + * Provide if you have one handy, to avoid re-parsing of the content. + * + * @return Array. A list of DataUpdate objects for putting information + * about this content object somewhere. + * + * @since WD.1 */ - public function getParserOutput( Title $title, $revId = null, ParserOptions $options = null, - $generateHtml = true ) - { - return $this->getContentHandler()->getParserOutput( - $this, $title, $revId, $options, $generateHtml ); + public function getSecondaryDataUpdates( Title $title, + Content $old = null, + $recursive = true, ParserOutput $parserOutput = null + ) { + if ( !$parserOutput ) { + $parserOutput = $this->getParserOutput( $title, null, null, false ); + } + + return $parserOutput->getSecondaryDataUpdates( $title, $recursive ); } + /** * @see Content::getRedirectChain() */ @@ -810,6 +877,60 @@ abstract class TextContent extends AbstractContent { return $diff; } + + /** + * Returns a generic ParserOutput object, wrapping the HTML returned by + * getHtml(). + * + * @param $title Title Context title for parsing + * @param $revId int|null Revision ID (for {{REVISIONID}}) + * @param $options ParserOptions|null Parser options + * @param $generateHtml bool Whether or not to generate HTML + * + * @return ParserOutput representing the HTML form of the text + */ + public function getParserOutput( Title $title, + $revId = null, + ParserOptions $options = null, $generateHtml = true + ) { + # Generic implementation, relying on $this->getHtml() + + if ( $generateHtml ) { + $html = $this->getHtml(); + } else { + $html = ''; + } + + $po = new ParserOutput( $html ); + return $po; + } + + /** + * Generates an HTML version of the content, for display. Used by + * getParserOutput() to construct a ParserOutput object. + * + * This default implementation just calls getHighlightHtml(). Content + * models that have another mapping to HTML (as is the case for markup + * languages like wikitext) should override this method to generate the + * appropriate HTML. + * + * @return string An HTML representation of the content + */ + protected function getHtml() { + return $this->getHighlightHtml(); + } + + /** + * Generates a syntax-highlighted version of the content, as HTML. + * Used by the default implementation of getHtml(). + * + * @return string an HTML representation of the content's markup + */ + protected function getHighlightHtml( ) { + # TODO: make Highlighter interface, use highlighter here, if available + return htmlspecialchars( $this->getNativeData() ); + } + } /** @@ -1024,6 +1145,44 @@ class WikitextContent extends TextContent { return $truncatedtext; } + + /** + * Returns a ParserOutput object resulting from parsing the content's text + * using $wgParser. + * + * @since WD.1 + * + * @param $content Content the content to render + * @param $title \Title + * @param $revId null + * @param $options null|ParserOptions + * @param $generateHtml bool + * + * @internal param \IContextSource|null $context + * @return ParserOutput representing the HTML form of the text + */ + public function getParserOutput( Title $title, + $revId = null, + ParserOptions $options = null, $generateHtml = true + ) { + global $wgParser; + + if ( !$options ) { + $options = new ParserOptions(); + } + + $po = $wgParser->parse( $this->getNativeData(), $title, $options, true, true, $revId ); + return $po; + } + + protected function getHtml() { + throw new MWException( + "getHtml() not implemented for wikitext. " + . "Use getParserOutput()->getText()." + ); + } + + } /** @@ -1103,6 +1262,15 @@ class JavaScriptContent extends TextContent { return new JavaScriptContent( $pst ); } + + protected function getHtml( ) { + $html = ""; + $html .= "
\n";
+		$html .= $this->getHighlightHtml( );
+		$html .= "\n
\n"; + + return $html; + } } /** @@ -1132,4 +1300,13 @@ class CssContent extends TextContent { return new CssContent( $pst ); } + + protected function getHtml( ) { + $html = ""; + $html .= "
\n";
+		$html .= $this->getHighlightHtml( );
+		$html .= "\n
\n"; + + return $html; + } } diff --git a/includes/ContentHandler.php b/includes/ContentHandler.php index f8bc256a5c..e460eeef21 100644 --- a/includes/ContentHandler.php +++ b/includes/ContentHandler.php @@ -766,71 +766,6 @@ abstract class ContentHandler { return $reason; } - /** - * Parse the Content object and generate a ParserOutput from the result. - * $result->getText() can be used to obtain the generated HTML. If no HTML - * is needed, $generateHtml can be set to false; in that case, - * $result->getText() may return null. - * - * @param $content Content the content to render - * @param $title Title The page title to use as a context for rendering - * @param $revId null|int The revision being rendered (optional) - * @param $options null|ParserOptions Any parser options - * @param $generateHtml Boolean Whether to generate HTML (default: true). If false, - * the result of calling getText() on the ParserOutput object returned by - * this method is undefined. - * - * @since WD.1 - * - * @return ParserOutput - */ - public abstract function getParserOutput( Content $content, Title $title, - $revId = null, - ParserOptions $options = null, $generateHtml = true ); - # TODO: make RenderOutput and RenderOptions base classes - - /** - * Returns a list of DataUpdate objects for recording information about this - * Content in some secondary data store. If the optional second argument, - * $old, is given, the updates may model only the changes that need to be - * made to replace information about the old content with information about - * the new content. - * - * This default implementation calls - * $this->getParserOutput( $content, $title, null, null, false ), - * and then calls getSecondaryDataUpdates( $title, $recursive ) on the - * resulting ParserOutput object. - * - * Subclasses may implement this to determine the necessary updates more - * efficiently, or make use of information about the old content. - * - * @param $content Content The content for determining the necessary updates - * @param $title Title The context for determining the necessary updates - * @param $old Content|null An optional Content object representing the - * previous content, i.e. the content being replaced by this Content - * object. - * @param $recursive boolean Whether to include recursive updates (default: - * false). - * @param $parserOutput ParserOutput|null Optional ParserOutput object. - * Provide if you have one handy, to avoid re-parsing of the content. - * - * @return Array. A list of DataUpdate objects for putting information - * about this content object somewhere. - * - * @since WD.1 - */ - public function getSecondaryDataUpdates( Content $content, Title $title, - Content $old = null, - $recursive = true, ParserOutput $parserOutput = null - ) { - if ( !$parserOutput ) { - $parserOutput = $this->getParserOutput( $content, $title, null, null, false ); - } - - return $parserOutput->getSecondaryDataUpdates( $title, $recursive ); - } - - /** * Get the Content object that needs to be saved in order to undo all revisions * between $undo and $undoafter. Revisions must belong to the same page, @@ -953,71 +888,6 @@ abstract class TextContentHandler extends ContentHandler { return $mergedContent; } - /** - * Returns a generic ParserOutput object, wrapping the HTML returned by - * getHtml(). - * - * @param $content Content The content to render - * @param $title Title Context title for parsing - * @param $revId int|null Revision ID (for {{REVISIONID}}) - * @param $options ParserOptions|null Parser options - * @param $generateHtml bool Whether or not to generate HTML - * - * @return ParserOutput representing the HTML form of the text - */ - public function getParserOutput( Content $content, Title $title, - $revId = null, - ParserOptions $options = null, $generateHtml = true - ) { - $this->checkModelID( $content->getModel() ); - - # Generic implementation, relying on $this->getHtml() - - if ( $generateHtml ) { - $html = $this->getHtml( $content ); - } else { - $html = ''; - } - - $po = new ParserOutput( $html ); - return $po; - } - - /** - * Generates an HTML version of the content, for display. Used by - * getParserOutput() to construct a ParserOutput object. - * - * This default implementation just calls getHighlightHtml(). Content - * models that have another mapping to HTML (as is the case for markup - * languages like wikitext) should override this method to generate the - * appropriate HTML. - * - * @param $content Content The content to render - * - * @return string An HTML representation of the content - */ - protected function getHtml( Content $content ) { - $this->checkModelID( $content->getModel() ); - - return $this->getHighlightHtml( $content ); - } - - /** - * Generates a syntax-highlighted version the content, as HTML. - * Used by the default implementation of getHtml(). - * - * @param $content Content the content to render - * - * @return string an HTML representation of the content's markup - */ - protected function getHighlightHtml( Content $content ) { - $this->checkModelID( $content->getModel() ); - - # TODO: make Highlighter interface, use highlighter here, if available - return htmlspecialchars( $content->getNativeData() ); - } - - } /** @@ -1039,44 +909,6 @@ class WikitextContentHandler extends TextContentHandler { return new WikitextContent( '' ); } - /** - * Returns a ParserOutput object resulting from parsing the content's text - * using $wgParser. - * - * @since WD.1 - * - * @param $content Content the content to render - * @param $title \Title - * @param $revId null - * @param $options null|ParserOptions - * @param $generateHtml bool - * - * @internal param \IContextSource|null $context - * @return ParserOutput representing the HTML form of the text - */ - public function getParserOutput( Content $content, Title $title, - $revId = null, - ParserOptions $options = null, $generateHtml = true - ) { - global $wgParser; - - $this->checkModelID( $content->getModel() ); - - if ( !$options ) { - $options = new ParserOptions(); - } - - $po = $wgParser->parse( $content->getNativeData(), $title, $options, true, true, $revId ); - return $po; - } - - protected function getHtml( Content $content ) { - throw new MWException( - "getHtml() not implemented for wikitext. " - . "Use getParserOutput()->getText()." - ); - } - /** * Returns true because wikitext supports sections. * @@ -1118,15 +950,6 @@ class JavaScriptContentHandler extends TextContentHandler { public function getPageLanguage( Title $title, Content $content = null ) { return wfGetLangObj( 'en' ); } - - protected function getHtml( Content $content ) { - $html = ""; - $html .= "
\n";
-		$html .= $this->getHighlightHtml( $content );
-		$html .= "\n
\n"; - - return $html; - } } /** @@ -1158,13 +981,4 @@ class CssContentHandler extends TextContentHandler { public function getPageLanguage( Title $title, Content $content = null ) { return wfGetLangObj( 'en' ); } - - protected function getHtml( Content $content ) { - $html = ""; - $html .= "
\n";
-		$html .= $this->getHighlightHtml( $content );
-		$html .= "\n
\n"; - - return $html; - } } diff --git a/includes/WikiPage.php b/includes/WikiPage.php index 276fe0ef26..613f4486eb 100644 --- a/includes/WikiPage.php +++ b/includes/WikiPage.php @@ -2046,8 +2046,7 @@ class WikiPage extends Page { } # Update the links tables and other secondary data - $contentHandler = $revision->getContentHandler(); - $updates = $contentHandler->getSecondaryDataUpdates( $content, $this->getTitle(), null, true, $editInfo->output ); + $updates = $content->getSecondaryDataUpdates( $this->getTitle(), null, true, $editInfo->output ); DataUpdate::runUpdates( $updates ); wfRunHooks( 'ArticleEditUpdates', array( &$this, &$editInfo, $options['changed'] ) ); diff --git a/includes/api/ApiPurge.php b/includes/api/ApiPurge.php index 5f2139086f..bc6a6edc1b 100644 --- a/includes/api/ApiPurge.php +++ b/includes/api/ApiPurge.php @@ -96,7 +96,7 @@ class ApiPurge extends ApiBase { $p_result = $content->getParserOutput( $title, $page->getLatest(), $popts, $wgEnableParserCache ); # Update the links tables - $updates = $content->getContentHandler()->getSecondaryDataUpdates( $content, $title, null, true, $p_result ); + $updates = $content->getSecondaryDataUpdates( $title, null, true, $p_result ); DataUpdate::runUpdates( $updates ); $r['linkupdate'] = ''; diff --git a/includes/job/RefreshLinksJob.php b/includes/job/RefreshLinksJob.php index 05adec0246..cc03070c43 100644 --- a/includes/job/RefreshLinksJob.php +++ b/includes/job/RefreshLinksJob.php @@ -63,7 +63,7 @@ class RefreshLinksJob extends Job { wfProfileOut( __METHOD__.'-parse' ); wfProfileIn( __METHOD__.'-update' ); - $updates = $content->getContentHandler()->getSecondaryDataUpdates( $content, $this->title, null, false, $parserOutput ); + $updates = $content->getSecondaryDataUpdates( $this->title, null, false, $parserOutput ); DataUpdate::runUpdates( $updates ); wfProfileOut( __METHOD__.'-update' ); @@ -139,7 +139,7 @@ class RefreshLinksJob2 extends Job { wfProfileOut( __METHOD__.'-parse' ); wfProfileIn( __METHOD__.'-update' ); - $updates = $content->getContentHandler()->getSecondaryDataUpdates( $content, $title, null, false, $parserOutput ); + $updates = $content->getSecondaryDataUpdates( $title, null, false, $parserOutput ); DataUpdate::runUpdates( $updates ); wfProfileOut( __METHOD__.'-update' ); diff --git a/maintenance/refreshLinks.php b/maintenance/refreshLinks.php index 21182d76e4..b563efb27f 100644 --- a/maintenance/refreshLinks.php +++ b/maintenance/refreshLinks.php @@ -218,8 +218,7 @@ class RefreshLinks extends Maintenance { $dbw = wfGetDB( DB_MASTER ); $dbw->begin( __METHOD__ ); - $contentHandler = $content->getContentHandler(); - $updates = $contentHandler->getSecondaryDataUpdates( $content, $page->getTitle() ); + $updates = $content->getSecondaryDataUpdates( $page->getTitle() ); DataUpdate::runUpdates( $updates ); $dbw->commit( __METHOD__ ); diff --git a/tests/phpunit/includes/ContentHandlerTest.php b/tests/phpunit/includes/ContentHandlerTest.php index 77950c39f9..1ef4ef9a17 100644 --- a/tests/phpunit/includes/ContentHandlerTest.php +++ b/tests/phpunit/includes/ContentHandlerTest.php @@ -231,71 +231,6 @@ class ContentHandlerTest extends MediaWikiTestCase { } - public function dataGetParserOutput() { - return array( - array("ContentHandlerTest_testGetParserOutput", "hello ''world''\n", "

hello world\n

"), - // @todo: more...? - ); - } - - /** - * @dataProvider dataGetParserOutput - */ - public function testGetParserOutput( $title, $text, $expectedHtml ) { - $title = Title::newFromText( $title ); - $handler = ContentHandler::getForModelID( $title->getContentModel() ); - $content = ContentHandler::makeContent( $text, $title ); - - $po = $handler->getParserOutput( $content, $title ); - - $this->assertEquals( $expectedHtml, $po->getText() ); - // @todo: assert more properties - } - - public function dataGetSecondaryDataUpdates() { - return array( - array("ContentHandlerTest_testGetSecondaryDataUpdates_1", "hello ''world''\n", - array( 'LinksUpdate' => array( 'mRecursive' => true, - 'mLinks' => array() ) ) - ), - array("ContentHandlerTest_testGetSecondaryDataUpdates_2", "hello [[world test 21344]]\n", - array( 'LinksUpdate' => array( 'mRecursive' => true, - 'mLinks' => array( array( 'World_test_21344' => 0 ) ) ) ) - ), - // @todo: more...? - ); - } - - /** - * @dataProvider dataGetSecondaryDataUpdates - */ - public function testGetSecondaryDataUpdates( $title, $text, $expectedStuff ) { - $title = Title::newFromText( $title ); - $title->resetArticleID( 2342 ); //dummy id. fine as long as we don't try to execute the updates! - - $handler = ContentHandler::getForModelID( $title->getContentModel() ); - $content = ContentHandler::makeContent( $text, $title ); - - $updates = $handler->getSecondaryDataUpdates( $content, $title ); - - // make updates accessible by class name - foreach ( $updates as $update ) { - $class = get_class( $update ); - $updates[ $class ] = $update; - } - - foreach ( $expectedStuff as $class => $fieldValues ) { - $this->assertArrayHasKey( $class, $updates, "missing an update of type $class" ); - - $update = $updates[ $class ]; - - foreach ( $fieldValues as $field => $value ) { - $v = $update->$field; #if the field doesn't exist, just crash and burn - $this->assertEquals( $value, $v, "unexpected value for field $field in instance of $class" ); - } - } - } - public function testSupportsSections() { $this->markTestIncomplete( "not yet implemented" ); } @@ -340,22 +275,6 @@ class DummyContentHandlerForTesting extends ContentHandler { { return new DummyContentForTesting( '' ); } - - /** - * @param Content $content - * @param Title $title - * @param null $revId - * @param null|ParserOptions $options - * @param Boolean $generateHtml whether to generate Html (default: true). If false, - * the result of calling getText() on the ParserOutput object returned by - * this method is undefined. - * - * @return ParserOutput - */ - public function getParserOutput( Content $content, Title $title, $revId = null, ParserOptions $options = NULL, $generateHtml = true ) - { - return new ParserOutput( $content->getNativeData() ); - } } class DummyContentForTesting extends AbstractContent { @@ -452,5 +371,20 @@ class DummyContentForTesting extends AbstractContent { { return false; } + + /** + * @param Title $title + * @param null $revId + * @param null|ParserOptions $options + * @param Boolean $generateHtml whether to generate Html (default: true). If false, + * the result of calling getText() on the ParserOutput object returned by + * this method is undefined. + * + * @return ParserOutput + */ + public function getParserOutput( Title $title, $revId = null, ParserOptions $options = NULL, $generateHtml = true ) + { + return new ParserOutput( $this->getNativeData() ); + } } diff --git a/tests/phpunit/includes/CssContentTest.php b/tests/phpunit/includes/CssContentTest.php index 66b6e7f633..64945f8a4c 100644 --- a/tests/phpunit/includes/CssContentTest.php +++ b/tests/phpunit/includes/CssContentTest.php @@ -12,7 +12,7 @@ class CssContentTest extends JavascriptContentTest { public function dataGetParserOutput() { return array( - array("hello \n", "
\nhello <world>\n\n
\n"), + array("MediaWiki:Test.css", "hello \n", "
\nhello <world>\n\n
\n"), // @todo: more...? ); } diff --git a/tests/phpunit/includes/JavascriptContentTest.php b/tests/phpunit/includes/JavascriptContentTest.php index c402458b8c..f8fb75ae63 100644 --- a/tests/phpunit/includes/JavascriptContentTest.php +++ b/tests/phpunit/includes/JavascriptContentTest.php @@ -12,7 +12,7 @@ class JavascriptContentTest extends WikitextContentTest { public function dataGetParserOutput() { return array( - array("hello \n", "
\nhello <world>\n\n
\n"), + array("MediaWiki:Test.js", "hello \n", "
\nhello <world>\n\n
\n"), // @todo: more...? ); } diff --git a/tests/phpunit/includes/WikitextContentTest.php b/tests/phpunit/includes/WikitextContentTest.php index 7e86c7fd77..e3870bdfaf 100644 --- a/tests/phpunit/includes/WikitextContentTest.php +++ b/tests/phpunit/includes/WikitextContentTest.php @@ -14,9 +14,10 @@ class WikitextContentTest extends MediaWikiTestCase { return new WikitextContent( $text ); } + public function dataGetParserOutput() { return array( - array("hello ''world''\n", "

hello world\n

"), + array("WikitextContentTest_testGetParserOutput", "hello ''world''\n", "

hello world\n

"), // @todo: more...? ); } @@ -24,15 +25,61 @@ class WikitextContentTest extends MediaWikiTestCase { /** * @dataProvider dataGetParserOutput */ - public function testGetParserOutput( $text, $expectedHtml ) { - $content = $this->newContent( $text ); + public function testGetParserOutput( $title, $text, $expectedHtml ) { + $title = Title::newFromText( $title ); + $content = ContentHandler::makeContent( $text, $title ); - $po = $content->getParserOutput( $this->context->getTitle() ); + $po = $content->getParserOutput( $title ); $this->assertEquals( $expectedHtml, $po->getText() ); - return $po; + // @todo: assert more properties } + public function dataGetSecondaryDataUpdates() { + return array( + array("WikitextContentTest_testGetSecondaryDataUpdates_1", "hello ''world''\n", + array( 'LinksUpdate' => array( 'mRecursive' => true, + 'mLinks' => array() ) ) + ), + array("WikitextContentTest_testGetSecondaryDataUpdates_2", "hello [[world test 21344]]\n", + array( 'LinksUpdate' => array( 'mRecursive' => true, + 'mLinks' => array( array( 'World_test_21344' => 0 ) ) ) ) + ), + // @todo: more...? + ); + } + + /** + * @dataProvider dataGetSecondaryDataUpdates + */ + public function testGetSecondaryDataUpdates( $title, $text, $expectedStuff ) { + $title = Title::newFromText( $title ); + $title->resetArticleID( 2342 ); //dummy id. fine as long as we don't try to execute the updates! + + $handler = ContentHandler::getForModelID( $title->getContentModel() ); + $content = ContentHandler::makeContent( $text, $title ); + + $updates = $content->getSecondaryDataUpdates( $title ); + + // make updates accessible by class name + foreach ( $updates as $update ) { + $class = get_class( $update ); + $updates[ $class ] = $update; + } + + foreach ( $expectedStuff as $class => $fieldValues ) { + $this->assertArrayHasKey( $class, $updates, "missing an update of type $class" ); + + $update = $updates[ $class ]; + + foreach ( $fieldValues as $field => $value ) { + $v = $update->$field; #if the field doesn't exist, just crash and burn + $this->assertEquals( $value, $v, "unexpected value for field $field in instance of $class" ); + } + } + } + + static $sections = "Intro -- 2.20.1