From: Brad Jorsch Date: Wed, 9 Mar 2016 17:39:50 +0000 (-0500) Subject: Allow passing a language into Status::getWikiText() etc. X-Git-Tag: 1.31.0-rc.0~7671 X-Git-Url: https://git.cyclocoop.org/%242?a=commitdiff_plain;h=7c543bb6c25ec41947075842aaf3a3d4fb2b8c87;p=lhc%2Fweb%2Fwiklou.git 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 --- diff --git a/includes/Status.php b/includes/Status.php index 75fe190a02..cc7abc8200 100644 --- a/includes/Status.php +++ b/includes/Status.php @@ -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 ); } /** diff --git a/includes/cache/MessageCache.php b/includes/cache/MessageCache.php index b058d1f818..b26dc8da2f 100644 --- a/includes/cache/MessageCache.php +++ b/includes/cache/MessageCache.php @@ -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 ) { diff --git a/tests/phpunit/includes/StatusTest.php b/tests/phpunit/includes/StatusTest.php index 6f4395b952..782fab0c6b 100644 --- a/tests/phpunit/includes/StatusTest.php +++ b/tests/phpunit/includes/StatusTest.php @@ -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))", "

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))\n

", ]; $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))", "

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))\n

", ]; $status = new Status(); @@ -368,7 +377,9 @@ class StatusTest extends MediaWikiLangTestCase { $testCases['1StringWarning'] = [ $status, "", + "(wrap-short: (fooBar!))", "

<fooBar!>\n

", + "

(wrap-short: (fooBar!))\n

", ]; $status = new Status(); @@ -377,7 +388,9 @@ class StatusTest extends MediaWikiLangTestCase { $testCases['2StringWarnings'] = [ $status, "* \n* \n", + "(wrap-long: * (fooBar!)\n* (fooBar2!)\n)", "
  • <fooBar!>
  • \n
  • <fooBar2!>
\n", + "

(wrap-long: * (fooBar!)\n

\n
  • (fooBar2!)
\n

)\n

", ]; $status = new Status(); @@ -385,7 +398,9 @@ class StatusTest extends MediaWikiLangTestCase { $testCases['1MessageWarning'] = [ $status, "", + "(wrap-short: (fooBar!: foo, bar))", "

<fooBar!>\n

", + "

(wrap-short: (fooBar!: foo, bar))\n

", ]; $status = new Status(); @@ -394,12 +409,26 @@ class StatusTest extends MediaWikiLangTestCase { $testCases['2MessageWarnings'] = [ $status, "* \n* \n", + "(wrap-long: * (fooBar!: foo, bar)\n* (fooBar2!)\n)", "
  • <fooBar!>
  • \n
  • <fooBar2!>
\n", + "

(wrap-long: * (fooBar!: foo, bar)\n

\n
  • (fooBar2!)
\n

)\n

", ]; 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' ];