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

Change subject: Add supportsDirectEditing methods to ContentHandler
......................................................................


Add supportsDirectEditing methods to ContentHandler

This adds supportsDirectApiEditing and
supportsDirectEditing methods to ContentHandler. Both
return false by default for the ContentHandler base
class, and true for TextContentHandler and it's
derivatives. (everything in core)

Extension content types that directly extend
AbstractContent / ContentHandler, often / generally don't
support direct editing. EntityContent in Wikibase
and Flow boards are the two such content types currently
in gerrit-hosted extensions.

The use and direct settings of the allowNonTextContent
member variable is replaced by enableApiEditOverride and
a setter for that. The only place allowNonTextContent is
used in all of Wikimedia-hosted git repos is core itself
(EditPage and ApiEditPage), so should be safe to make
this change.

With this change, Wikibase can remove its ApiCheckCanExecute
hook handler that disallows editing there, and MobileFrontend
could check if direct editing is allowed before enabling it's
editing features, instead of Wikibase having to add
MobileFrontend hook handlers to disable the features.

Bug: T96382
Change-Id: I276cd6ecedf38108f1f2be16b38e699e8c5d2d0c
---
M RELEASE-NOTES-1.26
M includes/EditPage.php
M includes/api/ApiEditPage.php
M includes/content/ContentHandler.php
M includes/content/TextContentHandler.php
M tests/TestsAutoLoader.php
M tests/phpunit/includes/EditPageTest.php
M tests/phpunit/includes/api/ApiEditPageTest.php
M tests/phpunit/includes/content/ContentHandlerTest.php
A tests/phpunit/includes/content/TextContentHandlerTest.php
M tests/phpunit/includes/content/WikitextContentHandlerTest.php
A tests/phpunit/mocks/content/DummyContentForTesting.php
A tests/phpunit/mocks/content/DummyContentHandlerForTesting.php
A tests/phpunit/mocks/content/DummyNonTextContent.php
A tests/phpunit/mocks/content/DummyNonTextContentHandler.php
15 files changed, 516 insertions(+), 200 deletions(-)

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



diff --git a/RELEASE-NOTES-1.26 b/RELEASE-NOTES-1.26
index bf9341d..eddfe30 100644
--- a/RELEASE-NOTES-1.26
+++ b/RELEASE-NOTES-1.26
@@ -35,6 +35,13 @@
 * ChangeTags::tagDescription() will return false if the interface message
   for the tag is disabled.
 * Added PageHistoryPager::doBatchLookups hook.
+* supportsDirectEditing and supportsDirectApiEditing methods added to
+ContentHandler, to provide a way for ApiEditPage and EditPage to check
+if direct editing of content is allowed. These methods return false,
+by default for the ContentHandler base class and true for TextContentHandler
+and it's derivative classes (everything in core). For Content types that
+do not support direct editing, an alternative mechanism should be provided
+for editing, such as action overrides or specific api modules.
 
 == Compatibility ==
 
diff --git a/includes/EditPage.php b/includes/EditPage.php
index 8d27eac..1679c3b 100644
--- a/includes/EditPage.php
+++ b/includes/EditPage.php
@@ -380,11 +380,13 @@
 
        public $suppressIntro = false;
 
-       /** @var bool Set to true to allow editing of non-text content types. */
-       public $allowNonTextContent = false;
-
        /** @var bool */
        protected $edit;
