X-Git-Url: http://git.cyclocoop.org/data/Luca_Pacioli_%28Gemaelde%29.jpeg?a=blobdiff_plain;f=includes%2Fpreferences%2FDefaultPreferencesFactory.php;h=1ba6d994298385201331954facf2186db007cd88;hb=10ec68ee372db0ead8aa9626ed9bb3bd328b98f1;hp=be2bf08660332669e5eaebd5ccd052ab0562755e;hpb=affd1dd473c3c453ad68e362385cba17ef9b11f1;p=lhc%2Fweb%2Fwiklou.git diff --git a/includes/preferences/DefaultPreferencesFactory.php b/includes/preferences/DefaultPreferencesFactory.php index be2bf08660..1ba6d99429 100644 --- a/includes/preferences/DefaultPreferencesFactory.php +++ b/includes/preferences/DefaultPreferencesFactory.php @@ -34,16 +34,17 @@ use LanguageCode; use LanguageConverter; use MediaWiki\Auth\AuthManager; use MediaWiki\Auth\PasswordAuthenticationRequest; +use MediaWiki\Config\ServiceOptions; use MediaWiki\Linker\LinkRenderer; use MediaWiki\MediaWikiServices; use MessageLocalizer; use MWException; -use MWNamespace; use MWTimestamp; +use NamespaceInfo; use OutputPage; use Parser; use ParserOptions; -use PreferencesFormLegacy; +use PreferencesFormOOUI; use Psr\Log\LoggerAwareTrait; use Psr\Log\NullLogger; use Skin; @@ -61,8 +62,8 @@ use Xml; class DefaultPreferencesFactory implements PreferencesFactory { use LoggerAwareTrait; - /** @var Config */ - protected $config; + /** @var ServiceOptions */ + protected $options; /** @var Language The wiki's content language. */ protected $contLang; @@ -73,22 +74,74 @@ class DefaultPreferencesFactory implements PreferencesFactory { /** @var LinkRenderer */ protected $linkRenderer; + /** @var NamespaceInfo */ + protected $nsInfo; + + /** + * TODO Make this a const when we drop HHVM support (T192166) + * + * @var array + * @since 1.34 + */ + public static $constructorOptions = [ + 'AllowUserCss', + 'AllowUserCssPrefs', + 'AllowUserJs', + 'DefaultSkin', + 'DisableLangConversion', + 'EmailAuthentication', + 'EmailConfirmToEdit', + 'EnableEmail', + 'EnableUserEmail', + 'EnableUserEmailBlacklist', + 'EnotifMinorEdits', + 'EnotifRevealEditorAddress', + 'EnotifUserTalk', + 'EnotifWatchlist', + 'HiddenPrefs', + 'ImageLimits', + 'LanguageCode', + 'LocalTZoffset', + 'MaxSigChars', + 'RCMaxAge', + 'RCShowWatchingUsers', + 'RCWatchCategoryMembership', + 'SecureLogin', + 'ThumbLimits', + ]; + /** - * @param Config $config + * Do not call this directly. Get it from MediaWikiServices. + * + * @param array|Config $options Config accepted for backwards compatibility * @param Language $contLang * @param AuthManager $authManager * @param LinkRenderer $linkRenderer + * @param NamespaceInfo|null $nsInfo */ public function __construct( - Config $config, + $options, Language $contLang, AuthManager $authManager, - LinkRenderer $linkRenderer + LinkRenderer $linkRenderer, + NamespaceInfo $nsInfo = null ) { - $this->config = $config; + if ( $options instanceof Config ) { + wfDeprecated( __METHOD__ . ' with Config parameter', '1.34' ); + $options = new ServiceOptions( self::$constructorOptions, $options ); + } + + $options->assertRequiredOptions( self::$constructorOptions ); + + if ( !$nsInfo ) { + wfDeprecated( __METHOD__ . ' with no NamespaceInfo argument', '1.34' ); + $nsInfo = MediaWikiServices::getInstance()->getNamespaceInfo(); + } + $this->options = $options; $this->contLang = $contLang; $this->authManager = $authManager; $this->linkRenderer = $linkRenderer; + $this->nsInfo = $nsInfo; $this->logger = new NullLogger(); } @@ -146,7 +199,7 @@ class DefaultPreferencesFactory implements PreferencesFactory { User $user, IContextSource $context, &$defaultPreferences ) { # # Remove preferences that wikis don't want to use - foreach ( $this->config->get( 'HiddenPrefs' ) as $pref ) { + foreach ( $this->options->get( 'HiddenPrefs' ) as $pref ) { if ( isset( $defaultPreferences[$pref] ) ) { unset( $defaultPreferences[$pref] ); } @@ -364,7 +417,7 @@ class DefaultPreferencesFactory implements PreferencesFactory { ]; } // Only show prefershttps if secure login is turned on - if ( $this->config->get( 'SecureLogin' ) && $canIPUseHTTPS ) { + if ( $this->options->get( 'SecureLogin' ) && $canIPUseHTTPS ) { $defaultPreferences['prefershttps'] = [ 'type' => 'toggle', 'label-message' => 'tog-prefershttps', @@ -374,7 +427,7 @@ class DefaultPreferencesFactory implements PreferencesFactory { } $languages = Language::fetchLanguageNames( null, 'mwfile' ); - $languageCode = $this->config->get( 'LanguageCode' ); + $languageCode = $this->options->get( 'LanguageCode' ); if ( !array_key_exists( $languageCode, $languages ) ) { $languages[$languageCode] = $languageCode; // Sort the array again @@ -408,7 +461,7 @@ class DefaultPreferencesFactory implements PreferencesFactory { ]; // see if there are multiple language variants to choose from - if ( !$this->config->get( 'DisableLangConversion' ) ) { + if ( !$this->options->get( 'DisableLangConversion' ) ) { foreach ( LanguageConverter::$languagesWithVariants as $langCode ) { if ( $langCode == $this->contLang->getCode() ) { if ( !$this->contLang->hasVariants() ) { @@ -443,18 +496,6 @@ class DefaultPreferencesFactory implements PreferencesFactory { } } - // Stuff from Language::getExtraUserToggles() - // FIXME is this dead code? $extraUserToggles doesn't seem to be defined for any language - $toggles = $this->contLang->getExtraUserToggles(); - - foreach ( $toggles as $toggle ) { - $defaultPreferences[$toggle] = [ - 'type' => 'toggle', - 'section' => 'personal/i18n', - 'label-message' => "tog-$toggle", - ]; - } - // show a preview of the old signature first $oldsigWikiText = MediaWikiServices::getInstance()->getParser()->preSaveTransform( '~~~', @@ -474,7 +515,7 @@ class DefaultPreferencesFactory implements PreferencesFactory { ]; $defaultPreferences['nickname'] = [ 'type' => $this->authManager->allowsPropertyChange( 'nickname' ) ? 'text' : 'info', - 'maxlength' => $this->config->get( 'MaxSigChars' ), + 'maxlength' => $this->options->get( 'MaxSigChars' ), 'label-message' => 'yournick', 'validation-callback' => function ( $signature, $alldata, HTMLForm $form ) { return $this->validateSignature( $signature, $alldata, $form ); @@ -494,13 +535,13 @@ class DefaultPreferencesFactory implements PreferencesFactory { # # Email stuff - if ( $this->config->get( 'EnableEmail' ) ) { + if ( $this->options->get( 'EnableEmail' ) ) { if ( $canViewPrivateInfo ) { - $helpMessages[] = $this->config->get( 'EmailConfirmToEdit' ) + $helpMessages[] = $this->options->get( 'EmailConfirmToEdit' ) ? 'prefs-help-email-required' : 'prefs-help-email'; - if ( $this->config->get( 'EnableUserEmail' ) ) { + if ( $this->options->get( 'EnableUserEmail' ) ) { // additional messages when users can send email to each other $helpMessages[] = 'prefs-help-email-others'; } @@ -531,7 +572,7 @@ class DefaultPreferencesFactory implements PreferencesFactory { $disableEmailPrefs = false; - if ( $this->config->get( 'EmailAuthentication' ) ) { + if ( $this->options->get( 'EmailAuthentication' ) ) { $emailauthenticationclass = 'mw-email-not-authenticated'; if ( $user->getEmail() ) { if ( $user->getEmailAuthenticationTimestamp() ) { @@ -575,7 +616,7 @@ class DefaultPreferencesFactory implements PreferencesFactory { } } - if ( $this->config->get( 'EnableUserEmail' ) && $user->isAllowed( 'sendemail' ) ) { + if ( $this->options->get( 'EnableUserEmail' ) && $user->isAllowed( 'sendemail' ) ) { $defaultPreferences['disablemail'] = [ 'id' => 'wpAllowEmail', 'type' => 'toggle', @@ -600,7 +641,7 @@ class DefaultPreferencesFactory implements PreferencesFactory { 'disabled' => $disableEmailPrefs, ]; - if ( $this->config->get( 'EnableUserEmailBlacklist' ) ) { + if ( $this->options->get( 'EnableUserEmailBlacklist' ) ) { $defaultPreferences['email-blacklist'] = [ 'type' => 'usersmultiselect', 'label-message' => 'email-blacklist-label', @@ -611,7 +652,7 @@ class DefaultPreferencesFactory implements PreferencesFactory { } } - if ( $this->config->get( 'EnotifWatchlist' ) ) { + if ( $this->options->get( 'EnotifWatchlist' ) ) { $defaultPreferences['enotifwatchlistpages'] = [ 'type' => 'toggle', 'section' => 'personal/email', @@ -619,7 +660,7 @@ class DefaultPreferencesFactory implements PreferencesFactory { 'disabled' => $disableEmailPrefs, ]; } - if ( $this->config->get( 'EnotifUserTalk' ) ) { + if ( $this->options->get( 'EnotifUserTalk' ) ) { $defaultPreferences['enotifusertalkpages'] = [ 'type' => 'toggle', 'section' => 'personal/email', @@ -627,8 +668,9 @@ class DefaultPreferencesFactory implements PreferencesFactory { 'disabled' => $disableEmailPrefs, ]; } - if ( $this->config->get( 'EnotifUserTalk' ) || $this->config->get( 'EnotifWatchlist' ) ) { - if ( $this->config->get( 'EnotifMinorEdits' ) ) { + if ( $this->options->get( 'EnotifUserTalk' ) || + $this->options->get( 'EnotifWatchlist' ) ) { + if ( $this->options->get( 'EnotifMinorEdits' ) ) { $defaultPreferences['enotifminoredits'] = [ 'type' => 'toggle', 'section' => 'personal/email', @@ -637,7 +679,7 @@ class DefaultPreferencesFactory implements PreferencesFactory { ]; } - if ( $this->config->get( 'EnotifRevealEditorAddress' ) ) { + if ( $this->options->get( 'EnotifRevealEditorAddress' ) ) { $defaultPreferences['enotifrevealaddr'] = [ 'type' => 'toggle', 'section' => 'personal/email', @@ -668,8 +710,8 @@ class DefaultPreferencesFactory implements PreferencesFactory { ]; } - $allowUserCss = $this->config->get( 'AllowUserCss' ); - $allowUserJs = $this->config->get( 'AllowUserJs' ); + $allowUserCss = $this->options->get( 'AllowUserCss' ); + $allowUserJs = $this->options->get( 'AllowUserJs' ); # Create links to user CSS/JS pages for all skins # This code is basically copied from generateSkinOptions(). It'd # be nice to somehow merge this back in there to avoid redundancy. @@ -822,7 +864,7 @@ class DefaultPreferencesFactory implements PreferencesFactory { ]; # # Page Rendering ############################## - if ( $this->config->get( 'AllowUserCssPrefs' ) ) { + if ( $this->options->get( 'AllowUserCssPrefs' ) ) { $defaultPreferences['underline'] = [ 'type' => 'select', 'options' => [ @@ -891,7 +933,7 @@ class DefaultPreferencesFactory implements PreferencesFactory { 'label-message' => 'tog-editondblclick', ]; - if ( $this->config->get( 'AllowUserCssPrefs' ) ) { + if ( $this->options->get( 'AllowUserCssPrefs' ) ) { $defaultPreferences['editfont'] = [ 'type' => 'select', 'section' => 'editing/editor', @@ -946,7 +988,7 @@ class DefaultPreferencesFactory implements PreferencesFactory { * @param array &$defaultPreferences */ protected function rcPreferences( User $user, MessageLocalizer $l10n, &$defaultPreferences ) { - $rcMaxAge = $this->config->get( 'RCMaxAge' ); + $rcMaxAge = $this->options->get( 'RCMaxAge' ); # # RecentChanges ##################################### $defaultPreferences['rcdays'] = [ 'type' => 'float', @@ -999,7 +1041,7 @@ class DefaultPreferencesFactory implements PreferencesFactory { 'type' => 'api', ]; - if ( $this->config->get( 'RCWatchCategoryMembership' ) ) { + if ( $this->options->get( 'RCWatchCategoryMembership' ) ) { $defaultPreferences['hidecategorization'] = [ 'type' => 'toggle', 'label-message' => 'tog-hidecategorization', @@ -1023,7 +1065,7 @@ class DefaultPreferencesFactory implements PreferencesFactory { ]; } - if ( $this->config->get( 'RCShowWatchingUsers' ) ) { + if ( $this->options->get( 'RCShowWatchingUsers' ) ) { $defaultPreferences['shownumberswatching'] = [ 'type' => 'toggle', 'section' => 'rc/advancedrc', @@ -1047,7 +1089,7 @@ class DefaultPreferencesFactory implements PreferencesFactory { protected function watchlistPreferences( User $user, IContextSource $context, &$defaultPreferences ) { - $watchlistdaysMax = ceil( $this->config->get( 'RCMaxAge' ) / ( 3600 * 24 ) ); + $watchlistdaysMax = ceil( $this->options->get( 'RCMaxAge' ) / ( 3600 * 24 ) ); # # Watchlist ##################################### if ( $user->isAllowed( 'editmywatchlist' ) ) { @@ -1127,10 +1169,7 @@ class DefaultPreferencesFactory implements PreferencesFactory { 'label-message' => 'tog-watchlisthideliu', ]; - if ( !\SpecialWatchlist::checkStructuredFilterUiEnabled( - $this->config, - $user - ) ) { + if ( !\SpecialWatchlist::checkStructuredFilterUiEnabled( $user ) ) { $defaultPreferences['watchlistreloadautomatically'] = [ 'type' => 'toggle', 'section' => 'watchlist/advancedwatchlist', @@ -1144,7 +1183,7 @@ class DefaultPreferencesFactory implements PreferencesFactory { 'label-message' => 'tog-watchlistunwatchlinks', ]; - if ( $this->config->get( 'RCWatchCategoryMembership' ) ) { + if ( $this->options->get( 'RCWatchCategoryMembership' ) ) { $defaultPreferences['watchlisthidecategorization'] = [ 'type' => 'toggle', 'section' => 'watchlist/changeswatchlist', @@ -1223,7 +1262,7 @@ class DefaultPreferencesFactory implements PreferencesFactory { * @param array &$defaultPreferences */ protected function searchPreferences( &$defaultPreferences ) { - foreach ( MWNamespace::getValidNamespaces() as $n ) { + foreach ( $this->nsInfo->getValidNamespaces() as $n ) { $defaultPreferences['searchNs' . $n] = [ 'type' => 'api', ]; @@ -1243,6 +1282,23 @@ class DefaultPreferencesFactory implements PreferencesFactory { # Only show skins that aren't disabled in $wgSkipSkins $validSkinNames = Skin::getAllowedSkins(); + $allInstalledSkins = Skin::getSkinNames(); + + // Display the installed skin the user has specifically requested via useskin=…. + $useSkin = $context->getRequest()->getRawVal( 'useskin' ); + if ( isset( $allInstalledSkins[$useSkin] ) + && $context->msg( "skinname-$useSkin" )->exists() + ) { + $validSkinNames[$useSkin] = $useSkin; + } + + // Display the skin if the user has set it as a preference already before it was hidden. + $currentUserSkin = $user->getOption( 'skin' ); + if ( isset( $allInstalledSkins[$currentUserSkin] ) + && $context->msg( "skinname-$useSkin" )->exists() + ) { + $validSkinNames[$currentUserSkin] = $currentUserSkin; + } foreach ( $validSkinNames as $skinkey => &$skinname ) { $msg = $context->msg( "skinname-{$skinkey}" ); @@ -1251,9 +1307,9 @@ class DefaultPreferencesFactory implements PreferencesFactory { } } - $defaultSkin = $this->config->get( 'DefaultSkin' ); - $allowUserCss = $this->config->get( 'AllowUserCss' ); - $allowUserJs = $this->config->get( 'AllowUserJs' ); + $defaultSkin = $this->options->get( 'DefaultSkin' ); + $allowUserCss = $this->options->get( 'AllowUserCss' ); + $allowUserJs = $this->options->get( 'AllowUserJs' ); # Sort by the internal name, so that the ordering is the same for each display language, # especially if some skin names are translated to use a different alphabet and some are not. @@ -1352,7 +1408,7 @@ class DefaultPreferencesFactory implements PreferencesFactory { $ret = []; $pixels = $l10n->msg( 'unit-pixel' )->text(); - foreach ( $this->config->get( 'ImageLimits' ) as $index => $limits ) { + foreach ( $this->options->get( 'ImageLimits' ) as $index => $limits ) { // Note: A left-to-right marker (U+200E) is inserted, see T144386 $display = "{$limits[0]}\u{200E}×{$limits[1]}$pixels"; $ret[$display] = $index; @@ -1369,7 +1425,7 @@ class DefaultPreferencesFactory implements PreferencesFactory { $ret = []; $pixels = $l10n->msg( 'unit-pixel' )->text(); - foreach ( $this->config->get( 'ThumbLimits' ) as $index => $size ) { + foreach ( $this->options->get( 'ThumbLimits' ) as $index => $size ) { $display = $size . $pixels; $ret[$display] = $index; } @@ -1384,7 +1440,7 @@ class DefaultPreferencesFactory implements PreferencesFactory { * @return bool|string */ protected function validateSignature( $signature, $alldata, HTMLForm $form ) { - $maxSigChars = $this->config->get( 'MaxSigChars' ); + $maxSigChars = $this->options->get( 'MaxSigChars' ); if ( mb_strlen( $signature ) > $maxSigChars ) { return Xml::element( 'span', [ 'class' => 'error' ], $form->msg( 'badsiglength' )->numParams( $maxSigChars )->text() ); @@ -1430,7 +1486,7 @@ class DefaultPreferencesFactory implements PreferencesFactory { public function getForm( User $user, IContextSource $context, - $formClass = PreferencesFormLegacy::class, + $formClass = PreferencesFormOOUI::class, array $remove = [] ) { // We use ButtonWidgets in some of the getPreferences() functions @@ -1454,6 +1510,14 @@ class DefaultPreferencesFactory implements PreferencesFactory { */ $htmlForm = new $formClass( $formDescriptor, $context, 'prefs' ); + // This allows users to opt-in to hidden skins. While this should be discouraged and is not + // discoverable, this allows users to still use hidden skins while preventing new users from + // adopting unsupported skins. If no useskin=… parameter was provided, it will not show up + // in the resulting URL. + $htmlForm->setAction( $context->getTitle()->getLocalURL( [ + 'useskin' => $context->getRequest()->getRawVal( 'useskin' ) + ] ) ); + $htmlForm->setModifiedUser( $user ); $htmlForm->setId( 'mw-prefs-form' ); $htmlForm->setAutocomplete( 'off' ); @@ -1477,7 +1541,7 @@ class DefaultPreferencesFactory implements PreferencesFactory { protected function getTimezoneOptions( IContextSource $context ) { $opt = []; - $localTZoffset = $this->config->get( 'LocalTZoffset' ); + $localTZoffset = $this->options->get( 'LocalTZoffset' ); $timeZoneList = $this->getTimeZoneList( $context->getLanguage() ); $timestamp = MWTimestamp::getLocalInstance(); @@ -1525,7 +1589,7 @@ class DefaultPreferencesFactory implements PreferencesFactory { protected function saveFormData( $formData, HTMLForm $form, array $formDescriptor ) { /** @var \User $user */ $user = $form->getModifiedUser(); - $hiddenPrefs = $this->config->get( 'HiddenPrefs' ); + $hiddenPrefs = $this->options->get( 'HiddenPrefs' ); $result = true; if ( !$user->isAllowedAny( 'editmyprivateinfo', 'editmyoptions' ) ) {