Merge "content: Recognise .json as JsonContent in User and MediaWiki namespace"
authorjenkins-bot <jenkins-bot@gerrit.wikimedia.org>
Wed, 3 Jun 2015 16:25:09 +0000 (16:25 +0000)
committerGerrit Code Review <gerrit@wikimedia.org>
Wed, 3 Jun 2015 16:25:09 +0000 (16:25 +0000)
1  2 
includes/content/ContentHandler.php
tests/phpunit/includes/content/ContentHandlerTest.php

@@@ -207,26 -207,26 +207,26 @@@ abstract class ContentHandler 
                        }
                }
  
-               // Could this page contain custom CSS or JavaScript, based on the title?
-               $isCssOrJsPage = NS_MEDIAWIKI == $ns && preg_match( '!\.(css|js)$!u', $title->getText(), $m );
-               if ( $isCssOrJsPage ) {
+               // Could this page contain code based on the title?
+               $isCodePage = NS_MEDIAWIKI == $ns && preg_match( '!\.(css|js|json)$!u', $title->getText(), $m );
+               if ( $isCodePage ) {
                        $ext = $m[1];
                }
  
                // Hook can force JS/CSS
-               Hooks::run( 'TitleIsCssOrJsPage', array( $title, &$isCssOrJsPage ), '1.25' );
+               Hooks::run( 'TitleIsCssOrJsPage', array( $title, &$isCodePage ), '1.25' );
  
-               // Is this a .css subpage of a user page?
-               $isJsCssSubpage = NS_USER == $ns
-                       && !$isCssOrJsPage
-                       && preg_match( "/\\/.*\\.(js|css)$/", $title->getText(), $m );
-               if ( $isJsCssSubpage ) {
+               // Is this a user subpage containing code?
+               $isCodeSubpage = NS_USER == $ns
+                       && !$isCodePage
+                       && preg_match( "/\\/.*\\.(js|css|json)$/", $title->getText(), $m );
+               if ( $isCodeSubpage ) {
                        $ext = $m[1];
                }
  
                // Is this wikitext, according to $wgNamespaceContentModels or the DefaultModelFor hook?
                $isWikitext = is_null( $model ) || $model == CONTENT_MODEL_WIKITEXT;
-               $isWikitext = $isWikitext && !$isCssOrJsPage && !$isJsCssSubpage;
+               $isWikitext = $isWikitext && !$isCodePage && !$isCodeSubpage;
  
                // Hook can override $isWikitext
                Hooks::run( 'TitleIsWikitextPage', array( $title, &$isWikitext ), '1.25' );
                                        return CONTENT_MODEL_JAVASCRIPT;
                                case 'css':
                                        return CONTENT_MODEL_CSS;
+                               case 'json':
+                                       return CONTENT_MODEL_JSON;
                                default:
                                        return is_null( $model ) ? CONTENT_MODEL_TEXT : $model;
                        }
        public function createDifferenceEngine( IContextSource $context, $old = 0, $new = 0,
                $rcid = 0, //FIXME: Deprecated, no longer used
                $refreshCache = false, $unhide = false ) {
 -              $diffEngineClass = $this->getDiffEngineClass();
  
 +              // hook: get difference engine
 +              $differenceEngine = null;
 +              if ( !Hooks::run( 'GetDifferenceEngine',
 +                      array( $context, $old, $new, $refreshCache, $unhide, &$differenceEngine )
 +              ) ) {
 +                      return $differenceEngine;
 +              }
 +              $diffEngineClass = $this->getDiffEngineClass();
                return new $diffEngineClass( $context, $old, $new, $rcid, $refreshCache, $unhide );
        }
  
                return false;
        }
  
 +      /**
 +       * 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.
@@@ -2,6 -2,11 +2,6 @@@
  
  /**
   * @group ContentHandler
 - * @group Database
 - *
 - * @note Declare that we are using the database, because otherwise we'll fail in
 - * the "databaseless" test run. This is because the LinkHolderArray used by the
 - * parser needs database access.
   */
  class ContentHandlerTest extends MediaWikiTestCase {
  
@@@ -22,6 -27,7 +22,7 @@@
                        'wgContentHandlers' => array(
                                CONTENT_MODEL_WIKITEXT => 'WikitextContentHandler',
                                CONTENT_MODEL_JAVASCRIPT => 'JavaScriptContentHandler',
+                               CONTENT_MODEL_JSON => 'JsonContentHandler',
                                CONTENT_MODEL_CSS => 'CssContentHandler',
                                CONTENT_MODEL_TEXT => 'TextContentHandler',
                                'testing' => 'DummyContentHandlerForTesting',
@@@ -31,8 -37,6 +32,8 @@@
                // Reset namespace cache
                MWNamespace::getCanonicalNamespaces( true );
                $wgContLang->resetNamespaces();
 +              // And LinkCache
 +              LinkCache::destroySingleton();
        }
  
        protected function tearDown() {
@@@ -41,8 -45,6 +42,8 @@@
                // Reset namespace cache
                MWNamespace::getCanonicalNamespaces( true );
                $wgContLang->resetNamespaces();
 +              // And LinkCache
 +              LinkCache::destroySingleton();
  
                parent::tearDown();
        }
                return array(
                        array( 'Help:Foo', CONTENT_MODEL_WIKITEXT ),
                        array( 'Help:Foo.js', CONTENT_MODEL_WIKITEXT ),
+                       array( 'Help:Foo.css', CONTENT_MODEL_WIKITEXT ),
+                       array( 'Help:Foo.json', CONTENT_MODEL_WIKITEXT ),
                        array( 'Help:Foo/bar.js', CONTENT_MODEL_WIKITEXT ),
                        array( 'User:Foo', CONTENT_MODEL_WIKITEXT ),
                        array( 'User:Foo.js', CONTENT_MODEL_WIKITEXT ),
+                       array( 'User:Foo.css', CONTENT_MODEL_WIKITEXT ),
+                       array( 'User:Foo.json', CONTENT_MODEL_WIKITEXT ),
                        array( 'User:Foo/bar.js', CONTENT_MODEL_JAVASCRIPT ),
                        array( 'User:Foo/bar.css', CONTENT_MODEL_CSS ),
+                       array( 'User:Foo/bar.json', CONTENT_MODEL_JSON ),
+                       array( 'User:Foo/bar.json.nope', CONTENT_MODEL_WIKITEXT ),
                        array( 'User talk:Foo/bar.css', CONTENT_MODEL_WIKITEXT ),
                        array( 'User:Foo/bar.js.xxx', CONTENT_MODEL_WIKITEXT ),
                        array( 'User:Foo/bar.xxx', CONTENT_MODEL_WIKITEXT ),
                        array( 'MediaWiki:Foo.js', CONTENT_MODEL_JAVASCRIPT ),
-                       array( 'MediaWiki:Foo.css', CONTENT_MODEL_CSS ),
                        array( 'MediaWiki:Foo.JS', CONTENT_MODEL_WIKITEXT ),
-                       array( 'MediaWiki:Foo.CSS', CONTENT_MODEL_WIKITEXT ),
+                       array( 'MediaWiki:Foo.css', CONTENT_MODEL_CSS ),
                        array( 'MediaWiki:Foo.css.xxx', CONTENT_MODEL_WIKITEXT ),
+                       array( 'MediaWiki:Foo.CSS', CONTENT_MODEL_WIKITEXT ),
+                       array( 'MediaWiki:Foo.json', CONTENT_MODEL_JSON ),
+                       array( 'MediaWiki:Foo.JSON', CONTENT_MODEL_WIKITEXT ),
                );
        }
  