+
+       /**
+        * @var bool Set in ApiEditPage, based on 
ContentHandler::allowsDirectApiEditing
+        */
+       private $enableApiEditOverride = false;
 
        /**
         * @param Article $article
@@ -447,8 +449,18 @@
         * @throws MWException If $modelId has no known handler
         */
        public function isSupportedContentModel( $modelId ) {
-               return $this->allowNonTextContent ||
-                       ContentHandler::getForModelID( $modelId ) instanceof 
TextContentHandler;
+               return $this->enableApiEditOverride === true ||
+                       ContentHandler::getForModelID( $modelId 
)->supportsDirectEditing();
+       }
+
+       /**
+        * Allow editing of content that supports API direct editing, but not 
general
+        * direct editing. Set to false by default.
+        *
+        * @param bool $enableOverride
+        */
+       public function setApiEditOverride( $enableOverride ) {
+               $this->enableApiEditOverride = $enableOverride;
        }
 
        function submit() {
diff --git a/includes/api/ApiEditPage.php b/includes/api/ApiEditPage.php
index 56c67e0..601c64c 100644
--- a/includes/api/ApiEditPage.php
+++ b/includes/api/ApiEditPage.php
@@ -96,8 +96,12 @@
                        $contentHandler = ContentHandler::getForModelID( 
$params['contentmodel'] );
                }
 
-               // @todo Ask handler whether direct editing is supported at 
all! make
-               // allowFlatEdit() method or some such
+               if ( $contentHandler->supportsDirectApiEditing() === false ) {
+                       $this->dieUsage(
+                               'Direct editing via API is not supported for 
this content type.',
+                               'no-direct-editing'
+                       );
+               }
 
                if ( !isset( $params['contentformat'] ) || 
$params['contentformat'] == '' ) {
                        $params['contentformat'] = 
$contentHandler->getDefaultFormat();
@@ -362,9 +366,7 @@
 
                $ep = new EditPage( $articleObject );
 
-               // allow editing of non-textual content.
-               $ep->allowNonTextContent = true;
-
+               $ep->setApiEditOverride( true );
                $ep->setContextTitle( $titleObj );
                $ep->importFormData( $req );
                $content = $ep->textbox1;
diff --git a/includes/content/ContentHandler.php 
b/includes/content/ContentHandler.php
index 371b267..9c2435a 100644
--- a/includes/content/ContentHandler.php
+++ b/includes/content/ContentHandler.php
@@ -1058,6 +1058,24 @@
        }
 
        /**
+        * Return true if this content model supports direct editing, such as 
via EditPage.
+        *
+        * @return bool Default is false, and true for TextContent and it's 
derivatives.
+        */
+       public function supportsDirectEditing() {
+               return false;
+       }
+
+       /**
+        * Whether or not this content model supports direct editing via 
ApiEditPage
+        *
+        * @return bool Default is false, and true for TextContent and 
derivatives.
+        */
+       public function supportsDirectApiEditing() {
+               return $this->supportsDirectEditing();
+       }
+
+       /**
         * Logs a deprecation warning, visible if $wgDevelopmentWarnings, but 
only if
         * self::$enableDeprecationWarnings is set to true.
         *
diff --git a/includes/content/TextContentHandler.php 
b/includes/content/TextContentHandler.php
index ffe1acb..f5e8783 100644
--- a/includes/content/TextContentHandler.php
+++ b/includes/content/TextContentHandler.php
@@ -134,4 +134,13 @@
                return new $class( '' );
        }
 
+       /**
+        * @see ContentHandler::supportsDirectEditing
+        *
+        * @return bool Default is true for TextContent and derivatives.
+        */
+       public function supportsDirectEditing() {
+               return true;
+       }
+
 }
diff --git a/tests/TestsAutoLoader.php b/tests/TestsAutoLoader.php
index def23da..1a2e0cb 100644
--- a/tests/TestsAutoLoader.php
+++ b/tests/TestsAutoLoader.php
@@ -66,8 +66,10 @@
        'TestRecentChangesHelper' => 
"$testDir/phpunit/includes/changes/TestRecentChangesHelper.php",
 
        # tests/phpunit/includes/content
-       'DummyContentHandlerForTesting' => 
"$testDir/phpunit/includes/content/ContentHandlerTest.php",
-       'DummyContentForTesting' => 
"$testDir/phpunit/includes/content/ContentHandlerTest.php",
+       'DummyContentHandlerForTesting' => 
"$testDir/phpunit/mocks/content/DummyContentHandlerForTesting.php",
+       'DummyContentForTesting' => 
"$testDir/phpunit/mocks/content/DummyContentForTesting.php",
+       'DummyNonTextContentHandler' => 
"$testDir/phpunit/mocks/content/DummyNonTextContentHandler.php",
+       'DummyNonTextContent' => 
"$testDir/phpunit/mocks/content/DummyNonTextContent.php",
        'ContentHandlerTest' => 
