jenkins-bot has submitted this change and it was merged.

Change subject: Hygiene: Move settings into standalone module
......................................................................


Hygiene: Move settings into standalone module

Rename settings methods.

Change-Id: I7ec0be06ebd7dd7aea0622f8a0e44ca08834597c
---
M includes/MobileFrontend.hooks.php
M includes/Resources.php
M javascripts/loggingSchemas/MobileWebClickTracking.js
M javascripts/modules/editor/EditorOverlay.js
M javascripts/modules/editor/EditorOverlayBase.js
M javascripts/modules/editor/VisualEditorOverlay.js
M javascripts/modules/editor/editor.js
M javascripts/modules/mf-stop-mobile-redirect.js
M javascripts/modules/preferredLanguages/preferred.js
M javascripts/modules/preferredLanguages/profiler.js
M javascripts/modules/toggling/toggle.js
M javascripts/settings.js
M javascripts/specials/mobileoptions.js
M tests/qunit/modules/preferredLanguages/test_preferred.js
M tests/qunit/modules/toggling/test_toggle.js
15 files changed, 79 insertions(+), 51 deletions(-)

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



diff --git a/includes/MobileFrontend.hooks.php 
b/includes/MobileFrontend.hooks.php
index e34ab5e..19048cd 100644
--- a/includes/MobileFrontend.hooks.php
+++ b/includes/MobileFrontend.hooks.php
@@ -914,6 +914,7 @@
                $wgResourceModules['mobile.loggingSchemas'] = 
$wgMFResourceFileModuleBoilerplate + array(
                        'dependencies' => array_merge( $additionalDependencies, 
array(
                                'mobile.startup',
+                               'mobile.settings',
                        ) ),
                        'scripts' => $scripts,
                );
diff --git a/includes/Resources.php b/includes/Resources.php
index 65f5c54..272be02 100644
--- a/includes/Resources.php
+++ b/includes/Resources.php
@@ -166,6 +166,16 @@
                ),
        ),
 
+       'mobile.settings' => $wgMFResourceFileModuleBoilerplate + array(
+               'dependencies' => array(
+                       'mobile.head',
+                       'jquery.cookie',
+               ),
+               'scripts' => array(
+                       'javascripts/settings.js',
+               ),
+       ),
+
        // FIXME: Split this module into different features.
        'mobile.startup' => $wgMFResourceFileModuleBoilerplate + array(
                'dependencies' => array(
@@ -173,7 +183,6 @@
                        'mobile.templates',
                        'mobile.user',
                        'mediawiki.api',
-                       'jquery.cookie',
                        'mobile.redlinks',
                        'ext.mantle.views',
                ),
@@ -192,7 +201,6 @@
                        'javascripts/Section.js',
                        'javascripts/Page.js',
                        'javascripts/application.js',
-                       'javascripts/settings.js',
                ),
                'position' => 'bottom',
        ),
@@ -223,6 +231,7 @@
                        'mobile.stable.common',
                        'mobile.overlays',
                        'mediawiki.ui.input',
