jenkins-bot has submitted this change and it was merged.

Change subject: Introducing ContentGetParserOutput hook.
......................................................................


Introducing ContentGetParserOutput hook.

This hooks allows extensions to override the normal model-specific rendering
of page content. A typical use would be to provide syntax highlighting for
pages that contain scripts. In that sense, ContentGetParserOutput is a
generalization of the old ShowRawCssJs hook.

Change-Id: Ibfb2cbefea44eeee9f2a027f47e7721bf177ba0f
---
M docs/hooks.txt
M includes/content/AbstractContent.php
M includes/content/CssContent.php
M includes/content/JavaScriptContent.php
M includes/content/TextContent.php
M includes/content/WikitextContent.php
M tests/phpunit/includes/content/ContentHandlerTest.php
M tests/phpunit/includes/content/CssContentTest.php
M tests/phpunit/includes/content/TextContentTest.php
9 files changed, 134 insertions(+), 55 deletions(-)

Approvals:
  Reedy: Looks good to me, approved
  jenkins-bot: Verified



diff --git a/docs/hooks.txt b/docs/hooks.txt
index 66b5068..02c9fad 100644
--- a/docs/hooks.txt
+++ b/docs/hooks.txt
@@ -801,6 +801,19 @@
 $modeName: the requested content model name
 &$handler: set this to a ContentHandler object, if desired.
 
+'ContentGetParserOutput': Customize parser output for a given content object,
+called by AbstractContent::getParserOutput. May be used to override the normal
+model-specific rendering of page content.
+$content: The Content to render
+$title: Title of the page, as context
+$revId: The revision ID, as context
+$options: ParserOptions for rendering. To avoid confusing the parser cache,
+the output can only depend on parameters provided to this hook function, not 
on global state.
+$generateHtml: boolean, indicating whether full HTML should be generated. If 
false,
+generation of HTML may be skipped, but other information should still be 
present in the
+ParserOutput object.
+&$output: ParserOutput, to manipulate or replace
+
 'ConvertContent': Called by AbstractContent::convert when a conversion to 
another
 content model is requested.
 $content: The Content object to be converted.
@@ -1994,7 +2007,7 @@
 $article: The article object corresponding to the page
 
 'ShowRawCssJs': Customise the output of raw CSS and JavaScript in page views.
-DEPRECATED, use the ContentHandler facility to handle CSS and JavaScript!
+DEPRECATED, use the ContentGetParserOutput hook instead!
 $text: Text being shown
 $title: Title of the custom script/stylesheet page
 $output: Current OutputPage object
diff --git a/includes/content/AbstractContent.php 
b/includes/content/AbstractContent.php
index 137efb8..8c6e24a 100644
--- a/includes/content/AbstractContent.php
+++ b/includes/content/AbstractContent.php
@@ -441,4 +441,57 @@
                wfRunHooks( 'ConvertContent', array( $this, $toModel, $lossy, 
&$result ) );
                return $result;
        }
+
+       /**
+        * Returns a ParserOutput object, filled by a call to 
fillParserOutput().
+        * Subclasses that want to control the parser output may override this, 
or
+        * they can override fillParserOutput(). If they override 
getParserOutput(),
+        * itself, they should take care to call the ContentGetParserOutput 
hook.
+        *
+        * @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 ( $options === null ) {
+                       $options = 
$this->getContentHandler()->makeParserOptions( 'canonical' );
+               }
+
+               $po = new ParserOutput();
+
+               if ( wfRunHooks( 'ContentGetParserOutput',
+                       array( $this, $title, $revId, $options, $generateHtml, 
&$po ) ) ) {
+
+                       $this->fillParserOutput( $title, $revId, $options, 
$generateHtml, $po );
+               }
+
+               return $po;
+       }
+
+       /**
+        * Fills the provided ParserOutput object with the HTML returned by 
getHtml().
+        * Subclasses should override this (or getParserOutput) appropriately.
+        * This placeholder implementation always throws an exception.
+        *
+        * @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
+        * @param &$output      ParserOutput The output object to fill 
(reference).
+        *
+        * @throws MWException
+        */
+       protected function fillParserOutput( Title $title, $revId,
+               ParserOptions $options, $generateHtml, ParserOutput &$output
+       ) {
+               // Don't make abstract, so subclasses that override 
getParserOutput() directly don't fail.
+               throw new MWException( 'Subclasses of AbstractContent must 
override fillParserOutput!' );
+       }
 }
