From f481de2a18c443e014d8ab5ef94ecc5ef3de0e27 Mon Sep 17 00:00:00 2001 From: Marcin Haba Date: Mon, 22 Apr 2019 07:03:56 +0200 Subject: [PATCH] baculum: Add text box list control to support directives that can be defined multiple times in one resource Use text box list control to: wild, wilddir, wildfile, regex, regexdir and regexfile FileSet directives. --- gui/baculum/protected/Web/Data/data_desc.json | 12 +-- .../protected/Web/Pages/JobHistoryView.page | 1 + gui/baculum/protected/Web/Pages/JobView.page | 1 + .../Web/Portlets/BaculaConfigDirectives.php | 44 +-------- .../Web/Portlets/ConfigListTemplate.php | 6 +- .../Web/Portlets/DirectiveControlTemplate.php | 42 +++++++++ .../Web/Portlets/DirectiveFileSet.php | 70 +++++++++++---- .../Web/Portlets/DirectiveListTemplate.php | 9 ++ .../Web/Portlets/DirectiveMultiTextBox.php | 89 +++++++++++++++++++ .../Web/Portlets/DirectiveMultiTextBox.tpl | 22 +++++ .../Web/Portlets/DirectiveRenderer.php | 15 +++- .../Web/Portlets/DirectiveTemplate.php | 18 +--- 12 files changed, 241 insertions(+), 88 deletions(-) create mode 100644 gui/baculum/protected/Web/Portlets/DirectiveControlTemplate.php create mode 100644 gui/baculum/protected/Web/Portlets/DirectiveMultiTextBox.php create mode 100644 gui/baculum/protected/Web/Portlets/DirectiveMultiTextBox.tpl diff --git a/gui/baculum/protected/Web/Data/data_desc.json b/gui/baculum/protected/Web/Data/data_desc.json index a039b4f7d..0e5142530 100644 --- a/gui/baculum/protected/Web/Data/data_desc.json +++ b/gui/baculum/protected/Web/Data/data_desc.json @@ -1288,37 +1288,37 @@ "Required": false, "ValueType": "str", "DefaultValue": 0, - "FieldType": "TextBox" + "FieldType": "MultiTextBox" }, "WildDir": { "Required": false, "ValueType": "str", "DefaultValue": 0, - "FieldType": "TextBox" + "FieldType": "MultiTextBox" }, "WildFile": { "Required": false, "ValueType": "str", "DefaultValue": 0, - "FieldType": "TextBox" + "FieldType": "MultiTextBox" }, "Regex": { "Required": false, "ValueType": "str", "DefaultValue": 0, - "FieldType": "TextBox" + "FieldType": "MultiTextBox" }, "RegexDir": { "Required": false, "ValueType": "str", "DefaultValue": 0, - "FieldType": "TextBox" + "FieldType": "MultiTextBox" }, "RegexFile": { "Required": false, "ValueType": "str", "DefaultValue": 0, - "FieldType": "TextBox" + "FieldType": "MultiTextBox" }, "Exclude": { "Required": false, diff --git a/gui/baculum/protected/Web/Pages/JobHistoryView.page b/gui/baculum/protected/Web/Pages/JobHistoryView.page index d8d2d995e..12cea7fcb 100644 --- a/gui/baculum/protected/Web/Pages/JobHistoryView.page +++ b/gui/baculum/protected/Web/Pages/JobHistoryView.page @@ -23,6 +23,7 @@ Text="<%[ Configure fileset ]%>" Visible="<%=!empty($_SESSION['dir'])%>" OnClick="loadFileSetConfig" + CommandParameter="show" /> RepeaterDirectives->dataBind(); } - public function createDirectiveElement($sender, $param) { - $load_values = $this->getLoadValues(); - for ($i = 0; $i < count($this->directive_types); $i++) { - $control = $this->getChildControl($param->Item, $this->directive_types[$i]); - if (is_object($control)) { - $control->setHost($param->Item->Data['host']); - $control->setComponentType($param->Item->Data['component_type']); - $control->setComponentName($param->Item->Data['component_name']); - $control->setResourceType($param->Item->Data['resource_type']); - $control->setResourceName($param->Item->Data['resource_name']); - $control->setDirectiveName($param->Item->Data['directive_name']); - $control->setDirectiveValue($param->Item->Data['directive_value']); - $control->setDefaultValue($param->Item->Data['default_value']); - $control->setRequired($param->Item->Data['required']); - $control->setData($param->Item->Data['data']); - $control->setResource($param->Item->Data['resource']); - $control->setLabel($param->Item->Data['label']); - $control->setInConfig($param->Item->Data['in_config']); - $show_all_directives = ($param->Item->Data['in_config'] || !$load_values || $this->getShowAllDirectives()); - $control->setShow($show_all_directives); - $control->setResourceNames($this->resource_names); - break; - } - } - for ($i = 0; $i < count($this->directive_list_types); $i++) { - $control = $this->getChildControl($param->Item, $this->directive_list_types[$i]); - if (is_object($control)) { - $control->setHost($param->Item->Data['host']); - $control->setComponentType($param->Item->Data['component_type']); - $control->setComponentName($param->Item->Data['component_name']); - $control->setResourceType($param->Item->Data['resource_type']); - $control->setResourceName($param->Item->Data['resource_name']); - $control->setDirectiveName($param->Item->Data['directive_name']); - $control->setData($param->Item->Data['directive_value']); - $control->setLoadValues($this->getLoadValues()); - $control->setResourceNames($this->resource_names); - $control->setShow(true); - $control->raiseEvent('OnDirectiveListLoad', $this, null); - } - } - } - - public function saveResource($sender, $param) { $directives = array(); $host = $this->getHost(); diff --git a/gui/baculum/protected/Web/Portlets/ConfigListTemplate.php b/gui/baculum/protected/Web/Portlets/ConfigListTemplate.php index db09f6d85..d1ad390aa 100644 --- a/gui/baculum/protected/Web/Portlets/ConfigListTemplate.php +++ b/gui/baculum/protected/Web/Portlets/ConfigListTemplate.php @@ -3,7 +3,7 @@ * Bacula(R) - The Network Backup Solution * Baculum - Bacula web interface * - * Copyright (C) 2013-2016 Kern Sibbald + * Copyright (C) 2013-2019 Kern Sibbald * * The main author of Baculum is Marcin Haba. * The original author of Bacula is Kern Sibbald, with contributions @@ -20,9 +20,9 @@ * Bacula(R) is a registered trademark of Kern Sibbald. */ -Prado::using('System.Web.UI.TTemplateControl'); +Prado::using('Application.Web.Portlets.DirectiveControlTemplate'); -class ConfigListTemplate extends TTemplateControl { +class ConfigListTemplate extends DirectiveControlTemplate { public function getChildControl($parent, $type) { $child_control = null; diff --git a/gui/baculum/protected/Web/Portlets/DirectiveControlTemplate.php b/gui/baculum/protected/Web/Portlets/DirectiveControlTemplate.php new file mode 100644 index 000000000..8ec576f28 --- /dev/null +++ b/gui/baculum/protected/Web/Portlets/DirectiveControlTemplate.php @@ -0,0 +1,42 @@ +getPage()->IsCallBack) { + if (method_exists($this->getPage()->CallBackEventTarget, 'getCommandParameter')) { + $command_param = $this->getPage()->CallBackEventTarget->getCommandParameter(); + } + } elseif ($this->getPage()->IsPostBack) { + if (method_exists($this->getPage()->PostBackEventTarget, 'getCommandParameter')) { + $command_param = $this->getPage()->PostBackEventTarget->getCommandParameter(); + } + } + return $command_param; + } + +} +?> diff --git a/gui/baculum/protected/Web/Portlets/DirectiveFileSet.php b/gui/baculum/protected/Web/Portlets/DirectiveFileSet.php index ee85e8c08..6b73d9d76 100644 --- a/gui/baculum/protected/Web/Portlets/DirectiveFileSet.php +++ b/gui/baculum/protected/Web/Portlets/DirectiveFileSet.php @@ -40,11 +40,15 @@ class DirectiveFileSet extends DirectiveListTemplate { 'DirectiveInteger' ); + private $directive_list_types = array( + 'DirectiveMultiTextBox' + ); + private $directive_inc_exc_types = array( 'DirectiveTextBox' ); - public function loadConfig($sender, $param) { + public function loadConfig() { $component_type = $this->getComponentType(); $component_name = $this->getComponentType(); $resource_type = $this->getResourceType(); @@ -188,6 +192,11 @@ class DirectiveFileSet extends DirectiveListTemplate { $directive_value = false; } } + + if ($field_type === 'MultiTextBox') { + $directive_value = array($directive_value); + } + if (!is_array($directive_value)) { $directive_value = array($directive_value); } @@ -244,14 +253,18 @@ class DirectiveFileSet extends DirectiveListTemplate { // value the same as default value, skip it continue; } - if (!isset($counter, $directive_values['Include'][$counter])) { - $directive_values['Include'][$counter] = array('Options' => array()); + if (!key_exists($counter, $directive_values['Include'])) { + $directive_values['Include'][$counter] = array(); } - if (!isset($directive_values['Include'][$counter]['Options'][$index])) { + if (!key_exists('Options', $directive_values['Include'][$counter])) { + $directive_values['Include'][$counter]['Options'] = array(); + } + if (!key_exists($index, $directive_values['Include'][$counter]['Options'])) { $directive_values['Include'][$counter]['Options'][$index] = array(); } $directive_values['Include'][$counter]['Options'][$index][$directive_name] = $directive_value; } + $controls = $value->RepeaterFileSetInclude->findControlsByType($this->directive_types[$i]); for ($j = 0; $j < count($controls); $j++) { $directive_name = $controls[$j]->getDirectiveName(); @@ -260,16 +273,36 @@ class DirectiveFileSet extends DirectiveListTemplate { // Include file directive removed continue; } - if (!key_exists('Include', $directive_values)) { - $directive_values['Include'] = array(); - } - if (!isset($directive_values['Include'][$counter])) { + if (!key_exists($counter, $directive_values['Include'])) { $directive_values['Include'][$counter] = array(); } if (!key_exists($directive_name, $directive_values['Include'][$counter])) { $directive_values['Include'][$counter][$directive_name] = array(); } - array_push($directive_values['Include'][$counter][$directive_name], $directive_value); + $directive_values['Include'][$counter][$directive_name][] = $directive_value; + } + } + for ($i = 0; $i < count($this->directive_list_types); $i++) { + $controls = $value->RepeaterFileSetOptions->findControlsByType($this->directive_list_types[$i]); + for ($j = 0; $j < count($controls); $j++) { + $directive_name = $controls[$j]->getDirectiveName(); + $directive_value = array_filter($controls[$j]->getDirectiveValue()); + sort($directive_value); + $index = $controls[$j]->getGroupName(); + if (count($directive_value) == 0) { + // option not set or removed + continue; + } + if (!key_exists($counter, $directive_values['Include'])) { + $directive_values['Include'][$counter] = array(); + } + if (!key_exists('Options', $directive_values['Include'][$counter])) { + $directive_values['Include'][$counter]['Options'] = array(); + } + if (!key_exists($index, $directive_values['Include'][$counter]['Options'])) { + $directive_values['Include'][$counter]['Options'][$index] = array(); + } + $directive_values['Include'][$counter]['Options'][$index][$directive_name] = $directive_value; } } $counter++; @@ -324,7 +357,7 @@ class DirectiveFileSet extends DirectiveListTemplate { $data = $this->getDirectiveValue(); $data['Include'][] = array(); $this->setData($data); - $this->loadConfig(null, null); + $this->loadConfig(); } public function newIncludeFile($sender, $param) { @@ -336,7 +369,7 @@ class DirectiveFileSet extends DirectiveListTemplate { } $data['Include'][$inc_index]['File'][$file_index] = ''; $this->setData($data); - $this->loadConfig(null, null); + $this->loadConfig(); } public function newExcludeFile($sender, $param) { @@ -349,7 +382,7 @@ class DirectiveFileSet extends DirectiveListTemplate { } $data['Exclude']['File'][$file_index] = ''; $this->setData($data); - $this->loadConfig(null, null); + $this->loadConfig(); } public function newIncludeOptions($sender, $param) { @@ -362,7 +395,7 @@ class DirectiveFileSet extends DirectiveListTemplate { $data['Include'][$inc_index]['Options'][$opt_index] = array(); $this->SourceTemplateControl->setShowAllDirectives(true); $this->setData($data); - $this->loadConfig(null, null); + $this->loadConfig(); } public function newIncludeExcludeFile($sender, $param) { @@ -370,8 +403,11 @@ class DirectiveFileSet extends DirectiveListTemplate { $inc_index = $this->RepeaterFileSetIncludes->getItems()->getCount() - 1; $inc_exc = $param->getCallbackParameter(); if (property_exists($inc_exc, 'Include') && is_array($inc_exc->Include)) { - if (!key_exists($inc_index, $data['Include']) || !key_exists('File', $data['Include'][$inc_index])) { - $data['Include'][$inc_index] = array('File' => array()); + if (!key_exists($inc_index, $data['Include'])){ + $data['Include'][$inc_index] = array(); + } + if (!key_exists('File', $data['Include'][$inc_index])) { + $data['Include'][$inc_index]['File'] = array(); } for ($i = 0; $i < count($inc_exc->Include); $i++) { if (in_array($inc_exc->Include[$i], $data['Include'][$inc_index]['File'])) { @@ -383,7 +419,7 @@ class DirectiveFileSet extends DirectiveListTemplate { } if (property_exists($inc_exc, 'Exclude') && is_array($inc_exc->Exclude)) { if (!key_exists('File', $data['Exclude'])) { - $data['Exclude'] = array('File' => array()); + $data['Exclude']['File'] = array(); } for ($i = 0; $i < count($inc_exc->Exclude); $i++) { if (in_array($inc_exc->Exclude[$i], $data['Exclude']['File'])) { @@ -394,7 +430,7 @@ class DirectiveFileSet extends DirectiveListTemplate { } } $this->setData($data); - $this->loadConfig(null, null); + $this->loadConfig(); } } ?> diff --git a/gui/baculum/protected/Web/Portlets/DirectiveListTemplate.php b/gui/baculum/protected/Web/Portlets/DirectiveListTemplate.php index 2b08f7e69..18d17feaf 100644 --- a/gui/baculum/protected/Web/Portlets/DirectiveListTemplate.php +++ b/gui/baculum/protected/Web/Portlets/DirectiveListTemplate.php @@ -36,6 +36,7 @@ class DirectiveListTemplate extends ConfigListTemplate implements IActiveControl const DATA = 'Data'; const LOAD_VALUES = 'LoadValues'; const SHOW = 'Show'; + const GROUP_NAME = 'GroupName'; public $display_directive; @@ -154,5 +155,13 @@ class DirectiveListTemplate extends ConfigListTemplate implements IActiveControl public function setShow($show) { $this->setViewState(self::SHOW, $show); } + + public function getGroupName() { + return $this->getViewState(self::GROUP_NAME); + } + + public function setGroupName($group_name) { + $this->setViewState(self::GROUP_NAME, $group_name); + } } ?> diff --git a/gui/baculum/protected/Web/Portlets/DirectiveMultiTextBox.php b/gui/baculum/protected/Web/Portlets/DirectiveMultiTextBox.php new file mode 100644 index 000000000..675705954 --- /dev/null +++ b/gui/baculum/protected/Web/Portlets/DirectiveMultiTextBox.php @@ -0,0 +1,89 @@ +getCmdParam() !== 'add_multitextbox') { + $this->loadConfig(); + } + } + + public function getDirectiveValue() { + $values = array(); + $controls = $this->MultiTextBoxRepeater->getItems(); + foreach ($controls as $control) { + $val = $control->Directive->getText(); + if (!empty($val)) { + $values[] = $val; + } else { + $values[] = null; + } + } + return $values; + } + + public function loadConfig() { + $load_values = $this->getLoadValues(); + $host = $this->getHost(); + $component_type = $this->getComponentType(); + $component_name = $this->getComponentName(); + $resource_type = $this->getResourceType(); + $resource_name = $this->getResourceName(); + $directive_name = $this->getDirectiveName(); + + $data = $this->getData(); + if (!is_array($data) ) { + $data = array($data); + } + $values = array(); + for ($i = 0; $i < count($data); $i++) { + $values[] = array( + 'directive_value' => $data[$i], + 'label' => $this->getDirectiveName(), + 'show' => $this->getShow() + ); + } + $this->MultiTextBoxRepeater->DataSource = $values; + $this->MultiTextBoxRepeater->dataBind(); + } + + public function createMultiTextBoxElement($sender, $param) { + $param->Item->Label->Text = $param->Item->Data['label']; + $param->Item->Directive->Text = $param->Item->Data['directive_value']; + + } + + public function addField($sender, $param) { + $data = $this->getDirectiveValue(); + $data[] = ''; + $this->setData($data); + $this->loadConfig(); + } +} +?> diff --git a/gui/baculum/protected/Web/Portlets/DirectiveMultiTextBox.tpl b/gui/baculum/protected/Web/Portlets/DirectiveMultiTextBox.tpl new file mode 100644 index 000000000..84e647a9b --- /dev/null +++ b/gui/baculum/protected/Web/Portlets/DirectiveMultiTextBox.tpl @@ -0,0 +1,22 @@ + + +
+
:
+
+ + + + + + +
+
+
+
diff --git a/gui/baculum/protected/Web/Portlets/DirectiveRenderer.php b/gui/baculum/protected/Web/Portlets/DirectiveRenderer.php index d064c0ad0..160960c00 100644 --- a/gui/baculum/protected/Web/Portlets/DirectiveRenderer.php +++ b/gui/baculum/protected/Web/Portlets/DirectiveRenderer.php @@ -31,6 +31,7 @@ Prado::using('Application.Web.Portlets.DirectiveInteger'); Prado::using('Application.Web.Portlets.DirectiveListBox'); Prado::using('Application.Web.Portlets.DirectiveSize'); Prado::using('Application.Web.Portlets.DirectiveTextBox'); +Prado::using('Application.Web.Portlets.DirectiveMultiTextBox'); Prado::using('Application.Web.Portlets.DirectiveTimePeriod'); Prado::using('Application.Web.Portlets.DirectiveRunscript'); Prado::using('Application.Web.Portlets.DirectiveMessages'); @@ -54,7 +55,8 @@ class DirectiveRenderer extends DirectiveListTemplate implements IItemDataRender 'DirectiveFileSet', 'DirectiveSchedule', 'DirectiveMessages', - 'DirectiveRunscript' + 'DirectiveRunscript', + 'DirectiveMultiTextBox' ); public $resource_names = array(); @@ -99,9 +101,16 @@ class DirectiveRenderer extends DirectiveListTemplate implements IItemDataRender $control->setData($data['directive_value']); $control->setLoadValues($this->SourceTemplateControl->getLoadValues()); $control->setResourceNames($this->SourceTemplateControl->getResourceNames()); - $control->setShow(true); + $control->setShow($data['show']); + $control->setGroupName($data['group_name']); $this->getControls()->add($control); - $control->raiseEvent('OnDirectiveListLoad', $this, null); + if (!$this->getPage()->IsCallBack || $this->getPage()->getCallbackEventParameter() === 'show_all_directives' || $this->getCmdParam() === 'show') { + /* + * List types should be loaded only by load request, not by callback request. + * Otherwise OnLoad above is called during callback and overwrites data in controls. + */ + $control->raiseEvent('OnDirectiveListLoad', $this, null); + } } } diff --git a/gui/baculum/protected/Web/Portlets/DirectiveTemplate.php b/gui/baculum/protected/Web/Portlets/DirectiveTemplate.php index 6e458abf9..b103a869a 100644 --- a/gui/baculum/protected/Web/Portlets/DirectiveTemplate.php +++ b/gui/baculum/protected/Web/Portlets/DirectiveTemplate.php @@ -20,11 +20,11 @@ * Bacula(R) is a registered trademark of Kern Sibbald. */ -Prado::using('System.Web.UI.TTemplateControl'); Prado::using('System.Web.UI.ActiveControls.TActiveControlAdapter'); +Prado::using('Application.Web.Portlets.DirectiveControlTemplate'); Prado::using('Application.Web.Portlets.IDirectiveField'); -class DirectiveTemplate extends TTemplateControl implements IDirectiveField, IActiveControl { +class DirectiveTemplate extends DirectiveControlTemplate implements IDirectiveField, IActiveControl { const HOST = 'Host'; const COMPONENT_TYPE = 'ComponentType'; @@ -81,20 +81,6 @@ class DirectiveTemplate extends TTemplateControl implements IDirectiveField, IAc } } - public function getCmdParam() { - $command_param = null; - if ($this->getPage()->IsCallBack) { - if (method_exists($this->getPage()->CallBackEventTarget, 'getCommandParameter')) { - $command_param = $this->getPage()->CallBackEventTarget->getCommandParameter(); - } - } elseif ($this->getPage()->IsPostBack) { - if (method_exists($this->getPage()->PostBackEventTarget, 'getCommandParameter')) { - $command_param = $this->getPage()->PostBackEventTarget->getCommandParameter(); - } - } - return $command_param; - } - public function onLoad($param) { parent::onLoad($param); if (!$this->getIsDirectiveCreated()) { -- 2.47.3