Robert Vogel has uploaded a new change for review. ( 
https://gerrit.wikimedia.org/r/374087 )

Change subject: [WiP]BS3: new MediaWiki based config mechansim
......................................................................

[WiP]BS3: new MediaWiki based config mechansim

* Introducing new database table for settings (using JSON as serialization 
format)
* Added base config classes
* Added migration path from old config
* Also removed some unnecessary settings

Change-Id: I0deecf4c38a9480a243fdeb008e50fcf466fca37
---
M extension.json
M i18n/core/en.json
M i18n/core/qqq.json
M includes/Core.class.php
M includes/DefaultSettings.php
A maintenance/BSMigrateSettings.php
A maintenance/db/bs_settings3.sql
M src/Config.php
A src/ExtensionConfig.php
A 
src/Hook/LoadExtensionSchemaUpdates/AddBlueSpice3SettingsAndMigrationMaintenanceScript.php
A src/ISetting.php
A tests/phpunit/ConfigTest.php
12 files changed, 283 insertions(+), 46 deletions(-)


  git pull 
ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/BlueSpiceFoundation 
refs/changes/87/374087/1

diff --git a/extension.json b/extension.json
index 0237668..f2a4a10 100644
--- a/extension.json
+++ b/extension.json
@@ -417,7 +417,8 @@
                "ExtensionTypes": "BsCoreHooks::onExtensionTypes",
                "PageContentSaveComplete": 
"BsCoreHooks::onPageContentSaveComplete",
                "UnitTestsList": "BsCoreHooks::onUnitTestsList",
-               "ResourceLoaderGetConfigVars": 
"BsExtensionManager::onResourceLoaderGetConfigVars"
+               "ResourceLoaderGetConfigVars": 
"BsExtensionManager::onResourceLoaderGetConfigVars",
+               "LoadExtensionSchemaUpdates": 
"BlueSpice\\Hook\\LoadExtensionSchemaUpdates\\AddBlueSpice3SettingsAndMigrationMaintenanceScript::callback"
        },
        "config": {
                "_prefix": "bsg",
@@ -582,7 +583,8 @@
                "BSApiTasksTestBase": "tests/phpunit/BSApiTasksTestBase.php",
                "BSTemplateHelper": "includes/TemplateHelper.php",
                "ResourceLoaderBSTemplateModule": 
"includes/resourceloader/ResourceLoaderBSTemplateModule.php",
-               "BSTasksApiSpec": "includes/utility/BSTasksApiSpec.php"
+               "BSTasksApiSpec": "includes/utility/BSTasksApiSpec.php",
+               "BSMigrateSettings": "maintenance/BSMigrateSettings.php"
        },
        "load_composer_autoloader": true,
        "manifest_version": 1,
diff --git a/i18n/core/en.json b/i18n/core/en.json
index 69431fa..b398205 100644
--- a/i18n/core/en.json
+++ b/i18n/core/en.json
@@ -37,7 +37,6 @@
        "bs-viewtagerrorlist-legend": "$1 - Error",
        "bs-readonly": "The database is currently locked to new entries and 
other modifications, probably for routine database maintenance, after which it 
will be back to normal. The administrator who locked it offered this 
explanation: $1",
        "bs-imageofotheruser": "You are not allowed to upload an image for 
another user.",
-       "bs-pref-sortalph": "Sort namespaces alphabetically",
        "bs-permissionerror": "Permission error!",
        "bs-filesystemhelper-no-directory": "<code>$1</code> is not a valid 
directory.",
        "bs-filesystemhelper-has-path-traversal": "Path traversal detected!",
diff --git a/i18n/core/qqq.json b/i18n/core/qqq.json
index 8710f12..23b8ec5 100644
--- a/i18n/core/qqq.json
+++ b/i18n/core/qqq.json
@@ -42,7 +42,6 @@
        "bs-viewtagerrorlist-legend": "Used in inline error messages produced 
by tags\n\nParameters:\n* $1 - name of the tag\n{{Identical|Error}}",
        "bs-readonly": "Shown in various messages when database is in readonly 
mode and a write operation is requested.\n\nParameters:\n* $1 - explanation as 
given in $wgReadOnly",
        "bs-imageofotheruser": "Error message when user tries to upload an 
avatar for another user",
-       "bs-pref-sortalph": "Label for checkbox to sort all namespaces 
alphabetically.",
        "bs-permissionerror": "Error message sent in ajax requests when user 
has no permissions to perform that action\n{{Identical|Permission error}}",
        "bs-filesystemhelper-no-directory": "Error message given when requested 