@@@ -82,7 -92,6 +91,7 @@@
         */
        public function testGetForTitle( $title, $expectedContentModel ) {
                $title = Title::newFromText( $title );
 +              LinkCache::singleton()->addBadLinkObj( $title );
                $handler = ContentHandler::getForTitle( $title );
                $this->assertEquals( $expectedContentModel, $handler->getModelID() );
        }
        public function testGetPageLanguage( $title, $expected ) {
                if ( is_string( $title ) ) {
                        $title = Title::newFromText( $title );
 +                      LinkCache::singleton()->addBadLinkObj( $title );
                }
  
                $expected = wfGetLangObj( $expected );
                $expectedModelId, $expectedNativeData, $shouldFail
        ) {
                $title = Title::newFromText( $title );
 -
 +              LinkCache::singleton()->addBadLinkObj( $title );
                try {
                        $content = ContentHandler::makeContent( $data, $title, $modelId, $format );
  
        }
        */
  
 +      public function testSupportsDirectEditing() {
 +              $handler = new DummyContentHandlerForTesting( CONTENT_MODEL_JSON );
 +              $this->assertFalse( $handler->supportsDirectEditing(), 'direct editing is not supported' );
 +      }
 +
        /**
         * @covers ContentHandler::runLegacyHooks
         */
                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() );
 -      }
 -}