Allow passing a language into Status::getWikiText() etc.

This also corrects a bug in MessageCache::parse() where it takes a
language code string but the Parser expects a Language object in
ParserOptions.

Bug: T128809
Change-Id: I3508c9e515e505890b3c62bc4a0982aa2a313782
This commit is contained in:
Brad Jorsch 2016-03-09 12:39:50 -05:00 committed by BryanDavis
parent 9b94bd502f
commit 7c543bb6c2
3 changed files with 115 additions and 49 deletions

View file

@ -178,15 +178,36 @@ class Status {
return $cleanParams;
}
/**
* @param string|Language|null $lang Language to use for processing
* messages, or null to default to the user language.
* @return Language
*/
protected function languageFromParam( $lang ) {
global $wgLang;
if ( $lang === null ) {
// @todo: Use RequestContext::getMain()->getLanguage() instead
return $wgLang;
} elseif ( $lang instanceof Language || $lang instanceof StubUserLang ) {
return $lang;
} else {
return Language::factory( $lang );
}
}
/**
* Get the error list as a wikitext formatted list
*
* @param string|bool $shortContext A short enclosing context message name, to
* be used when there is a single error
* @param string|bool $longContext A long enclosing context message name, for a list
* @param string|Language $lang Language to use for processing messages
* @return string
*/
public function getWikiText( $shortContext = false, $longContext = false ) {
public function getWikiText( $shortContext = false, $longContext = false, $lang = null ) {
$lang = $this->languageFromParam( $lang );
$rawErrors = $this->sv->getErrors();
if ( count( $rawErrors ) == 0 ) {
if ( $this->sv->isOK() ) {
@ -199,22 +220,22 @@ class Status {
$rawErrors = $this->sv->getErrors(); // just added a fatal
}
if ( count( $rawErrors ) == 1 ) {
$s = $this->getErrorMessage( $rawErrors[0] )->plain();
$s = $this->getErrorMessage( $rawErrors[0], $lang )->plain();
if ( $shortContext ) {
$s = wfMessage( $shortContext, $s )->plain();
$s = wfMessage( $shortContext, $s )->inLanguage( $lang )->plain();
} elseif ( $longContext ) {
$s = wfMessage( $longContext, "* $s\n" )->plain();
$s = wfMessage( $longContext, "* $s\n" )->inLanguage( $lang )->plain();
}
} else {
$errors = $this->getErrorMessageArray( $rawErrors );
$errors = $this->getErrorMessageArray( $rawErrors, $lang );
foreach ( $errors as &$error ) {
$error = $error->plain();
}
$s = '* ' . implode( "\n* ", $errors ) . "\n";
if ( $longContext ) {
$s = wfMessage( $longContext, $s )->plain();
$s = wfMessage( $longContext, $s )->inLanguage( $lang )->plain();
} elseif ( $shortContext ) {
$s = wfMessage( $shortContext, "\n$s\n" )->plain();
$s = wfMessage( $shortContext, "\n$s\n" )->inLanguage( $lang )->plain();
}
}
return $s;
@ -227,10 +248,12 @@ class Status {
* message names), to be used when there is a single error.
* @param string|string[] $longContext A long enclosing context message name (or an array of
* message names), for a list.
*
* @param string|Language $lang Language to use for processing messages
* @return Message
*/
public function getMessage( $shortContext = false, $longContext = false ) {
public function getMessage( $shortContext = false, $longContext = false, $lang = null ) {
$lang = $this->languageFromParam( $lang );
$rawErrors = $this->sv->getErrors();
if ( count( $rawErrors ) == 0 ) {
if ( $this->sv->isOK() ) {
@ -243,16 +266,16 @@ class Status {
$rawErrors = $this->sv->getErrors(); // just added a fatal
}
if ( count( $rawErrors ) == 1 ) {
$s = $this->getErrorMessage( $rawErrors[0] );
$s = $this->getErrorMessage( $rawErrors[0], $lang );
if ( $shortContext ) {
$s = wfMessage( $shortContext, $s );
$s = wfMessage( $shortContext, $s )->inLanguage( $lang );
} elseif ( $longContext ) {
$wrapper = new RawMessage( "* \$1\n" );
$wrapper->params( $s )->parse();
$s = wfMessage( $longContext, $wrapper );
$s = wfMessage( $longContext, $wrapper )->inLanguage( $lang );
}
} else {
$msgs = $this->getErrorMessageArray( $rawErrors );
$msgs = $this->getErrorMessageArray( $rawErrors, $lang );
$msgCount = count( $msgs );
if ( $shortContext ) {
@ -263,11 +286,11 @@ class Status {
$s->params( $msgs )->parse();
if ( $longContext ) {
$s = wfMessage( $longContext, $s );
$s = wfMessage( $longContext, $s )->inLanguage( $lang );
} elseif ( $shortContext ) {
$wrapper = new RawMessage( "\n\$1\n", [ $s ] );
$wrapper->parse();
$s = wfMessage( $shortContext, $wrapper );
$s = wfMessage( $shortContext, $wrapper )->inLanguage( $lang );
}
}
@ -280,10 +303,10 @@ class Status {
* 'message' and 'params', use those keys-value pairs.
* Otherwise, if its an array, just use the first value as the
* message and the remaining items as the params.
*
* @param string|Language $lang Language to use for processing messages
* @return Message
*/
protected function getErrorMessage( $error ) {
protected function getErrorMessage( $error, $lang = null ) {
if ( is_array( $error ) ) {
if ( isset( $error['message'] ) && $error['message'] instanceof Message ) {
$msg = $error['message'];
@ -298,6 +321,8 @@ class Status {
} else {
$msg = wfMessage( $error );
}
$msg->inLanguage( $this->languageFromParam( $lang ) );
return $msg;
}
@ -307,21 +332,27 @@ class Status {
* @param string $shortContext A short enclosing context message name, to
* be used when there is a single error
* @param string $longContext A long enclosing context message name, for a list
* @param string|Language $lang Language to use for processing messages
* @return string
*/
public function getHTML( $shortContext = false, $longContext = false ) {
$text = $this->getWikiText( $shortContext, $longContext );
$out = MessageCache::singleton()->parse( $text, null, true, true );
public function getHTML( $shortContext = false, $longContext = false, $lang = null ) {
$lang = $this->languageFromParam( $lang );
$text = $this->getWikiText( $shortContext, $longContext, $lang );
$out = MessageCache::singleton()->parse( $text, null, true, true, $lang );
return $out instanceof ParserOutput ? $out->getText() : $out;
}
/**
* Return an array with a Message object for each error.
* @param array $errors
* @param string|Language $lang Language to use for processing messages
* @return Message[]
*/
protected function getErrorMessageArray( $errors ) {
return array_map( [ $this, 'getErrorMessage' ], $errors );
protected function getErrorMessageArray( $errors, $lang = null ) {
$lang = $this->languageFromParam( $lang );
return array_map( function ( $e ) use ( $lang ) {
return $this->getErrorMessage( $e, $lang );
}, $errors );
}
/**

View file

@ -1054,7 +1054,7 @@ class MessageCache {
* @param Title $title
* @param bool $linestart Whether or not this is at the start of a line
* @param bool $interface Whether this is an interface message
* @param string $language Language code
* @param Language|string $language Language code
* @return ParserOutput|string
*/
public function parse( $text, $title = null, $linestart = true,
@ -1067,6 +1067,10 @@ class MessageCache {
$parser = $this->getParser();
$popts = $this->getParserOptions();
$popts->setInterfaceMessage( $interface );
if ( is_string( $language ) ) {
$language = Language::factory( $language );
}
$popts->setTargetLanguage( $language );
if ( !$title || !$title instanceof Title ) {

View file

@ -321,24 +321,25 @@ class StatusTest extends MediaWikiLangTestCase {
/**
* @dataProvider provideGetWikiTextAndHtml
* @covers Status::getWikiText
* @todo test long and short context messages generated through this method
* this can not really be done now due to use of wfMessage()->plain()
* It is possible to mock such methods but only if namespaces are used
*/
public function testGetWikiText( Status $status, $wikitext, $html ) {
public function testGetWikiText(
Status $status, $wikitext, $wrappedWikitext, $html, $wrappedHtml
) {
$this->assertEquals( $wikitext, $status->getWikiText() );
$this->assertEquals( $wrappedWikitext, $status->getWikiText( 'wrap-short', 'wrap-long', 'qqx' ) );
}
/**
* @dataProvider provideGetWikiTextAndHtml
* @covers Status::getHtml
* @todo test long and short context messages generated through this method
* this can not really be done now due to use of $this->getWikiText using
* wfMessage()->plain(). It is possible to mock such methods but only if
* namespaces are used.
*/
public function testGetHtml( Status $status, $wikitext, $html ) {
public function testGetHtml(
Status $status, $wikitext, $wrappedWikitext, $html, $wrappedHtml
) {
$this->assertEquals( $html, $status->getHTML() );
$this->assertEquals( $wrappedHtml, $status->getHTML( 'wrap-short', 'wrap-long', 'qqx' ) );
}
/**
@ -352,7 +353,11 @@ class StatusTest extends MediaWikiLangTestCase {
$testCases['GoodStatus'] = [
new Status(),
"Internal error: Status::getWikiText called for a good result, this is incorrect\n",
"(wrap-short: (internalerror_info: Status::getWikiText called for a good result, " .
"this is incorrect\n))",
"<p>Internal error: Status::getWikiText called for a good result, this is incorrect\n</p>",
"<p>(wrap-short: (internalerror_info: Status::getWikiText called for a good result, " .
"this is incorrect\n))\n</p>",
];
$status = new Status();
@ -360,7 +365,11 @@ class StatusTest extends MediaWikiLangTestCase {
$testCases['GoodButNoError'] = [
$status,
"Internal error: Status::getWikiText: Invalid result object: no error text but not OK\n",
"(wrap-short: (internalerror_info: Status::getWikiText: Invalid result object: " .
"no error text but not OK\n))",
"<p>Internal error: Status::getWikiText: Invalid result object: no error text but not OK\n</p>",
"<p>(wrap-short: (internalerror_info: Status::getWikiText: Invalid result object: " .
"no error text but not OK\n))\n</p>",
];
$status = new Status();
@ -368,7 +377,9 @@ class StatusTest extends MediaWikiLangTestCase {
$testCases['1StringWarning'] = [
$status,
"<fooBar!>",
"(wrap-short: (fooBar!))",
"<p>&lt;fooBar!&gt;\n</p>",
"<p>(wrap-short: (fooBar!))\n</p>",
];
$status = new Status();
@ -377,7 +388,9 @@ class StatusTest extends MediaWikiLangTestCase {
$testCases['2StringWarnings'] = [
$status,
"* <fooBar!>\n* <fooBar2!>\n",
"(wrap-long: * (fooBar!)\n* (fooBar2!)\n)",
"<ul><li> &lt;fooBar!&gt;</li>\n<li> &lt;fooBar2!&gt;</li></ul>\n",
"<p>(wrap-long: * (fooBar!)\n</p>\n<ul><li> (fooBar2!)</li></ul>\n<p>)\n</p>",
];
$status = new Status();
@ -385,7 +398,9 @@ class StatusTest extends MediaWikiLangTestCase {
$testCases['1MessageWarning'] = [
$status,
"<fooBar!>",
"(wrap-short: (fooBar!: foo, bar))",
"<p>&lt;fooBar!&gt;\n</p>",
"<p>(wrap-short: (fooBar!: foo, bar))\n</p>",
];
$status = new Status();
@ -394,12 +409,26 @@ class StatusTest extends MediaWikiLangTestCase {
$testCases['2MessageWarnings'] = [
$status,
"* <fooBar!>\n* <fooBar2!>\n",
"(wrap-long: * (fooBar!: foo, bar)\n* (fooBar2!)\n)",
"<ul><li> &lt;fooBar!&gt;</li>\n<li> &lt;fooBar2!&gt;</li></ul>\n",
"<p>(wrap-long: * (fooBar!: foo, bar)\n</p>\n<ul><li> (fooBar2!)</li></ul>\n<p>)\n</p>",
];
return $testCases;
}
private static function sanitizedMessageParams( Message $message ) {
return array_map( function ( $p ) {
return $p instanceof Message
? [
'key' => $p->getKey(),
'params' => self::sanitizedMessageParams( $p ),
'lang' => $p->getLanguage()->getCode(),
]
: $p;
}, $message->getParams() );
}
/**
* @dataProvider provideGetMessage
* @covers Status::getMessage
@ -407,9 +436,10 @@ class StatusTest extends MediaWikiLangTestCase {
public function testGetMessage(
Status $status, $expectedParams = [], $expectedKey, $expectedWrapper
) {
$message = $status->getMessage();
$message = $status->getMessage( null, null, 'qqx' );
$this->assertInstanceOf( 'Message', $message );
$this->assertEquals( $expectedParams, $message->getParams(), 'Message::getParams' );
$this->assertEquals( $expectedParams, self::sanitizedMessageParams( $message ),
'Message::getParams' );
$this->assertEquals( $expectedKey, $message->getKey(), 'Message::getKey' );
$message = $status->getMessage( 'wrapper-short', 'wrapper-long' );
@ -462,20 +492,18 @@ class StatusTest extends MediaWikiLangTestCase {
'wrapper-short'
];
// FIXME: Assertion tries to compare a StubUserLang with a Language object, because
// "data providers are executed before both the call to the setUpBeforeClass static method
// and the first call to the setUp method. Because of that you can't access any variables
// you create there from within a data provider."
// http://phpunit.de/manual/3.7/en/writing-tests-for-phpunit.html
// $status = new Status();
// $status->warning( 'fooBar!' );
// $status->warning( 'fooBar2!' );
// $testCases[ '2StringWarnings' ] = array(
// $status,
// array( new Message( 'fooBar!' ), new Message( 'fooBar2!' ) ),
// "* \$1\n* \$2",
// 'wrapper-long'
// );
$status = new Status();
$status->warning( 'fooBar!' );
$status->warning( 'fooBar2!' );
$testCases[ '2StringWarnings' ] = [
$status,
[
[ 'key' => 'fooBar!', 'params' => [], 'lang' => 'qqx' ],
[ 'key' => 'fooBar2!', 'params' => [], 'lang' => 'qqx' ]
],
"* \$1\n* \$2",
'wrapper-long'
];
$status = new Status();
$status->warning( new Message( 'fooBar!', [ 'foo', 'bar' ] ) );
@ -491,7 +519,10 @@ class StatusTest extends MediaWikiLangTestCase {
$status->warning( new Message( 'fooBar2!' ) );
$testCases['2MessageWarnings'] = [
$status,
[ new Message( 'fooBar!', [ 'foo', 'bar' ] ), new Message( 'fooBar2!' ) ],
[
[ 'key' => 'fooBar!', 'params' => [ 'foo', 'bar' ], 'lang' => 'qqx' ],
[ 'key' => 'fooBar2!', 'params' => [], 'lang' => 'qqx' ]
],
"* \$1\n* \$2",
'wrapper-long'
];