diff --git a/includes/Constants.php b/includes/Constants.php index 1c368fb1d..f9c017966 100644 --- a/includes/Constants.php +++ b/includes/Constants.php @@ -32,11 +32,6 @@ final class Constants { */ public const SKIN_VERSION_LATEST = '2'; - /** - * @var string - */ - public const SERVICE_FEATURE_MANAGER = 'Vector.FeatureManager'; - // These are tightly coupled to skin.json's configs. See skin.json for documentation. /** * @var string diff --git a/includes/FeatureManagement/FeatureManagerFactory.php b/includes/FeatureManagement/FeatureManagerFactory.php new file mode 100644 index 000000000..19883c780 --- /dev/null +++ b/includes/FeatureManagement/FeatureManagerFactory.php @@ -0,0 +1,356 @@ +userOptionsLookup = $userOptionsLookup; + } + + public function createFeatureManager( IContextSource $context ): FeatureManager { + $featureManager = new FeatureManager(); + + $request = $context->getRequest(); + $config = $context->getConfig(); + $user = $context->getUser(); + $title = $context->getTitle(); + + $featureManager->registerRequirement( + new DynamicConfigRequirement( + $config, + Constants::CONFIG_KEY_FULLY_INITIALISED, + Constants::REQUIREMENT_FULLY_INITIALISED + ) + ); + + // Feature: Languages in sidebar + // ================================ + $featureManager->registerRequirement( + new OverridableConfigRequirement( + $config, + $user, + $request, + Constants::CONFIG_KEY_LANGUAGE_IN_HEADER, + Constants::REQUIREMENT_LANGUAGE_IN_HEADER + ) + ); + + // --- + + $featureManager->registerFeature( + Constants::FEATURE_LANGUAGE_IN_HEADER, + [ + Constants::REQUIREMENT_FULLY_INITIALISED, + Constants::REQUIREMENT_LANGUAGE_IN_HEADER, + ] + ); + + // Feature: T293470: Language in main page header + // ================================ + $featureManager->registerRequirement( + new OverridableConfigRequirement( + $config, + $user, + $request, + Constants::CONFIG_LANGUAGE_IN_MAIN_PAGE_HEADER, + Constants::REQUIREMENT_LANGUAGE_IN_MAIN_PAGE_HEADER + ) + ); + + $featureManager->registerSimpleRequirement( + Constants::REQUIREMENT_IS_MAIN_PAGE, + $title ? $title->isMainPage() : false + ); + + $featureManager->registerFeature( + Constants::FEATURE_LANGUAGE_IN_MAIN_PAGE_HEADER, + [ + Constants::REQUIREMENT_FULLY_INITIALISED, + Constants::REQUIREMENT_IS_MAIN_PAGE, + Constants::REQUIREMENT_LANGUAGE_IN_HEADER, + Constants::REQUIREMENT_LANGUAGE_IN_MAIN_PAGE_HEADER + ] + ); + + // Feature: Sticky header + // ================================ + $featureManager->registerRequirement( + new OverridableConfigRequirement( + $config, + $user, + $request, + Constants::CONFIG_STICKY_HEADER, + Constants::REQUIREMENT_STICKY_HEADER + ) + ); + + $featureManager->registerFeature( + Constants::FEATURE_STICKY_HEADER, + [ + Constants::REQUIREMENT_FULLY_INITIALISED, + Constants::REQUIREMENT_STICKY_HEADER + ] + ); + + // Feature: Page tools pinned + // ================================ + $featureManager->registerRequirement( + new LoggedInRequirement( + $user, + Constants::REQUIREMENT_LOGGED_IN + ) + ); + + $featureManager->registerRequirement( + new UserPreferenceRequirement( + $user, + $this->userOptionsLookup, + Constants::PREF_KEY_PAGE_TOOLS_PINNED, + Constants::REQUIREMENT_PAGE_TOOLS_PINNED, + $request, + $title + ) + ); + + $featureManager->registerFeature( + Constants::FEATURE_PAGE_TOOLS_PINNED, + [ + Constants::REQUIREMENT_FULLY_INITIALISED, + Constants::REQUIREMENT_LOGGED_IN, + Constants::REQUIREMENT_PAGE_TOOLS_PINNED + ] + ); + + // Feature: Table of Contents pinned + // ================================ + $featureManager->registerRequirement( + new UserPreferenceRequirement( + $user, + $this->userOptionsLookup, + Constants::PREF_KEY_TOC_PINNED, + Constants::REQUIREMENT_TOC_PINNED, + $request, + $title + ) + ); + + $featureManager->registerFeature( + Constants::FEATURE_TOC_PINNED, + [ + Constants::REQUIREMENT_FULLY_INITIALISED, + Constants::REQUIREMENT_TOC_PINNED + ] + ); + + // Feature: Main menu pinned + // ================================ + $featureManager->registerRequirement( + new UserPreferenceRequirement( + $user, + $this->userOptionsLookup, + Constants::PREF_KEY_MAIN_MENU_PINNED, + Constants::REQUIREMENT_MAIN_MENU_PINNED, + $request, + $title + ) + ); + + $featureManager->registerFeature( + Constants::FEATURE_MAIN_MENU_PINNED, + [ + Constants::REQUIREMENT_FULLY_INITIALISED, + Constants::REQUIREMENT_LOGGED_IN, + Constants::REQUIREMENT_MAIN_MENU_PINNED + ] + ); + + // Feature: Max Width (skin) + // ================================ + $featureManager->registerRequirement( + new UserPreferenceRequirement( + $user, + $this->userOptionsLookup, + Constants::PREF_KEY_LIMITED_WIDTH, + Constants::REQUIREMENT_LIMITED_WIDTH, + $request, + $title + ) + ); + $featureManager->registerFeature( + Constants::FEATURE_LIMITED_WIDTH, + [ + Constants::REQUIREMENT_FULLY_INITIALISED, + Constants::REQUIREMENT_LIMITED_WIDTH + ] + ); + + // Feature: Max Width (content) + // ================================ + $featureManager->registerRequirement( + new LimitedWidthContentRequirement( + $config, + $request, + $title + ) + ); + $featureManager->registerFeature( + Constants::FEATURE_LIMITED_WIDTH_CONTENT, + [ + Constants::REQUIREMENT_FULLY_INITIALISED, + Constants::REQUIREMENT_LIMITED_WIDTH_CONTENT, + ] + ); + + // Feature: T343928: Feature Font Size. + // ================================ + $featureManager->registerRequirement( + new UserPreferenceRequirement( + $user, + $this->userOptionsLookup, + Constants::PREF_KEY_FONT_SIZE, + Constants::REQUIREMENT_FONT_SIZE, + $request, + $title + ) + ); + + // Register 'custom-font-size' as the default requirement + $featureManager->registerFeature( + Constants::FEATURE_FONT_SIZE, + [ + Constants::REQUIREMENT_FULLY_INITIALISED, + Constants::REQUIREMENT_FONT_SIZE + ] + ); + + // Feature: T345363: Client preferences dialog + // ============================================ + $featureManager->registerRequirement( + new OverridableConfigRequirement( + $config, + $user, + $request, + Constants::CONFIG_KEY_CLIENT_PREFERENCES, + Constants::REQUIREMENT_CLIENT_PREFERENCES + ) + ); + + $featureManager->registerFeature( + Constants::FEATURE_CLIENT_PREFERENCES, + [ + Constants::REQUIREMENT_FULLY_INITIALISED, + Constants::REQUIREMENT_CLIENT_PREFERENCES + ] + ); + + // Feature: Client preference pinned + // ================================ + $featureManager->registerRequirement( + new UserPreferenceRequirement( + $user, + $this->userOptionsLookup, + Constants::PREF_KEY_CLIENT_PREFS_PINNED, + Constants::REQUIREMENT_CLIENT_PREFS_PINNED, + $request, + $title + ) + ); + + $featureManager->registerFeature( + Constants::FEATURE_CLIENT_PREFS_PINNED, + [ + Constants::REQUIREMENT_FULLY_INITIALISED, + Constants::REQUIREMENT_LOGGED_IN, + Constants::REQUIREMENT_CLIENT_PREFERENCES, + Constants::REQUIREMENT_CLIENT_PREFS_PINNED + ] + ); + + // Feature: Night mode (T355065) + // ============================================ + $featureManager->registerRequirement( + new OverridableConfigRequirement( + $config, + $user, + $request, + Constants::CONFIG_KEY_NIGHT_MODE, + Constants::REQUIREMENT_NIGHT_MODE + ) + ); + + $featureManager->registerFeature( + Constants::FEATURE_NIGHT_MODE, + [ + Constants::REQUIREMENT_FULLY_INITIALISED, + Constants::REQUIREMENT_NIGHT_MODE + ] + ); + + // Preference: Night mode (T355065) + // ============================================ + $featureManager->registerRequirement( + new UserPreferenceRequirement( + $user, + $this->userOptionsLookup, + Constants::PREF_KEY_NIGHT_MODE, + Constants::REQUIREMENT_PREF_NIGHT_MODE, + $request, + $title + ) + ); + + $featureManager->registerFeature( + Constants::PREF_NIGHT_MODE, + [ + Constants::REQUIREMENT_FULLY_INITIALISED, + Constants::REQUIREMENT_NIGHT_MODE, + Constants::REQUIREMENT_PREF_NIGHT_MODE + ] + ); + + return $featureManager; + } + +} diff --git a/includes/ServiceWiring.php b/includes/ServiceWiring.php index f5c5fb34b..332b4cddd 100644 --- a/includes/ServiceWiring.php +++ b/includes/ServiceWiring.php @@ -23,13 +23,7 @@ */ use MediaWiki\MediaWikiServices; -use MediaWiki\Skins\Vector\Constants; -use MediaWiki\Skins\Vector\FeatureManagement\FeatureManager; -use MediaWiki\Skins\Vector\FeatureManagement\Requirements\DynamicConfigRequirement; -use MediaWiki\Skins\Vector\FeatureManagement\Requirements\LimitedWidthContentRequirement; -use MediaWiki\Skins\Vector\FeatureManagement\Requirements\LoggedInRequirement; -use MediaWiki\Skins\Vector\FeatureManagement\Requirements\OverridableConfigRequirement; -use MediaWiki\Skins\Vector\FeatureManagement\Requirements\UserPreferenceRequirement; +use MediaWiki\Skins\Vector\FeatureManagement\FeatureManagerFactory; // PHP unit does not understand code coverage for this file // as the @covers annotation cannot cover a specific file @@ -37,306 +31,10 @@ use MediaWiki\Skins\Vector\FeatureManagement\Requirements\UserPreferenceRequirem // @codeCoverageIgnoreStart return [ - Constants::SERVICE_FEATURE_MANAGER => static function ( MediaWikiServices $services ): FeatureManager { - $featureManager = new FeatureManager(); - - $featureManager->registerRequirement( - new DynamicConfigRequirement( - $services->getMainConfig(), - Constants::CONFIG_KEY_FULLY_INITIALISED, - Constants::REQUIREMENT_FULLY_INITIALISED - ) + 'Vector.FeatureManagerFactory' => static function ( MediaWikiServices $services ): FeatureManagerFactory { + return new FeatureManagerFactory( + $services->getUserOptionsLookup() ); - - $context = RequestContext::getMain(); - $request = $context->getRequest(); - - // Feature: Languages in sidebar - // ================================ - $featureManager->registerRequirement( - new OverridableConfigRequirement( - $services->getMainConfig(), - $context->getUser(), - $request, - Constants::CONFIG_KEY_LANGUAGE_IN_HEADER, - Constants::REQUIREMENT_LANGUAGE_IN_HEADER - ) - ); - - // --- - - $featureManager->registerFeature( - Constants::FEATURE_LANGUAGE_IN_HEADER, - [ - Constants::REQUIREMENT_FULLY_INITIALISED, - Constants::REQUIREMENT_LANGUAGE_IN_HEADER, - ] - ); - - // Feature: T293470: Language in main page header - // ================================ - $featureManager->registerRequirement( - new OverridableConfigRequirement( - $services->getMainConfig(), - $context->getUser(), - $request, - Constants::CONFIG_LANGUAGE_IN_MAIN_PAGE_HEADER, - Constants::REQUIREMENT_LANGUAGE_IN_MAIN_PAGE_HEADER - ) - ); - - $featureManager->registerSimpleRequirement( - Constants::REQUIREMENT_IS_MAIN_PAGE, - $context->getTitle() ? $context->getTitle()->isMainPage() : false - ); - - $featureManager->registerFeature( - Constants::FEATURE_LANGUAGE_IN_MAIN_PAGE_HEADER, - [ - Constants::REQUIREMENT_FULLY_INITIALISED, - Constants::REQUIREMENT_IS_MAIN_PAGE, - Constants::REQUIREMENT_LANGUAGE_IN_HEADER, - Constants::REQUIREMENT_LANGUAGE_IN_MAIN_PAGE_HEADER - ] - ); - - // Feature: Sticky header - // ================================ - $featureManager->registerRequirement( - new OverridableConfigRequirement( - $services->getMainConfig(), - $context->getUser(), - $request, - Constants::CONFIG_STICKY_HEADER, - Constants::REQUIREMENT_STICKY_HEADER - ) - ); - - $featureManager->registerFeature( - Constants::FEATURE_STICKY_HEADER, - [ - Constants::REQUIREMENT_FULLY_INITIALISED, - Constants::REQUIREMENT_STICKY_HEADER - ] - ); - - // Feature: Page tools pinned - // ================================ - $featureManager->registerRequirement( - new LoggedInRequirement( - $context->getUser(), - Constants::REQUIREMENT_LOGGED_IN - ) - ); - - $featureManager->registerRequirement( - new UserPreferenceRequirement( - $context->getUser(), - $services->getUserOptionsLookup(), - Constants::PREF_KEY_PAGE_TOOLS_PINNED, - Constants::REQUIREMENT_PAGE_TOOLS_PINNED, - $request, - $context->getTitle() - ) - ); - - $featureManager->registerFeature( - Constants::FEATURE_PAGE_TOOLS_PINNED, - [ - Constants::REQUIREMENT_FULLY_INITIALISED, - Constants::REQUIREMENT_LOGGED_IN, - Constants::REQUIREMENT_PAGE_TOOLS_PINNED - ] - ); - - // Feature: Table of Contents pinned - // ================================ - $featureManager->registerRequirement( - new UserPreferenceRequirement( - $context->getUser(), - $services->getUserOptionsLookup(), - Constants::PREF_KEY_TOC_PINNED, - Constants::REQUIREMENT_TOC_PINNED, - $request, - $context->getTitle() - ) - ); - - $featureManager->registerFeature( - Constants::FEATURE_TOC_PINNED, - [ - Constants::REQUIREMENT_FULLY_INITIALISED, - Constants::REQUIREMENT_TOC_PINNED - ] - ); - - // Feature: Main menu pinned - // ================================ - $featureManager->registerRequirement( - new UserPreferenceRequirement( - $context->getUser(), - $services->getUserOptionsLookup(), - Constants::PREF_KEY_MAIN_MENU_PINNED, - Constants::REQUIREMENT_MAIN_MENU_PINNED, - $request, - $context->getTitle() - ) - ); - - $featureManager->registerFeature( - Constants::FEATURE_MAIN_MENU_PINNED, - [ - Constants::REQUIREMENT_FULLY_INITIALISED, - Constants::REQUIREMENT_LOGGED_IN, - Constants::REQUIREMENT_MAIN_MENU_PINNED - ] - ); - - // Feature: Max Width (skin) - // ================================ - $featureManager->registerRequirement( - new UserPreferenceRequirement( - $context->getUser(), - $services->getUserOptionsLookup(), - Constants::PREF_KEY_LIMITED_WIDTH, - Constants::REQUIREMENT_LIMITED_WIDTH, - $request, - $context->getTitle() - ) - ); - $featureManager->registerFeature( - Constants::FEATURE_LIMITED_WIDTH, - [ - Constants::REQUIREMENT_FULLY_INITIALISED, - Constants::REQUIREMENT_LIMITED_WIDTH - ] - ); - - // Feature: Max Width (content) - // ================================ - $featureManager->registerRequirement( - new LimitedWidthContentRequirement( - $services->getMainConfig(), - $request, - $context->getTitle() - ) - ); - $featureManager->registerFeature( - Constants::FEATURE_LIMITED_WIDTH_CONTENT, - [ - Constants::REQUIREMENT_FULLY_INITIALISED, - Constants::REQUIREMENT_LIMITED_WIDTH_CONTENT, - ] - ); - - // Feature: T343928: Feature Font Size. - // ================================ - $featureManager->registerRequirement( - new UserPreferenceRequirement( - $context->getUser(), - $services->getUserOptionsLookup(), - Constants::PREF_KEY_FONT_SIZE, - Constants::REQUIREMENT_FONT_SIZE, - $request, - $context->getTitle() - ) - ); - - // Register 'custom-font-size' as the default requirement - $featureManager->registerFeature( - Constants::FEATURE_FONT_SIZE, - [ - Constants::REQUIREMENT_FULLY_INITIALISED, - Constants::REQUIREMENT_FONT_SIZE - ] - ); - - // Feature: T345363: Client preferences dialog - // ============================================ - $featureManager->registerRequirement( - new OverridableConfigRequirement( - $services->getMainConfig(), - $context->getUser(), - $request, - Constants::CONFIG_KEY_CLIENT_PREFERENCES, - Constants::REQUIREMENT_CLIENT_PREFERENCES - ) - ); - - $featureManager->registerFeature( - Constants::FEATURE_CLIENT_PREFERENCES, - [ - Constants::REQUIREMENT_FULLY_INITIALISED, - Constants::REQUIREMENT_CLIENT_PREFERENCES - ] - ); - - // Feature: Client preference pinned - // ================================ - $featureManager->registerRequirement( - new UserPreferenceRequirement( - $context->getUser(), - $services->getUserOptionsLookup(), - Constants::PREF_KEY_CLIENT_PREFS_PINNED, - Constants::REQUIREMENT_CLIENT_PREFS_PINNED, - $request, - $context->getTitle() - ) - ); - - $featureManager->registerFeature( - Constants::FEATURE_CLIENT_PREFS_PINNED, - [ - Constants::REQUIREMENT_FULLY_INITIALISED, - Constants::REQUIREMENT_LOGGED_IN, - Constants::REQUIREMENT_CLIENT_PREFERENCES, - Constants::REQUIREMENT_CLIENT_PREFS_PINNED - ] - ); - - // Feature: Night mode (T355065) - // ============================================ - $featureManager->registerRequirement( - new OverridableConfigRequirement( - $services->getMainConfig(), - $context->getUser(), - $request, - Constants::CONFIG_KEY_NIGHT_MODE, - Constants::REQUIREMENT_NIGHT_MODE - ) - ); - - $featureManager->registerFeature( - Constants::FEATURE_NIGHT_MODE, - [ - Constants::REQUIREMENT_FULLY_INITIALISED, - Constants::REQUIREMENT_NIGHT_MODE - ] - ); - - // Preference: Night mode (T355065) - // ============================================ - $featureManager->registerRequirement( - new UserPreferenceRequirement( - $context->getUser(), - $services->getUserOptionsLookup(), - Constants::PREF_KEY_NIGHT_MODE, - Constants::REQUIREMENT_PREF_NIGHT_MODE, - $request, - $context->getTitle() - ) - ); - - $featureManager->registerFeature( - Constants::PREF_NIGHT_MODE, - [ - Constants::REQUIREMENT_FULLY_INITIALISED, - Constants::REQUIREMENT_NIGHT_MODE, - Constants::REQUIREMENT_PREF_NIGHT_MODE - ] - ); - - return $featureManager; } ]; diff --git a/includes/SkinVector22.php b/includes/SkinVector22.php index 8767d66a2..e023bae8c 100644 --- a/includes/SkinVector22.php +++ b/includes/SkinVector22.php @@ -16,6 +16,8 @@ use MediaWiki\Skins\Vector\Components\VectorComponentStickyHeader; use MediaWiki\Skins\Vector\Components\VectorComponentTableOfContents; use MediaWiki\Skins\Vector\Components\VectorComponentUserLinks; use MediaWiki\Skins\Vector\Components\VectorComponentVariants; +use MediaWiki\Skins\Vector\FeatureManagement\FeatureManager; +use MediaWiki\Skins\Vector\FeatureManagement\FeatureManagerFactory; use RuntimeException; use SkinMustache; use SkinTemplate; @@ -30,6 +32,19 @@ class SkinVector22 extends SkinMustache { /** @var null|array for caching purposes */ private $languages; + private FeatureManagerFactory $featureManagerFactory; + private ?FeatureManager $featureManager = null; + + public function __construct( + FeatureManagerFactory $featureManagerFactory, + array $options + ) { + parent::__construct( $options ); + + // Cannot use the context in the constructor, setContext is called after construction + $this->featureManagerFactory = $featureManagerFactory; + } + /** * @inheritDoc */ @@ -113,6 +128,13 @@ class SkinVector22 extends SkinMustache { return $hasAddTopicButton; } + private function getFeatureManager(): FeatureManager { + if ( $this->featureManager === null ) { + $this->featureManager = $this->featureManagerFactory->createFeatureManager( $this->getContext() ); + } + return $this->featureManager; + } + /** * @param string $location Either 'top' or 'bottom' is accepted. * @return bool @@ -121,7 +143,7 @@ class SkinVector22 extends SkinMustache { if ( !$this->canHaveLanguages() ) { return false; } - $featureManager = VectorServices::getFeatureManager(); + $featureManager = $this->getFeatureManager(); $inContent = $featureManager->isFeatureEnabled( Constants::FEATURE_LANGUAGE_IN_HEADER ); @@ -229,7 +251,7 @@ class SkinVector22 extends SkinMustache { */ public function getHtmlElementAttributes() { $original = parent::getHtmlElementAttributes(); - $featureManager = VectorServices::getFeatureManager(); + $featureManager = $this->getFeatureManager(); $original['class'] .= ' ' . implode( ' ', $featureManager->getFeatureBodyClass() ); if ( $featureManager->isFeatureEnabled( Constants::FEATURE_STICKY_HEADER ) ) { @@ -307,7 +329,7 @@ class SkinVector22 extends SkinMustache { $langData = $portlets['data-languages'] ?? null; $config = $this->getConfig(); - $featureManager = VectorServices::getFeatureManager(); + $featureManager = $this->getFeatureManager(); $sidebar = $parentData[ 'data-portlets-sidebar' ]; $pageToolsMenu = []; diff --git a/includes/VectorServices.php b/includes/VectorServices.php index 48a80efcb..8e75a683a 100644 --- a/includes/VectorServices.php +++ b/includes/VectorServices.php @@ -2,8 +2,6 @@ namespace MediaWiki\Skins\Vector; -use MediaWiki\MediaWikiServices; -use MediaWiki\Skins\Vector\FeatureManagement\FeatureManager; use MediaWiki\Skins\Vector\Services\LanguageService; /** @@ -14,18 +12,6 @@ use MediaWiki\Skins\Vector\Services\LanguageService; */ final class VectorServices { - /** - * Gets the feature manager service. - * - * Per its definition in ServiceWiring.php, the feature manager service is bound to the global - * request and user objects. - * - * @return FeatureManager - */ - public static function getFeatureManager(): FeatureManager { - return MediaWikiServices::getInstance()->getService( Constants::SERVICE_FEATURE_MANAGER ); - } - /** * Gets the language service. * diff --git a/skin.json b/skin.json index 83f2e5e4c..f9d988ff3 100644 --- a/skin.json +++ b/skin.json @@ -33,6 +33,9 @@ "ValidSkinNames": { "vector-2022": { "class": "MediaWiki\\Skins\\Vector\\SkinVector22", + "services": [ + "Vector.FeatureManagerFactory" + ], "args": [ { "name": "vector-2022", diff --git a/tests/phpunit/integration/VectorHooksTest.php b/tests/phpunit/integration/VectorHooksTest.php index 9d215bed1..cb9cf8171 100644 --- a/tests/phpunit/integration/VectorHooksTest.php +++ b/tests/phpunit/integration/VectorHooksTest.php @@ -411,7 +411,10 @@ class VectorHooksTest extends MediaWikiIntegrationTestCase { */ public function testOnSkinTemplateNavigation() { $this->overrideConfigValue( 'VectorUseIconWatch', true ); - $skin = new SkinVector22( [ 'name' => 'vector' ] ); + $skin = new SkinVector22( + $this->getServiceContainer()->get( 'Vector.FeatureManagerFactory' ), + [ 'name' => 'vector' ] + ); $skin->getContext()->setTitle( Title::newFromText( 'Foo' ) ); $contentNavWatch = [ 'associated-pages' => [], @@ -450,7 +453,10 @@ class VectorHooksTest extends MediaWikiIntegrationTestCase { * @covers ::updateUserLinksItems */ public function testUpdateUserLinksItems() { - $vector2022Skin = new SkinVector22( [ 'name' => 'vector-2022' ] ); + $vector2022Skin = new SkinVector22( + $this->getServiceContainer()->get( 'Vector.FeatureManagerFactory' ), + [ 'name' => 'vector-2022' ] + ); $contentNav = [ 'associated-pages' => [], 'views' => [], @@ -491,7 +497,10 @@ class VectorHooksTest extends MediaWikiIntegrationTestCase { $updateUserLinksDropdownItems->setAccessible( true ); // Anon users - $skin = new SkinVector22( [ 'name' => 'vector-2022' ] ); + $skin = new SkinVector22( + $this->getServiceContainer()->get( 'Vector.FeatureManagerFactory' ), + [ 'name' => 'vector-2022' ] + ); $contentAnon = [ 'user-menu' => [ 'anonuserpage' => [ 'class' => [], 'icon' => 'anonuserpage' ],