From 821505367e41597e23d3547ca70c2485f1d9da26 Mon Sep 17 00:00:00 2001 From: Timo Tijhof Date: Sat, 13 Apr 2019 04:27:31 +0100 Subject: [PATCH] title: Allow passing MessageLocalizer to newMainPage() The method could not be used in session-less endpoints. This was worked around once in the Startup module. I plan to use this method in an extension module as well, and would prefer not to duplicate core's logic for determining the main page, outside this repository. As general dependency-injection pattern, it seems desirable to allow injecting a MessageLocalizer here. Change-Id: I76cd02b2f489882e9404b93270f76aad9f0a4d9d --- includes/Title.php | 26 +++++++++++--- .../ResourceLoaderStartUpModule.php | 12 ++----- tests/phpunit/includes/TitleTest.php | 35 +++++++++++++++++++ 3 files changed, 60 insertions(+), 13 deletions(-) diff --git a/includes/Title.php b/includes/Title.php index 3891c82418..12ab532558 100644 --- a/includes/Title.php +++ b/includes/Title.php @@ -623,15 +623,33 @@ class Title implements LinkTarget, IDBAccessObject { /** * Create a new Title for the Main Page * + * This uses the 'mainpage' interface message, which could be specified in + * `$wgForceUIMsgAsContentMsg`. If that is the case, then calling this method + * will use the user language, which would involve initialising the session + * via `RequestContext::getMain()->getLanguage()`. For session-less endpoints, + * be sure to pass in a MessageLocalizer (such as your own RequestContext, + * or ResourceloaderContext) to prevent an error. + * * @note The Title instance returned by this method is not guaranteed to be a fresh instance. * It may instead be a cached instance created previously, with references to it remaining * elsewhere. * - * @return Title The new object + * @param MessageLocalizer|null $localizer An optional context to use (since 1.34) + * @return Title */ - public static function newMainPage() { - $title = self::newFromText( wfMessage( 'mainpage' )->inContentLanguage()->text() ); - // Don't give fatal errors if the message is broken + public static function newMainPage( MessageLocalizer $localizer = null ) { + if ( $localizer ) { + $msg = $localizer->msg( 'mainpage' ); + } else { + $msg = wfMessage( 'mainpage' ); + } + + $title = self::newFromText( $msg->inContentLanguage()->text() ); + + // Every page renders at least one link to the Main Page (e.g. sidebar). + // If the localised value is invalid, don't produce fatal errors that + // would make the wiki inaccessible (and hard to fix the invalid message). + // Gracefully fallback... if ( !$title ) { $title = self::newFromText( 'Main Page' ); } diff --git a/includes/resourceloader/ResourceLoaderStartUpModule.php b/includes/resourceloader/ResourceLoaderStartUpModule.php index acc2503d90..da6063ea89 100644 --- a/includes/resourceloader/ResourceLoaderStartUpModule.php +++ b/includes/resourceloader/ResourceLoaderStartUpModule.php @@ -49,15 +49,9 @@ class ResourceLoaderStartUpModule extends ResourceLoaderModule { private function getConfigSettings( $context ) { $conf = $this->getConfig(); - // We can't use Title::newMainPage() if 'mainpage' is in - // $wgForceUIMsgAsContentMsg because that will try to use the session - // user's language and we have no session user. This does the - // equivalent but falling back to our ResourceLoaderContext language - // instead. - $mainPage = Title::newFromText( $context->msg( 'mainpage' )->inContentLanguage()->text() ); - if ( !$mainPage ) { - $mainPage = Title::newFromText( 'Main Page' ); - } + // Passing a context is important as Title::newMainPage() may otherwise + // try to intialise a session, which is not allowed on load.php requests. + $mainPage = Title::newMainPage( $context ); /** * Namespace related preparation diff --git a/tests/phpunit/includes/TitleTest.php b/tests/phpunit/includes/TitleTest.php index 149c25bc5f..e29b7e7a3e 100644 --- a/tests/phpunit/includes/TitleTest.php +++ b/tests/phpunit/includes/TitleTest.php @@ -2,6 +2,7 @@ use MediaWiki\Linker\LinkTarget; use MediaWiki\MediaWikiServices; +use Wikimedia\TestingAccessWrapper; /** * @group Database @@ -20,6 +21,12 @@ class TitleTest extends MediaWikiTestCase { $this->setContentLang( 'en' ); } + protected function tearDown() { + // For testNewMainPage + MessageCache::destroyInstance(); + parent::tearDown(); + } + /** * @covers Title::legalChars */ @@ -1097,4 +1104,32 @@ class TitleTest extends MediaWikiTestCase { $firstValue->equals( $secondValue ) ); } + + /** + * @covers Title::newMainPage + */ + public function testNewMainPage() { + $msgCache = TestingAccessWrapper::newFromClass( MessageCache::class ); + $msgCache->instance = $this->createMock( MessageCache::class ); + $msgCache->instance->method( 'get' )->willReturn( 'Foresheet' ); + $msgCache->instance->method( 'transform' )->willReturn( 'Foresheet' ); + + $this->assertSame( + 'Foresheet', + Title::newMainPage()->getText() + ); + } + + /** + * @covers Title::newMainPage + */ + public function testNewMainPageWithLocal() { + $local = $this->createMock( MessageLocalizer::class ); + $local->method( 'msg' )->willReturn( new RawMessage( 'Prime Article' ) ); + + $this->assertSame( + 'Prime Article', + Title::newMainPage( $local )->getText() + ); + } } -- 2.20.1