+                       'mobile.settings',
                ),
                'messages' => array(
                        // editor.js
@@ -281,7 +290,7 @@
                        'mobile.stable',
                        'mobile.templates',
                        'mobile.editor.api',
-                       'jquery.cookie',
+                       'mobile.settings',
                ),
                'scripts' => array(
                        'javascripts/modules/editor/EditorOverlayBase.js',
@@ -452,6 +461,7 @@
        'mobile.preferredLanguages' => $wgMFResourceFileModuleBoilerplate + 
array(
                'dependencies' => array(
                        'mobile.startup',
+                       'mobile.settings',
                ),
                'scripts' => array(
                        'javascripts/modules/preferredLanguages/profiler.js',
@@ -697,6 +707,7 @@
                'dependencies' => array(
                        'mobile.startup',
                        'mobile.toast',
+                       'mobile.settings',
                ),
                'scripts' => array(
                        'javascripts/modules/mf-stop-mobile-redirect.js',
@@ -759,6 +770,7 @@
        'mobile.toggling' => $wgMFResourceFileModuleBoilerplate + array(
                'dependencies' => array(
                        'mobile.startup',
+                       'mobile.settings',
                ),
                'styles' => array(
                        'less/modules/toggle.less',
@@ -1045,6 +1057,7 @@
                'position' => 'top',
                'dependencies' => array(
                        'mobile.startup',
+                       'mobile.settings',
                        'mobile.templates',
                ),
                'scripts' => array(
diff --git a/javascripts/loggingSchemas/MobileWebClickTracking.js 
b/javascripts/loggingSchemas/MobileWebClickTracking.js
index 1b98e53..23c977d 100644
--- a/javascripts/loggingSchemas/MobileWebClickTracking.js
+++ b/javascripts/loggingSchemas/MobileWebClickTracking.js
@@ -1,5 +1,5 @@
 ( function ( M, $ ) {
-       var s = M.settings, name, href;
+       var s = M.require( 'settings' ), name, href;
 
        function log( name, destination ) {
                var
@@ -18,8 +18,8 @@
                return M.log( 'MobileWebClickTracking', data );
        }
        function futureLog( name, href ) {
-               s.saveUserSetting( 'MobileWebClickTracking-name', name );
-               s.saveUserSetting( 'MobileWebClickTracking-href', href );
+               s.save( 'MobileWebClickTracking-name', name );
+               s.save( 'MobileWebClickTracking-href', href );
        }
 
        function hijackLink( selector, name ) {
@@ -29,12 +29,12 @@
        }
 
        // Deal with events requested on the preview page
-       name = s.getUserSetting( 'MobileWebClickTracking-name' );
-       href = s.getUserSetting( 'MobileWebClickTracking-href' );
+       name = s.get( 'MobileWebClickTracking-name' );
+       href = s.get( 'MobileWebClickTracking-href' );
        // Make sure they do not log a second time...
        if ( name && href ) {
-               s.saveUserSetting( 'MobileWebClickTracking-name', '' );
-               s.saveUserSetting( 'MobileWebClickTracking-href', '' );
+               s.save( 'MobileWebClickTracking-name', '' );
+               s.save( 'MobileWebClickTracking-href', '' );
                // Since MobileWebEditing schema declares the dependencies to
                // EventLogging and the schema we can be confident this will 
always log.
                log( name, href );
diff --git a/javascripts/modules/editor/EditorOverlay.js 
b/javascripts/modules/editor/EditorOverlay.js
index cc63b5e..3007b09 100644
--- a/javascripts/modules/editor/EditorOverlay.js
+++ b/javascripts/modules/editor/EditorOverlay.js
@@ -8,6 +8,7 @@
                Section = M.require( 'Section' ),
                EditorApi = M.require( 'modules/editor/EditorApi' ),
                AbuseFilterPanel = M.require( 'modules/editor/AbuseFilterPanel' 
),
+               settings = M.require( 'settings' ),
                EditorOverlay;
 
        /**
@@ -194,7 +195,7 @@
                        var self = this;
                        this.log( 'switch' );
                        // Save a user setting indicating that this user 
prefers using the VisualEditor
-                       M.settings.saveUserSetting( 'preferredEditor', 
'VisualEditor', true );
+                       settings.save( 'preferredEditor', 'VisualEditor', true 
);
                        // Load the VisualEditor and replace the SourceEditor 
overlay with it
                        this.showSpinner();
                        this.$content.hide();
diff --git a/javascripts/modules/editor/EditorOverlayBase.js 
b/javascripts/modules/editor/EditorOverlayBase.js
index 74d95ef..14690b6 100644
--- a/javascripts/modules/editor/EditorOverlayBase.js
+++ b/javascripts/modules/editor/EditorOverlayBase.js
@@ -4,6 +4,7 @@
                Icon = M.require( 'Icon' ),
                toast = M.require( 'toast' ),
                user = M.require( 'user' ),
+               settings = M.require( 'settings' ),
                EditorOverlayBase;
 
        /**
@@ -92,7 +93,7 @@
                        }
                        msg = mw.msg( msg );
 
-                       M.settings.saveUserSetting( 'mobile-pending-toast', msg 
);
+                       settings.save( 'mobile-pending-toast', msg );
 
                        // Ensure we don't lose this event when logging
                        this.log( 'success' ).always( function () {
diff --git a/javascripts/modules/editor/VisualEditorOverlay.js 
b/javascripts/modules/editor/VisualEditorOverlay.js
index 0a3a860..00a4889 100644
--- a/javascripts/modules/editor/VisualEditorOverlay.js
+++ b/javascripts/modules/editor/VisualEditorOverlay.js
@@ -1,5 +1,6 @@
 ( function ( M, $, ve ) {
        var EditorOverlayBase = M.require( 'modules/editor/EditorOverlayBase' ),
+               settings = M.require( 'settings' ),
                VisualEditorOverlay;
 
        /**
@@ -139,7 +140,7 @@
                        var self = this;
                        this.log( 'switch' );
                        // Save a user setting indicating that this user 
prefers using the SourceEditor
-                       M.settings.saveUserSetting( 'preferredEditor', 
'SourceEditor', true );
+                       settings.save( 'preferredEditor', 'SourceEditor', true 
);
                        this.showSpinner();
                        this.$( '.surface' ).hide();
                        // Load the SourceEditor and replace the VisualEditor 
overlay with it
diff --git a/javascripts/modules/editor/editor.js 
b/javascripts/modules/editor/editor.js
index c56b31b..7485990 100644
--- a/javascripts/modules/editor/editor.js
+++ b/javascripts/modules/editor/editor.js
@@ -1,6 +1,7 @@
 ( function ( M, $ ) {
 
        var
+               settings = M.require( 'settings' ),
                Icon = M.require( 'Icon' ),
                disabledEditIcon = new Icon( { name: 'edit' } ),
                enabledEditIcon = new Icon( { name: 'edit-enabled' } ),
@@ -19,7 +20,7 @@
                isVisualEditorEnabled = M.isWideScreen() && veConfig,
                CtaDrawer = M.require( 'CtaDrawer' ),
                toast = M.require( 'toast' ),
-               pendingToast = M.settings.getUserSetting( 
'mobile-pending-toast' ),
+               pendingToast = settings.get( 'mobile-pending-toast' ),
                drawer = new CtaDrawer( {
                        queryParams: {
                                campaign: 'mobile_editPageActionCta'
@@ -30,7 +31,7 @@
 
        if ( pendingToast ) {
                // delete the pending toast
-               M.settings.saveUserSetting( 'mobile-pending-toast', '' );
+               settings.save( 'mobile-pending-toast', '' );
                toast.show( pendingToast );
        }
 
@@ -72,7 +73,7 @@
         * @return {string} Either 'VisualEditor' or 'SourceEditor'
         */
        function getPreferredEditor() {
-               var preferredEditor = M.settings.getUserSetting( 
'preferredEditor', true );
+               var preferredEditor = settings.get( 'preferredEditor', true );
                if ( preferredEditor === null ) {
                        // For now, we are going to ignore which editor is set 
as the default for the
                        // wiki and always default to the source editor. Once 
we decide to honor the
diff --git a/javascripts/modules/mf-stop-mobile-redirect.js 
b/javascripts/modules/mf-stop-mobile-redirect.js
index 672a525..779c8c4 100644
--- a/javascripts/modules/mf-stop-mobile-redirect.js
+++ b/javascripts/modules/mf-stop-mobile-redirect.js
@@ -4,7 +4,8 @@
 
 ( function ( M, $ ) {
 
-       var cookiesEnabled = M.settings.cookiesEnabled,
+       var settings = M.require( 'settings' ),
+               cookiesEnabled = settings.cookiesEnabled,
                popup = M.require( 'toast' );
 
        function desktopViewClick() {
diff --git a/javascripts/modules/preferredLanguages/preferred.js 
b/javascripts/modules/preferredLanguages/preferred.js
index 04f2c1e..4a89b44 100644
--- a/javascripts/modules/preferredLanguages/preferred.js
+++ b/javascripts/modules/preferredLanguages/preferred.js
@@ -1,6 +1,8 @@
 // When set orders LanguageOverlay list of languages by most frequently chosen
 ( function ( M,  $ ) {
-       var langMap = M.settings.getUserSetting( 'langMap' );
+       var settings = M.require( 'settings' ),
+               langMap = settings.get( 'langMap' );
+
        langMap = langMap ? $.parseJSON( langMap ) : {};
 
        M.on( 'language-overlay-initialize', function ( options ) {
diff --git a/javascripts/modules/preferredLanguages/profiler.js 
b/javascripts/modules/preferredLanguages/profiler.js
index 519e7c8..e6ee671 100644
--- a/javascripts/modules/preferredLanguages/profiler.js
+++ b/javascripts/modules/preferredLanguages/profiler.js
@@ -3,11 +3,12 @@
 ( function ( M ) {
 
        var supported = M.supportsLocalStorage,
+               settings = M.require( 'settings' ),
                langMap,
                curLanguage = mw.config.get( 'wgContentLanguage' );
 
        function loadLanguageMap() {
-               langMap = M.settings.getUserSetting( 'langMap' );
+               langMap = settings.get( 'langMap' );
                langMap = langMap ? JSON.parse( langMap ) : {};
        }
 
@@ -19,7 +20,7 @@
                        count += 1;
                        // cap at 100 as this is enough data to work on
                        langMap[ language ] = count > 100 ? 100 : count;
-                       M.settings.saveUserSetting( 'langMap', JSON.stringify( 
langMap ) );
+                       settings.save( 'langMap', JSON.stringify( langMap ) );
                }
        }
 
diff --git a/javascripts/modules/toggling/toggle.js 
b/javascripts/modules/toggling/toggle.js
index 8f29cc6..76ed8f6 100644
--- a/javascripts/modules/toggling/toggle.js
+++ b/javascripts/modules/toggling/toggle.js
@@ -1,5 +1,6 @@
 ( function ( M, $ ) {
        var currentPageTitle =  M.getCurrentPage().title,
+               settings = M.require( 'settings' ),
                Icon = M.require( 'Icon' ),
                iconUp = new Icon( { name: 'arrow-up', hasText: true } ),
                iconDown = new Icon( { name: 'arrow-down', hasText: true, 
additionalClassNames: 'icon-15px' } ),
@@ -8,7 +9,7 @@
 
        function getExpandedSections() {
                var expandedSections = $.parseJSON(
-                       M.settings.getUserSetting( 'expandedSections', false ) 
|| '{}'
+                       settings.get( 'expandedSections', false ) || '{}'
                );
                expandedSections[currentPageTitle] = 
expandedSections[currentPageTitle] || {};
                return expandedSections;
@@ -18,7 +19,7 @@
         * Save expandedSections to localStorage
         */
        function saveExpandedSections( expandedSections ) {
-               M.settings.saveUserSetting(
+               settings.save(
                        'expandedSections', JSON.stringify( expandedSections ), 
false
                );
        }
@@ -172,7 +173,7 @@
                        collapseSectionsByDefault = true;
                }
                expandSections = !collapseSectionsByDefault ||
-                       ( M.isAlphaGroupMember() && M.settings.getUserSetting( 
'expandSections', true ) === 'true' );
+                       ( M.isAlphaGroupMember() && settings.get( 
'expandSections', true ) === 'true' );
 
                $container.find( tagName ).each( function ( i ) {
                        var $heading = $( this ),
diff --git a/javascripts/settings.js b/javascripts/settings.js
index a4edd81..b16b88f 100644
--- a/javascripts/settings.js
+++ b/javascripts/settings.js
@@ -6,7 +6,7 @@
  */
 ( function ( M, $ ) {
 
-       M.settings = ( function () {
+       var settings = ( function () {
 
                function cookiesEnabled() {
                        // If session cookie already set, return true
@@ -27,7 +27,7 @@
                 * @param {Boolean} useCookieFallback Optional: When set this 
will use cookies when local storage not available.
                 * @returns {Boolean} Whether the save was successful or not
                 */
-               function saveUserSetting( name, value, useCookieFallback ) {
+               function save( name, value, useCookieFallback ) {
                        return M.supportsLocalStorage ?
                                localStorage.setItem( name, value ) :
                                        ( useCookieFallback ? $.cookie( name, 
value, { expires: 1 } ) : false );
@@ -40,7 +40,7 @@
                 * @param {Boolean} useCookieFallback Optional: When set this 
will use cookies when local storage not available.
                 * @returns {String|Boolean} Returns the associated value or 
False if nothing is found
                 */
-               function getUserSetting( name, useCookieFallback ) {
+               function get( name, useCookieFallback ) {
                        return M.supportsLocalStorage ? localStorage.getItem( 
name ) :
                                ( useCookieFallback ? $.cookie( name ) : false 
);
                }
@@ -52,17 +52,19 @@
                 * @param {Boolean} useCookieFallback Optional: When set this 
will use cookies when local storage not available.
                 * @returns {Boolean} Whether the delete was successful or not
                 */
-               function deleteUserSetting( name, useCookieFallback ) {
+               function remove( name, useCookieFallback ) {
                        return M.supportsLocalStorage ? 
localStorage.removeItem( name ) :
                                ( useCookieFallback ? $.removeCookie( name ) : 
false );
                }
 
                return {
-                       getUserSetting: getUserSetting,
-                       saveUserSetting: saveUserSetting,
-                       deleteUserSetting: deleteUserSetting,
+                       get: get,
+                       save: save,
+                       remove: remove,
                        cookiesEnabled: cookiesEnabled
                };
        }() );
 
+       M.define( 'settings', settings );
+
 }( mw.mobileFrontend, jQuery ) );
diff --git a/javascripts/specials/mobileoptions.js 
b/javascripts/specials/mobileoptions.js
index 1252e08..3ab3c00 100644
--- a/javascripts/specials/mobileoptions.js
+++ b/javascripts/specials/mobileoptions.js
@@ -1,5 +1,6 @@
 ( function ( M, $ ) {
-       var View = M.require( 'View' ), Checkbox;
+       var View = M.require( 'View' ), Checkbox,
+               settings = M.require( 'settings' );
 
        /**
         * Wrapper for checkboxes styled as in MediaWiki UI style guide
@@ -9,12 +10,12 @@
        Checkbox = View.extend( {
                template: mw.template.get( 
'mobile.special.mobileoptions.scripts', 'Checkbox.hogan' ),
                save: function () {
-                       M.settings.saveUserSetting( this.options.name, 
this.cb.prop( 'checked' ) ? 'true' : 'false', true );
+                       settings.save( this.options.name, this.cb.prop( 
'checked' ) ? 'true' : 'false', true );
                },
                postRender: function () {
                        var cbview = this;
                        this.cb = this.$( 'input[type=checkbox]' );
-                       this.cb.prop( 'checked', M.settings.getUserSetting( 
this.options.name, true ) === 'true' );
+                       this.cb.prop( 'checked', settings.get( 
this.options.name, true ) === 'true' );
                        $( 'form.mw-mf-settings' ).on( 'submit', $.proxy( 
cbview, 'save' ) );
                }
        } );
diff --git a/tests/qunit/modules/preferredLanguages/test_preferred.js 
b/tests/qunit/modules/preferredLanguages/test_preferred.js
index 12248b4..84920e1 100644
--- a/tests/qunit/modules/preferredLanguages/test_preferred.js
+++ b/tests/qunit/modules/preferredLanguages/test_preferred.js
@@ -1,17 +1,18 @@
 ( function ( $, M ) {
 
-       var oldLangMap = M.settings.getUserSetting( 'langMap' );
+       var settings = M.require( 'settings' ),
+               oldLangMap = settings.get( 'langMap' );
 
        QUnit.module( 'MobileFrontend modules/mf-translator', {
                setup: function() {
                        // save old value of langMap
-                       oldLangMap = M.settings.getUserSetting( 'langMap' );
+                       oldLangMap = settings.get( 'langMap' );
                        // destroy actual value
-                       M.settings.saveUserSetting( 'langMap', JSON.stringify( 
{} ) );
+                       settings.save( 'langMap', JSON.stringify( {} ) );
                },
                teardown: function() {
                        // restore old langMap
-                       M.settings.saveUserSetting( 'langMap', oldLangMap );
+                       settings.save( 'langMap', oldLangMap );
                }
        } );
 
@@ -21,7 +22,7 @@
                // fake click on german language link (de)
                M.emit( 'language-select', 'de' );
                // check, if the click was saved
-               langMap = JSON.parse( M.settings.getUserSetting( 'langMap' ) );
+               langMap = JSON.parse( settings.get( 'langMap' ) );
                assert.strictEqual( langMap.de, 1, "Saved click on 'de' 
language link" );
        } );
 
diff --git a/tests/qunit/modules/toggling/test_toggle.js 
b/tests/qunit/modules/toggling/test_toggle.js
index 834d033..5c5b8b2 100644
--- a/tests/qunit/modules/toggling/test_toggle.js
+++ b/tests/qunit/modules/toggling/test_toggle.js
@@ -1,6 +1,7 @@
 ( function ( M, $ ) {
 
 var sectionHtml = mw.template.get( 'mobile.toggling.tests', 'section.hogan' 
).render(),
+       settings = M.require( 'settings' ),
        toggle = M.require( 'toggle' );
 
 /**
@@ -18,7 +19,7 @@
        },
        teardown: function() {
                window.location.hash = "#";
-               M.settings.deleteUserSetting( 'expandedSections', false );
+               settings.remove( 'expandedSections', false );
        }
 });
 
@@ -106,7 +107,7 @@
        },
        teardown: function() {
                window.location.hash = "#";
-               M.settings.deleteUserSetting( 'expandedSections', false );
+               settings.remove( 'expandedSections', false );
        }
 } );
 
@@ -123,14 +124,14 @@
 
 QUnit.module( 'MobileFrontend toggle.js: user setting', {
        setup: function() {
-               M.settings.saveUserSetting('expandSections', 'true', true);
+               settings.save('expandSections', 'true', true);
                this.$container = $( '<div>' ).html( sectionHtml );
                toggle.enable( this.$container );
        },
        teardown: function() {
                window.location.hash = "#";
-               M.settings.saveUserSetting('expandSections', '', true);
-               M.settings.deleteUserSetting( 'expandedSections', false );
+               settings.save('expandSections', '', true);
+               settings.remove( 'expandedSections', false );
        }
 } );
 
@@ -152,8 +153,8 @@
        },
        teardown: function() {
                window.location.hash = "#";
-               M.settings.deleteUserSetting('expandSections', true);
-               M.settings.deleteUserSetting( 'expandedSections', false );
+               settings.remove('expandSections', true);
+               settings.remove( 'expandedSections', false );
        }
 } );
 
@@ -200,8 +201,8 @@
        },
        teardown: function() {
                window.location.hash = "#";
-               M.settings.deleteUserSetting( 'expandedSections', false );
-               M.settings.deleteUserSetting('expandSections', true);
+               settings.remove( 'expandedSections', false );
+               settings.remove('expandSections', true);
        }
 } );
 
@@ -229,7 +230,7 @@
 
 QUnit.test( 'Check for and remove obsolete stored sections.', 2, function( 
assert ) {
        this.expandedSections[this.pageTitle][this.headline] = ( new Date( 
1990, 1, 1 ) ).getTime();
-       M.settings.saveUserSetting( 'expandedSections',
+       settings.save( 'expandedSections',
                JSON.stringify( this.expandedSections )
        );
        this.expandedSections = toggle._getExpandedSections( this.pageTitle );
@@ -299,8 +300,8 @@
        },
        teardown: function() {
                window.location.hash = "#";
-               M.settings.deleteUserSetting( 'expandedSections', false );
-               M.settings.deleteUserSetting('expandSections', true);
+               settings.remove( 'expandedSections', false );
+               settings.remove('expandSections', true);
        }
 } );
 
@@ -314,7 +315,7 @@
 
        // save a toggle state manually
        this.expandedSections[this.pageTitle][this.headline] = ( new Date() 
).getTime();
-       M.settings.saveUserSetting( 'expandedSections', JSON.stringify( 
this.expandedSections ), false );
+       settings.save( 'expandedSections', JSON.stringify( 
this.expandedSections ), false );
        this.expandedSections = toggle._getExpandedSections( this.pageTitle );
        assert.strictEqual( typeof 
this.expandedSections[this.pageTitle][this.headline],
                'number',

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

Gerrit-MessageType: merged
Gerrit-Change-Id: I7ec0be06ebd7dd7aea0622f8a0e44ca08834597c
Gerrit-PatchSet: 8
Gerrit-Project: mediawiki/extensions/MobileFrontend
Gerrit-Branch: master
Gerrit-Owner: Jdlrobson <[email protected]>
Gerrit-Reviewer: Awjrichards <[email protected]>
Gerrit-Reviewer: Robmoen <[email protected]>
Gerrit-Reviewer: jenkins-bot <>

_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to