* Add PasswordPolicy to check the password isn't in the large blacklist.
* The AuthManagerLoginAuthenticateAudit hook has a new parameter for
additional information about the authentication event.
+* TextContent::getText() was introduced as a replacement for
+ Content::getNativeData() for text-based content models.
* …
=== External library changes in 1.33 ===
requiresUnblock() returns the proper result (the default is `true`).
* (T211608) The MediaWiki\Services namespace has been renamed to
Wikimedia\Services. The old name is still supported, but deprecated.
+* (T155582) Content::getNativeData has been deprecated. Please use model-
+ specific getters, such as TextContent::getText().
* …
=== Other changes in 1.33 ===
}
/**
+ * Decides whether two Content objects are equal.
+ * Two Content objects MUST not be considered equal if they do not share the same content model.
+ * Two Content objects that are equal SHOULD have the same serialization.
+ *
+ * This default implementation relies on equalsInternal() to determin whether the
+ * Content objects are logically equivalent. Subclasses that need to implement a custom
+ * equality check should consider overriding equalsInternal(). Subclasses that override
+ * equals() itself MUST make sure that the implementation returns false for $that === null,
+ * and true for $that === this. It MUST also return false if $that does not have the same
+ * content model.
+ *
* @since 1.21
*
* @param Content|null $that
return false;
}
- return $this->getNativeData() === $that->getNativeData();
+ // For type safety. Needed for odd cases like MessageContent using CONTENT_MODEL_WIKITEXT
+ if ( get_class( $that ) !== get_class( $this ) ) {
+ return false;
+ }
+
+ return $this->equalsInternal( $that );
+ }
+
+ /**
+ * Checks whether $that is logically equal to this Content object.
+ *
+ * This method can be overwritten by subclasses that need to implement custom
+ * equality checks.
+ *
+ * This default implementation checks whether the serializations
+ * of $this and $that are the same: $this->serialize() === $that->serialize()
+ *
+ * Implementors can assume that $that is an instance of the same class
+ * as the present Content object, as long as equalsInternal() is only called
+ * by the standard implementation of equals().
+ *
+ * @note Do not call this method directly, call equals() instead.
+ *
+ * @param Content $that
+ * @return bool
+ */
+ protected function equalsInternal( Content $that ) {
+ return $this->serialize() === $that->serialize();
}
/**
*
* @since 1.21
*
+ * @deprecated since 1.33 use getText() for TextContent instances.
+ * For other content models, use specialized getters.
+ *
* @return mixed The native representation of the content. Could be a
* string, a nested array structure, an object, a binary blob...
* anything, really.
*
* - Will return false if $that is null.
* - Will return true if $that === $this.
- * - Will return false if $that->getModel() != $this->getModel().
- * - Will return false if $that->getNativeData() is not equal to $this->getNativeData(),
- * where the meaning of "equal" depends on the actual data model.
+ * - Will return false if $that->getModel() !== $this->getModel().
+ * - Will return false if get_class( $that ) !== get_class( $this )
+ * - Should return false if $that->getModel() == $this->getModel() and
+ * $that is not semantically equivalent to $this, according to
+ * the data model defined by $this->getModel().
*
* Implementations should be careful to make equals() transitive and reflexive:
*
}
if ( $content instanceof TextContent ) {
- return $content->getNativeData();
+ return $content->getText();
}
wfDebugLog( 'ContentHandler', 'Accessing ' . $content->getModel() . ' content as text!' );
global $wgParser;
// @todo Make pre-save transformation optional for script pages
- $text = $this->getNativeData();
+ $text = $this->getText();
$pst = $wgParser->preSaveTransform( $text, $title, $user, $popts );
return new static( $pst );
protected function getHtml() {
$html = "";
$html .= "<pre class=\"mw-code mw-css\" dir=\"ltr\">\n";
- $html .= htmlspecialchars( $this->getNativeData() );
+ $html .= htmlspecialchars( $this->getText() );
$html .= "\n</pre>\n";
return $html;
return $this->redirectTarget;
}
$this->redirectTarget = null;
- $text = $this->getNativeData();
+ $text = $this->getText();
if ( strpos( $text, '/* #REDIRECT */' ) === 0 ) {
// Extract the title from the url
preg_match( '/title=(.*?)&action=raw/', $text, $matches );
// @todo Make pre-save transformation optional for script pages
// See T34858
- $text = $this->getNativeData();
+ $text = $this->getText();
$pst = $wgParser->preSaveTransform( $text, $title, $user, $popts );
return new static( $pst );
protected function getHtml() {
$html = "";
$html .= "<pre class=\"mw-code mw-js\" dir=\"ltr\">\n";
- $html .= htmlspecialchars( $this->getNativeData() );
+ $html .= htmlspecialchars( $this->getText() );
$html .= "\n</pre>\n";
return $html;
return $this->redirectTarget;
}
$this->redirectTarget = null;
- $text = $this->getNativeData();
+ $text = $this->getText();
if ( strpos( $text, '/* #REDIRECT */' ) === 0 ) {
// Extract the title from the url
preg_match( '/title=(.*?)\\\\u0026action=raw/', $text, $matches );
*/
public function getJsonData() {
wfDeprecated( __METHOD__, '1.25' );
- return FormatJson::decode( $this->getNativeData(), true );
+ return FormatJson::decode( $this->getText(), true );
}
/**
*/
public function getData() {
if ( $this->jsonParse === null ) {
- $this->jsonParse = FormatJson::parse( $this->getNativeData() );
+ $this->jsonParse = FormatJson::parse( $this->getText() );
}
return $this->jsonParse;
}
/**
* Returns the message object, with any parameters already substituted.
*
+ * @deprecated since 1.33 use getMessage() instead.
+ *
* @return Message The message object.
*/
public function getNativeData() {
+ return $this->getMessage();
+ }
+
+ /**
+ * Returns the message object, with any parameters already substituted.
+ *
+ * @since 1.33
+ *
+ * @return Message The message object.
+ */
+ public function getMessage() {
// NOTE: Message objects are mutable. Cloning here makes MessageContent immutable.
return clone $this->mMessage;
}
* @see Content::copy
*/
public function copy() {
- // MessageContent is immutable (because getNativeData() returns a clone of the Message object)
+ // MessageContent is immutable (because getNativeData() and getMessage()
+ // returns a clone of the Message object)
return $this;
}
}
public function getTextForSummary( $maxlength = 250 ) {
- $text = $this->getNativeData();
+ $text = $this->getText();
$truncatedtext = MediaWikiServices::getInstance()->getContentLanguage()->
truncateForDatabase( preg_replace( "/[\n\r]/", ' ', $text ), max( 0, $maxlength ) );
* @return int
*/
public function getSize() {
- $text = $this->getNativeData();
+ $text = $this->getText();
return strlen( $text );
}
/**
* Returns the text represented by this Content object, as a string.
*
- * @return string The raw text.
+ * @deprecated since 1.33 use getText() instead.
+ *
+ * @return string The raw text. Subclasses may guarantee a specific syntax here.
*/
public function getNativeData() {
+ return $this->getText();
+ }
+
+ /**
+ * Returns the text represented by this Content object, as a string.
+ *
+ * @since 1.33
+ *
+ * @return string The raw text.
+ */
+ public function getText() {
return $this->mText;
}
* @return string The raw text.
*/
public function getTextForSearchIndex() {
- return $this->getNativeData();
+ return $this->getText();
}
/**
$wikitext = $this->convert( CONTENT_MODEL_WIKITEXT, 'lossy' );
if ( $wikitext ) {
- return $wikitext->getNativeData();
+ return $wikitext->getText();
} else {
return false;
}
* @return Content
*/
public function preSaveTransform( Title $title, User $user, ParserOptions $popts ) {
- $text = $this->getNativeData();
+ $text = $this->getText();
$pst = self::normalizeLineEndings( $text );
return ( $text === $pst ) ? $this : new static( $pst, $this->getModel() );
$lang = MediaWikiServices::getInstance()->getContentLanguage();
}
- $otext = $this->getNativeData();
- $ntext = $that->getNativeData();
+ $otext = $this->getText();
+ $ntext = $that->getText();
# Note: Use native PHP diff, external engines don't give us abstract output
$ota = explode( "\n", $lang->segmentForDiff( $otext ) );
if ( in_array( $this->getModel(), $wgTextModelsToParse ) ) {
// parse just to get links etc into the database, HTML is replaced below.
- $output = $wgParser->parse( $this->getNativeData(), $title, $options, true, true, $revId );
+ $output = $wgParser->parse( $this->getText(), $title, $options, true, true, $revId );
}
if ( $generateHtml ) {
* @return string An HTML representation of the content
*/
protected function getHighlightHtml() {
- return htmlspecialchars( $this->getNativeData() );
+ return htmlspecialchars( $this->getText() );
}
/**
if ( $toHandler instanceof TextContentHandler ) {
// NOTE: ignore content serialization format - it's just text anyway.
- $text = $this->getNativeData();
+ $text = $this->getText();
$converted = $toHandler->unserializeContent( $text );
}
public function serializeContent( Content $content, $format = null ) {
$this->checkFormat( $format );
- return $content->getNativeData();
+ return $content->getText();
}
/**
public function getSection( $sectionId ) {
global $wgParser;
- $text = $this->getNativeData();
+ $text = $this->getText();
$sect = $wgParser->getSection( $text, $sectionId, false );
if ( $sect === false ) {
"section uses $sectionModelId." );
}
- $oldtext = $this->getNativeData();
- $text = $with->getNativeData();
+ $oldtext = $this->getText();
+ $text = $with->getText();
if ( strval( $sectionId ) === '' ) {
return $with; # XXX: copy first?
$text = wfMessage( 'newsectionheaderdefaultlevel' )
->rawParams( $header )->inContentLanguage()->text();
$text .= "\n\n";
- $text .= $this->getNativeData();
+ $text .= $this->getText();
return new static( $text );
}
public function preSaveTransform( Title $title, User $user, ParserOptions $popts ) {
global $wgParser;
- $text = $this->getNativeData();
+ $text = $this->getText();
$pst = $wgParser->preSaveTransform( $text, $title, $user, $popts );
if ( $text === $pst ) {
public function preloadTransform( Title $title, ParserOptions $popts, $params = [] ) {
global $wgParser;
- $text = $this->getNativeData();
+ $text = $this->getText();
$plt = $wgParser->getPreloadText( $text, $title, $popts, $params );
return new static( $plt );
if ( $wgMaxRedirects < 1 ) {
// redirects are disabled, so quit early
- $this->redirectTargetAndText = [ null, $this->getNativeData() ];
+ $this->redirectTargetAndText = [ null, $this->getText() ];
return $this->redirectTargetAndText;
}
$redir = MediaWikiServices::getInstance()->getMagicWordFactory()->get( 'redirect' );
- $text = ltrim( $this->getNativeData() );
+ $text = ltrim( $this->getText() );
if ( $redir->matchStartAndRemove( $text ) ) {
// Extract the first link and see if it's usable
// Ensure that it really does come directly after #REDIRECT
$title = Title::newFromText( $m[1] );
// If the title is a redirect to bad special pages or is invalid, return null
if ( !$title instanceof Title || !$title->isValidRedirectTarget() ) {
- $this->redirectTargetAndText = [ null, $this->getNativeData() ];
+ $this->redirectTargetAndText = [ null, $this->getText() ];
return $this->redirectTargetAndText;
}
}
}
- $this->redirectTargetAndText = [ null, $this->getNativeData() ];
+ $this->redirectTargetAndText = [ null, $this->getText() ];
return $this->redirectTargetAndText;
}
# so the regex has to be fairly general
$newText = preg_replace( '/ \[ \[ [^\]]* \] \] /x',
'[[' . $target->getFullText() . ']]',
- $this->getNativeData(), 1 );
+ $this->getText(), 1 );
return new static( $newText );
}
* @see Content::matchMagicWord()
*/
public function matchMagicWord( MagicWord $word ) {
- return $word->match( $this->getNativeData() );
+ return $word->match( $this->getText() );
}
}
return $fields;
}
+ /**
+ * Returns the content's text as-is.
+ *
+ * @param Content $content
+ * @param string|null $format The serialization format to check
+ *
+ * @return mixed
+ */
+ public function serializeContent( Content $content, $format = null ) {
+ $this->checkFormat( $format );
+
+ // NOTE: MessageContent also uses CONTENT_MODEL_WIKITEXT, but it's not a TextContent!
+ // Perhaps MessageContent should use a separate ContentHandler instead.
+ if ( $content instanceof MessageContent ) {
+ return $content->getMessage()->plain();
+ }
+
+ return parent::serializeContent( $content, $format );
+ }
+
}
$content = new WikitextContent( "hello world" );
$text = ContentHandler::getContentText( $content );
- $this->assertEquals( $content->getNativeData(), $text );
+ $this->assertEquals( $content->getText(), $text );
}
/**
public static function dataMakeContent() {
return [
- [ 'hallo', 'Help:Test', null, null, CONTENT_MODEL_WIKITEXT, 'hallo', false ],
- [ 'hallo', 'MediaWiki:Test.js', null, null, CONTENT_MODEL_JAVASCRIPT, 'hallo', false ],
- [ serialize( 'hallo' ), 'Dummy:Test', null, null, "testing", 'hallo', false ],
+ [ 'hallo', 'Help:Test', null, null, CONTENT_MODEL_WIKITEXT, false ],
+ [ 'hallo', 'MediaWiki:Test.js', null, null, CONTENT_MODEL_JAVASCRIPT, false ],
+ [ serialize( 'hallo' ), 'Dummy:Test', null, null, "testing", false ],
[
'hallo',
null,
CONTENT_FORMAT_WIKITEXT,
CONTENT_MODEL_WIKITEXT,
- 'hallo',
false
],
[
null,
CONTENT_FORMAT_JAVASCRIPT,
CONTENT_MODEL_JAVASCRIPT,
- 'hallo',
false
],
- [ serialize( 'hallo' ), 'Dummy:Test', null, "testing", "testing", 'hallo', false ],
+ [ serialize( 'hallo' ), 'Dummy:Test', null, "testing", "testing", false ],
- [ 'hallo', 'Help:Test', CONTENT_MODEL_CSS, null, CONTENT_MODEL_CSS, 'hallo', false ],
+ [ 'hallo', 'Help:Test', CONTENT_MODEL_CSS, null, CONTENT_MODEL_CSS, false ],
[
'hallo',
'MediaWiki:Test.js',
CONTENT_MODEL_CSS,
null,
CONTENT_MODEL_CSS,
- 'hallo',
false
],
[
CONTENT_MODEL_CSS,
null,
CONTENT_MODEL_CSS,
- serialize( 'hallo' ),
false
],
- [ 'hallo', 'Help:Test', CONTENT_MODEL_WIKITEXT, "testing", null, null, true ],
- [ 'hallo', 'MediaWiki:Test.js', CONTENT_MODEL_CSS, "testing", null, null, true ],
- [ 'hallo', 'Dummy:Test', CONTENT_MODEL_JAVASCRIPT, "testing", null, null, true ],
+ [ 'hallo', 'Help:Test', CONTENT_MODEL_WIKITEXT, "testing", null, true ],
+ [ 'hallo', 'MediaWiki:Test.js', CONTENT_MODEL_CSS, "testing", null, true ],
+ [ 'hallo', 'Dummy:Test', CONTENT_MODEL_JAVASCRIPT, "testing", null, true ],
];
}
* @covers ContentHandler::makeContent
*/
public function testMakeContent( $data, $title, $modelId, $format,
- $expectedModelId, $expectedNativeData, $shouldFail
+ $expectedModelId, $shouldFail
) {
$title = Title::newFromText( $title );
MediaWikiServices::getInstance()->getLinkCache()->addBadLinkObj( $title );
}
$this->assertEquals( $expectedModelId, $content->getModel(), 'bad model id' );
- $this->assertEquals( $expectedNativeData, $content->getNativeData(), 'bads native data' );
+ $this->assertEquals( $data, $content->serialize(), 'bad serialized data' );
} catch ( MWException $ex ) {
if ( !$shouldFail ) {
$this->fail( "ContentHandler::makeContent failed unexpectedly: " . $ex->getMessage() );
$content = new JavaScriptContent( $oldText );
$newContent = $content->updateRedirect( $target );
- $this->assertEquals( $expectedText, $newContent->getNativeData() );
+ $this->assertEquals( $expectedText, $newContent->getText() );
}
public static function provideUpdateRedirect() {
--- /dev/null
+<?php
+
+/**
+ * @group ContentHandler
+ */
+class MessageContentTest extends MediaWikiLangTestCase {
+
+ public function testGetHtml() {
+ $msg = new Message( 'about' );
+ $cnt = new MessageContent( $msg );
+
+ $this->assertSame( $msg->parse(), $cnt->getHtml() );
+ }
+
+ public function testGetWikitext() {
+ $msg = new Message( 'about' );
+ $cnt = new MessageContent( $msg );
+
+ $this->assertSame( $msg->text(), $cnt->getWikitext() );
+ }
+
+ public function testGetMessage() {
+ $msg = new Message( 'about' );
+ $cnt = new MessageContent( $msg );
+
+ $this->assertEquals( $msg, $cnt->getMessage() );
+ }
+
+ public function testGetParserOutput() {
+ $msg = new Message( 'about' );
+ $cnt = new MessageContent( $msg );
+
+ $title = Title::makeTitle( NS_MEDIAWIKI, 'about' );
+
+ $this->assertSame( $msg->parse(), $cnt->getParserOutput( $title )->getText() );
+ }
+
+ public function testSerialize() {
+ $msg = new Message( 'about' );
+ $cnt = new MessageContent( $msg );
+
+ $this->assertSame( $msg->plain(), $cnt->serialize() );
+ }
+
+ public function testEquals() {
+ $msg1 = new Message( 'about' );
+ $cnt1 = new MessageContent( $msg1 );
+
+ $msg2 = new Message( 'about' );
+ $cnt2 = new MessageContent( $msg2 );
+
+ $msg3 = new Message( 'faq' );
+ $cnt3 = new MessageContent( $msg3 );
+ $cnt4 = new WikitextContent( $msg3->plain() );
+
+ $this->assertTrue( $cnt1->equals( $cnt2 ) );
+ $this->assertFalse( $cnt1->equals( $cnt3 ) );
+ $this->assertFalse( $cnt1->equals( $cnt4 ) );
+ }
+}
parent::tearDown();
}
+ /**
+ * @param string $text
+ * @return TextContent
+ */
public function newContent( $text ) {
return new TextContent( $text );
}
$options
);
- $this->assertEquals( $expected, $content->getNativeData() );
+ $this->assertEquals( $expected, $content->getText() );
}
public static function dataPreloadTransform() {
$content = $this->newContent( $text );
$content = $content->preloadTransform( $this->context->getTitle(), $options );
- $this->assertEquals( $expected, $content->getNativeData() );
+ $this->assertEquals( $expected, $content->getText() );
}
public static function dataGetRedirectTarget() {
$copy = $content->copy();
$this->assertTrue( $content->equals( $copy ), 'copy must be equal to original' );
- $this->assertEquals( 'hello world.', $copy->getNativeData() );
+ $this->assertEquals( 'hello world.', $copy->getText() );
}
/**
$this->assertEquals( 12, $content->getSize() );
}
+ /**
+ * @covers TextContent::getText
+ */
+ public function testGetText() {
+ $content = $this->newContent( 'hello world.' );
+
+ $this->assertEquals( 'hello world.', $content->getText() );
+ }
+
/**
* @covers TextContent::getNativeData
*/
public function testGetNativeData() {
$content = $this->newContent( 'hello world.' );
- $this->assertEquals( 'hello world.', $content->getNativeData() );
+ $this->assertEquals( 'hello world.', $content->getText() );
}
/**
public function testConvert( $text, $model, $lossy, $expectedNative ) {
$content = $this->newContent( $text );
+ /** @var TextContent $converted */
$converted = $content->convert( $model, $lossy );
if ( $expectedNative === false ) {
$this->assertFalse( $converted, "conversion to $model was expected to fail!" );
} else {
$this->assertInstanceOf( Content::class, $converted );
- $this->assertEquals( $expectedNative, $converted->getNativeData() );
+ $this->assertEquals( $expectedNative, $converted->getText() );
}
}
];
}
+ public function testSerialize() {
+ $cnt = $this->newContent( 'testing text' );
+
+ $this->assertSame( 'testing text', $cnt->serialize() );
+ }
+
}
*/
public function testUnserializeContent() {
$content = $this->handler->unserializeContent( 'hello world' );
- $this->assertEquals( 'hello world', $content->getNativeData() );
+ $this->assertEquals( 'hello world', $content->getText() );
$content = $this->handler->unserializeContent( 'hello world', CONTENT_FORMAT_WIKITEXT );
- $this->assertEquals( 'hello world', $content->getNativeData() );
+ $this->assertEquals( 'hello world', $content->getText() );
try {
$this->handler->unserializeContent( 'hello world', 'dummy/foo' );
$content = $this->handler->makeEmptyContent();
$this->assertTrue( $content->isEmpty() );
- $this->assertEquals( '', $content->getNativeData() );
+ $this->assertEquals( '', $content->getText() );
}
public static function dataIsSupportedFormat() {
$merged = $this->handler->merge3( $oldContent, $myContent, $yourContent );
- $this->assertEquals( $expected, $merged ? $merged->getNativeData() : $merged );
+ $this->assertEquals( $expected, $merged ? $merged->getText() : $merged );
}
public static function dataGetAutosummary() {
$sectionContent = $content->getSection( $sectionId );
if ( is_object( $sectionContent ) ) {
- $sectionText = $sectionContent->getNativeData();
+ $sectionText = $sectionContent->getText();
} else {
$sectionText = $sectionContent;
}
$content = $this->newContent( $text );
$c = $content->replaceSection( $section, $this->newContent( $with ), $sectionTitle );
- $this->assertEquals( $expected, is_null( $c ) ? null : $c->getNativeData() );
+ $this->assertEquals( $expected, is_null( $c ) ? null : $c->getText() );
}
/**
$content = $this->newContent( 'hello world' );
$content = $content->addSectionHeader( 'test' );
- $this->assertEquals( "== test ==\n\nhello world", $content->getNativeData() );
+ $this->assertEquals( "== test ==\n\nhello world", $content->getText() );
}
public static function dataPreSaveTransform() {