"$testDir/phpunit/includes/content/ContentHandlerTest.php",
        'JavaScriptContentTest' => 
"$testDir/phpunit/includes/content/JavaScriptContentTest.php",
        'TextContentTest' => 
"$testDir/phpunit/includes/content/TextContentTest.php",
diff --git a/tests/phpunit/includes/EditPageTest.php 
b/tests/phpunit/includes/EditPageTest.php
index 15778e4..27959b1 100644
--- a/tests/phpunit/includes/EditPageTest.php
+++ b/tests/phpunit/includes/EditPageTest.php
@@ -11,6 +11,28 @@
  */
 class EditPageTest extends MediaWikiLangTestCase {
 
+       protected function setUp() {
+               global $wgExtraNamespaces, $wgNamespaceContentModels, 
$wgContentHandlers, $wgContLang;
+
+               parent::setUp();
+
+               $this->setMwGlobals( array(
+                       'wgExtraNamespaces' => $wgExtraNamespaces,
+                       'wgNamespaceContentModels' => $wgNamespaceContentModels,
+                       'wgContentHandlers' => $wgContentHandlers,
+                       'wgContLang' => $wgContLang,
+               ) );
+
+               $wgExtraNamespaces[12312] = 'Dummy';
+               $wgExtraNamespaces[12313] = 'Dummy_talk';
+
+               $wgNamespaceContentModels[12312] = "testing";
+               $wgContentHandlers["testing"] = 'DummyContentHandlerForTesting';
+
+               MWNamespace::getCanonicalNamespaces( true ); # reset namespace 
cache
+               $wgContLang->resetNamespaces(); # reset namespace cache
+       }
+
        /**
         * @dataProvider provideExtractSectionTitle
         * @covers EditPage::extractSectionTitle
@@ -499,4 +521,37 @@
                $this->assertEdit( 'EditPageTest_testAutoMerge', null, 'Berta', 
$bertasEdit,
                        $expectedCode, $expectedText, $message );
        }
+
+       /**
+        * @depends testAutoMerge
+        */
+       public function testCheckDirectEditingDisallowed_forNonTextContent() {
+               $title = Title::newFromText( 'Dummy:NonTextPageForEditPage' );
+               $page = WikiPage::factory( $title );
+
+               $article = new Article( $title );
+               $article->getContext()->setTitle( $title );
+               $ep = new EditPage( $article );
+               $ep->setContextTitle( $title );
+
+               $user = $GLOBALS['wgUser'];
+
+               $edit = array(
+                       'wpTextbox1' => serialize( 'non-text content' ),
+                       'wpEditToken' => $user->getEditToken(),
+                       'wpEdittime' => '',
+                       'wpStarttime' => wfTimestampNow()
+               );
+
+               $req = new FauxRequest( $edit, true );
+               $ep->importFormData( $req );
+
+               $this->setExpectedException(
+                       'MWException',
+                       'This content model is not supported: testing'
+               );
+
+               $ep->internalAttemptSave( $result, false );
+       }
+
 }
diff --git a/tests/phpunit/includes/api/ApiEditPageTest.php 
b/tests/phpunit/includes/api/ApiEditPageTest.php
index 3179a45..865f1c2 100644
--- a/tests/phpunit/includes/api/ApiEditPageTest.php
+++ b/tests/phpunit/includes/api/ApiEditPageTest.php
@@ -27,9 +27,14 @@
 
                $wgExtraNamespaces[12312] = 'Dummy';
                $wgExtraNamespaces[12313] = 'Dummy_talk';
+               $wgExtraNamespaces[12314] = 'DummyNonText';
+               $wgExtraNamespaces[12315] = 'DummyNonText_talk';
 
                $wgNamespaceContentModels[12312] = "testing";
