mirror of
https://github.com/the-djmaze/snappymail.git
synced 2026-08-30 12:39:20 +03:00
Extend plugin config with a grouping class
This commit is contained in:
parent
05f1d62041
commit
e0ebc999d5
10 changed files with 162 additions and 129 deletions
|
|
@ -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;
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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', []);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ namespace RainLoop\Enumerations;
|
|||
class PluginPropertyType
|
||||
{
|
||||
const
|
||||
GROUP = 7,
|
||||
STRING = 0,
|
||||
INT = 1,
|
||||
STRING_TEXT = 2,
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,37 +1,35 @@
|
|||
<label data-bind="text: Label, visible: 5 !== Type"></label>
|
||||
<div>
|
||||
<!-- ko if: 0 === Type -->
|
||||
<input type="text" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false"
|
||||
data-bind="value: value, attr: {placeholder: placeholder}" />
|
||||
<!-- /ko -->
|
||||
<!-- ko if: 1 === Type -->
|
||||
<input type="number" step="1"
|
||||
data-bind="value: value, attr: {placeholder: placeholder}" />
|
||||
<!-- /ko -->
|
||||
<!-- ko if: 3 === Type -->
|
||||
<input type="password" autocomplete="current-password" autocorrect="off" autocapitalize="off" spellcheck="false"
|
||||
data-bind="value: value, attr: {placeholder: placeholder}" />
|
||||
<!-- /ko -->
|
||||
<!-- ko if: 2 === Type -->
|
||||
<div data-bind="component: {
|
||||
name: 'TextArea',
|
||||
params: { value: value, placeholder: placeholder }
|
||||
}"></div>
|
||||
<!-- /ko -->
|
||||
<!-- ko if: 4 === Type -->
|
||||
<select data-bind="options: Default, value: value"></select>
|
||||
<!-- /ko -->
|
||||
<!-- ko if: 5 === Type -->
|
||||
<div data-bind="component: {
|
||||
name: 'Checkbox',
|
||||
params: { value: value, label: Label }
|
||||
}"></div>
|
||||
<!-- /ko -->
|
||||
<!-- ko if: 6 === Type -->
|
||||
<input type="url"
|
||||
data-bind="value: value, attr: {placeholder: placeholder}" />
|
||||
<!-- /ko -->
|
||||
<!-- ko if: '' !== Desc -->
|
||||
<span tabindex="0" class="help-block"><span data-bind="text: Desc"></span></span>
|
||||
<!-- /ko -->
|
||||
</div>
|
||||
<!-- ko if: 0 === Type -->
|
||||
<input type="text" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false"
|
||||
data-bind="value: value, attr: {placeholder: placeholder}" />
|
||||
<!-- /ko -->
|
||||
<!-- ko if: 1 === Type -->
|
||||
<input type="number" step="1"
|
||||
data-bind="value: value, attr: {placeholder: placeholder}" />
|
||||
<!-- /ko -->
|
||||
<!-- ko if: 3 === Type -->
|
||||
<input type="password" autocomplete="current-password" autocorrect="off" autocapitalize="off" spellcheck="false"
|
||||
data-bind="value: value, attr: {placeholder: placeholder}" />
|
||||
<!-- /ko -->
|
||||
<!-- ko if: 2 === Type -->
|
||||
<div data-bind="component: {
|
||||
name: 'TextArea',
|
||||
params: { value: value, placeholder: placeholder }
|
||||
}"></div>
|
||||
<!-- /ko -->
|
||||
<!-- ko if: 4 === Type -->
|
||||
<select data-bind="options: Default, value: value"></select>
|
||||
<!-- /ko -->
|
||||
<!-- ko if: 5 === Type -->
|
||||
<div data-bind="component: {
|
||||
name: 'Checkbox',
|
||||
params: { value: value, label: Label }
|
||||
}"></div>
|
||||
<!-- /ko -->
|
||||
<!-- ko if: 6 === Type -->
|
||||
<input type="url"
|
||||
data-bind="value: value, attr: {placeholder: placeholder}" />
|
||||
<!-- /ko -->
|
||||
<!-- ko if: '' !== Desc -->
|
||||
<span tabindex="0" class="help-block"><span data-bind="text: Desc"></span></span>
|
||||
<!-- /ko -->
|
||||
|
|
|
|||
|
|
@ -14,8 +14,18 @@
|
|||
<a href="#" class="close" data-bind="click: function () { saveError('') }">×</a>
|
||||
<span data-bind="text: saveError"></span>
|
||||
</div>
|
||||
<div data-bind="foreach: configures, visible: hasConfiguration">
|
||||
<div data-bind="foreach: config, visible: hasConfiguration">
|
||||
<!-- ko if: 7 == Type -->
|
||||
<details open="">
|
||||
<summary class="legend" data-bind="text: Label"></summary>
|
||||
<div data-bind="foreach: config">
|
||||
<div class="control-group" data-bind="template: { name: 'AdminSettingsPluginProperty' }"></div>
|
||||
</div>
|
||||
</details>
|
||||
<!-- /ko -->
|
||||
<!-- ko if: 7 != Type -->
|
||||
<div class="control-group" data-bind="template: { name: 'AdminSettingsPluginProperty' }"></div>
|
||||
<!-- /ko -->
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue