* (bug 15484) Users will now be redirected to the login page when they need to
log in, rather than being shown a page asking them to log in and having to click
another link to actually get to the login page.
-* A JSONContent and JSONContentHandler were added for extensions to extend.
+* A JsonContent and JsonContentHandler were added for extensions to extend.
* (bug 35045) Redirects to sections will now update the URL in browser's address
bar using the HTML5 History API. When [[Dog]] redirects to [[Animals#Dog]],
the user will now see "Animals#Dog" in their browser instead of "Dog#Dog".
# includes/content
'AbstractContent' => 'includes/content/AbstractContent.php',
- 'ContentHandler' => 'includes/content/ContentHandler.php',
+ 'CodeContentHandler' => 'includes/content/CodeContentHandler.php',
'Content' => 'includes/content/Content.php',
- 'CssContentHandler' => 'includes/content/CssContentHandler.php',
+ 'ContentHandler' => 'includes/content/ContentHandler.php',
'CssContent' => 'includes/content/CssContent.php',
- 'JavaScriptContentHandler' => 'includes/content/JavaScriptContentHandler.php',
+ 'CssContentHandler' => 'includes/content/CssContentHandler.php',
'JavaScriptContent' => 'includes/content/JavaScriptContent.php',
- 'JSONContentHandler' => 'includes/content/JSONContentHandler.php',
- 'JSONContent' => 'includes/content/JSONContent.php',
+ 'JavaScriptContentHandler' => 'includes/content/JavaScriptContentHandler.php',
+ 'JsonContent' => 'includes/content/JsonContent.php',
+ 'JsonContentHandler' => 'includes/content/JsonContentHandler.php',
'MessageContent' => 'includes/content/MessageContent.php',
'MWContentSerializationException' => 'includes/content/ContentHandler.php',
- 'TextContentHandler' => 'includes/content/TextContentHandler.php',
'TextContent' => 'includes/content/TextContent.php',
- 'WikitextContentHandler' => 'includes/content/WikitextContentHandler.php',
+ 'TextContentHandler' => 'includes/content/TextContentHandler.php',
'WikitextContent' => 'includes/content/WikitextContent.php',
+ 'WikitextContentHandler' => 'includes/content/WikitextContentHandler.php',
# includes/context
'ContextSource' => 'includes/context/ContextSource.php',
// dumb version, no syntax highlighting
CONTENT_MODEL_JAVASCRIPT => 'JavaScriptContentHandler',
// simple implementation, for use by extensions, etc.
- CONTENT_MODEL_JSON => 'JSONContentHandler',
+ CONTENT_MODEL_JSON => 'JsonContentHandler',
// dumb version, no syntax highlighting
CONTENT_MODEL_CSS => 'CssContentHandler',
// plain text, for use by extensions, etc.
--- /dev/null
+<?php
+/**
+ * Content handler for the pages with code, such as CSS, JavaScript, JSON.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ * @ingroup Content
+ */
+
+/**
+ * Content handler for code content such as CSS, JavaScript, JSON, etc
+ * @since 1.24
+ * @ingroup Content
+ */
+abstract class CodeContentHandler extends TextContentHandler {
+
+ /**
+ * Returns the english language, because code is english, and should be handled as such.
+ *
+ * @param Title $title
+ * @param Content $content
+ *
+ * @return Language Return of wfGetLangObj( 'en' )
+ *
+ * @see ContentHandler::getPageLanguage()
+ */
+ public function getPageLanguage( Title $title, Content $content = null ) {
+ return wfGetLangObj( 'en' );
+ }
+
+ /**
+ * Returns the english language, because code is english, and should be handled as such.
+ *
+ * @param Title $title
+ * @param Content $content
+ *
+ * @return Language Return of wfGetLangObj( 'en' )
+ *
+ * @see ContentHandler::getPageViewLanguage()
+ */
+ public function getPageViewLanguage( Title $title, Content $content = null ) {
+ return wfGetLangObj( 'en' );
+ }
+
+ /**
+ * @return string
+ */
+ protected function getContentClass() {
+ throw new MWException( 'Subclass must override' );
+ }
+}
* @since 1.21
* @ingroup Content
*/
-class CssContentHandler extends TextContentHandler {
+class CssContentHandler extends CodeContentHandler {
/**
* @param string $modelId
protected function getContentClass() {
return 'CssContent';
}
-
- /**
- * Returns the english language, because CSS is english, and should be handled as such.
- *
- * @param Title $title
- * @param Content $content
- *
- * @return Language Return of wfGetLangObj( 'en' )
- *
- * @see ContentHandler::getPageLanguage()
- */
- public function getPageLanguage( Title $title, Content $content = null ) {
- return wfGetLangObj( 'en' );
- }
-
- /**
- * Returns the english language, because CSS is english, and should be handled as such.
- *
- * @param Title $title
- * @param Content $content
- *
- * @return Language Return of wfGetLangObj( 'en' )
- *
- * @see ContentHandler::getPageViewLanguage()
- */
- public function getPageViewLanguage( Title $title, Content $content = null ) {
- return wfGetLangObj( 'en' );
- }
-
}
+++ /dev/null
-<?php
-/**
- * JSON Content Model
- *
- * @file
- *
- * @author Ori Livneh <ori@wikimedia.org>
- * @author Kunal Mehta <legoktm@gmail.com>
- */
-
-/**
- * Represents the content of a JSON content.
- * @since 1.24
- */
-class JSONContent extends TextContent {
-
- public function __construct( $text, $modelId = CONTENT_MODEL_JSON ) {
- parent::__construct( $text, $modelId );
- }
-
- /**
- * Decodes the JSON into a PHP associative array.
- * @return array
- */
- public function getJsonData() {
- return FormatJson::decode( $this->getNativeData(), true );
- }
-
- /**
- * @return bool Whether content is valid JSON.
- */
- public function isValid() {
- return $this->getJsonData() !== null;
- }
-
- /**
- * Pretty-print JSON
- *
- * @return bool|null|string
- */
- public function beautifyJSON() {
- $decoded = FormatJson::decode( $this->getNativeData(), true );
- if ( !is_array( $decoded ) ) {
- return null;
- }
- return FormatJson::encode( $decoded, true );
-
- }
-
- /**
- * Beautifies JSON prior to save.
- * @param Title $title Title
- * @param User $user User
- * @param ParserOptions $popts
- * @return JSONContent
- */
- public function preSaveTransform( Title $title, User $user, ParserOptions $popts ) {
- return new static( $this->beautifyJSON() );
- }
-
- /**
- * Set the HTML and add the appropriate styles
- *
- *
- * @param Title $title
- * @param int $revId
- * @param ParserOptions $options
- * @param bool $generateHtml
- * @param ParserOutput $output
- */
- protected function fillParserOutput( Title $title, $revId,
- ParserOptions $options, $generateHtml, ParserOutput &$output
- ) {
- if ( $generateHtml ) {
- $output->setText( $this->objectTable( $this->getJsonData() ) );
- $output->addModuleStyles( 'mediawiki.content.json' );
- } else {
- $output->setText( '' );
- }
- }
- /**
- * Constructs an HTML representation of a JSON object.
- * @param array $mapping
- * @return string HTML
- */
- protected function objectTable( $mapping ) {
- $rows = array();
-
- foreach ( $mapping as $key => $val ) {
- $rows[] = $this->objectRow( $key, $val );
- }
- return Xml::tags( 'table', array( 'class' => 'mw-json' ),
- Xml::tags( 'tbody', array(), join( "\n", $rows ) )
- );
- }
-
- /**
- * Constructs HTML representation of a single key-value pair.
- * @param string $key
- * @param mixed $val
- * @return string HTML.
- */
- protected function objectRow( $key, $val ) {
- $th = Xml::elementClean( 'th', array(), $key );
- if ( is_array( $val ) ) {
- $td = Xml::tags( 'td', array(), self::objectTable( $val ) );
- } else {
- if ( is_string( $val ) ) {
- $val = '"' . $val . '"';
- } else {
- $val = FormatJson::encode( $val );
- }
-
- $td = Xml::elementClean( 'td', array( 'class' => 'value' ), $val );
- }
-
- return Xml::tags( 'tr', array(), $th . $td );
- }
-
-}
+++ /dev/null
-<?php
-/**
- * JSON Schema Content Handler
- *
- * @file
- *
- * @author Ori Livneh <ori@wikimedia.org>
- * @author Kunal Mehta <legoktm@gmail.com>
- */
-
-/**
- * @since 1.24
- */
-class JSONContentHandler extends TextContentHandler {
-
- public function __construct( $modelId = CONTENT_MODEL_JSON ) {
- parent::__construct( $modelId, array( CONTENT_FORMAT_JSON ) );
- }
-
- /**
- * @return string
- */
- protected function getContentClass() {
- return 'JSONContent';
- }
-
- /**
- * Returns the english language, because JSON is english, and should be handled as such.
- *
- * @param Title $title
- * @param Content|null $content
- *
- * @return Language Return of wfGetLangObj( 'en' )
- *
- * @see ContentHandler::getPageLanguage()
- */
- public function getPageLanguage( Title $title, Content $content = null ) {
- return wfGetLangObj( 'en' );
- }
-
- /**
- * Returns the english language, because JSON is english, and should be handled as such.
- *
- * @param Title $title
- * @param Content|null $content
- *
- * @return Language Return of wfGetLangObj( 'en' )
- *
- * @see ContentHandler::getPageLanguage()
- */
- public function getPageViewLanguage( Title $title, Content $content = null ) {
- return wfGetLangObj( 'en' );
- }
-}
* @ingroup Content
* @todo make ScriptContentHandler base class, do highlighting stuff there?
*/
-class JavaScriptContentHandler extends TextContentHandler {
+class JavaScriptContentHandler extends CodeContentHandler {
/**
* @param string $modelId
protected function getContentClass() {
return 'JavaScriptContent';
}
-
- /**
- * Returns the english language, because JS is english, and should be handled as such.
- *
- * @param Title $title
- * @param Content $content
- *
- * @return Language Return of wfGetLangObj( 'en' )
- *
- * @see ContentHandler::getPageLanguage()
- */
- public function getPageLanguage( Title $title, Content $content = null ) {
- return wfGetLangObj( 'en' );
- }
-
- /**
- * Returns the english language, because JS is english, and should be handled as such.
- *
- * @param Title $title
- * @param Content $content
- *
- * @return Language Return of wfGetLangObj( 'en' )
- *
- * @see ContentHandler::getPageViewLanguage()
- */
- public function getPageViewLanguage( Title $title, Content $content = null ) {
- return wfGetLangObj( 'en' );
- }
-
}
--- /dev/null
+<?php
+/**
+ * JSON Content Model
+ *
+ * @file
+ *
+ * @author Ori Livneh <ori@wikimedia.org>
+ * @author Kunal Mehta <legoktm@gmail.com>
+ */
+
+/**
+ * Represents the content of a JSON content.
+ * @since 1.24
+ */
+class JsonContent extends TextContent {
+
+ public function __construct( $text, $modelId = CONTENT_MODEL_JSON ) {
+ parent::__construct( $text, $modelId );
+ }
+
+ /**
+ * Decodes the JSON into a PHP associative array.
+ * @return array
+ */
+ public function getJsonData() {
+ return FormatJson::decode( $this->getNativeData(), true );
+ }
+
+ /**
+ * @return bool Whether content is valid JSON.
+ */
+ public function isValid() {
+ return $this->getJsonData() !== null;
+ }
+
+ /**
+ * Pretty-print JSON
+ *
+ * @return bool|null|string
+ */
+ public function beautifyJSON() {
+ $decoded = FormatJson::decode( $this->getNativeData(), true );
+ if ( !is_array( $decoded ) ) {
+ return null;
+ }
+ return FormatJson::encode( $decoded, true );
+
+ }
+
+ /**
+ * Beautifies JSON prior to save.
+ * @param Title $title Title
+ * @param User $user User
+ * @param ParserOptions $popts
+ * @return JsonContent
+ */
+ public function preSaveTransform( Title $title, User $user, ParserOptions $popts ) {
+ return new static( $this->beautifyJSON() );
+ }
+
+ /**
+ * Set the HTML and add the appropriate styles
+ *
+ *
+ * @param Title $title
+ * @param int $revId
+ * @param ParserOptions $options
+ * @param bool $generateHtml
+ * @param ParserOutput $output
+ */
+ protected function fillParserOutput( Title $title, $revId,
+ ParserOptions $options, $generateHtml, ParserOutput &$output
+ ) {
+ if ( $generateHtml ) {
+ $output->setText( $this->objectTable( $this->getJsonData() ) );
+ $output->addModuleStyles( 'mediawiki.content.json' );
+ } else {
+ $output->setText( '' );
+ }
+ }
+ /**
+ * Constructs an HTML representation of a JSON object.
+ * @param array $mapping
+ * @return string HTML
+ */
+ protected function objectTable( $mapping ) {
+ $rows = array();
+
+ foreach ( $mapping as $key => $val ) {
+ $rows[] = $this->objectRow( $key, $val );
+ }
+ return Xml::tags( 'table', array( 'class' => 'mw-json' ),
+ Xml::tags( 'tbody', array(), join( "\n", $rows ) )
+ );
+ }
+
+ /**
+ * Constructs HTML representation of a single key-value pair.
+ * @param string $key
+ * @param mixed $val
+ * @return string HTML.
+ */
+ protected function objectRow( $key, $val ) {
+ $th = Xml::elementClean( 'th', array(), $key );
+ if ( is_array( $val ) ) {
+ $td = Xml::tags( 'td', array(), self::objectTable( $val ) );
+ } else {
+ if ( is_string( $val ) ) {
+ $val = '"' . $val . '"';
+ } else {
+ $val = FormatJson::encode( $val );
+ }
+
+ $td = Xml::elementClean( 'td', array( 'class' => 'value' ), $val );
+ }
+
+ return Xml::tags( 'tr', array(), $th . $td );
+ }
+
+}
--- /dev/null
+<?php
+/**
+ * JSON Schema Content Handler
+ *
+ * @file
+ *
+ * @author Ori Livneh <ori@wikimedia.org>
+ * @author Kunal Mehta <legoktm@gmail.com>
+ */
+
+/**
+ * @since 1.24
+ */
+class JsonContentHandler extends CodeContentHandler {
+
+ public function __construct( $modelId = CONTENT_MODEL_JSON ) {
+ parent::__construct( $modelId, array( CONTENT_FORMAT_JSON ) );
+ }
+
+ /**
+ * @return string
+ */
+ protected function getContentClass() {
+ return 'JsonContent';
+ }
+}
* Wrapper allowing us to handle a system message as a Content object.
* Note that this is generally *not* used to represent content from the
* MediaWiki namespace, and that there is no MessageContentHandler.
- * MessageContent is just intended as glue for wrapping a message programatically.
+ * MessageContent is just intended as glue for wrapping a message programmatically.
*
* @ingroup Content
*/
+++ /dev/null
-<?php
-
-/**
- * @author Adam Shorland
- * @covers JSONContent
- */
-class JSONContentTest extends MediaWikiLangTestCase {
-
- /**
- * @dataProvider provideValidConstruction
- */
- public function testValidConstruct( $text, $modelId, $isValid, $expected ) {
- $obj = new JSONContent( $text, $modelId );
- $this->assertEquals( $isValid, $obj->isValid() );
- $this->assertEquals( $expected, $obj->getJsonData() );
- }
-
- public function provideValidConstruction() {
- return array(
- array( 'foo', CONTENT_MODEL_JSON, false, null ),
- array( FormatJson::encode( array() ), CONTENT_MODEL_JSON, true, array() ),
- array( FormatJson::encode( array( 'foo' ) ), CONTENT_MODEL_JSON, true, array( 'foo' ) ),
- );
- }
-
- /**
- * @dataProvider provideDataToEncode
- */
- public function testBeautifyUsesFormatJson( $data ) {
- $obj = new JSONContent( FormatJson::encode( $data ) );
- $this->assertEquals( FormatJson::encode( $data, true ), $obj->beautifyJSON() );
- }
-
- public function provideDataToEncode() {
- return array(
- array( array() ),
- array( array( 'foo' ) ),
- array( array( 'foo', 'bar' ) ),
- array( array( 'baz' => 'foo', 'bar' ) ),
- array( array( 'baz' => 1000, 'bar' ) ),
- );
- }
-
- /**
- * @dataProvider provideDataToEncode
- */
- public function testPreSaveTransform( $data ) {
- $obj = new JSONContent( FormatJson::encode( $data ) );
- $newObj = $obj->preSaveTransform( $this->getMockTitle(), $this->getMockUser(), $this->getMockParserOptions() );
- $this->assertTrue( $newObj->equals( new JSONContent( FormatJson::encode( $data, true ) ) ) );
- }
-
- private function getMockTitle() {
- return $this->getMockBuilder( 'Title' )
- ->disableOriginalConstructor()
- ->getMock();
- }
-
- private function getMockUser() {
- return $this->getMockBuilder( 'User' )
- ->disableOriginalConstructor()
- ->getMock();
- }
- private function getMockParserOptions() {
- return $this->getMockBuilder( 'ParserOptions' )
- ->disableOriginalConstructor()
- ->getMock();
- }
-
- /**
- * @dataProvider provideDataAndParserText
- */
- public function testFillParserOutput( $data, $expected ) {
- $obj = new JSONContent( FormatJson::encode( $data ) );
- $parserOutput = $obj->getParserOutput( $this->getMockTitle(), null, null, true );
- $this->assertInstanceOf( 'ParserOutput', $parserOutput );
-// var_dump( $parserOutput->getText(), "\n" );
- $this->assertEquals( $expected, $parserOutput->getText() );
- }
-
- public function provideDataAndParserText() {
- return array(
- array(
- array(),
- '<table class="mw-json"><tbody></tbody></table>'
- ),
- array(
- array( 'foo' ),
- '<table class="mw-json"><tbody><tr><th>0</th><td class="value">"foo"</td></tr></tbody></table>'
- ),
- array(
- array( 'foo', 'bar' ),
- '<table class="mw-json"><tbody><tr><th>0</th><td class="value">"foo"</td></tr>' .
- "\n" .
- '<tr><th>1</th><td class="value">"bar"</td></tr></tbody></table>'
- ),
- array(
- array( 'baz' => 'foo', 'bar' ),
- '<table class="mw-json"><tbody><tr><th>baz</th><td class="value">"foo"</td></tr>' .
- "\n" .
- '<tr><th>0</th><td class="value">"bar"</td></tr></tbody></table>'
- ),
- array(
- array( 'baz' => 1000, 'bar' ),
- '<table class="mw-json"><tbody><tr><th>baz</th><td class="value">1000</td></tr>' .
- "\n" .
- '<tr><th>0</th><td class="value">"bar"</td></tr></tbody></table>'
- ),
- array(
- array( '<script>alert("evil!")</script>'),
- '<table class="mw-json"><tbody><tr><th>0</th><td class="value">"<script>alert("evil!")</script>"</td></tr></tbody></table>',
- ),
- );
- }
-}
--- /dev/null
+<?php
+
+/**
+ * @author Adam Shorland
+ * @covers JsonContent
+ */
+class JsonContentTest extends MediaWikiLangTestCase {
+
+ /**
+ * @dataProvider provideValidConstruction
+ */
+ public function testValidConstruct( $text, $modelId, $isValid, $expected ) {
+ $obj = new JsonContent( $text, $modelId );
+ $this->assertEquals( $isValid, $obj->isValid() );
+ $this->assertEquals( $expected, $obj->getJsonData() );
+ }
+
+ public function provideValidConstruction() {
+ return array(
+ array( 'foo', CONTENT_MODEL_JSON, false, null ),
+ array( FormatJson::encode( array() ), CONTENT_MODEL_JSON, true, array() ),
+ array( FormatJson::encode( array( 'foo' ) ), CONTENT_MODEL_JSON, true, array( 'foo' ) ),
+ );
+ }
+
+ /**
+ * @dataProvider provideDataToEncode
+ */
+ public function testBeautifyUsesFormatJson( $data ) {
+ $obj = new JsonContent( FormatJson::encode( $data ) );
+ $this->assertEquals( FormatJson::encode( $data, true ), $obj->beautifyJSON() );
+ }
+
+ public function provideDataToEncode() {
+ return array(
+ array( array() ),
+ array( array( 'foo' ) ),
+ array( array( 'foo', 'bar' ) ),
+ array( array( 'baz' => 'foo', 'bar' ) ),
+ array( array( 'baz' => 1000, 'bar' ) ),
+ );
+ }
+
+ /**
+ * @dataProvider provideDataToEncode
+ */
+ public function testPreSaveTransform( $data ) {
+ $obj = new JsonContent( FormatJson::encode( $data ) );
+ $newObj = $obj->preSaveTransform( $this->getMockTitle(), $this->getMockUser(), $this->getMockParserOptions() );
+ $this->assertTrue( $newObj->equals( new JsonContent( FormatJson::encode( $data, true ) ) ) );
+ }
+
+ private function getMockTitle() {
+ return $this->getMockBuilder( 'Title' )
+ ->disableOriginalConstructor()
+ ->getMock();
+ }
+
+ private function getMockUser() {
+ return $this->getMockBuilder( 'User' )
+ ->disableOriginalConstructor()
+ ->getMock();
+ }
+ private function getMockParserOptions() {
+ return $this->getMockBuilder( 'ParserOptions' )
+ ->disableOriginalConstructor()
+ ->getMock();
+ }
+
+ /**
+ * @dataProvider provideDataAndParserText
+ */
+ public function testFillParserOutput( $data, $expected ) {
+ $obj = new JsonContent( FormatJson::encode( $data ) );
+ $parserOutput = $obj->getParserOutput( $this->getMockTitle(), null, null, true );
+ $this->assertInstanceOf( 'ParserOutput', $parserOutput );
+// var_dump( $parserOutput->getText(), "\n" );
+ $this->assertEquals( $expected, $parserOutput->getText() );
+ }
+
+ public function provideDataAndParserText() {
+ return array(
+ array(
+ array(),
+ '<table class="mw-json"><tbody></tbody></table>'
+ ),
+ array(
+ array( 'foo' ),
+ '<table class="mw-json"><tbody><tr><th>0</th><td class="value">"foo"</td></tr></tbody></table>'
+ ),
+ array(
+ array( 'foo', 'bar' ),
+ '<table class="mw-json"><tbody><tr><th>0</th><td class="value">"foo"</td></tr>' .
+ "\n" .
+ '<tr><th>1</th><td class="value">"bar"</td></tr></tbody></table>'
+ ),
+ array(
+ array( 'baz' => 'foo', 'bar' ),
+ '<table class="mw-json"><tbody><tr><th>baz</th><td class="value">"foo"</td></tr>' .
+ "\n" .
+ '<tr><th>0</th><td class="value">"bar"</td></tr></tbody></table>'
+ ),
+ array(
+ array( 'baz' => 1000, 'bar' ),
+ '<table class="mw-json"><tbody><tr><th>baz</th><td class="value">1000</td></tr>' .
+ "\n" .
+ '<tr><th>0</th><td class="value">"bar"</td></tr></tbody></table>'
+ ),
+ array(
+ array( '<script>alert("evil!")</script>'),
+ '<table class="mw-json"><tbody><tr><th>0</th><td class="value">"<script>alert("evil!")</script>"</td></tr></tbody></table>',
+ ),
+ );
+ }
+}