From 3d80501829396b14b1984e8a4ff6d2d56974c0ba Mon Sep 17 00:00:00 2001 From: Adam Wight Date: Fri, 6 Dec 2019 10:12:25 +0100 Subject: [PATCH] Narrow message localizer interface We never access Language directly, so proxy its method instead of returning the full object. I believe I've found a bug, but not fixing here: the footnote body numeric backlinks like "2.1" behave as if they were decimals rather than two numbers stuck together with a dot. So they are localized to "2,1". Bug: T239725 Change-Id: If386bf96d48cb95c0a287a02bedfe984941efe30 --- src/FootnoteBodyFormatter.php | 2 +- src/FootnoteMarkFormatter.php | 6 +-- src/ReferenceMessageLocalizer.php | 20 ++++++++-- .../unit/FootnoteBodyFormatterTest.php | 14 +------ .../unit/FootnoteMarkFormatterTest.php | 10 +---- .../ReferenceMessageLocalizerUnitTest.php | 37 +++++++++++++++++++ 6 files changed, 61 insertions(+), 28 deletions(-) create mode 100644 tests/phpunit/unit/ReferenceMessageLocalizerUnitTest.php diff --git a/src/FootnoteBodyFormatter.php b/src/FootnoteBodyFormatter.php index c937bd2d8..f3954fa35 100644 --- a/src/FootnoteBodyFormatter.php +++ b/src/FootnoteBodyFormatter.php @@ -253,7 +253,7 @@ class FootnoteBodyFormatter { int $offset, int $max ) : string { - return $this->messageLocalizer->getLanguage()->formatNum( + return $this->messageLocalizer->formatNum( $base . '.' . str_pad( $offset, strlen( $max ), '0', STR_PAD_LEFT ) diff --git a/src/FootnoteMarkFormatter.php b/src/FootnoteMarkFormatter.php index 2344fab22..77c2100e2 100644 --- a/src/FootnoteMarkFormatter.php +++ b/src/FootnoteMarkFormatter.php @@ -64,17 +64,15 @@ class FootnoteMarkFormatter { * @return string */ public function linkRef( string $group, array $ref ) : string { - $language = $this->messageLocalizer->getLanguage(); - $label = $this->getLinkLabel( $group, $ref['number'] ); if ( $label === null ) { - $label = $language->formatNum( $ref['number'] ); + $label = $this->messageLocalizer->formatNum( $ref['number'] ); if ( $group !== Cite::DEFAULT_GROUP ) { $label = "$group $label"; } } if ( isset( $ref['extendsIndex'] ) ) { - $label .= '.' . $language->formatNum( $ref['extendsIndex'], true ); + $label .= '.' . $this->messageLocalizer->formatNumNoSeparators( $ref['extendsIndex'] ); } $key = $ref['name'] ?? $ref['key']; diff --git a/src/ReferenceMessageLocalizer.php b/src/ReferenceMessageLocalizer.php index f74c4ff6a..f125168c8 100644 --- a/src/ReferenceMessageLocalizer.php +++ b/src/ReferenceMessageLocalizer.php @@ -24,10 +24,23 @@ class ReferenceMessageLocalizer implements MessageLocalizer { } /** - * @return Language + * Transliterate numerals, add thousands separators and localize the decimal point. + * + * @param string $number + * @return string */ - public function getLanguage(): Language { - return $this->language; + public function formatNum( string $number ): string { + return $this->language->formatNum( $number ); + } + + /** + * Transliterate numerals, without adding or changing separators. + * + * @param string $number + * @return string + */ + public function formatNumNoSeparators( string $number ): string { + return $this->language->formatNumNoSeparators( $number ); } /** @@ -47,4 +60,5 @@ class ReferenceMessageLocalizer implements MessageLocalizer { public function msg( $key, ...$params ): Message { return wfMessage( $key, ...$params )->inLanguage( $this->language ); } + } diff --git a/tests/phpunit/unit/FootnoteBodyFormatterTest.php b/tests/phpunit/unit/FootnoteBodyFormatterTest.php index 58d81b9a5..5bd678d98 100644 --- a/tests/phpunit/unit/FootnoteBodyFormatterTest.php +++ b/tests/phpunit/unit/FootnoteBodyFormatterTest.php @@ -6,7 +6,6 @@ use Cite\CiteErrorReporter; use Cite\CiteKeyFormatter; use Cite\FootnoteBodyFormatter; use Cite\ReferenceMessageLocalizer; -use Language; use MediaWikiUnitTestCase; use Message; use Parser; @@ -213,13 +212,7 @@ class FootnoteBodyFormatterTest extends MediaWikiUnitTestCase { ); /** @var ReferenceMessageLocalizer $mockMessageLocalizer */ $mockMessageLocalizer = $this->createMock( ReferenceMessageLocalizer::class ); - $mockMessageLocalizer->method( 'getLanguage' )->willReturnCallback( - function () { - $mockLanguage = $this->createMock( Language::class ); - $mockLanguage->method( 'formatNum' )->willReturnArgument( 0 ); - return $mockLanguage; - } - ); + $mockMessageLocalizer->method( 'formatNum' )->willReturnArgument( 0 ); $mockMessageLocalizer->method( 'msg' )->willReturnCallback( function ( ...$args ) { $mockMessage = $this->createMock( Message::class ); @@ -415,12 +408,9 @@ class FootnoteBodyFormatterTest extends MediaWikiUnitTestCase { public function testReferencesFormatEntryNumericBacklinkLabel( string $expectedLabel, int $base, int $offset, int $max ) { - $mockLanguage = $this->createMock( Language::class ); - $mockLanguage->method( 'formatNum' )->with( $expectedLabel ) - ->willReturnArgument( 0 ); /** @var ReferenceMessageLocalizer $mockMessageLocalizer */ $mockMessageLocalizer = $this->createMock( ReferenceMessageLocalizer::class ); - $mockMessageLocalizer->method( 'getLanguage' )->willReturn( $mockLanguage ); + $mockMessageLocalizer->method( 'formatNum' )->willReturnArgument( 0 ); $formatter = TestingAccessWrapper::newFromObject( new FootnoteBodyFormatter( $this->createMock( Parser::class ), $this->createMock( CiteErrorReporter::class ), diff --git a/tests/phpunit/unit/FootnoteMarkFormatterTest.php b/tests/phpunit/unit/FootnoteMarkFormatterTest.php index e713bde31..a3769ffdf 100644 --- a/tests/phpunit/unit/FootnoteMarkFormatterTest.php +++ b/tests/phpunit/unit/FootnoteMarkFormatterTest.php @@ -2,7 +2,6 @@ namespace Cite; -use Language; use MediaWikiUnitTestCase; use Message; use Parser; @@ -34,13 +33,8 @@ class FootnoteMarkFormatterTest extends MediaWikiUnitTestCase { } ); $mockMessageLocalizer = $this->createMock( ReferenceMessageLocalizer::class ); - $mockMessageLocalizer->method( 'getLanguage' )->willReturnCallback( - function () { - $mockLanguage = $this->createMock( Language::class ); - $mockLanguage->method( 'formatNum' )->willReturnArgument( 0 ); - return $mockLanguage; - } - ); + $mockMessageLocalizer->method( 'formatNum' )->willReturnArgument( 0 ); + $mockMessageLocalizer->method( 'formatNumNoSeparators' )->willReturnArgument( 0 ); $mockMessageLocalizer->method( 'msg' )->willReturnCallback( function ( ...$args ) use ( $group, $fooLabels ) { $mockMessage = $this->createMock( Message::class ); diff --git a/tests/phpunit/unit/ReferenceMessageLocalizerUnitTest.php b/tests/phpunit/unit/ReferenceMessageLocalizerUnitTest.php new file mode 100644 index 000000000..724d9df33 --- /dev/null +++ b/tests/phpunit/unit/ReferenceMessageLocalizerUnitTest.php @@ -0,0 +1,37 @@ +createMock( Language::class ); + $mockLanguage->method( 'formatNum' )->willReturn( '10,0' ); + /** @var Language $mockLanguage */ + $messageLocalizer = new ReferenceMessageLocalizer( $mockLanguage ); + $this->assertSame( '10,0', $messageLocalizer->formatNum( '10.0' ) ); + } + + /** + * @covers ::formatNumNoSeparators + */ + public function testFormatNumNoSeparators() { + $mockLanguage = $this->createMock( Language::class ); + $mockLanguage->method( 'formatNumNoSeparators' )->willReturn( 'ה' ); + /** @var Language $mockLanguage */ + $messageLocalizer = new ReferenceMessageLocalizer( $mockLanguage ); + $this->assertSame( 'ה', $messageLocalizer->formatNumNoSeparators( '5' ) ); + } + +}