Moved getParserOutput to Content interface.
authordaniel <daniel.kinzler@wikimedia.de>
Mon, 23 Jul 2012 21:52:34 +0000 (23:52 +0200)
committerdaniel <daniel.kinzler@wikimedia.de>
Mon, 23 Jul 2012 21:52:34 +0000 (23:52 +0200)
On Tim's request, this change moved getParserOutput() and getSecondaryDataUpdates()
from the ContentHandler to the Content interface.

Change-Id: Ia654aa8710a242ba5fe7a4eb528e6a6449035f59

includes/Content.php
includes/ContentHandler.php
includes/WikiPage.php
includes/api/ApiPurge.php
includes/job/RefreshLinksJob.php
maintenance/refreshLinks.php
tests/phpunit/includes/ContentHandlerTest.php
tests/phpunit/includes/CssContentTest.php
tests/phpunit/includes/JavascriptContentTest.php
tests/phpunit/includes/WikitextContentTest.php

index 0f2fa0b..54d8110 100644 (file)
@@ -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 .= "<pre class=\"mw-code mw-js\" dir=\"ltr\">\n";
+               $html .= $this->getHighlightHtml( );
+               $html .= "\n</pre>\n";
+
+               return $html;
+       }
 }
 
 /**
@@ -1132,4 +1300,13 @@ class CssContent extends TextContent {
                return new CssContent( $pst );
        }
 
+
+       protected function getHtml( ) {
+               $html = "";
+               $html .= "<pre class=\"mw-code mw-css\" dir=\"ltr\">\n";
+               $html .= $this->getHighlightHtml( );
+               $html .= "\n</pre>\n";
+
+               return $html;
+       }
 }
index f8bc256..e460eee 100644 (file)
@@ -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 .= "<pre class=\"mw-code mw-js\" dir=\"ltr\">\n";
-               $html .= $this->getHighlightHtml( $content );
-               $html .= "\n</pre>\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 .= "<pre class=\"mw-code mw-css\" dir=\"ltr\">\n";
-               $html .= $this->getHighlightHtml( $content );
-               $html .= "\n</pre>\n";
-
-               return $html;
-       }
 }
index 276fe0e..613f448 100644 (file)
@@ -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'] ) );
index 5f21390..bc6a6ed 100644 (file)
@@ -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'] = '';
index 05adec0..cc03070 100644 (file)
@@ -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' );
index 21182d7..b563efb 100644 (file)
@@ -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__ );
index 77950c3..1ef4ef9 100644 (file)
@@ -231,71 +231,6 @@ class ContentHandlerTest extends MediaWikiTestCase {
 
        }
 
-       public function dataGetParserOutput() {
-               return array(
-                       array("ContentHandlerTest_testGetParserOutput", "hello ''world''\n", "<p>hello <i>world</i>\n</p>"),
-                       // @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() );
+       }
 }
 
index 66b6e7f..64945f8 100644 (file)
@@ -12,7 +12,7 @@ class CssContentTest extends JavascriptContentTest {
 
        public function dataGetParserOutput() {
                return array(
-                       array("hello <world>\n", "<pre class=\"mw-code mw-css\" dir=\"ltr\">\nhello &lt;world&gt;\n\n</pre>\n"),
+                       array("MediaWiki:Test.css", "hello <world>\n", "<pre class=\"mw-code mw-css\" dir=\"ltr\">\nhello &lt;world&gt;\n\n</pre>\n"),
                        // @todo: more...?
                );
        }
index c402458..f8fb75a 100644 (file)
@@ -12,7 +12,7 @@ class JavascriptContentTest extends WikitextContentTest {
 
        public function dataGetParserOutput() {
                return array(
-                       array("hello <world>\n", "<pre class=\"mw-code mw-js\" dir=\"ltr\">\nhello &lt;world&gt;\n\n</pre>\n"),
+                       array("MediaWiki:Test.js", "hello <world>\n", "<pre class=\"mw-code mw-js\" dir=\"ltr\">\nhello &lt;world&gt;\n\n</pre>\n"),
                        // @todo: more...?
                );
        }
index 7e86c7f..e3870bd 100644 (file)
@@ -14,9 +14,10 @@ class WikitextContentTest extends MediaWikiTestCase {
                return new WikitextContent( $text );
        }
 
+
        public function dataGetParserOutput() {
                return array(
-                       array("hello ''world''\n", "<p>hello <i>world</i>\n</p>"),
+                       array("WikitextContentTest_testGetParserOutput", "hello ''world''\n", "<p>hello <i>world</i>\n</p>"),
                        // @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