jenkins-bot has submitted this change and it was merged. ( 
https://gerrit.wikimedia.org/r/383304 )

Change subject: Local overrides for global prefs
......................................................................


Local overrides for global prefs

This allows individual local overrides for globalized preferences,
by adding a checkbox to the "this is a global pref" notice.

Bug: T178044
Change-Id: I8e15f1570f314cae63a38325589f3d4811919bc6
---
M extension.json
M i18n/en.json
M i18n/qqq.json
M includes/GlobalPreferencesFactory.php
M includes/GlobalPreferencesForm.php
M includes/Hooks.php
M includes/SpecialGlobalPreferences.php
R resources/ext.GlobalPreferences.global-nojs.css
R resources/ext.GlobalPreferences.global.css
R resources/ext.GlobalPreferences.global.js
A resources/ext.GlobalPreferences.local-nojs.css
A resources/ext.GlobalPreferences.local.css
A resources/ext.GlobalPreferences.local.js
13 files changed, 170 insertions(+), 35 deletions(-)

Approvals:
  MaxSem: Looks good to me, approved
  jenkins-bot: Verified



diff --git a/extension.json b/extension.json
index 4824a25..c28c5e8 100644
--- a/extension.json
+++ b/extension.json
@@ -44,6 +44,9 @@
                ],
                "MediaWikiServices": [
                        "GlobalPreferences\\Hooks::onMediaWikiServices"
+               ],
+               "BeforePageDisplay": [
+                       "GlobalPreferences\\Hooks::onBeforePageDisplay"
                ]
        },
        "ResourceFileModulePaths": {
@@ -51,13 +54,20 @@
                "remoteExtPath": "GlobalPreferences/resources"
        },
        "ResourceModules": {
-               "ext.GlobalPreferences.special": {
-                       "styles": "ext.GlobalPreferences.special.css",
-                       "scripts": "ext.GlobalPreferences.special.js",
+               "ext.GlobalPreferences.global": {
+                       "styles": "ext.GlobalPreferences.global.css",
+                       "scripts": "ext.GlobalPreferences.global.js",
                        "messages": [ "globalprefs-select-all" ]
                },
-               "ext.GlobalPreferences.special.nojs": {
-                       "styles": "ext.GlobalPreferences.special.nojs.css"
+               "ext.GlobalPreferences.global-nojs": {
+                       "styles": "ext.GlobalPreferences.global-nojs.css"
+               },
+               "ext.GlobalPreferences.local": {
+                       "styles": "ext.GlobalPreferences.local.css",
+                       "scripts": "ext.GlobalPreferences.local.js"
+               },
+               "ext.GlobalPreferences.local-nojs": {
+                       "styles": "ext.GlobalPreferences.local-nojs.css"
                }
        },
        "manifest_version": 1
diff --git a/i18n/en.json b/i18n/en.json
index 119902e..03c9156 100644
--- a/i18n/en.json
+++ b/i18n/en.json
@@ -5,7 +5,8 @@
                ]
        },
        "globalprefs-desc": "Allows users to set global preferences",