+               $wgNamespaceContentModels[12314] = "testing-nontext";
+
                $wgContentHandlers["testing"] = 'DummyContentHandlerForTesting';
+               $wgContentHandlers["testing-nontext"] = 
'DummyNonTextContentHandler';
 
                MWNamespace::getCanonicalNamespaces( true ); # reset namespace 
cache
                $wgContLang->resetNamespaces(); # reset namespace cache
@@ -94,33 +99,6 @@
                        $data[0]['edit']['oldrevid'],
                        "revision id should change after edit"
                );
-       }
-
-       public function testNonTextEdit() {
-               $name = 'Dummy:ApiEditPageTest_testNonTextEdit';
-               $data = serialize( 'some bla bla text' );
-
-               // -- test new page --------------------------------------------
-               $apiResult = $this->doApiRequestWithToken( array(
-                       'action' => 'edit',
-                       'title' => $name,
-                       'text' => $data, ) );
-               $apiResult = $apiResult[0];
-
-               // Validate API result data
-               $this->assertArrayHasKey( 'edit', $apiResult );
-               $this->assertArrayHasKey( 'result', $apiResult['edit'] );
-               $this->assertEquals( 'Success', $apiResult['edit']['result'] );
-
-               $this->assertArrayHasKey( 'new', $apiResult['edit'] );
-               $this->assertArrayNotHasKey( 'nochange', $apiResult['edit'] );
-
-               $this->assertArrayHasKey( 'pageid', $apiResult['edit'] );
-
-               // validate resulting revision
-               $page = WikiPage::factory( Title::newFromText( $name ) );
-               $this->assertEquals( "testing", $page->getContentModel() );
-               $this->assertEquals( $data, $page->getContent()->serialize() );
        }
 
        /**
@@ -493,4 +471,45 @@
 
                $page->clear();
        }
+
+       public function testCheckDirectApiEditingDisallowed_forNonTextContent() 
{
+               $this->setExpectedException(
+                       'UsageException',
+                       'Direct editing via API is not supported for this 
content type.'
+               );
+
+               $this->doApiRequestWithToken( array(
+                       'action' => 'edit',
+                       'title' => 'Dummy:ApiEditPageTest_nonTextPageEdit',
+                       'text' => '{"animals":["kittens!"]}'
+               ) );
+       }
+
+       public function 
testSupportsDirectApiEditing_withContentHandlerOverride() {
+               $name = 'DummyNonText:ApiEditPageTest_testNonTextEdit';
+               $data = serialize( 'some bla bla text' );
+
+               $result = $this->doApiRequestWithToken( array(
+                       'action' => 'edit',
+                       'title' => $name,
+                       'text' => $data,
+               ) );
+
+               $apiResult = $result[0];
+
+               // Validate API result data
+               $this->assertArrayHasKey( 'edit', $apiResult );
+               $this->assertArrayHasKey( 'result', $apiResult['edit'] );
+               $this->assertEquals( 'Success', $apiResult['edit']['result'] );
+
+               $this->assertArrayHasKey( 'new', $apiResult['edit'] );
+               $this->assertArrayNotHasKey( 'nochange', $apiResult['edit'] );
+
+               $this->assertArrayHasKey( 'pageid', $apiResult['edit'] );
+
+               // validate resulting revision
+               $page = WikiPage::factory( Title::newFromText( $name ) );
+               $this->assertEquals( "testing-nontext", 
$page->getContentModel() );
+               $this->assertEquals( $data, $page->getContent()->serialize() );
+       }
 }
diff --git a/tests/phpunit/includes/content/ContentHandlerTest.php 
b/tests/phpunit/includes/content/ContentHandlerTest.php
index 988a59e..63743eb 100644
--- a/tests/phpunit/includes/content/ContentHandlerTest.php
+++ b/tests/phpunit/includes/content/ContentHandlerTest.php
@@ -338,6 +338,11 @@
        }
        */
 
