From e0ebc999d58ce861462654bc5cc4f78767c01b07 Mon Sep 17 00:00:00 2001 From: the-djmaze <> Date: Wed, 9 Feb 2022 17:48:05 +0100 Subject: [PATCH] Extend plugin config with a grouping class --- dev/View/Popup/Plugin.js | 23 +++--- plugins/change-password/index.php | 32 +++++---- .../app/libraries/RainLoop/Actions/Admin.php | 53 ++++++++------ .../app/libraries/RainLoop/Config/Plugin.php | 25 ++----- .../Enumerations/PluginPropertyType.php | 1 + .../RainLoop/Plugins/AbstractPlugin.php | 20 +++++- .../libraries/RainLoop/Plugins/Manager.php | 23 +++--- .../libraries/RainLoop/Plugins/Property.php | 32 ++++++--- .../Admin/AdminSettingsPluginProperty.html | 70 +++++++++---------- .../templates/Views/Admin/PopupsPlugin.html | 12 +++- 10 files changed, 162 insertions(+), 129 deletions(-) diff --git a/dev/View/Popup/Plugin.js b/dev/View/Popup/Plugin.js index 2dc20ba91..cfa8aa3cf 100644 --- a/dev/View/Popup/Plugin.js +++ b/dev/View/Popup/Plugin.js @@ -21,11 +21,11 @@ class PluginPopupView extends AbstractViewPopup { readme: '' }); - this.configures = ko.observableArray(); + this.config = ko.observableArray(); this.addComputables({ hasReadme: () => !!this.readme(), - hasConfiguration: () => 0 < this.configures().length + hasConfiguration: () => 0 < this.config().length }); this.bDisabeCloseOnEsc = true; @@ -44,7 +44,7 @@ class PluginPopupView extends AbstractViewPopup { Settings: {} }; - this.configures.forEach(oItem => { + this.config.forEach(oItem => { let value = oItem.value(); if (false === value || true === value) { value = value ? 1 : 0; @@ -64,7 +64,7 @@ class PluginPopupView extends AbstractViewPopup { this.id(''); this.name(''); this.readme(''); - this.configures([]); + this.config([]); if (oPlugin) { this.id(oPlugin.Id); @@ -73,16 +73,11 @@ class PluginPopupView extends AbstractViewPopup { const config = oPlugin.Config; if (arrayLength(config)) { - this.configures( - config.map(item => ({ - value: ko.observable(item[0]), - placeholder: ko.observable(item[6]), - Name: item[1], - Type: item[2], - Label: item[3], - Default: item[4], - Desc: item[5] - })) + this.config( + config.map(item => { + item.value = ko.observable(item.value); + return item; + }) ); } } diff --git a/plugins/change-password/index.php b/plugins/change-password/index.php index 57524f604..13ba2f35a 100644 --- a/plugins/change-password/index.php +++ b/plugins/change-password/index.php @@ -6,9 +6,9 @@ class ChangePasswordPlugin extends \RainLoop\Plugins\AbstractPlugin { const NAME = 'Change Password', - VERSION = '2.9', - RELEASE = '2021-07-20', - REQUIRED = '2.9.1', + VERSION = '2.12', + RELEASE = '2022-02-10', + REQUIRED = '2.12.0', CATEGORY = 'Security', DESCRIPTION = 'Extension to allow users to change their passwords'; @@ -96,17 +96,21 @@ class ChangePasswordPlugin extends \RainLoop\Plugins\AbstractPlugin ->SetDefaultValue(70), ]; foreach ($this->getSupportedDrivers(true) as $name => $class) { - $result[] = \RainLoop\Plugins\Property::NewInstance("driver_{$name}_enabled") - ->SetLabel('Enable ' . $class::NAME) - ->SetType(\RainLoop\Enumerations\PluginPropertyType::BOOL) - ->SetDescription($class::DESCRIPTION) - ->SetDefaultValue(false); - $result[] = \RainLoop\Plugins\Property::NewInstance("driver_{$name}_allowed_emails") - ->SetLabel('Allowed emails') - ->SetType(\RainLoop\Enumerations\PluginPropertyType::STRING_TEXT) - ->SetDescription('Allowed emails, space as delimiter, wildcard supported. Example: user1@example.net user2@example1.net *@example2.net') - ->SetDefaultValue('*'); - $result = \array_merge($result, \call_user_func("{$class}::configMapping")); + $group = new \RainLoop\Plugins\PropertyCollection($name); + $props = [ + \RainLoop\Plugins\Property::NewInstance("driver_{$name}_enabled") + ->SetLabel('Enable ' . $class::NAME) + ->SetType(\RainLoop\Enumerations\PluginPropertyType::BOOL) + ->SetDescription($class::DESCRIPTION) + ->SetDefaultValue(false), + \RainLoop\Plugins\Property::NewInstance("driver_{$name}_allowed_emails") + ->SetLabel('Allowed emails') + ->SetType(\RainLoop\Enumerations\PluginPropertyType::STRING_TEXT) + ->SetDescription('Allowed emails, space as delimiter, wildcard supported. Example: user1@example.net user2@example1.net *@example2.net') + ->SetDefaultValue('*') + ]; + $group->exchangeArray(\array_merge($props, \call_user_func("{$class}::configMapping"))); + $result[] = $group; } return $result; } diff --git a/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/Admin.php b/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/Admin.php index 8e6e0b2fc..edd45c2f5 100644 --- a/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/Admin.php +++ b/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/Admin.php @@ -791,34 +791,41 @@ trait Admin $mResult = false; $sId = (string) $this->GetActionParam('Id', ''); - if (!empty($sId)) - { + if (!empty($sId)) { $oPlugin = $this->Plugins()->CreatePluginByName($sId); - if ($oPlugin) - { + if ($oPlugin) { $mResult = array( - 'Id' => $sId, - 'Name' => $oPlugin->Name(), - 'Readme' => $oPlugin->Description(), - 'Config' => array() + '@Object' => 'Object/Plugin', + 'Id' => $sId, + 'Name' => $oPlugin->Name(), + 'Readme' => $oPlugin->Description(), + 'Config' => array() ); $aMap = $oPlugin->ConfigMap(); - $oConfig = $oPlugin->Config(); - if (is_array($aMap)) - { - foreach ($aMap as $oItem) - { - if ($oItem && ($oItem instanceof \RainLoop\Plugins\Property)) - { - $aItem = $oItem->ToArray(); - $aItem[0] = $oConfig->Get('plugin', $oItem->Name(), ''); - if (PluginPropertyType::PASSWORD === $oItem->Type()) - { - $aItem[0] = APP_DUMMY; + if (\is_array($aMap)) { + $oConfig = $oPlugin->Config(); + foreach ($aMap as $oItem) { + if ($oItem) { + if ($oItem instanceof \RainLoop\Plugins\Property) { + if (PluginPropertyType::PASSWORD === $oItem->Type()) { + $oItem->SetValue(APP_DUMMY); + } else { + $oItem->SetValue($oConfig->Get('plugin', $oItem->Name(), '')); + } + $mResult['Config'][] = $oItem; + } else if ($oItem instanceof \RainLoop\Plugins\PropertyCollection) { + foreach ($oItem as $oSubItem) { + if ($oSubItem && $oSubItem instanceof \RainLoop\Plugins\Property) { + if (PluginPropertyType::PASSWORD === $oSubItem->Type()) { + $oSubItem->SetValue(APP_DUMMY); + } else { + $oSubItem->SetValue($oConfig->Get('plugin', $oSubItem->Name(), '')); + } + } + } + $mResult['Config'][] = $oItem; } - - $mResult['Config'][] = $aItem; } } } @@ -841,7 +848,7 @@ trait Admin if ($oPlugin) { $oConfig = $oPlugin->Config(); - $aMap = $oPlugin->ConfigMap(); + $aMap = $oPlugin->ConfigMap(true); if (is_array($aMap)) { $aSettings = (array) $this->GetActionParam('Settings', []); diff --git a/snappymail/v/0.0.0/app/libraries/RainLoop/Config/Plugin.php b/snappymail/v/0.0.0/app/libraries/RainLoop/Config/Plugin.php index cae7f4131..d848e333b 100644 --- a/snappymail/v/0.0.0/app/libraries/RainLoop/Config/Plugin.php +++ b/snappymail/v/0.0.0/app/libraries/RainLoop/Config/Plugin.php @@ -7,39 +7,28 @@ class Plugin extends \RainLoop\Config\AbstractConfig /** * @var array */ - private $aMap; + private $aMap = array(); public function __construct(string $sPluginName, array $aMap = array()) { - $this->aMap = is_array($aMap) ? $this->convertConfigMap($aMap) : array(); - - parent::__construct('plugin-'.$sPluginName.'.ini', '; SnappyMail plugin ('.$sPluginName.')'); - } - - private function convertConfigMap(array $aMap) : array - { - if (\count($aMap)) - { + if (\count($aMap)) { $aResultMap = array(); - foreach ($aMap as /* @var $oProperty \RainLoop\Plugins\Property */ $oProperty) - { - if ($oProperty) - { + foreach ($aMap as /* @var $oProperty \RainLoop\Plugins\Property */ $oProperty) { + if ($oProperty) { $mValue = $oProperty->DefaultValue(); $sValue = \is_array($mValue) && isset($mValue[0]) ? $mValue[0] : $mValue; $aResultMap[$oProperty->Name()] = array($sValue, ''); } } - if (\count($aResultMap)) - { - return array( + if (\count($aResultMap)) { + $this->aMap = array( 'plugin' => $aResultMap ); } } - return array(); + parent::__construct('plugin-'.$sPluginName.'.ini', '; SnappyMail plugin ('.$sPluginName.')'); } protected function defaultValues() : array diff --git a/snappymail/v/0.0.0/app/libraries/RainLoop/Enumerations/PluginPropertyType.php b/snappymail/v/0.0.0/app/libraries/RainLoop/Enumerations/PluginPropertyType.php index 31784f44c..6b18a05f9 100644 --- a/snappymail/v/0.0.0/app/libraries/RainLoop/Enumerations/PluginPropertyType.php +++ b/snappymail/v/0.0.0/app/libraries/RainLoop/Enumerations/PluginPropertyType.php @@ -5,6 +5,7 @@ namespace RainLoop\Enumerations; class PluginPropertyType { const + GROUP = 7, STRING = 0, INT = 1, STRING_TEXT = 2, diff --git a/snappymail/v/0.0.0/app/libraries/RainLoop/Plugins/AbstractPlugin.php b/snappymail/v/0.0.0/app/libraries/RainLoop/Plugins/AbstractPlugin.php index fa893501d..a270f0417 100644 --- a/snappymail/v/0.0.0/app/libraries/RainLoop/Plugins/AbstractPlugin.php +++ b/snappymail/v/0.0.0/app/libraries/RainLoop/Plugins/AbstractPlugin.php @@ -111,13 +111,31 @@ abstract class AbstractPlugin return $this->sPath; } - final public function ConfigMap() : array + final public function ConfigMap(bool $flatten = false) : array { if (null === $this->aConfigMap) { $this->aConfigMap = $this->configMapping(); } + if ($flatten) { + $result = []; + foreach ($this->aConfigMap as $oItem) { + if ($oItem) { + if ($oItem instanceof \RainLoop\Plugins\Property) { + $result[] = $oItem; + } else if ($oItem instanceof \RainLoop\Plugins\PropertyCollection) { + foreach ($oItem as $oSubItem) { + if ($oSubItem && $oSubItem instanceof \RainLoop\Plugins\Property) { + $result[] = $oSubItem; + } + } + } + } + } + return $result; + } + return $this->aConfigMap; } diff --git a/snappymail/v/0.0.0/app/libraries/RainLoop/Plugins/Manager.php b/snappymail/v/0.0.0/app/libraries/RainLoop/Plugins/Manager.php index 84def593f..353371da1 100644 --- a/snappymail/v/0.0.0/app/libraries/RainLoop/Plugins/Manager.php +++ b/snappymail/v/0.0.0/app/libraries/RainLoop/Plugins/Manager.php @@ -82,7 +82,7 @@ class Manager ->SetName($sName) ->SetPath(static::getPluginPath($sName)) ->SetPluginManager($this) - ->SetPluginConfig(new \RainLoop\Config\Plugin($sName, $oPlugin->ConfigMap())) + ->SetPluginConfig(new \RainLoop\Config\Plugin($sName, $oPlugin->ConfigMap(true))) ; } @@ -223,7 +223,7 @@ class Manager if ($oPlugin) { $aConfig = array(); - $aMap = $oPlugin->ConfigMap(); + $aMap = $oPlugin->ConfigMap(true); if (\is_array($aMap)) { foreach ($aMap as /* @var $oPluginProperty \RainLoop\Plugins\Property */ $oPluginProperty) @@ -468,16 +468,15 @@ class Manager return false; } - public function ReadLang(string $sLang, array &$aLang) : self + public function ReadLang(string $sLang, array &$aLang) : void { - if ($this->bIsEnabled) - { - foreach ($this->aPlugins as $oPlugin) - { - if ($oPlugin->UseLangs()) - { + if ($this->bIsEnabled) { + foreach ($this->aPlugins as $oPlugin) { + if ($oPlugin->UseLangs()) { $sPath = $oPlugin->Path().'/langs/'; $aPLang = []; + + // First get english if (\is_file("{$sPath}en.ini")) { $aPLang = \parse_ini_file("{$sPath}en.ini", true); } else if (\is_file("{$sPath}en.json")) { @@ -487,8 +486,8 @@ class Manager $aLang = \array_replace_recursive($aLang, $aPLang); } - if ('en' !== $sLang) - { + // Now get native + if ('en' !== $sLang) { $aPLang = []; if (\is_file("{$sPath}{$sLang}.ini")) { $aPLang = \parse_ini_file("{$sPath}{$sLang}.ini", true); @@ -504,8 +503,6 @@ class Manager } } } - - return $this; } public function IsEnabled() : bool diff --git a/snappymail/v/0.0.0/app/libraries/RainLoop/Plugins/Property.php b/snappymail/v/0.0.0/app/libraries/RainLoop/Plugins/Property.php index dac5e8267..187f6847b 100644 --- a/snappymail/v/0.0.0/app/libraries/RainLoop/Plugins/Property.php +++ b/snappymail/v/0.0.0/app/libraries/RainLoop/Plugins/Property.php @@ -2,13 +2,18 @@ namespace RainLoop\Plugins; -class Property +class Property implements \JsonSerializable { /** * @var string */ private $sName; + /** + * @var mixed + */ + private $mValue; + /** * @var string */ @@ -62,6 +67,14 @@ class Property return $this; } + /** + * @param mixed $mValue + */ + public function SetValue($mValue) : void + { + $this->mValue = $mValue; + } + /** * @param mixed $mDefaultValue */ @@ -138,16 +151,17 @@ class Property return $this->sPlaceholder; } - public function ToArray() : array + public function jsonSerialize() { return array( - '', - $this->sName, - $this->iType, - $this->sLabel, - $this->mDefaultValue, - $this->sDesc, - $this->sPlaceholder + '@Object' => 'Object/PluginProperty', + 'value' => $this->mValue, + 'placeholder' => $this->sPlaceholder, + 'Name' => $this->sName, + 'Type' => $this->iType, + 'Label' => $this->sLabel, + 'Default' => $this->mDefaultValue, + 'Desc' => $this->sDesc ); } } diff --git a/snappymail/v/0.0.0/app/templates/Views/Admin/AdminSettingsPluginProperty.html b/snappymail/v/0.0.0/app/templates/Views/Admin/AdminSettingsPluginProperty.html index 489a2531f..9ce8c52ee 100644 --- a/snappymail/v/0.0.0/app/templates/Views/Admin/AdminSettingsPluginProperty.html +++ b/snappymail/v/0.0.0/app/templates/Views/Admin/AdminSettingsPluginProperty.html @@ -1,37 +1,35 @@ -
- - - - - - - - - - -
- - - - - -
- - - - - - - -
+ + + + + + + + + + +
+ + + + + +
+ + + + + + + diff --git a/snappymail/v/0.0.0/app/templates/Views/Admin/PopupsPlugin.html b/snappymail/v/0.0.0/app/templates/Views/Admin/PopupsPlugin.html index 6ea2e1e2e..ef0c0a18d 100644 --- a/snappymail/v/0.0.0/app/templates/Views/Admin/PopupsPlugin.html +++ b/snappymail/v/0.0.0/app/templates/Views/Admin/PopupsPlugin.html @@ -14,8 +14,18 @@ × -
+
+ +
+ +
+
+
+
+ +
+