. * * @file * @ingroup extensions */ namespace Popups; use ExtensionRegistry; use MediaWiki\Auth\Hook\LocalUserCreatedHook; use MediaWiki\Config\Config; use MediaWiki\Hook\BeforePageDisplayHook; use MediaWiki\Hook\MakeGlobalVariablesScriptHook; use MediaWiki\MediaWikiServices; use MediaWiki\Output\OutputPage; use MediaWiki\Preferences\Hook\GetPreferencesHook; use MediaWiki\ResourceLoader\Hook\ResourceLoaderGetConfigVarsHook; use MediaWiki\User\Hook\UserGetDefaultOptionsHook; use MediaWiki\User\Options\UserOptionsManager; use MediaWiki\User\User; use Skin; /** * Hooks definitions for Popups extension * * @package Popups */ class PopupsHooks implements GetPreferencesHook, BeforePageDisplayHook, ResourceLoaderGetConfigVarsHook, MakeGlobalVariablesScriptHook, UserGetDefaultOptionsHook, LocalUserCreatedHook { private const PREVIEWS_PREFERENCES_SECTION = 'rendering/reading'; /** @var UserOptionsManager */ private $userOptionsManager; /** * @param UserOptionsManager $userOptionsManager */ public function __construct( UserOptionsManager $userOptionsManager ) { $this->userOptionsManager = $userOptionsManager; } /** * Get custom Popups types registered by extensions * @return array */ public static function getCustomPopupTypes(): array { $rl = MediaWikiServices::getInstance()->getService( 'ResourceLoader' ); // FIXME: If the module ext.cite.referencePreviews does not exist register reference previews. // This code can be removed once T355194 is complete. $others = $rl->getModule( 'ext.cite.referencePreviews' ) ? [] : [ 'ext.popups.referencePreviews' ]; return array_merge( ExtensionRegistry::getInstance()->getAttribute( 'PopupsPluginModules' ), $others ); } /** * Add options to user Preferences page * * @param User $user User whose preferences are being modified * @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() ) { return; } $skinPosition = array_search( 'skin', array_keys( $prefs ) ); $readingOptions = self::getPagePreviewPrefToggle( $user, $context ); $config = MediaWikiServices::getInstance()->getService( 'Popups.Config' ); if ( $config->get( 'PopupsReferencePreviews' ) ) { $readingOptions = array_merge( $readingOptions, self::getReferencePreviewPrefToggle( $user, $context ) ); } if ( $skinPosition !== false ) { $injectIntoIndex = $skinPosition + 1; $prefs = array_slice( $prefs, 0, $injectIntoIndex, true ) + $readingOptions + array_slice( $prefs, $injectIntoIndex, null, true ); } else { $prefs += $readingOptions; } } /** * Get Page Preview option * * @param User $user User whose preferences are being modified * @param PopupsContext $context * @return array[] */ private static function getPagePreviewPrefToggle( User $user, PopupsContext $context ) { $option = [ 'type' => 'toggle', 'label-message' => 'popups-prefs-optin', 'help-message' => 'popups-prefs-conflicting-gadgets-info', 'section' => self::PREVIEWS_PREFERENCES_SECTION ]; if ( $context->conflictsWithNavPopupsGadget( $user ) ) { $option[ 'disabled' ] = true; $option[ 'help-message' ] = [ 'popups-prefs-disable-nav-gadgets-info', 'Special:Preferences#mw-prefsection-gadgets' ]; } return [ PopupsContext::PREVIEWS_OPTIN_PREFERENCE_NAME => $option ]; } /** * Get Reference Preview option * * @param User $user User whose preferences are being modified * @param PopupsContext $context * @return array[] */ private static function getReferencePreviewPrefToggle( User $user, PopupsContext $context ) { $option = [ 'type' => 'toggle', 'label-message' => 'popups-refpreview-user-preference-label', 'help-message' => 'popups-prefs-conflicting-gadgets-info', 'section' => self::PREVIEWS_PREFERENCES_SECTION ]; $isNavPopupsGadgetEnabled = $context->conflictsWithNavPopupsGadget( $user ); $isRefTooltipsGadgetEnabled = $context->conflictsWithRefTooltipsGadget( $user ); if ( $isNavPopupsGadgetEnabled && $isRefTooltipsGadgetEnabled ) { $option[ 'disabled' ] = true; $option[ 'help-message' ] = [ 'popups-prefs-reftooltips-and-navpopups-gadget-conflict-info', 'Special:Preferences#mw-prefsection-gadgets' ]; } elseif ( $isNavPopupsGadgetEnabled ) { $option[ 'disabled' ] = true; $option[ 'help-message' ] = [ 'popups-prefs-navpopups-gadget-conflict-info', 'Special:Preferences#mw-prefsection-gadgets' ]; } elseif ( $isRefTooltipsGadgetEnabled ) { $option[ 'disabled' ] = true; $option[ 'help-message' ] = [ 'popups-prefs-reftooltips-gadget-conflict-info', 'Special:Preferences#mw-prefsection-gadgets' ]; } return [ PopupsContext::REFERENCE_PREVIEWS_PREFERENCE_NAME => $option ]; } /** * Allows last minute changes to the output page, e.g. adding of CSS or JavaScript by extensions. * * @param OutputPage $out The Output page object * @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() ) ) { return; } if ( !$context->areDependenciesMet() ) { $logger = $context->getLogger(); $logger->error( 'Popups requires the PageImages extensions. TextExtracts extension is required when using mwApiPlain gateway.' ); return; } $user = $out->getUser(); if ( $context->shouldSendModuleToUser( $user ) ) { $out->addModules( [ 'ext.popups' ] ); } } /** * Hook handler for the ResourceLoaderStartUpModule that makes static configuration visible to * the frontend. These variables end in the only "startup" ResourceLoader module that is loaded * before all others. * * Dynamic configuration that depends on the context needs to be published via the * MakeGlobalVariablesScript hook. * * @param array &$vars Array of variables to be added into the output of the startup module * @param string $skin * @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' ); } /** * Hook handler publishing dynamic configuration that depends on the context, e.g. the page or * the users settings. These variables end in an inline