-       "globalprefs-set-globally": "This preference has been set globally and 
must be modified through [[Special:GlobalPreferences#$1|your global 
preferences]].",
+       "globalprefs-set-local-exception": "Set a local exception for this 
[[Special:GlobalPreferences#$1|global preference]].",
+       "globalprefs-has-local-exception": "This global preference has a 
[[Special:Preferences#$1|local exception on this wiki]].",
        "tooltip-globalprefs-check-label": "Make this setting global",
        "globalprefs-error-header": "Error",
        "globalprefs-notglobal": "Your account is not a global account and 
cannot set global preferences.",
diff --git a/i18n/qqq.json b/i18n/qqq.json
index d2c1323..38c7f30 100644
--- a/i18n/qqq.json
+++ b/i18n/qqq.json
@@ -6,7 +6,8 @@
                ]
        },
        "globalprefs-desc": "{{desc|name=Global 
Preferences|url=https://www.mediawiki.org/wiki/Extension:GlobalPreferences}}";,
-       "globalprefs-set-globally": "Help message below a disabled preference 
option instructing the user to change it at their global preferences page.",
+       "globalprefs-set-local-exception": "Label for the checkbox below a 
globally-set preference, inviting user to set a local exception for it. $1 is 
the fragment identifier for the current preferences section, with which to link 
to the correct section on Special:GlobalPreferences.",
+       "globalprefs-has-local-exception": "Help text on a global preference 
that has a local exception. $1 is the fragment identifier for the current 
preferences section, with which to link to the correct section on 
Special:Preferences.",
        "tooltip-globalprefs-check-label": "The tooltip and the label text for 
the checkbox to enable a preference globally.",
        "globalprefs-error-header": "Page title for error 
message.\n{{Identical|Error}}",
        "globalprefs-notglobal": "Error message a user sees if they do not have 
a global account.",
diff --git a/includes/GlobalPreferencesFactory.php 
b/includes/GlobalPreferencesFactory.php
index b161269..3d29e59 100644
--- a/includes/GlobalPreferencesFactory.php
+++ b/includes/GlobalPreferencesFactory.php
@@ -27,6 +27,17 @@
  */
 class GlobalPreferencesFactory extends DefaultPreferencesFactory {
 
+       /**
+        * The suffix appended to preference names
+        * for the associated preference that tracks whether they have a local 
override.
+        */
+       const LOCAL_EXCEPTION_SUFFIX = '-local-exception';
+
+       /**
+        * The suffix appended to preference names for their global 
counterparts.
+        */
+       const GLOBAL_EXCEPTION_SUFFIX = '-global';
+
        /** @var User */
        protected $user;
 
@@ -106,30 +117,33 @@
         * @return mixed[][]
         */
        protected function getPreferencesLocal( $preferences, $globalPrefNames 
) {
+               $modifiedPrefs = [];
                foreach ( $preferences as $name => $def ) {
+                       $modifiedPrefs[$name] = $def;
+
                        // If this has been set globally.
                        if ( in_array( $name, $globalPrefNames ) ) {
-                               // Disable this preference.
-                               $preferences[$name]['disabled'] = true;
+                               // Disable this preference unless it has a 
local exception.
+                               $localException = $this->user->getOption( $name 
. static::LOCAL_EXCEPTION_SUFFIX );
+                               $modifiedPrefs[$name]['disabled'] = is_null( 
$localException );
 
-                               // Append a help message.
-                               $help = '';
-                               if ( isset( $preferences[$name]['help-message'] 
) ) {
-                                       $help .= wfMessage( 
$preferences[$name]['help-message'] )->parse() . '<br />';
-                               } elseif ( isset( $preferences[$name]['help'] ) 
) {
-                                       $help .= $preferences[$name]['help'] . 
'<br />';
-                               }
-
-                               // Create a link to the relevant section of 
GlobalPreferences.
-                               $section = substr( $def['section'], 0, strpos( 
$def['section'], '/' ) );
-                               $secFragment = 'mw-prefsection-' . $section;
-
-                               // Set the new full help text.
-                               $help .= wfMessage( 'globalprefs-set-globally', 
[ $secFragment ] )->parse();
-                               $preferences[$name]['help'] = $help;
-                               unset( $preferences[$name]['help-message'] );
+                               // Add a new local exception preference after 
this one.
+                               $cssClasses = [
+                                       'mw-globalprefs-local-exception',
+                                       'mw-globalprefs-local-exception-for-' . 
$name,
+                               ];
+                               $secFragment = static::getSectionFragmentId( 
$def['section'] );
+                               $labelMsg = wfMessage( 
'globalprefs-set-local-exception', [ $secFragment ] );
+                               $modifiedPrefs[ $name . 
static::LOCAL_EXCEPTION_SUFFIX ] = [
+                                       'type' => 'toggle',
+                                       'label-raw' => $labelMsg->parse(),
+                                       'default' => $this->user->getOption( 
$name . static::LOCAL_EXCEPTION_SUFFIX ),
+                                       'section' => $def['section'],
+                                       'cssclass' => join( ' ', $cssClasses ),
+                               ];
                        }
                }
+               $preferences = $modifiedPrefs;
 
                // Add a link to GlobalPreferences to the local preferences 
form.
                $linkRenderer = 
MediaWikiServices::getInstance()->getLinkRenderer();
@@ -162,19 +176,48 @@
                                continue;
                        }
                        // Create the new preference.
-                       $allPrefs[$pref.'-global'] = [
+                       $isGlobal = in_array( $pref, $globalPrefNames );
+                       $allPrefs[$pref . static::GLOBAL_EXCEPTION_SUFFIX] = [
                                'type' => 'toggle',
                                // Make the tooltip and the label the same, 
because the label is normally hidden.
                                'tooltip' => 'globalprefs-check-label',
                                'label-message' => 
'tooltip-globalprefs-check-label',
-                               'default' => in_array( $pref, $globalPrefNames 
),
+                               'default' => $isGlobal,
                                'section' => $def['section'],
                                'cssclass' => 'mw-globalprefs-global-check 
mw-globalprefs-checkbox-for-' . $pref,
                        ];
+                       // If this has a local exception, append a help message 
to say so.
+                       if ( $isGlobal
+                               && $this->user->getOption( $pref . 
static::LOCAL_EXCEPTION_SUFFIX )
+                       ) {
+                               $help = '';
+                               if ( isset( $def['help-message'] ) ) {
+                                       $help .= wfMessage( 
$def['help-message'] )->parse() . '<br />';
+                               } elseif ( isset( $def['help'] ) ) {
+                                       $help .= $def['help'] . '<br />';
+                               }
+                               // Create a link to the relevant section of 
GlobalPreferences.
+                               $secFragment = static::getSectionFragmentId( 
$def['section'] );
+                               // Merge the help texts.
+                               $helpMsg = wfMessage( 
'globalprefs-has-local-exception', [ $secFragment ] );
+                               unset( $def['help-message'] );
+                               $def['help'] = $help . $helpMsg->parse();
+                       }
 
                        $allPrefs[$pref] = $def;
                }
                return $allPrefs;
+       }
+
+       /**
+        * Get the HTML fragment identifier for a given preferences section. 
This is the leading part
+        * of the provided section name, up to a slash (if there is one).
+        * @param string $section A section name, as used in a preference 
definition.
+        * @return string
+        */
+       public static function getSectionFragmentId( $section ) {
+               $sectionId = preg_replace( '#/.*$#', '', $section );
+               return 'mw-prefsection-' . $sectionId;
        }
 
        /**
@@ -191,7 +234,7 @@
                }
 
                // Ignore "is global" checkboxes
-               if ( substr( $name, -strlen( '-global' ) ) === '-global' ) {
+               if ( static::isGlobalPrefName( $name ) ) {
                        return false;
                }
 
@@ -211,6 +254,36 @@
        }
 
        /**
+        * A convenience function to check if a preference name is for a global 
one.
+        * @param string $name The name to check.
+        * @return bool
+        */
+       public static function isGlobalPrefName( $name ) {
+               return static::strEndsWith( $name, 
static::GLOBAL_EXCEPTION_SUFFIX );
+       }
+
+       /**
+        * A convenience function to check if a preference name is for a 
local-exception preference.
+        * @param string $name The name to check.
+        * @return bool
+        */
+       public static function isLocalPrefName( $name ) {
+               return static::strEndsWith( $name, 
static::LOCAL_EXCEPTION_SUFFIX );
+       }
+
+       /**
+        * A convenience function to check a string to see if it ends in a 
given suffix.
+        * @todo This could probably exist somewhere like StringUtils.
+        * @param string $name The name to check.
+        * @param string $suffix The suffix to check for.
+        * @return bool
+        */
+       protected static function strEndsWith( $name, $suffix ) {
+               $nameSuffix = substr( $name, -strlen( $suffix ) );
+               return ( $nameSuffix === $suffix );
+       }
+
+       /**
         * Checks if the user is globalized.
         * @return bool
         */
diff --git a/includes/GlobalPreferencesForm.php 
b/includes/GlobalPreferencesForm.php
index 5c36867..b872421 100644
--- a/includes/GlobalPreferencesForm.php
+++ b/includes/GlobalPreferencesForm.php
@@ -4,6 +4,7 @@
 
 use Html;
 use IContextSource;
+use MediaWiki\MediaWikiServices;
 use PreferencesForm;
 
 /**
@@ -33,6 +34,28 @@
         * @return string
         */
        function getBody() {
+               // Load global values for any preferences with local exceptions.
+               /** @var GlobalPreferencesFactory $globalPreferences */
+               $globalPreferences = 
MediaWikiServices::getInstance()->getPreferencesFactory();
+               $globalPreferences->setUser( $this->getUser() );
+               $globalPrefValues = 
$globalPreferences->getGlobalPreferencesValues();
+               foreach ( $this->mFlatFields as $fieldName => $field ) {
+                       // Ignore this if it's a global or a local-exception 
preference.
+                       $isGlobal = GlobalPreferencesFactory::isGlobalPrefName( 
$fieldName );
+                       $isLocalException = 
GlobalPreferencesFactory::isLocalPrefName( $fieldName );
+                       if ( $isGlobal || $isLocalException ) {
+                               continue;
+                       }
+                       // See if it's got a local exception. It should also 
always then have a global value,
+                       // but we check anyway just to be sure.
+                       $localExceptionName = $fieldName . 
GlobalPreferencesFactory::LOCAL_EXCEPTION_SUFFIX;
+                       $hasGlobalValue = isset( $globalPrefValues[ $fieldName 
] );
+                       if ( $this->getUser()->getOption( $localExceptionName ) 
&& $hasGlobalValue ) {
+                               // And if it does, use the global value.
+                               $this->mFieldData[ $fieldName ] = 
$globalPrefValues[ $fieldName ];
+                       }
+               }
+
                // Add help text to the top of every section.
                foreach ( $this->getPreferenceSections() as $section ) {
                        $colHeaderText = Html::element(
@@ -47,6 +70,7 @@
                        );
                        $this->addHeaderText( $secHeader, $section );
                }
+
                return parent::getBody();
        }
 }
diff --git a/includes/Hooks.php b/includes/Hooks.php
index bd2dd72..83e9e1b 100644
--- a/includes/Hooks.php
+++ b/includes/Hooks.php
@@ -6,10 +6,27 @@
 use Language;
 use MediaWiki\Auth\AuthManager;
 use MediaWiki\MediaWikiServices;
+use OutputPage;
 use PreferencesForm;
+use Skin;
 use User;
 
 class Hooks {
+
+       /**
+        * Allows last minute changes to the output page, e.g. adding of CSS or 
JavaScript by extensions.
+        * @link https://www.mediawiki.org/wiki/Manual:Hooks/BeforePageDisplay
+        * @param OutputPage &$out The output page.
+        * @param Skin &$skin The skin. Not used.
+        */
+       public static function onBeforePageDisplay( OutputPage &$out, Skin 
&$skin ) {
+               if ( $out->getTitle()->isSpecial( 'Preferences' ) ) {
+                       // Add module styles and scripts separately
+                       // so non-JS users get the styles quicker and to avoid 
a FOUC.
+                       $out->addModuleStyles( 
'ext.GlobalPreferences.local-nojs' );
+                       $out->addModules( 'ext.GlobalPreferences.local' );
+               }
+       }
 
        /**
         * Load global preferences.
@@ -28,6 +45,10 @@
 
                // Overwrite all options that have a global counterpart.
                foreach ( $globalPreferences->getGlobalPreferencesValues() as 
$optName => $globalValue ) {
+                       // But not if it has a local exception.
+                       if ( $user->getOption( $optName . 
GlobalPreferencesFactory::LOCAL_EXCEPTION_SUFFIX ) ) {
+                               continue;
+                       }
                        $options[ $optName ] = $globalValue;
                }
        }
@@ -51,11 +72,10 @@
 
                foreach ( $options as $optName => $optVal ) {
                        // Ignore if ends in "-global".
-                       if ( substr( $optName, -strlen( '-global' ) ) === 
'-global' ) {
+                       if ( GlobalPreferencesFactory::isGlobalPrefName( 
$optName ) ) {
                                unset( $options[ $optName ] );
                        }
                }
-
                return true;
        }
 
@@ -82,10 +102,11 @@
 
                $prefs = [];
                foreach ( $formData as $name => $value ) {
-                       // If this is the '-global' counterpart of a preference.
-                       if ( substr( $name, -strlen( 'global' ) ) === 'global' 
&& $value === true ) {
+                       // If this is the '-global' counterpart to a preference.
+                       if ( GlobalPreferencesFactory::isGlobalPrefName( $name 
) && $value === true ) {
                                // Determine the real name of the preference.
-                               $realName = substr( $name, 0, -strlen( 
'-global' ) );
+                               $suffixLen = strlen( 
GlobalPreferencesFactory::GLOBAL_EXCEPTION_SUFFIX );
+                               $realName = substr( $name, 0, -$suffixLen );
                                if ( isset( $formData[$realName] ) ) {
                                        // Store normal preference values.
                                        $prefs[$realName] = 
$formData[$realName];
diff --git a/includes/SpecialGlobalPreferences.php 
b/includes/SpecialGlobalPreferences.php
index fc0d235..204623c 100644
--- a/includes/SpecialGlobalPreferences.php
+++ b/includes/SpecialGlobalPreferences.php
@@ -57,8 +57,8 @@
 
                // Add module styles and scripts separately
                // so non-JS users get the styles quicker and to avoid a FOUC.
-               $this->getOutput()->addModuleStyles( 
'ext.GlobalPreferences.special.nojs' );
-               $this->getOutput()->addModules( 'ext.GlobalPreferences.special' 
);
+               $this->getOutput()->addModuleStyles( 
'ext.GlobalPreferences.global-nojs' );
+               $this->getOutput()->addModules( 'ext.GlobalPreferences.global' 
);
                parent::execute( $par );
        }
 
diff --git a/resources/ext.GlobalPreferences.special.nojs.css 
b/resources/ext.GlobalPreferences.global-nojs.css
similarity index 100%
rename from resources/ext.GlobalPreferences.special.nojs.css
rename to resources/ext.GlobalPreferences.global-nojs.css
diff --git a/resources/ext.GlobalPreferences.special.css 
b/resources/ext.GlobalPreferences.global.css
similarity index 100%
rename from resources/ext.GlobalPreferences.special.css
rename to resources/ext.GlobalPreferences.global.css
diff --git a/resources/ext.GlobalPreferences.special.js 
b/resources/ext.GlobalPreferences.global.js
similarity index 100%
rename from resources/ext.GlobalPreferences.special.js
rename to resources/ext.GlobalPreferences.global.js
diff --git a/resources/ext.GlobalPreferences.local-nojs.css 
b/resources/ext.GlobalPreferences.local-nojs.css
new file mode 100644
index 0000000..7ac2e44
--- /dev/null
+++ b/resources/ext.GlobalPreferences.local-nojs.css
@@ -0,0 +1,3 @@
+.mw-globalprefs-local-exception label {
+       font-size: smaller;
+}
diff --git a/resources/ext.GlobalPreferences.local.css 
b/resources/ext.GlobalPreferences.local.css
new file mode 100644
index 0000000..3bd33cf
--- /dev/null
+++ b/resources/ext.GlobalPreferences.local.css
@@ -0,0 +1 @@
+/* @TODO hover styles etc. */
diff --git a/resources/ext.GlobalPreferences.local.js 
b/resources/ext.GlobalPreferences.local.js
new file mode 100644
index 0000000..5f68fbe
--- /dev/null
+++ b/resources/ext.GlobalPreferences.local.js
@@ -0,0 +1 @@
+// @TODO re-enable global preferences. T178267

-- 
To view, visit https://gerrit.wikimedia.org/r/383304
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings

Gerrit-MessageType: merged
Gerrit-Change-Id: I8e15f1570f314cae63a38325589f3d4811919bc6
Gerrit-PatchSet: 12
Gerrit-Project: mediawiki/extensions/GlobalPreferences
Gerrit-Branch: master
Gerrit-Owner: Samwilson <s...@samwilson.id.au>
Gerrit-Reviewer: Legoktm <lego...@member.fsf.org>
Gerrit-Reviewer: MaxSem <maxsem.w...@gmail.com>
Gerrit-Reviewer: Samwilson <s...@samwilson.id.au>
Gerrit-Reviewer: jenkins-bot <>

_______________________________________________
MediaWiki-commits mailing list
MediaWiki-commits@lists.wikimedia.org
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to