directory is not a directory, put $1 in code tags\n\nParameters:\n* $1 - name 
of the requested directory",
        "bs-filesystemhelper-has-path-traversal": "Error message given when a 
file path tries to access files outside mediawiki root.\n\nSee [[w:Directory 
traversal attack]].",
diff --git a/includes/Core.class.php b/includes/Core.class.php
index de26310..9656925 100644
--- a/includes/Core.class.php
+++ b/includes/Core.class.php
@@ -106,42 +106,6 @@
 
        protected static $bHtmlFormClassLoaded = false;
 
-       /**
-        * The constructor is protected because of the singleton pattern.
-        */
-       protected function __construct() {
-               wfProfileIn('Performance: ' . __METHOD__);
-               global $wgScriptPath;
-               $sPath = $wgScriptPath . 
"/extensions/BlueSpiceFoundation/resources/bluespice/images/";
-
-               $aFiles = array(
-                       'txt', 'rtf',
-                       'doc', 'dot', 'docx', 'dotx', 'dotm',
-                       'xls', 'xlt', 'xlm', 'xlsx', 'xlsm', 'xltm', 'xltx',
-                       'ppt', 'pot', 'pps', 'pptx', 'pptm', 'potx', 'potm', 
'ppsx', 'ppsm', 'sldx', 'sldm',
-                       'odt', 'fodt', 'ods', 'fods', 'odp', 'fodp',
-                       'pdf',
-                       'zip', 'rar', 'tar', 'tgz', 'gz', 'bzip2', '7zip',
-                       'xml', 'svg'
-               );
-               $aImages = array( 'png', 'gif', 'jpg', 'jpeg' );
-               BsConfig::registerVar( 'MW::FileExtensions', $aFiles, 
BsConfig::LEVEL_PUBLIC  | BsConfig::TYPE_ARRAY_STRING, 
'bs-pref-fileextensions', 'multiselectplusadd' );
-               BsConfig::registerVar( 'MW::ImageExtensions', $aImages, 
BsConfig::LEVEL_PUBLIC | BsConfig::TYPE_ARRAY_STRING, 
'bs-pref-imageextensions', 'multiselectplusadd' );
-               BsConfig::registerVar( 'MW::LogoPath', $sPath . 'bs-logo.png', 
BsConfig::LEVEL_PUBLIC | BsConfig::TYPE_STRING, 'bs-pref-logopath' );
-               BsConfig::registerVar( 'MW::FaviconPath', $sPath . 
'favicon.ico', BsConfig::LEVEL_PUBLIC | BsConfig::TYPE_STRING, 
'bs-pref-faviconpath' );
-               BsConfig::registerVar( 'MW::DefaultUserImage', $sPath . 
'bs-user-default-image.png', BsConfig::LEVEL_PUBLIC | BsConfig::TYPE_STRING, 
'bs-pref-defaultuserimage' );
-               BsConfig::registerVar( 'MW::MiniProfileEnforceHeight', true, 
BsConfig::LEVEL_PUBLIC | BsConfig::TYPE_BOOL, 
'bs-pref-miniprofileenforceheight', 'toggle' );
-               BsConfig::registerVar( 'MW::AnonUserImage', $sPath . 
'bs-user-anon-image.png', BsConfig::LEVEL_PUBLIC | BsConfig::TYPE_STRING, 
'bs-pref-anonuserimage' );
-               BsConfig::registerVar( 'MW::DeletedUserImage', $sPath . 
'bs-user-deleted-image.png', BsConfig::LEVEL_PUBLIC | BsConfig::TYPE_STRING, 
'bs-pref-deleteduserimage' );
-               BsConfig::registerVar( 'MW::UserImage', '', 
BsConfig::LEVEL_USER | BsConfig::TYPE_STRING | BsConfig::NO_DEFAULT, 
'bs-authors-profileimage' );
-               BsConfig::registerVar( 'MW::PingInterval', 10, 
BsConfig::LEVEL_PUBLIC | BsConfig::RENDER_AS_JAVASCRIPT | BsConfig::TYPE_INT, 
'bs-pref-bspinginterval' );
-               BsConfig::registerVar( 'MW::SortAlph', false, 
BsConfig::LEVEL_PUBLIC | BsConfig::LEVEL_USER | BsConfig::TYPE_BOOL, 
'bs-pref-sortalph', 'toggle' );
-               BsConfig::registerVar( 'MW::TestMode', false, 
BsConfig::LEVEL_PUBLIC | BsConfig::TYPE_BOOL, 'bs-pref-testmode', 'toggle' );
-
-               BsConfig::set( 'MW::ApplicationContext', 'Wiki' );
-               wfProfileOut('Performance: ' . __METHOD__);
-       }
-
        public static function getForbiddenCharsInArticleTitle() {
                return self::$prForbiddenCharsInArticleTitle;
        }
