diff --git a/includes/LanguagesHelper.php b/includes/LanguagesHelper.php new file mode 100644 index 0000000..66e416a --- /dev/null +++ b/includes/LanguagesHelper.php @@ -0,0 +1,51 @@ +hasLanguages = !empty( $out->getLanguageLinks() ); + } + + /** + * Whether the Title is also available in other languages or variants + * @param Title $title + * @return bool + */ + public function doesTitleHasLanguagesOrVariants( Title $title ) { + return $this->hasLanguages || $title->getPageLanguage()->hasVariants(); + } +} diff --git a/includes/ServiceWiring.php b/includes/ServiceWiring.php index 811485e..dd40895 100644 --- a/includes/ServiceWiring.php +++ b/includes/ServiceWiring.php @@ -20,6 +20,7 @@ */ use MediaWiki\MediaWikiServices; +use MediaWiki\Minerva\LanguagesHelper; use MediaWiki\Minerva\Menu\Definitions; use MediaWiki\Minerva\Menu\Main as MainMenu; use MediaWiki\Minerva\Menu\PageActions as PageActionsMenu; @@ -53,9 +54,9 @@ return [ $skinOptions = $services->getService( 'Minerva.SkinOptions' ); $context = RequestContext::getMain(); $title = $context->getTitle(); - $output = $context->getOutput(); $user = $context->getUser(); $userPageHelper = $services->getService( 'Minerva.SkinUserPageHelper' ); + $languagesHelper = $services->getService( 'Minerva.LanguagesHelper' ); $toolbarBuilder = new PageActionsMenu\ToolbarBuilder( $title, $user, @@ -63,18 +64,17 @@ return [ $services->getPermissionManager(), $services->getService( 'Minerva.Permissions' ), $skinOptions, - $services->get( 'Minerva.SkinUserPageHelper' ) + $userPageHelper, + $languagesHelper ); if ( $skinOptions->get( SkinOptions::OPTION_OVERFLOW_SUBMENU ) ) { - $hasVariants = $title->getPageLanguage()->hasVariants(); - $hasLanguages = count( $output->getLanguageLinks() ); $overflowBuilder = $userPageHelper->isUserPage() ? new PageActionsMenu\UserNamespaceOverflowBuilder( $title, $context, $userPageHelper, $services->getService( 'Minerva.Permissions' ), - $hasVariants || $hasLanguages + $languagesHelper ) : new PageActionsMenu\DefaultOverflowBuilder( $context @@ -92,6 +92,9 @@ return [ 'Minerva.SkinUserPageHelper' => function (): SkinUserPageHelper { return new SkinUserPageHelper( RequestContext::getMain()->getTitle() ); }, + 'Minerva.LanguagesHelper' => function (): LanguagesHelper { + return new LanguagesHelper( RequestContext::getMain()->getOutput() ); + }, 'Minerva.SkinOptions' => function (): SkinOptions { return new SkinOptions(); }, @@ -107,9 +110,9 @@ return [ $context->getTitle(), $context->getConfig(), $context->getUser(), - $context->getOutput(), $services->getService( 'Minerva.SkinOptions' ), - $contentHandler + $contentHandler, + $services->getService( 'Minerva.LanguagesHelper' ) ); } else { return new MinervaNoPagePermissions(); diff --git a/includes/menu/PageActions/PageActionsDirector.php b/includes/menu/PageActions/PageActionsDirector.php index 742ad80..b7aa8b7 100644 --- a/includes/menu/PageActions/PageActionsDirector.php +++ b/includes/menu/PageActions/PageActionsDirector.php @@ -51,8 +51,11 @@ final class PageActionsDirector { * @param IOverflowBuilder $overflowBuilder The overflow menu builder * @param MessageLocalizer $messageLocalizer Message localizer used to translate texts */ - public function __construct( ToolbarBuilder $toolbarBuilder, IOverflowBuilder $overflowBuilder, - MessageLocalizer $messageLocalizer ) { + public function __construct( + ToolbarBuilder $toolbarBuilder, + IOverflowBuilder $overflowBuilder, + MessageLocalizer $messageLocalizer + ) { $this->toolbarBuilder = $toolbarBuilder; $this->overflowBuilder = $overflowBuilder; $this->messageLocalizer = $messageLocalizer; @@ -61,12 +64,11 @@ final class PageActionsDirector { /** * Build the menu data array that can be passed to views/javascript * @param array $toolbox An array of common toolbox items from the sidebar menu - * @param bool $doesHaveLangUrls Whether the page is also available in other languages or variants * @return array * @throws MWException */ - public function buildMenu( array $toolbox, $doesHaveLangUrls ): array { - $toolbar = $this->toolbarBuilder->getGroup( $doesHaveLangUrls ); + public function buildMenu( array $toolbox ): array { + $toolbar = $this->toolbarBuilder->getGroup(); $overflowMenu = $this->overflowBuilder->getGroup( $toolbox ); $menu = [ diff --git a/includes/menu/PageActions/ToolbarBuilder.php b/includes/menu/PageActions/ToolbarBuilder.php index fc58422..9d006f0 100644 --- a/includes/menu/PageActions/ToolbarBuilder.php +++ b/includes/menu/PageActions/ToolbarBuilder.php @@ -22,6 +22,7 @@ namespace MediaWiki\Minerva\Menu\PageActions; use ExtensionRegistry; use Hooks; +use MediaWiki\Minerva\LanguagesHelper; use MediaWiki\Minerva\Menu\Entries\IMenuEntry; use MediaWiki\Minerva\Menu\Entries\LanguageSelectorEntry; use MediaWiki\Minerva\Menu\Group; @@ -71,6 +72,11 @@ class ToolbarBuilder { * @var SkinUserPageHelper */ private $userPageHelper; + + /** + * @var LanguagesHelper + */ + private $languagesHelper; /** * Build Group containing icons for toolbar * @param Title $title Article title user is currently browsing @@ -80,6 +86,7 @@ class ToolbarBuilder { * @param IMinervaPagePermissions $permissions Minerva permissions system * @param SkinOptions $skinOptions Skin options * @param SkinUserPageHelper $userPageHelper User Page helper + * @param LanguagesHelper $languagesHelper Helper to check title languages/variants */ public function __construct( Title $title, @@ -88,7 +95,8 @@ class ToolbarBuilder { PermissionManager $permissionManager, IMinervaPagePermissions $permissions, SkinOptions $skinOptions, - SkinUserPageHelper $userPageHelper + SkinUserPageHelper $userPageHelper, + LanguagesHelper $languagesHelper ) { $this->title = $title; $this->user = $user; @@ -97,15 +105,14 @@ class ToolbarBuilder { $this->permissions = $permissions; $this->skinOptions = $skinOptions; $this->userPageHelper = $userPageHelper; + $this->languagesHelper = $languagesHelper; } /** - * @param bool $doesPageHaveLanguages Whether the page is also available in other languages - * or variants * @return Group * @throws MWException */ - public function getGroup( $doesPageHaveLanguages ): Group { + public function getGroup(): Group { $group = new Group(); $permissions = $this->permissions; $userPageWithOveflowMode = $this->skinOptions->get( SkinOptions::OPTION_OVERFLOW_SUBMENU ) && @@ -115,7 +122,7 @@ class ToolbarBuilder { IMinervaPagePermissions::SWITCH_LANGUAGE ) ) { $group->insertEntry( new LanguageSelectorEntry( $this->title, - $doesPageHaveLanguages, + $this->languagesHelper->doesTitleHasLanguagesOrVariants( $this->title ), $this->messageLocalizer, MinervaUI::iconClass( 'language-switcher', 'element', '' ) ) ); diff --git a/includes/menu/PageActions/UserNamespaceOverflowBuilder.php b/includes/menu/PageActions/UserNamespaceOverflowBuilder.php index aa00795..286c80d 100644 --- a/includes/menu/PageActions/UserNamespaceOverflowBuilder.php +++ b/includes/menu/PageActions/UserNamespaceOverflowBuilder.php @@ -21,6 +21,7 @@ namespace MediaWiki\Minerva\Menu\PageActions; use Hooks; +use MediaWiki\Minerva\LanguagesHelper; use MediaWiki\Minerva\Menu\Group; use MediaWiki\Minerva\Menu\Entries\LanguageSelectorEntry; use MediaWiki\Minerva\Permissions\IMinervaPagePermissions; @@ -55,9 +56,9 @@ class UserNamespaceOverflowBuilder implements IOverflowBuilder { private $permissions; /** - * @var bool + * @var LanguagesHelper */ - private $doesPageHaveLanguages; + private $languagesHelper; /** * Initialize the overflow menu visible on the User namespace @@ -65,20 +66,20 @@ class UserNamespaceOverflowBuilder implements IOverflowBuilder { * @param MessageLocalizer $msgLocalizer * @param SkinUserPageHelper $userPageHelper * @param IMinervaPagePermissions $permissions - * @param bool $doesPageHaveLanguages + * @param LanguagesHelper $languagesHelper */ public function __construct( Title $title, MessageLocalizer $msgLocalizer, SkinUserPageHelper $userPageHelper, IMinervaPagePermissions $permissions, - $doesPageHaveLanguages + LanguagesHelper $languagesHelper ) { $this->title = $title; $this->messageLocalizer = $msgLocalizer; $this->pageUser = $userPageHelper->getPageUser(); $this->permissions = $permissions; - $this->doesPageHaveLanguages = $doesPageHaveLanguages; + $this->languagesHelper = $languagesHelper; } /** @@ -88,8 +89,10 @@ class UserNamespaceOverflowBuilder implements IOverflowBuilder { public function getGroup( array $toolbox ): Group { $group = new Group(); if ( $this->permissions->isAllowed( IMinervaPagePermissions::SWITCH_LANGUAGE ) ) { - $group->insertEntry( new LanguageSelectorEntry( $this->title, - $this->doesPageHaveLanguages, $this->messageLocalizer, + $group->insertEntry( new LanguageSelectorEntry( + $this->title, + $this->languagesHelper->doesTitleHasLanguagesOrVariants( $this->title ), + $this->messageLocalizer, MinervaUI::iconClass( 'language-switcher-base20', 'before', 'minerva-page-actions-language-switcher toggle-list-item__anchor--menu' ), 'minerva-page-actions-language-switcher' diff --git a/includes/permissions/MinervaPagePermissions.php b/includes/permissions/MinervaPagePermissions.php index e285145..a279d51 100644 --- a/includes/permissions/MinervaPagePermissions.php +++ b/includes/permissions/MinervaPagePermissions.php @@ -22,8 +22,8 @@ namespace MediaWiki\Minerva\Permissions; use Config; use ConfigException; use ContentHandler; +use MediaWiki\Minerva\LanguagesHelper; use MediaWiki\Minerva\SkinOptions; -use OutputPage; use Title; use User; @@ -51,39 +51,39 @@ final class MinervaPagePermissions implements IMinervaPagePermissions { */ private $contentHandler; - /** - * @var OutputPage just to retrieve list of language links - */ - private $output; - /** * @var SkinOptions Minerva skin options */ private $skinOptions; + /** + * @var LanguagesHelper + */ + private $languagesHelper; + /** * Initialize internal Minerva Permissions system * @param Title $title Current page title * @param Config $config Minerva config * @param User $user Currently logged in user - * @param OutputPage $output Output page used to fetch languages * @param SkinOptions $skinOptions Skin options` * @param ContentHandler $contentHandler + * @param LanguagesHelper $languagesHelper */ public function __construct( Title $title, Config $config, User $user, - OutputPage $output, SkinOptions $skinOptions, - ContentHandler $contentHandler + ContentHandler $contentHandler, + LanguagesHelper $languagesHelper ) { $this->title = $title; $this->config = $config; $this->user = $user; - $this->output = $output; $this->skinOptions = $skinOptions; $this->contentHandler = $contentHandler; + $this->languagesHelper = $languagesHelper; } /** @@ -148,11 +148,8 @@ final class MinervaPagePermissions implements IMinervaPagePermissions { if ( $wgHideInterlanguageLinks ) { return false; } - $hasVariants = $this->title->getPageLanguage()->hasVariants(); - $hasLanguages = count( $this->output->getLanguageLinks() ); - - return $hasVariants || $hasLanguages || - $this->config->get( 'MinervaAlwaysShowLanguageButton' ); + return $this->languagesHelper->doesTitleHasLanguagesOrVariants( $this->title ) || + $this->config->get( 'MinervaAlwaysShowLanguageButton' ); } return true; } diff --git a/includes/skins/SkinMinerva.php b/includes/skins/SkinMinerva.php index a2f06ef..fdbedee 100644 --- a/includes/skins/SkinMinerva.php +++ b/includes/skins/SkinMinerva.php @@ -39,9 +39,6 @@ class SkinMinerva extends SkinTemplate { /** @var string $template Name of this used template */ public $template = 'MinervaTemplate'; - /** @var bool Whether the page is also available in other languages or variants */ - protected $doesPageHaveLanguages = false; - /** @var SkinOptions */ private $skinOptions; @@ -152,9 +149,6 @@ class SkinMinerva extends SkinTemplate { // Generate skin template $tpl = parent::prepareQuickTemplate(); - $this->doesPageHaveLanguages = $tpl->data['content_navigation']['variants'] || - $tpl->data['language_urls']; - // Set whether or not the page content should be wrapped in div.content (for // example, on a special page) $tpl->set( 'unstyledContent', $out->getProperty( 'unstyledContent' ) ); @@ -713,8 +707,10 @@ class SkinMinerva extends SkinTemplate { * @return array */ protected function getSecondaryActions( BaseTemplate $tpl ) { + /** @var \MediaWiki\Minerva\LanguagesHelper $languagesHelper */ + $languagesHelper = MediaWikiServices::getInstance() + ->getService( 'Minerva.LanguagesHelper' ); $buttons = []; - // always add a button to link to the talk page // in beta it will be the entry point for the talk overlay feature, // in stable it will link to the wikitext talk page @@ -742,7 +738,7 @@ class SkinMinerva extends SkinTemplate { } } - if ( $this->doesPageHaveLanguages && $title->isMainPage() ) { + if ( $languagesHelper->doesTitleHasLanguagesOrVariants( $title ) && $title->isMainPage() ) { $buttons['language'] = $this->getLanguageButton(); } @@ -766,7 +762,7 @@ class SkinMinerva extends SkinTemplate { /** @var \MediaWiki\Minerva\Menu\PageActions\PageActionsDirector $director */ $director = MediaWikiServices::getInstance()->getService( 'Minerva.Menu.PageActionsDirector' ); $tpl->set( 'page_actions', - $director->buildMenu( $tpl->getToolbox(), $this->doesPageHaveLanguages ) + $director->buildMenu( $tpl->getToolbox() ) ); } diff --git a/skin.json b/skin.json index aa2ded2..2f657d3 100644 --- a/skin.json +++ b/skin.json @@ -86,6 +86,7 @@ "MediaWiki\\Minerva\\MenuBuilder": "includes/menu/Group.php", "MediaWiki\\Minerva\\ResourceLoaderLessVarFileModule": "includes/ResourceLoaderLessVarFileModule.php", "MediaWiki\\Minerva\\SkinOptions": "includes/SkinOptions.php", + "MediaWiki\\Minerva\\LanguagesHelper": "includes/LanguagesHelper.php", "MediaWiki\\Minerva\\SkinUserPageHelper": "includes/skins/SkinUserPageHelper.php" }, "ConfigRegistry": { diff --git a/tests/phpunit/permissions/MinervaPagePermissionsTest.php b/tests/phpunit/permissions/MinervaPagePermissionsTest.php index 04d058f..9bd5434 100644 --- a/tests/phpunit/permissions/MinervaPagePermissionsTest.php +++ b/tests/phpunit/permissions/MinervaPagePermissionsTest.php @@ -3,13 +3,12 @@ namespace Tests\MediaWiki\Minerva; use ContentHandler; +use MediaWiki\Minerva\LanguagesHelper; use MediaWiki\Minerva\Permissions\IMinervaPagePermissions; use MediaWiki\Minerva\Permissions\MinervaPagePermissions; use MediaWiki\Minerva\SkinOptions; use MediaWikiTestCase; -use OutputPage; use Title; -use RequestContext; use User; /** @@ -24,10 +23,19 @@ class MinervaPagePermissionsTest extends MediaWikiTestCase { array $options = [], ContentHandler $contentHandler = null, User $user = null, - OutputPage $outputPage = null, + $hasOtherLanguagesOrVariants = false, $alwaysShowLanguageButton = true ) { - $outputPage = $outputPage ?? RequestContext::getMain()->getOutput(); + $languageHelper = $this->getMock( + LanguagesHelper::class, + [ 'doesTitleHasLanguagesOrVariants' ], + [], + '', + false + ); + $languageHelper->expects( $this->any() ) + ->method( 'doesTitleHasLanguagesOrVariants' ) + ->willReturn( $hasOtherLanguagesOrVariants ); $user = $user ?? $this->getTestUser()->getUser(); $actions = $actions ?? [ @@ -36,7 +44,6 @@ class MinervaPagePermissionsTest extends MediaWikiTestCase { IMinervaPagePermissions::TALK, IMinervaPagePermissions::SWITCH_LANGUAGE, ]; - $contentHandler = $contentHandler ?? $this->getMockForAbstractClass( ContentHandler::class, [], '', false ); $skinOptions = new SkinOptions(); @@ -51,9 +58,9 @@ class MinervaPagePermissionsTest extends MediaWikiTestCase { 'MinervaAlwaysShowLanguageButton' => $alwaysShowLanguageButton ] ), $user, - $outputPage, $skinOptions, - $contentHandler + $contentHandler, + $languageHelper ); } @@ -144,10 +151,9 @@ class MinervaPagePermissionsTest extends MediaWikiTestCase { public static function switchLanguagePageActionProvider() { return [ - [ true, true, false, true ], - [ false, false, true, true ], - [ false, false, false, false ], - [ true, false, false, true ], + [ true, false, true ], + [ false, true, true ], + [ false, false, false ], ]; } @@ -182,25 +188,14 @@ class MinervaPagePermissionsTest extends MediaWikiTestCase { * @covers ::isAllowed */ public function testSwitchLanguagePageAction( - $hasLanguages, - $hasVariants, + $hasLanguagesOrVariants, $minervaAlwaysShowLanguageButton, $expected ) { - $out = RequestContext::getMain()->getOutput(); - $out->setLanguageLinks( $hasLanguages ? [ 'pl:StronaTestowa', 'en:TestPage' ] : [] ); - - $languageMock = $this->getMock( \Language::class, [ 'hasVariants' ], [], '', false ); - $languageMock->expects( $this->once() ) - ->method( 'hasVariants' ) - ->willReturn( $hasVariants ); - $title = $this->getMock( Title::class, [ 'isMainPage', 'getPageLanguage' ] ); + $title = $this->getMock( Title::class, [ 'isMainPage' ] ); $title->expects( $this->once() ) ->method( 'isMainPage' ) ->willReturn( false ); - $title->expects( $this->once() ) - ->method( 'getPageLanguage' ) - ->willReturn( $languageMock ); $permissions = $this->buildPermissionsObject( $title, @@ -208,7 +203,7 @@ class MinervaPagePermissionsTest extends MediaWikiTestCase { [], null, null, - $out, + $hasLanguagesOrVariants, $minervaAlwaysShowLanguageButton ); diff --git a/tests/phpunit/unit/LanguagesHelperTest.php b/tests/phpunit/unit/LanguagesHelperTest.php new file mode 100644 index 0000000..d6f36e5 --- /dev/null +++ b/tests/phpunit/unit/LanguagesHelperTest.php @@ -0,0 +1,79 @@ +getMock( + \OutputPage::class, + [ 'getLanguageLinks' ], + [], + '', + false + ); + $out->expects( $this->once() ) + ->method( 'getLanguageLinks' ) + ->willReturn( $langLinks ); + + return $out; + } + + /** + * Build test Title object + * @param $hasVariants + * @param Invocation|null $matcher + * @return \Title + */ + private function getTitle( $hasVariants, Invocation $matcher = null ) { + $languageMock = $this->getMock( \Language::class, [ 'hasVariants' ], [], '', false ); + $languageMock->expects( $matcher ?? $this->any() ) + ->method( 'hasVariants' ) + ->willReturn( $hasVariants ); + + $title = $this->getMock( \Title::class, [ 'getPageLanguage' ] ); + $title->expects( $matcher ?? $this->any() ) + ->method( 'getPageLanguage' ) + ->willReturn( $languageMock ); + + return $title; + } + + /** + * @covers ::__construct + * @covers ::doesTitleHasLanguagesOrVariants + */ + public function testReturnsWhenOutputPageHasLangLinks() { + $helper = new LanguagesHelper( $this->getOutput( [ 'pl:StronaTestowa', 'en:TestPage' ] ) ); + + $this->assertTrue( $helper->doesTitleHasLanguagesOrVariants( $this->getTitle( false ) ) ); + $this->assertTrue( $helper->doesTitleHasLanguagesOrVariants( $this->getTitle( true ) ) ); + } + + /** + * @covers ::__construct + * @covers ::doesTitleHasLanguagesOrVariants + */ + public function testReturnsWhenOutputDoesNotHaveLangLinks() { + $helper = new LanguagesHelper( $this->getOutput( [] ) ); + + $this->assertFalse( $helper->doesTitleHasLanguagesOrVariants( + $this->getTitle( false ), $this->once() ) ); + $this->assertTrue( $helper->doesTitleHasLanguagesOrVariants( + $this->getTitle( true ), $this->once() ) ); + } +}