diff --git a/includes/content/CssContent.php b/includes/content/CssContent.php
index 03cc2d0..a25bd76 100644
--- a/includes/content/CssContent.php
+++ b/includes/content/CssContent.php
@@ -57,7 +57,7 @@
        protected function getHtml() {
                $html = "";
                $html .= "<pre class=\"mw-code mw-css\" dir=\"ltr\">\n";
-               $html .= $this->getHighlightHtml();
+               $html .= htmlspecialchars( $this->getNativeData() );
                $html .= "\n</pre>\n";
 
                return $html;
diff --git a/includes/content/JavaScriptContent.php 
b/includes/content/JavaScriptContent.php
index 2ae572b..247de6d 100644
--- a/includes/content/JavaScriptContent.php
+++ b/includes/content/JavaScriptContent.php
@@ -58,7 +58,7 @@
        protected function getHtml() {
                $html = "";
                $html .= "<pre class=\"mw-code mw-js\" dir=\"ltr\">\n";
-               $html .= $this->getHighlightHtml();
+               $html .= htmlspecialchars( $this->getNativeData() );
                $html .= "\n</pre>\n";
 
                return $html;
diff --git a/includes/content/TextContent.php b/includes/content/TextContent.php
index f66dacd..a6ee7b0 100644
--- a/includes/content/TextContent.php
+++ b/includes/content/TextContent.php
@@ -189,32 +189,27 @@
        }
 
        /**
-        * Returns a generic ParserOutput object, wrapping the HTML returned by
-        * getHtml().
+        * Fills the provided ParserOutput object with the HTML returned by 
getHtml().
+        *
+        * Content models in $wgTextModelsToParse will be parsed as wikitext to 
process links,
+        * magic words, etc.
+        *
+        * Subclasses may override this to provide custom rendering.
         *
         * @param $title Title Context title for parsing
         * @param int|null $revId Revision ID (for {{REVISIONID}})
         * @param $options ParserOptions|null Parser options
         * @param bool $generateHtml Whether or not to generate HTML
-        *
-        * @return ParserOutput representing the HTML form of the text
+        * @param $output ParserOutput The output object to fill (reference).
         */
-       public function getParserOutput( Title $title,
-               $revId = null,
-               ParserOptions $options = null, $generateHtml = true
+       protected function fillParserOutput( Title $title, $revId,
+               ParserOptions $options, $generateHtml, ParserOutput &$output
        ) {
                global $wgParser, $wgTextModelsToParse;
 
-               if ( !$options ) {
-                       //NOTE: use canonical options per default to produce 
cacheable output
-                       $options = 
$this->getContentHandler()->makeParserOptions( 'canonical' );
-               }
-
                if ( in_array( $this->getModel(), $wgTextModelsToParse ) ) {
-                       // parse just to get links etc into the database
-                       $po = $wgParser->parse( $this->getNativeData(), $title, 
$options, true, true, $revId );
-               } else {
-                       $po = new ParserOutput();
+                       // parse just to get links etc into the database, HTML 
is replaced below.
+                       $output = $wgParser->parse( $this->getNativeData(), 
$title, $options, true, true, $revId );
                }
 
                if ( $generateHtml ) {
@@ -223,34 +218,25 @@
                        $html = '';
                }
 
-               $po->setText( $html );
-               return $po;
+               $output->setText( $html );
        }
 
        /**
         * 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.
+        * This default implementation runs the text returned by 
$this->getNativeData()
+        * through htmlspecialchars and tried to convert line breaks and 
indentation to 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() );
+       public static function convertWhiteSpaceToHTML( $msg ) {
+               $msg = htmlspecialchars( $msg );
+               $msg = preg_replace( '/^ /m', '&#160;', $msg );
+               $msg = preg_replace( '/ $/m', '&#160;', $msg );
+               $msg = preg_replace( '/  /', '&#160; ', $msg );
+               $msg = str_replace( "\n", '<br />', $msg );
+               return $msg;
        }
 
        /**
diff --git a/includes/content/WikitextContent.php 
b/includes/content/WikitextContent.php
index 26337db..d821d9d 100644
--- a/includes/content/WikitextContent.php
+++ b/includes/content/WikitextContent.php
@@ -277,28 +277,21 @@
         * using $wgParser.
         *
         * @since    1.21
+        * @see AbstractContent::fillParserOutput().
         *
         * @param $title Title
         * @param int $revId Revision to pass to the parser (default: null)
         * @param $options ParserOptions (default: null)
         * @param bool $generateHtml (default: false)
-        *
-        * @internal param \IContextSource|null $context
-        * @return ParserOutput representing the HTML form of the text
+        * @param &$output ParserOutput representing the HTML form of the text,
+        *           may be manipulated or replaced.
         */
-       public function getParserOutput( Title $title,
-               $revId = null,
-               ParserOptions $options = null, $generateHtml = true
+       protected function fillParserOutput( Title $title, $revId,
+                       ParserOptions $options, $generateHtml, ParserOutput 
&$output
        ) {
                global $wgParser;
 
-               if ( !$options ) {
-                       //NOTE: use canonical options per default to produce 
cacheable output
-                       $options = 
$this->getContentHandler()->makeParserOptions( 'canonical' );
-               }
-
-               $po = $wgParser->parse( $this->getNativeData(), $title, 
$options, true, true, $revId );
-               return $po;
+               $output = $wgParser->parse( $this->getNativeData(), $title, 
$options, true, true, $revId );
        }
 
        protected function getHtml() {
diff --git a/tests/phpunit/includes/content/ContentHandlerTest.php 
b/tests/phpunit/includes/content/ContentHandlerTest.php
index c345513..2904472 100644
--- a/tests/phpunit/includes/content/ContentHandlerTest.php
+++ b/tests/phpunit/includes/content/ContentHandlerTest.php
@@ -431,4 +431,18 @@
        public function getParserOutput( Title $title, $revId = null, 
ParserOptions $options = null, $generateHtml = true ) {
                return new ParserOutput( $this->getNativeData() );
        }
+
+       /**
+        * @see AbstractContent::fillParserOutput()
+        *
+        * @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
+        * @param $output       ParserOutput The output object to fill 
(reference).
+        */
+       protected function fillParserOutput( Title $title, $revId,
+                       ParserOptions $options, $generateHtml, ParserOutput 
&$output ) {
+               $output = new ParserOutput( $this->getNativeData() );
+       }
 }
diff --git a/tests/phpunit/includes/content/CssContentTest.php 
b/tests/phpunit/includes/content/CssContentTest.php
index 1c45820..61716f9 100644
--- a/tests/phpunit/includes/content/CssContentTest.php
+++ b/tests/phpunit/includes/content/CssContentTest.php
@@ -5,7 +5,7 @@
  * @group Database
  *        ^--- needed, because we do need the database to test link updates
  */
-class CssContentTest extends MediaWikiTestCase {
+class CssContentTest extends JavaScriptContentTest {
 
        protected function setUp() {
                parent::setUp();
diff --git a/tests/phpunit/includes/content/TextContentTest.php 
b/tests/phpunit/includes/content/TextContentTest.php
index c7138b7..d7dde37 100644
--- a/tests/phpunit/includes/content/TextContentTest.php
+++ b/tests/phpunit/includes/content/TextContentTest.php
@@ -7,13 +7,20 @@
  */
 class TextContentTest extends MediaWikiLangTestCase {
        protected $context;
+       protected $savedContentGetParserOutput;
 
        protected function setUp() {
+               global $wgHooks;
+
                parent::setUp();
 
                // Anon user
                $user = new User();
                $user->setName( '127.0.0.1' );
+
+               $this->context = new RequestContext( new FauxRequest() );
+               $this->context->setTitle( Title::newFromText( 'Test' ) );
+               $this->context->setUser( $user );
 
                $this->setMwGlobals( array(
                        'wgUser' => $user,
@@ -26,9 +33,22 @@
                        'wgAlwaysUseTidy' => false,
                ) );
 
-               $this->context = new RequestContext( new FauxRequest() );
-               $this->context->setTitle( Title::newFromText( 'Test' ) );
-               $this->context->setUser( $user );
+               // bypass hooks that force custom rendering
+               if ( isset( $wgHooks['ContentGetParserOutput'] )  ) {
+                       $this->savedContentGetParserOutput = 
$wgHooks['ContentGetParserOutput'];
+                       unset( $wgHooks['ContentGetParserOutput'] );
+               }
+       }
+
+       public function teardown() {
+               global $wgHooks;
+
+               // restore hooks that force custom rendering
+               if ( $this->savedContentGetParserOutput !== null ) {
+                       $wgHooks['ContentGetParserOutput'] = 
$this->savedContentGetParserOutput;
+               }
+
+               parent::teardown();
        }
 
        public function newContent( $text ) {

-- 
To view, visit https://gerrit.wikimedia.org/r/28199
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings

Gerrit-MessageType: merged
Gerrit-Change-Id: Ibfb2cbefea44eeee9f2a027f47e7721bf177ba0f
Gerrit-PatchSet: 11
Gerrit-Project: mediawiki/core
Gerrit-Branch: master
Gerrit-Owner: Daniel Kinzler <[email protected]>
Gerrit-Reviewer: Anomie <[email protected]>
Gerrit-Reviewer: Daniel Kinzler <[email protected]>
Gerrit-Reviewer: Daniel Werner <[email protected]>
Gerrit-Reviewer: Demon <[email protected]>
Gerrit-Reviewer: GWicke <[email protected]>
Gerrit-Reviewer: Nikerabbit <[email protected]>
Gerrit-Reviewer: Platonides <[email protected]>
Gerrit-Reviewer: Reedy <[email protected]>
Gerrit-Reviewer: Spage <[email protected]>
Gerrit-Reviewer: jenkins-bot

_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to