@@ -357,8 +321,10 @@
 
                //TODO: This does not seem to be the right place for stuff like 
this.
                global $wgFileExtensions;
-               $aFileExtensions  = BsConfig::get( 'MW::FileExtensions' );
-               $aImageExtensions = BsConfig::get( 'MW::ImageExtensions' );
+               $config = MediaWiki\MediaWikiServices::getInstance()
+                       ->getConfigFactory()->makeConfig( 'bsg' );
+               $aFileExtensions  = $config->get( 'FileExtensions' );
+               $aImageExtensions = $config->get( 'ImageExtensions' );
                $wgFileExtensions = array_merge( $aFileExtensions, 
$aImageExtensions );
                $wgFileExtensions = array_values( array_unique( 
$wgFileExtensions ) );
        }
diff --git a/includes/DefaultSettings.php b/includes/DefaultSettings.php
index 51ae783..557a945 100644
--- a/includes/DefaultSettings.php
+++ b/includes/DefaultSettings.php
@@ -349,4 +349,27 @@
        )
 );
 
-$GLOBALS['bsgUserMiniProfileParams'] = [ 'width' => 40, 'height' => 40 ];
\ No newline at end of file
+$GLOBALS['bsgUserMiniProfileParams'] = [ 'width' => 40, 'height' => 40 ];
+$GLOBALS['bsgMiniProfileEnforceHeight'] = true;
+$GLOBALS['bsgPingInterval'] = 10;
+
+/**
+ * ATTENTION: Not to confuse with 'bsgTestSystem'.
+ * This settings influences e-mail-, export- and other features
+ * @global string $GLOBALS['bsgTestMode']
+ * @name $bsgTestMode
+ */
+$GLOBALS['bsgTestMode'] = false;
+$GLOBALS['bsgFileExtensions'] = [
+                       'txt', 'rtf',
+                       'doc', 'dot', 'docx', 'dotx', 'dotm',
+                       'xls', 'xlt', 'xlm', 'xlsx', 'xlsm', 'xltm', 'xltx',
+                       'ppt', 'pot', 'pps', 'pptx', 'pptm', 'potx', 'potm', 
'ppsx', 'ppsm', 'sldx', 'sldm',
+                       'odt', 'fodt', 'ods', 'fods', 'odp', 'fodp',
+                       'pdf',
+                       'zip', 'rar', 'tar', 'tgz', 'gz', 'bzip2', '7zip',
+                       'xml', 'svg'
+];
+
+
+$GLOBALS['bsgImageExtensions'] = [ 'png', 'gif', 'jpg', 'jpeg' ];
\ No newline at end of file
diff --git a/maintenance/BSMigrateSettings.php 
b/maintenance/BSMigrateSettings.php
new file mode 100644
index 0000000..fb400a8
--- /dev/null
+++ b/maintenance/BSMigrateSettings.php
@@ -0,0 +1,92 @@
+<?php
+
+require_once( 'BSMaintenance.php' );
+
+class BSMigrateSettings extends Maintenance {
+
+       public function execute() {
+               if( $this->noDataToMigrate() ) {
+                       $this->output( "bs_settings -> bs_settings3: No data to 
migrate" );
+                       return;
+               }
+
+               $this->readOldData();
+               $this->convertData();
+               $this->saveConvertedData();
+       }
+
+       protected function noDataToMigrate() {
+               return $this->getDB( DB_SLAVE )->tableExists( 'bs_settings' ) 
=== false;
+       }
+
+       protected $oldData = [];
+       protected function readOldData() {
+               $res = $this->getDB( DB_SLAVE )->select( 'bs_settings', '*' );
+               foreach( $res as $row ) {
+                       $this->oldData[$row->key] = $row->value;
+               }
+       }
+
+       protected $newData = [];
+       protected function convertData() {
+               foreach( $this->oldData as $oldName => $serializedValue ) {
+                       $newName = $this->makeNewName( $oldName );
+                       $newValue = $this->convertValue( $serializedValue );
+                       $this->output( "$oldName => $newName\n" );
+                       $this->newData[ $newName ] = $newValue;
+               }
+       }
+
+       protected function makeNewName( $oldName ) {
+               if( $oldName === 'MW::LogoPath' ) {
+                       return 'wgLogo';
+               }
+
+               //$oldName = "MW::TopMenuBarCustomizer::NumberOfSubEntries"
+               $nameParts = explode( '::', $oldName );
+               array_shift( $nameParts ); //MW
+               $newName = 'bsg' . implode( '', $nameParts );
+
+               if( strlen( $newName ) > 255 ) {
+                       throw new Exception( "Variable name '$newName' is too 
long!" );
+               }
+
+               return $newName;
+       }
+
+       protected function saveConvertedData() {
+               foreach( $this->newData as $newName => $newValue ) {
+                       $this->getDB( DB_MASTER )->insert( 'bs_settings3', [
+                               's_name' => $newName,
+                               's_value' => $newValue
+                       ] );
+               }
+       }
+
+       protected function convertValue( $serializedValue ) {
+               $newValue = unserialize( $serializedValue );
+               /*if( is_int(  $newValue ) ) {
+                       $newValue = (int) $newValue;
+               }
+               if( is_array( $newValue ) ) {
+                       $newArray = [];
+                       foreach( $newValue as $key => $element ) {
+                               $newArray[$key] = $this->convertValue( $element 
);
+                       }
+                       $newValue = $newArray;
+               }
+               if( is_bool( $newValue ) ) {
+                       $newValue = (bool) $newValue;
+               }*/
+
+               return FormatJson::encode( $newValue );
+       }
+
+}
+
+$maintClass = 'BSMigrateSettings';
+if (defined('RUN_MAINTENANCE_IF_AIN')) {
+       require_once( RUN_MAINTENANCE_IF_MAIN );
+} else {
+       require_once( DO_MAINTENANCE ); # Make this work on versions before 1.17
+}
\ No newline at end of file
diff --git a/maintenance/db/bs_settings3.sql b/maintenance/db/bs_settings3.sql
new file mode 100644
index 0000000..b911781
--- /dev/null
+++ b/maintenance/db/bs_settings3.sql
@@ -0,0 +1,5 @@
+CREATE TABLE IF NOT EXISTS /*_*/bs_settings3 (
+       s_name VARCHAR(255) NOT NULL,
+       s_value mediumblob,
+       PRIMARY KEY ( s_name )
+) /*$wgDBTableOptions*/;
\ No newline at end of file
diff --git a/src/Config.php b/src/Config.php
index 1ec57d9..56f3a30 100644
--- a/src/Config.php
+++ b/src/Config.php
@@ -2,8 +2,45 @@
 
 namespace BlueSpice;
 
-class Config extends \GlobalVarConfig {
-       public static function newInstance() {
-               return new self( 'bsg' );
+class Config extends \MultiConfig {
+
+       /**
+        *
+        * @var \LoadBalancer
+        */
+       protected $loadBalancer = null;
+
+
+       /**
+        *
+        * @param \LoadBalancer $loadBalancer
+        */
+       public function __construct( $loadBalancer ) {
+               $this->loadBalancer = $loadBalancer;
+               parent::__construct( [
+                       $this->makeDatabaseConfig(),
+                       new \GlobalVarConfig( 'bsg' )
+               ] );
        }
+
+       public static function newInstance() {
+               $lb = \LBFactory::singleton()->getMainLB();
+               return new self( $lb );
+       }
+
+       protected function makeDatabaseConfig() {
+               $hash = [];
+               $dbr = $this->loadBalancer->getConnection( DB_SLAVE );
+               $res = $dbr->select( 'bs_settings3', '*' );
+
+               foreach( $res as $row ) {
+                       if( strpos(  $row->s_name, 'bsg' ) === 0 ) {
+                               $name = substr( $row->s_name, 3 );
+                               $hash[$name] = \FormatJson::decode( 
$row->s_value );
+                       }
+               }
+
+               return new \HashConfig( $hash );
+       }
+
 }
diff --git a/src/ExtensionConfig.php b/src/ExtensionConfig.php
new file mode 100644
index 0000000..a4abe2d
--- /dev/null
+++ b/src/ExtensionConfig.php
@@ -0,0 +1,2 @@
+<?php
+
diff --git 
a/src/Hook/LoadExtensionSchemaUpdates/AddBlueSpice3SettingsAndMigrationMaintenanceScript.php
 
b/src/Hook/LoadExtensionSchemaUpdates/AddBlueSpice3SettingsAndMigrationMaintenanceScript.php
new file mode 100644
index 0000000..ecca3c3
--- /dev/null
+++ 
b/src/Hook/LoadExtensionSchemaUpdates/AddBlueSpice3SettingsAndMigrationMaintenanceScript.php
@@ -0,0 +1,24 @@
+<?php
+
+namespace BlueSpice\Hook\LoadExtensionSchemaUpdates;
+
+use BlueSpice\Hook\LoadExtensionSchemaUpdates;
+
+class AddBlueSpice3SettingsAndMigrationMaintenanceScript extends 
LoadExtensionSchemaUpdates {
+       protected function doProcess() {
+               $this->updater->addExtensionTable(
+                       'bs_settings3',
+                       $this->getExtensionPath() . 
'/maintenance/db/bs_settings3.sql'
+               );
+
+               $this->updater->addPostDatabaseUpdateMaintenance(
+                       'BSMigrateSettings'
+               );
+               return true;
+       }
+
+       protected function getExtensionPath() {
+               return dirname( dirname( dirname( __DIR__ ) ) );
+       }
+
+}
\ No newline at end of file
diff --git a/src/ISetting.php b/src/ISetting.php
new file mode 100644
index 0000000..15a52e2
--- /dev/null
+++ b/src/ISetting.php
@@ -0,0 +1,29 @@
+<?php
+
+namespace BlueSpice;
+
+interface ISetting {
+       /**
+        * @return string The variable name like it would be in 
'LoalSettings.php'.
+        * E.g. 'wgLogo' or 'bsgPingInterval'
+        */
+       public function getVariableName();
+
+       /**
+        * @return array An array of paths that define where to provide an input
+        * field within the settings UI. E.g.
+        * [ 'site/interface', 'site/<extensionX>' ]
+        * ATTENTION: Path elements need a message key to be available following
+        * the pattern 'bs-setting-path-<elementName>'. E. g.
+        * 'bs-setting-path-<extensionX>'
+        */
+       public function getPaths();
+
+       /**
+        *
+        * @param mixed $value Whatever the current value of the setting may be
+        * @return \HTMLFormField A ready to use HTML-form-field-descriptor, 
with
+        * default, labels, descriptions, ...
+        */
+       public function getField( $value );
+}
diff --git a/tests/phpunit/ConfigTest.php b/tests/phpunit/ConfigTest.php
new file mode 100644
index 0000000..611e9ee
--- /dev/null
+++ b/tests/phpunit/ConfigTest.php
@@ -0,0 +1,59 @@
+<?php
+
+namespace BlueSpice\Tests;
+
+use \MediaWiki\MediaWikiServices;
+
+/**
+ * @group BlueSpice
+ * @group BlueSpiceFoundation
+ * @group Medium
+ */
+class ConfigTest extends \MediaWikiTestCase {
+       protected $tablesUsed = [ 'bs_settings3' ];
+
+       public function setUp() {
+               parent::setUp();
+
+               $GLOBALS[ 'bsgUnitTestSetting']  = 5;
+               $GLOBALS[ 'bsgUnitTestSetting2' ] = [ 'An', 'array' ];
+       }
+
+       public function addDBData() {
+               parent::addDBData();
+               $this->db->insert( 'bs_settings3', [
+                       's_name' => 'bsgUnitTestSetting',
+                       's_value' => '"9"' //JSON formatted
+               ] );
+       }
+
+       public function testFactoryReturn() {
+               $config = MediaWikiServices::getInstance()->getConfigFactory()
+                       ->makeConfig( 'bsg' );
+
+               $this->assertInstanceOf(
+                       '\\BlueSpice\\Config', //Can be discussed whether just 
\Config is sufficient to test
+                       $config,
+                       'MediaWiki ConfigFactory should return propert instance'
+               );
+       }
+
+       public function testDatabasePreval() {
+               $config = new \BlueSpice\Config( wfGetLB() );
+               $this->assertEquals(
+                       9,
+                       $config->get( 'UnitTestSetting' ),
+                       'Should return value from database'
+               );
+       }
+
+       public function testGlobalVarDefaulting() {
+               $config = new \BlueSpice\Config( wfGetLB() );
+
+               $this->assertArrayEquals(
+                       [ 'An', 'array' ],
+                       $config->get( 'UnitTestSetting2' ),
+                       'Should fall back to global vars'
+               );
+       }
+}

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

Gerrit-MessageType: newchange
Gerrit-Change-Id: I0deecf4c38a9480a243fdeb008e50fcf466fca37
Gerrit-PatchSet: 1
Gerrit-Project: mediawiki/extensions/BlueSpiceFoundation
Gerrit-Branch: master
Gerrit-Owner: Robert Vogel <vo...@hallowelt.biz>

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

Reply via email to