. * * @file * @ingroup extensions */ use Popups\PopupsContext; class PopupsHooks { const PREVIEWS_PREFERENCES_SECTION = 'rendering/reading'; private static $context; static function onGetBetaPreferences( User $user, array &$prefs ) { global $wgExtensionAssetsPath; if ( self::getModuleContext()->getConfig()->get( 'PopupsBetaFeature' ) !== true ) { return; } $prefs[PopupsContext::PREVIEWS_BETA_PREFERENCE_NAME] = [ 'label-message' => 'popups-message', 'desc-message' => 'popups-desc', 'screenshot' => [ 'ltr' => "$wgExtensionAssetsPath/Popups/images/popups-ltr.svg", 'rtl' => "$wgExtensionAssetsPath/Popups/images/popups-rtl.svg", ], 'info-link' => 'https://www.mediawiki.org/wiki/Beta_Features/Hovercards', 'discussion-link' => 'https://www.mediawiki.org/wiki/Talk:Beta_Features/Hovercards', 'requirements' => [ 'javascript' => true, ], ]; } /** * Add Page Previews options to user Preferences page * * @param User $user * @param array $prefs */ static function onGetPreferences( User $user, array &$prefs ) { $module = self::getModuleContext(); if ( !$module->showPreviewsOptInOnPreferencesPage() ) { return; } $prefs[PopupsContext::PREVIEWS_OPTIN_PREFERENCE_NAME] = [ 'type' => 'radio', 'label-message' => 'popups-prefs-optin-title', 'options' => [ wfMessage( 'popups-prefs-optin-enabled-label' )->text() => PopupsContext::PREVIEWS_ENABLED, wfMessage( 'popups-prefs-optin-disabled-label' )->text() => PopupsContext::PREVIEWS_DISABLED ], 'section' => self::PREVIEWS_PREFERENCES_SECTION ]; } /** * @return PopupsContext */ private static function getModuleContext() { if ( !self::$context ) { self::$context = new \Popups\PopupsContext(); } return self::$context; } private static function areDependenciesMet() { $registry = ExtensionRegistry::getInstance(); return $registry->isLoaded( 'TextExtracts' ) && class_exists( 'ApiQueryPageImages' ); } public static function onBeforePageDisplay( OutputPage &$out, Skin &$skin ) { $module = self::getModuleContext(); if ( !self::areDependenciesMet() ) { $logger = $module->getLogger(); $logger->error( 'Popups requires the PageImages and TextExtracts extensions.' ); return true; } if ( $module->isEnabledByUser( $skin->getUser() ) ) { $out->addModules( [ 'ext.popups' ] ); } return true; } /** * @param array &$testModules * @param ResourceLoader $resourceLoader * @return bool */ public static function onResourceLoaderTestModules( array &$testModules, ResourceLoader &$resourceLoader ) { $localBasePath = __DIR__; $scripts = glob( "{$localBasePath}/tests/qunit/ext.popups/{,**/}*.test.js", GLOB_BRACE ); $start = strlen( $localBasePath ) + 1; $scripts = array_map( function ( $script ) use ( $start ) { return substr( $script, $start ); }, $scripts ); $testModules['qunit']['ext.popups.tests.stubs'] = [ 'scripts' => [ 'tests/qunit/ext.popups/stubs/index.js', 'tests/qunit/ext.popups/stubs/user.js', ], 'dependencies' => [ 'ext.popups', // The mw.popups is required. ], 'localBasePath' => __DIR__, 'remoteExtPath' => 'Popups', ]; $testModules['qunit']['ext.popups.tests'] = [ 'scripts' => $scripts, 'dependencies' => [ 'ext.popups', 'ext.popups.tests.stubs', ], 'localBasePath' => __DIR__, 'remoteExtPath' => 'Popups', ]; } /** * @param array $vars */ public static function onResourceLoaderGetConfigVars( array &$vars ) { $module = self::getModuleContext(); $conf = $module->getConfig(); $vars['wgPopupsSchemaPopupsSamplingRate'] = $conf->get( 'SchemaPopupsSamplingRate' ); } /** * Register default preferences for popups */ public static function onExtensionRegistration() { global $wgDefaultUserOptions; /** * We use MainConfig because PopupConfig is not available yet. We cannot use * ExtensionFunctions as it's called too late (see T153280) * * @todo Use ConfigFactory() - when T153280 gets fixed switch it to ExtensionFunctions hook * or when ConfigRegistry gets populated before calling `callback` ExtensionRegistry hook */ $config = \MediaWiki\MediaWikiServices::getInstance()->getMainConfig(); $wgDefaultUserOptions[ PopupsContext::PREVIEWS_OPTIN_PREFERENCE_NAME ] = $config->get( 'PopupsOptInDefaultState' ); } /** * Inject Mocked context * As there is no service registration this is used for tests only. * * @param PopupsContext $context * @throws MWException */ public static function injectContext( PopupsContext $context ) { if ( !defined( 'MW_PHPUNIT_TEST' ) ) { throw new MWException( 'injectContext() must not be used outside unit tests.' ); } self::$context = $context; } /** * Remove cached context. * As there is no service registration this is used for tests only. * * * @throws MWException */ public static function resetContext() { if ( !defined( 'MW_PHPUNIT_TEST' ) ) { throw new MWException( 'injectContext() must not be used outside unit tests.' ); } self::$context = null; } }