diff --git a/extension.json b/extension.json index 37b67eb67..51f3b714c 100644 --- a/extension.json +++ b/extension.json @@ -30,6 +30,8 @@ "PopupsHooks": { "class": "Popups\\PopupsHooks", "services": [ + "Popups.Config", + "Popups.Context", "UserOptionsManager" ] } diff --git a/includes/PopupsHooks.php b/includes/PopupsHooks.php index 0897ff1e4..10f2260bd 100644 --- a/includes/PopupsHooks.php +++ b/includes/PopupsHooks.php @@ -50,15 +50,27 @@ class PopupsHooks implements private const PREVIEWS_PREFERENCES_SECTION = 'rendering/reading'; + /** @var Config */ + private $config; + + /** @var PopupsContext */ + private $popupsContext; + /** @var UserOptionsManager */ private $userOptionsManager; /** + * @param Config $config + * @param PopupsContext $popupsContext * @param UserOptionsManager $userOptionsManager */ public function __construct( + Config $config, + PopupsContext $popupsContext, UserOptionsManager $userOptionsManager ) { + $this->config = $config; + $this->popupsContext = $popupsContext; $this->userOptionsManager = $userOptionsManager; } @@ -85,21 +97,17 @@ class PopupsHooks implements * @param array[] &$prefs Preferences description array, to be fed to a HTMLForm object */ public function onGetPreferences( $user, &$prefs ) { - /** @var PopupsContext $context */ - $context = MediaWikiServices::getInstance()->getService( 'Popups.Context' ); - - if ( !$context->showPreviewsOptInOnPreferencesPage() ) { + if ( !$this->popupsContext->showPreviewsOptInOnPreferencesPage() ) { return; } $skinPosition = array_search( 'skin', array_keys( $prefs ) ); - $readingOptions = self::getPagePreviewPrefToggle( $user, $context ); + $readingOptions = self::getPagePreviewPrefToggle( $user, $this->popupsContext ); - $config = MediaWikiServices::getInstance()->getService( 'Popups.Config' ); - if ( $config->get( 'PopupsReferencePreviews' ) ) { + if ( $this->config->get( 'PopupsReferencePreviews' ) ) { $readingOptions = array_merge( $readingOptions, - self::getReferencePreviewPrefToggle( $user, $context ) + self::getReferencePreviewPrefToggle( $user, $this->popupsContext ) ); } @@ -183,21 +191,19 @@ class PopupsHooks implements * @param Skin $skin Skin object that will be used to generate the page */ public function onBeforePageDisplay( $out, $skin ): void { - /** @var PopupsContext $context */ - $context = MediaWikiServices::getInstance()->getService( 'Popups.Context' ); - if ( $context->isTitleExcluded( $out->getTitle() ) ) { + if ( $this->popupsContext->isTitleExcluded( $out->getTitle() ) ) { return; } - if ( !$context->areDependenciesMet() ) { - $logger = $context->getLogger(); + if ( !$this->popupsContext->areDependenciesMet() ) { + $logger = $this->popupsContext->getLogger(); $logger->error( 'Popups requires the PageImages extensions. TextExtracts extension is required when using mwApiPlain gateway.' ); return; } $user = $out->getUser(); - if ( $context->shouldSendModuleToUser( $user ) ) { + if ( $this->popupsContext->shouldSendModuleToUser( $user ) ) { $out->addModules( [ 'ext.popups' ] ); } } @@ -215,14 +221,11 @@ class PopupsHooks implements * @param Config $config */ public function onResourceLoaderGetConfigVars( array &$vars, $skin, Config $config ): void { - /** @var Config $config */ - $config = MediaWikiServices::getInstance()->getService( 'Popups.Config' ); - - $vars['wgPopupsVirtualPageViews'] = $config->get( 'PopupsVirtualPageViews' ); - $vars['wgPopupsGateway'] = $config->get( 'PopupsGateway' ); - $vars['wgPopupsRestGatewayEndpoint'] = $config->get( 'PopupsRestGatewayEndpoint' ); - $vars['wgPopupsStatsvSamplingRate'] = $config->get( 'PopupsStatsvSamplingRate' ); - $vars['wgPopupsTextExtractsIntroOnly'] = $config->get( 'PopupsTextExtractsIntroOnly' ); + $vars['wgPopupsVirtualPageViews'] = $this->config->get( 'PopupsVirtualPageViews' ); + $vars['wgPopupsGateway'] = $this->config->get( 'PopupsGateway' ); + $vars['wgPopupsRestGatewayEndpoint'] = $this->config->get( 'PopupsRestGatewayEndpoint' ); + $vars['wgPopupsStatsvSamplingRate'] = $this->config->get( 'PopupsStatsvSamplingRate' ); + $vars['wgPopupsTextExtractsIntroOnly'] = $this->config->get( 'PopupsTextExtractsIntroOnly' ); } /** @@ -241,9 +244,7 @@ class PopupsHooks implements * @param \IContextSource $out OutputPage instance calling the hook */ public function onMakeGlobalVariablesScript( &$vars, $out ): void { - /** @var PopupsContext $context */ - $context = MediaWikiServices::getInstance()->getService( 'Popups.Context' ); - $vars['wgPopupsFlags'] = $context->getConfigBitmaskFromUser( $out->getUser() ); + $vars['wgPopupsFlags'] = $this->popupsContext->getConfigBitmaskFromUser( $out->getUser() ); } /** @@ -252,12 +253,10 @@ class PopupsHooks implements * @param array &$defaultOptions */ public function onUserGetDefaultOptions( &$defaultOptions ) { - /** @var Config $config */ - $config = MediaWikiServices::getInstance()->getService( 'Popups.Config' ); - $default = $config->get( 'PopupsOptInDefaultState' ); + $default = $this->config->get( 'PopupsOptInDefaultState' ); $defaultOptions[PopupsContext::PREVIEWS_OPTIN_PREFERENCE_NAME] = $default; - if ( $config->get( 'PopupsReferencePreviews' ) ) { + if ( $this->config->get( 'PopupsReferencePreviews' ) ) { $defaultOptions[PopupsContext::REFERENCE_PREVIEWS_PREFERENCE_NAME] = '1'; } } @@ -269,16 +268,14 @@ class PopupsHooks implements * @param bool $isAutoCreated */ public function onLocalUserCreated( $user, $isAutoCreated ) { - /** @var Config $config */ - $config = MediaWikiServices::getInstance()->getService( 'Popups.Config' ); - $default = $config->get( 'PopupsOptInStateForNewAccounts' ); + $default = $this->config->get( 'PopupsOptInStateForNewAccounts' ); $this->userOptionsManager->setOption( $user, PopupsContext::PREVIEWS_OPTIN_PREFERENCE_NAME, $default ); - if ( $config->get( 'PopupsReferencePreviews' ) ) { + if ( $this->config->get( 'PopupsReferencePreviews' ) ) { $this->userOptionsManager->setOption( $user, PopupsContext::REFERENCE_PREVIEWS_PREFERENCE_NAME, diff --git a/tests/phpunit/PopupsHooksTest.php b/tests/phpunit/PopupsHooksTest.php index 050c6a748..a8a906ca9 100644 --- a/tests/phpunit/PopupsHooksTest.php +++ b/tests/phpunit/PopupsHooksTest.php @@ -19,6 +19,7 @@ * @ingroup extensions */ +use MediaWiki\Config\HashConfig; use MediaWiki\Config\MultiConfig; use MediaWiki\Output\OutputPage; use MediaWiki\User\Options\UserOptionsManager; @@ -44,11 +45,13 @@ class PopupsHooksTest extends MediaWikiIntegrationTestCase { ->method( 'showPreviewsOptInOnPreferencesPage' ) ->willReturn( false ); - $this->setService( 'Popups.Context', $contextMock ); $prefs = [ 'someNotEmptyValue' => 'notEmpty' ]; - $userOptionsManager = $this->getServiceContainer()->getUserOptionsManager(); - ( new PopupsHooks( $userOptionsManager ) ) + ( new PopupsHooks( + new HashConfig(), + $contextMock, + $this->getServiceContainer()->getUserOptionsManager() + ) ) ->onGetPreferences( $this->createMock( User::class ), $prefs ); $this->assertCount( 1, $prefs, 'No preferences are retrieved.' ); $this->assertSame( 'notEmpty', @@ -72,13 +75,15 @@ class PopupsHooksTest extends MediaWikiIntegrationTestCase { ->with( $userMock ) ->willReturn( true ); - $this->setService( 'Popups.Context', $contextMock ); $prefs = []; - $this->setMwGlobals( 'wgPopupsReferencePreviews', $enabled ); - - $userOptionsManager = $this->getServiceContainer()->getUserOptionsManager(); - ( new PopupsHooks( $userOptionsManager ) ) + ( new PopupsHooks( + new HashConfig( [ + 'PopupsReferencePreviews' => $enabled, + ] ), + $contextMock, + $this->getServiceContainer()->getUserOptionsManager() + ) ) ->onGetPreferences( $userMock, $prefs ); $this->assertArrayHasKey( PopupsContext::PREVIEWS_OPTIN_PREFERENCE_NAME, $prefs, @@ -106,17 +111,19 @@ class PopupsHooksTest extends MediaWikiIntegrationTestCase { ->method( 'conflictsWithNavPopupsGadget' ) ->willReturn( false ); - $this->setService( 'Popups.Context', $contextMock ); $prefs = [ 'skin' => 'skin stuff', 'someNotEmptyValue' => 'notEmpty', 'other' => 'notEmpty' ]; - $this->setMwGlobals( 'wgPopupsReferencePreviews', $enabled ); - - $userOptionsManager = $this->getServiceContainer()->getUserOptionsManager(); - ( new PopupsHooks( $userOptionsManager ) ) + ( new PopupsHooks( + new HashConfig( [ + 'PopupsReferencePreviews' => $enabled, + ] ), + $contextMock, + $this->getServiceContainer()->getUserOptionsManager() + ) ) ->onGetPreferences( $this->createMock( User::class ), $prefs ); $this->assertGreaterThan( 3, count( $prefs ), 'A preference is retrieved.' ); $this->assertSame( 'notEmpty', @@ -144,16 +151,18 @@ class PopupsHooksTest extends MediaWikiIntegrationTestCase { ->method( 'conflictsWithNavPopupsGadget' ) ->willReturn( false ); - $this->setService( 'Popups.Context', $contextMock ); $prefs = [ 'someNotEmptyValue' => 'notEmpty', 'other' => 'notEmpty' ]; - $this->setMwGlobals( 'wgPopupsReferencePreviews', $enabled ); - - $userOptionsManager = $this->getServiceContainer()->getUserOptionsManager(); - ( new PopupsHooks( $userOptionsManager ) ) + ( new PopupsHooks( + new HashConfig( [ + 'PopupsReferencePreviews' => $enabled, + ] ), + $contextMock, + $this->getServiceContainer()->getUserOptionsManager() + ) ) ->onGetPreferences( $this->createMock( User::class ), $prefs ); $this->assertGreaterThan( 2, count( $prefs ), 'A preference is retrieved.' ); $this->assertArrayHasKey( PopupsContext::PREVIEWS_OPTIN_PREFERENCE_NAME, @@ -171,23 +180,25 @@ class PopupsHooksTest extends MediaWikiIntegrationTestCase { public function testOnResourceLoaderGetConfigVars() { $vars = [ 'something' => 'notEmpty' ]; $config = [ - 'wgPopupsRestGatewayEndpoint' => '/api', - 'wgPopupsVirtualPageViews' => true, - 'wgPopupsGateway' => 'mwApiPlain', - 'wgPopupsStatsvSamplingRate' => 0, - 'wgPopupsTextExtractsIntroOnly' => true, + 'PopupsRestGatewayEndpoint' => '/api', + 'PopupsVirtualPageViews' => true, + 'PopupsGateway' => 'mwApiPlain', + 'PopupsStatsvSamplingRate' => 0, + 'PopupsTextExtractsIntroOnly' => true, ]; - $this->setMwGlobals( $config ); - $userOptionsManager = $this->getServiceContainer()->getUserOptionsManager(); - ( new PopupsHooks( $userOptionsManager ) ) + ( new PopupsHooks( + new HashConfig( $config ), + $this->getServiceContainer()->getService( 'Popups.Context' ), + $this->getServiceContainer()->getUserOptionsManager() + ) ) ->onResourceLoaderGetConfigVars( $vars, '', new MultiConfig( $config ) ); $this->assertCount( 6, $vars, 'A configuration is retrieved.' ); foreach ( $config as $key => $value ) { $this->assertSame( $value, - $vars[ $key ], - "It forwards the \"{$key}\" config variable to the client." + $vars[ "wg$key" ], + "It forwards the \"wg{$key}\" config variable to the client." ); } } @@ -215,9 +226,11 @@ class PopupsHooksTest extends MediaWikiIntegrationTestCase { ->method( 'getLogger' ) ->willReturn( $loggerMock ); - $this->setService( 'Popups.Context', $contextMock ); - $userOptionsManager = $this->getServiceContainer()->getUserOptionsManager(); - ( new PopupsHooks( $userOptionsManager ) ) + ( new PopupsHooks( + new HashConfig(), + $contextMock, + $this->getServiceContainer()->getUserOptionsManager() + ) ) ->onBeforePageDisplay( $outPageMock, $skinMock ); } @@ -262,9 +275,11 @@ class PopupsHooksTest extends MediaWikiIntegrationTestCase { ->method( 'isTitleExcluded' ) ->willReturn( $isTitleExcluded ); - $this->setService( 'Popups.Context', $contextMock ); - $userOptionsManager = $this->getServiceContainer()->getUserOptionsManager(); - ( new PopupsHooks( $userOptionsManager ) ) + ( new PopupsHooks( + new HashConfig(), + $contextMock, + $this->getServiceContainer()->getUserOptionsManager() + ) ) ->onBeforePageDisplay( $outPageMock, $skinMock ); } @@ -283,11 +298,12 @@ class PopupsHooksTest extends MediaWikiIntegrationTestCase { ->with( $user ) ->willReturn( 0 ); - $this->setService( 'Popups.Context', $contextMock ); - $vars = []; - $userOptionsManager = $this->getServiceContainer()->getUserOptionsManager(); - ( new PopupsHooks( $userOptionsManager ) ) + ( new PopupsHooks( + new HashConfig(), + $contextMock, + $this->getServiceContainer()->getUserOptionsManager() + ) ) ->onMakeGlobalVariablesScript( $vars, $outputPage ); $this->assertCount( 1, $vars, 'Number of added variables.' ); @@ -304,13 +320,14 @@ class PopupsHooksTest extends MediaWikiIntegrationTestCase { 'test' => 'not_empty' ]; - $this->setMwGlobals( [ - 'wgPopupsOptInDefaultState' => '1', - 'wgPopupsReferencePreviews' => $enabled, - ] ); - - $userOptionsManager = $this->getServiceContainer()->getUserOptionsManager(); - ( new PopupsHooks( $userOptionsManager ) ) + ( new PopupsHooks( + new HashConfig( [ + 'PopupsOptInDefaultState' => '1', + 'PopupsReferencePreviews' => $enabled, + ] ), + $this->getServiceContainer()->getService( 'Popups.Context' ), + $this->getServiceContainer()->getUserOptionsManager() + ) ) ->onUserGetDefaultOptions( $userOptions ); $this->assertCount( $enabled ? 3 : 2, $userOptions ); $this->assertSame( '1', $userOptions[ PopupsContext::PREVIEWS_OPTIN_PREFERENCE_NAME ] ); @@ -342,11 +359,14 @@ class PopupsHooksTest extends MediaWikiIntegrationTestCase { unset( $expectedOptions[$option] ); } ); - $this->setMwGlobals( [ - 'wgPopupsOptInStateForNewAccounts' => $expectedState, - 'wgPopupsReferencePreviews' => $enabled, - ] ); - ( new PopupsHooks( $userOptionsManagerMock ) ) + ( new PopupsHooks( + new HashConfig( [ + 'PopupsOptInStateForNewAccounts' => $expectedState, + 'PopupsReferencePreviews' => $enabled, + ] ), + $this->getServiceContainer()->getService( 'Popups.Context' ), + $userOptionsManagerMock + ) ) ->onLocalUserCreated( $userMock, false ); }