+       public function testSupportsDirectEditing() {
+               $handler = new DummyContentHandlerForTesting( 
CONTENT_MODEL_JSON );
+               $this->assertFalse( $handler->supportsDirectEditing(), 'direct 
editing is not supported' );
+       }
+
        /**
         * @covers ContentHandler::runLegacyHooks
         */
@@ -363,166 +368,5 @@
                $text = strtoupper( $text );
 
                return true;
-       }
-}
-
-class DummyContentHandlerForTesting extends ContentHandler {
-
-       public function __construct( $dataModel ) {
-               parent::__construct( $dataModel, array( "testing" ) );
-       }
-
-       /**
-        * @see ContentHandler::serializeContent
-        *
-        * @param Content $content
-        * @param string $format
-        *
-        * @return string
-        */
-       public function serializeContent( Content $content, $format = null ) {
-               return $content->serialize();
-       }
-
-       /**
-        * @see ContentHandler::unserializeContent
-        *
-        * @param string $blob
-        * @param string $format Unused.
-        *
-        * @return Content
-        */
-       public function unserializeContent( $blob, $format = null ) {
-               $d = unserialize( $blob );
-
-               return new DummyContentForTesting( $d );
-       }
-
-       /**
-        * Creates an empty Content object of the type supported by this 
ContentHandler.
-        *
-        */
-       public function makeEmptyContent() {
-               return new DummyContentForTesting( '' );
-       }
-}
-
-class DummyContentForTesting extends AbstractContent {
-
-       public function __construct( $data ) {
-               parent::__construct( "testing" );
-
-               $this->data = $data;
-       }
-
-       public function serialize( $format = null ) {
-               return serialize( $this->data );
-       }
-
-       /**
-        * @return string A string representing the content in a way useful for
-        *   building a full text search index. If no useful representation 
exists,
-        *   this method returns an empty string.
-        */
-       public function getTextForSearchIndex() {
-               return '';
-       }
-
-       /**
-        * @return string|bool The wikitext to include when another page 
includes this  content,
-        *  or false if the content is not includable in a wikitext page.
-        */
-       public function getWikitextForTransclusion() {
-               return false;
-       }
-
-       /**
-        * Returns a textual representation of the content suitable for use in 
edit
-        * summaries and log messages.
-        *
-        * @param int $maxlength Maximum length of the summary text.
-        * @return string The summary text.
-        */
-       public function getTextForSummary( $maxlength = 250 ) {
-               return '';
-       }
-
-       /**
-        * Returns native represenation of the data. Interpretation depends on 
the data model used,
-        * as given by getDataModel().
-        *
-        * @return mixed The native representation of the content. Could be a 
string, a nested array
-        *  structure, an object, a binary blob... anything, really.
-        */
-       public function getNativeData() {
-               return $this->data;
-       }
-
-       /**
-        * returns the content's nominal size in bogo-bytes.
-        *
-        * @return int
-        */
-       public function getSize() {
-               return strlen( $this->data );
-       }
-
-       /**
-        * Return a copy of this Content object. The following must be true for 
the object returned
-        * if $copy = $original->copy()
-        *
-        * * get_class($original) === get_class($copy)
-        * * $original->getModel() === $copy->getModel()
-        * * $original->equals( $copy )
-        *
-        * If and only if the Content object is imutable, the copy() method can 
and should
-        * return $this. That is,  $copy === $original may be true, but only 
for imutable content
-        * objects.
-        *
-        * @return Content A copy of this object
-        */
-       public function copy() {
-               return $this;
-       }
-
-       /**
-        * Returns true if this content is countable as a "real" wiki page, 
provided
-        * that it's also in a countable location (e.g. a current revision in 
the main namespace).
-        *
-        * @param bool $hasLinks If it is known whether this content contains 
links,
-        * provide this information here, to avoid redundant parsing to find 
out.
-        * @return bool
-        */
-       public function isCountable( $hasLinks = null ) {
-               return false;
-       }
-
-       /**
-        * @param Title $title
-        * @param int $revId Unused.
-        * @param null|ParserOptions $options
-        * @param bool $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() );
-       }
-
-       /**
-        * @see AbstractContent::fillParserOutput()
-        *
-        * @param Title $title Context title for parsing
-        * @param int|null $revId Revision ID (for {{REVISIONID}})
-        * @param ParserOptions $options Parser options
-        * @param bool $generateHtml Whether or not to generate HTML
-        * @param ParserOutput &$output 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/TextContentHandlerTest.php 
b/tests/phpunit/includes/content/TextContentHandlerTest.php
new file mode 100644
index 0000000..33861f1
--- /dev/null
+++ b/tests/phpunit/includes/content/TextContentHandlerTest.php
@@ -0,0 +1,13 @@
+<?php
+
+/**
+ * @group ContentHandler
+ */
+class TextContentHandlerTest extends MediaWikiLangTestCase {
+
+       public function testSupportsDirectEditing() {
+               $handler = new TextContentHandler();
+               $this->assertTrue( $handler->supportsDirectEditing(), 'direct 
editing is supported' );
+       }
+
+}
diff --git a/tests/phpunit/includes/content/WikitextContentHandlerTest.php 
b/tests/phpunit/includes/content/WikitextContentHandlerTest.php
index 38fb573..361238b 100644
--- a/tests/phpunit/includes/content/WikitextContentHandlerTest.php
+++ b/tests/phpunit/includes/content/WikitextContentHandlerTest.php
@@ -115,6 +115,11 @@
                $this->assertEquals( $supported, 
$this->handler->isSupportedFormat( $format ) );
        }
 
+       public function testSupportsDirectEditing() {
+               $handler = new WikiTextContentHandler();
+               $this->assertTrue( $handler->supportsDirectEditing(), 'direct 
editing is supported' );
+       }
+
        public static function dataMerge3() {
                return array(
                        array(
diff --git a/tests/phpunit/mocks/content/DummyContentForTesting.php 
b/tests/phpunit/mocks/content/DummyContentForTesting.php
new file mode 100644
index 0000000..0c69027
--- /dev/null
+++ b/tests/phpunit/mocks/content/DummyContentForTesting.php
@@ -0,0 +1,121 @@
+<?php
+
+class DummyContentForTesting extends AbstractContent {
+
+       public function __construct( $data ) {
+               parent::__construct( "testing" );
+
+               $this->data = $data;
+       }
+
+       public function serialize( $format = null ) {
+               return serialize( $this->data );
+       }
+
+       /**
+        * @return string A string representing the content in a way useful for
+        *   building a full text search index. If no useful representation 
exists,
+        *   this method returns an empty string.
+        */
+       public function getTextForSearchIndex() {
+               return '';
+       }
+
+       /**
+        * @return string|bool The wikitext to include when another page 
includes this  content,
+        *  or false if the content is not includable in a wikitext page.
+        */
+       public function getWikitextForTransclusion() {
+               return false;
+       }
+
+       /**
+        * Returns a textual representation of the content suitable for use in 
edit
+        * summaries and log messages.
+        *
+        * @param int $maxlength Maximum length of the summary text.
+        * @return string The summary text.
+        */
+       public function getTextForSummary( $maxlength = 250 ) {
+               return '';
+       }
+
+       /**
+        * Returns native represenation of the data. Interpretation depends on 
the data model used,
+        * as given by getDataModel().
+        *
+        * @return mixed The native representation of the content. Could be a 
string, a nested array
+        *  structure, an object, a binary blob... anything, really.
+        */
+       public function getNativeData() {
+               return $this->data;
+       }
+
+       /**
+        * returns the content's nominal size in bogo-bytes.
+        *
+        * @return int
+        */
+       public function getSize() {
+               return strlen( $this->data );
+       }
+
+       /**
+        * Return a copy of this Content object. The following must be true for 
the object returned
+        * if $copy = $original->copy()
+        *
+        * * get_class($original) === get_class($copy)
+        * * $original->getModel() === $copy->getModel()
+        * * $original->equals( $copy )
+        *
+        * If and only if the Content object is imutable, the copy() method can 
and should
+        * return $this. That is,  $copy === $original may be true, but only 
for imutable content
+        * objects.
+        *
+        * @return Content A copy of this object
+        */
+       public function copy() {
+               return $this;
+       }
+
+       /**
+        * Returns true if this content is countable as a "real" wiki page, 
provided
+        * that it's also in a countable location (e.g. a current revision in 
the main namespace).
+        *
+        * @param bool $hasLinks If it is known whether this content contains 
links,
+        * provide this information here, to avoid redundant parsing to find 
out.
+        * @return bool
+        */
+       public function isCountable( $hasLinks = null ) {
+               return false;
+       }
+
+       /**
+        * @param Title $title
+        * @param int $revId Unused.
+        * @param null|ParserOptions $options
+        * @param bool $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() );
+       }
+
+       /**
+        * @see AbstractContent::fillParserOutput()
+        *
+        * @param Title $title Context title for parsing
+        * @param int|null $revId Revision ID (for {{REVISIONID}})
+        * @param ParserOptions $options Parser options
+        * @param bool $generateHtml Whether or not to generate HTML
+        * @param ParserOutput &$output 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/mocks/content/DummyContentHandlerForTesting.php 
b/tests/phpunit/mocks/content/DummyContentHandlerForTesting.php
new file mode 100644
index 0000000..fd253f2
--- /dev/null
+++ b/tests/phpunit/mocks/content/DummyContentHandlerForTesting.php
@@ -0,0 +1,42 @@
+<?php
+
+class DummyContentHandlerForTesting extends ContentHandler {
+
+       public function __construct( $dataModel ) {
+               parent::__construct( $dataModel, array( "testing" ) );
+       }
+
+       /**
+        * @see ContentHandler::serializeContent
+        *
+        * @param Content $content
+        * @param string $format
+        *
+        * @return string
+        */
+       public function serializeContent( Content $content, $format = null ) {
+               return $content->serialize();
+       }
+
+       /**
+        * @see ContentHandler::unserializeContent
+        *
+        * @param string $blob
+        * @param string $format Unused.
+        *
+        * @return Content
+        */
+       public function unserializeContent( $blob, $format = null ) {
+               $d = unserialize( $blob );
+
+               return new DummyContentForTesting( $d );
+       }
+
+       /**
+        * Creates an empty Content object of the type supported by this 
ContentHandler.
+        *
+        */
+       public function makeEmptyContent() {
+               return new DummyContentForTesting( '' );
+       }
+}
diff --git a/tests/phpunit/mocks/content/DummyNonTextContent.php 
b/tests/phpunit/mocks/content/DummyNonTextContent.php
new file mode 100644
index 0000000..889efb7
--- /dev/null
+++ b/tests/phpunit/mocks/content/DummyNonTextContent.php
@@ -0,0 +1,121 @@
+<?php
+
+class DummyNonTextContent extends AbstractContent {
+
+       public function __construct( $data ) {
+               parent::__construct( "testing-nontext" );
+
+               $this->data = $data;
+       }
+
+       public function serialize( $format = null ) {
+               return serialize( $this->data );
+       }
+
+       /**
+        * @return string A string representing the content in a way useful for
+        *   building a full text search index. If no useful representation 
exists,
+        *   this method returns an empty string.
+        */
+       public function getTextForSearchIndex() {
+               return '';
+       }
+
+       /**
+        * @return string|bool The wikitext to include when another page 
includes this  content,
+        *  or false if the content is not includable in a wikitext page.
+        */
+       public function getWikitextForTransclusion() {
+               return false;
+       }
+
+       /**
+        * Returns a textual representation of the content suitable for use in 
edit
+        * summaries and log messages.
+        *
+        * @param int $maxlength Maximum length of the summary text.
+        * @return string The summary text.
+        */
+       public function getTextForSummary( $maxlength = 250 ) {
+               return '';
+       }
+
+       /**
+        * Returns native represenation of the data. Interpretation depends on 
the data model used,
+        * as given by getDataModel().
+        *
+        * @return mixed The native representation of the content. Could be a 
string, a nested array
+        *  structure, an object, a binary blob... anything, really.
+        */
+       public function getNativeData() {
+               return $this->data;
+       }
+
+       /**
+        * returns the content's nominal size in bogo-bytes.
+        *
+        * @return int
+        */
+       public function getSize() {
+               return strlen( $this->data );
+       }
+
+       /**
+        * Return a copy of this Content object. The following must be true for 
the object returned
+        * if $copy = $original->copy()
+        *
+        * * get_class($original) === get_class($copy)
+        * * $original->getModel() === $copy->getModel()
+        * * $original->equals( $copy )
+        *
+        * If and only if the Content object is imutable, the copy() method can 
and should
+        * return $this. That is,  $copy === $original may be true, but only 
for imutable content
+        * objects.
+        *
+        * @return Content A copy of this object
+        */
+       public function copy() {
+               return $this;
+       }
+
+       /**
+        * Returns true if this content is countable as a "real" wiki page, 
provided
+        * that it's also in a countable location (e.g. a current revision in 
the main namespace).
+        *
+        * @param bool $hasLinks If it is known whether this content contains 
links,
+        * provide this information here, to avoid redundant parsing to find 
out.
+        * @return bool
+        */
+       public function isCountable( $hasLinks = null ) {
+               return false;
+       }
+
+       /**
+        * @param Title $title
+        * @param int $revId Unused.
+        * @param null|ParserOptions $options
+        * @param bool $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() );
+       }
+
+       /**
+        * @see AbstractContent::fillParserOutput()
+        *
+        * @param Title $title Context title for parsing
+        * @param int|null $revId Revision ID (for {{REVISIONID}})
+        * @param ParserOptions $options Parser options
+        * @param bool $generateHtml Whether or not to generate HTML
+        * @param ParserOutput &$output 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/mocks/content/DummyNonTextContentHandler.php 
b/tests/phpunit/mocks/content/DummyNonTextContentHandler.php
new file mode 100644
index 0000000..6995ae7
--- /dev/null
+++ b/tests/phpunit/mocks/content/DummyNonTextContentHandler.php
@@ -0,0 +1,46 @@
+<?php
+
+class DummyNonTextContentHandler extends DummyContentHandlerForTesting {
+
+       public function __construct( $dataModel ) {
+               parent::__construct( $dataModel, array( "testing-nontext" ) );
+       }
+
+       /**
+        * @see ContentHandler::serializeContent
+        *
+        * @param Content $content
+        * @param string $format
+        *
+        * @return string
+        */
+       public function serializeContent( Content $content, $format = null ) {
+               return $content->serialize();
+       }
+
+       /**
+        * @see ContentHandler::unserializeContent
+        *
+        * @param string $blob
+        * @param string $format Unused.
+        *
+        * @return Content
+        */
+       public function unserializeContent( $blob, $format = null ) {
+               $d = unserialize( $blob );
+
+               return new DummyNonTextContent( $d );
+       }
+
+       /**
+        * Creates an empty Content object of the type supported by this 
ContentHandler.
+        */
+       public function makeEmptyContent() {
+               return new DummyNonTextContent( '' );
+       }
+
+       public function supportsDirectApiEditing() {
+               return true;
+       }
+
+}

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

Gerrit-MessageType: merged
Gerrit-Change-Id: I276cd6ecedf38108f1f2be16b38e699e8c5d2d0c
Gerrit-PatchSet: 8
Gerrit-Project: mediawiki/core
Gerrit-Branch: master
Gerrit-Owner: Aude <[email protected]>
Gerrit-Reviewer: Anomie <[email protected]>
Gerrit-Reviewer: Aude <[email protected]>
Gerrit-Reviewer: Bene <[email protected]>
Gerrit-Reviewer: Daniel Kinzler <[email protected]>
Gerrit-Reviewer: EBernhardson <[email protected]>
Gerrit-Reviewer: Hoo man <[email protected]>
Gerrit-Reviewer: Legoktm <[email protected]>
Gerrit-Reviewer: Tpt <[email protected]>
Gerrit-Reviewer: jenkins-bot <>

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

Reply via email to