From 5367dfdb5a0e5d675bc1e089f0d89c6ac5d5b724 Mon Sep 17 00:00:00 2001 From: Daniel Seifert Date: Fri, 25 Jun 2021 15:33:57 +0200 Subject: [PATCH] #10782: implement form manager for task specific form elements --- composer.json | 3 +- src/Application/Model/ActionBase.php | 49 +++++++++++++++++++ src/Application/Model/Configuration.php | 13 +++-- .../Model/Exceptions/DataWizardException.php | 4 +- .../Model/Exceptions/DebugException.php | 2 +- .../Exceptions/InputUnvalidException.php | 46 +++++++++++++++++ .../NoSuitableRendererException.php | 2 +- .../Model/Exceptions/RenderException.php | 4 +- .../Model/Exceptions/TaskException.php | 3 +- src/Application/Model/ExportBase.php | 49 +++++++++++++++++++ src/Application/Model/Exports/KeyFigures.php | 46 +++++++++++++++-- src/Application/Model/QueryBase.php | 17 +++++++ .../views/admin/de/d3DataWizard_lang.php | 2 + .../views/admin/tpl/d3ActionWizard.tpl | 18 +++++-- .../views/admin/tpl/d3ExportWizard.tpl | 18 +++++-- 15 files changed, 253 insertions(+), 23 deletions(-) create mode 100644 src/Application/Model/Exceptions/InputUnvalidException.php diff --git a/composer.json b/composer.json index 26c80fa..a5e4a97 100644 --- a/composer.json +++ b/composer.json @@ -28,7 +28,8 @@ "php": ">=7.1", "oxid-esales/oxideshop-ce": "6.3 - 6.8", "league/csv": "^9.0", - "mathieuviossat/arraytotexttable": "^1.0" + "mathieuviossat/arraytotexttable": "^1.0", + "form-manager/form-manager": "^6.1" }, "extra": { "oxideshop": { diff --git a/src/Application/Model/ActionBase.php b/src/Application/Model/ActionBase.php index 20c9e43..7044123 100644 --- a/src/Application/Model/ActionBase.php +++ b/src/Application/Model/ActionBase.php @@ -15,6 +15,10 @@ declare(strict_types=1); namespace D3\DataWizard\Application\Model; +use D3\DataWizard\Application\Model\Exceptions\InputUnvalidException; +use FormManager\Inputs\Checkbox; +use FormManager\Inputs\Input; +use FormManager\Inputs\Radio; use OxidEsales\Eshop\Core\DatabaseProvider; use OxidEsales\Eshop\Core\Exception\DatabaseConnectionException; use OxidEsales\Eshop\Core\Exception\DatabaseErrorException; @@ -22,6 +26,8 @@ use OxidEsales\Eshop\Core\Registry; abstract class ActionBase implements QueryBase { + protected $formElements = []; + /** * @return string */ @@ -36,6 +42,15 @@ abstract class ActionBase implements QueryBase */ public function run() { + if ($this->hasFormElements()) { + /** @var Input $element */ + foreach ($this->getFormElements() as $element) { + if (false === $element->isValid()) { + throw oxNew(InputUnvalidException::class, $this, $element); + } + } + } + $this->executeAction( $this->getQuery() ); } @@ -81,4 +96,38 @@ abstract class ActionBase implements QueryBase { return "D3_DATAWIZARD_ACTION_SUBMIT"; } + + /** + * @param Input $input + */ + public function registerFormElement(Input $input) + { + switch (get_class($input)) { + case Radio::class: + case Checkbox::class: + $input->setTemplate('

{{ input }} {{ label }}

'); + $input->setAttribute('class', 'form-check-input'); + break; + default: + $input->setTemplate('

{{ label }} {{ input }}

'); + $input->setAttribute('class', 'form-control'); + } + $this->formElements[] = $input; + } + + /** + * @return bool + */ + public function hasFormElements(): bool + { + return (bool) count($this->formElements); + } + + /** + * @return array + */ + public function getFormElements(): array + { + return $this->formElements; + } } \ No newline at end of file diff --git a/src/Application/Model/Configuration.php b/src/Application/Model/Configuration.php index c565431..991201a 100644 --- a/src/Application/Model/Configuration.php +++ b/src/Application/Model/Configuration.php @@ -16,6 +16,7 @@ declare(strict_types=1); namespace D3\DataWizard\Application\Model; use D3\DataWizard\Application\Model\Actions\FixArtextendsItems; +use D3\DataWizard\Application\Model\Exceptions\DataWizardException; use D3\DataWizard\Application\Model\Exports\InactiveCategories; use D3\DataWizard\Application\Model\Exports\KeyFigures; use OxidEsales\Eshop\Core\Registry; @@ -53,7 +54,7 @@ class Configuration */ public function registerAction($group, ActionBase $action) { - $this->actions[$group][md5(serialize($action))] = $action; + $this->actions[$group][md5(get_class($action))] = $action; } /** @@ -62,7 +63,7 @@ class Configuration */ public function registerExport($group, ExportBase $export) { - $this->exports[$group][md5(serialize($export))] = $export; + $this->exports[$group][md5(get_class($export))] = $export; } /** @@ -162,6 +163,12 @@ class Configuration */ public function getExportById($id) : ExportBase { - return $this->getAllExports()[$id]; + $allExports = $this->getAllExports(); + + if (false == $allExports[$id]) { + throw oxNew(DataWizardException::class, 'no export with id '.$id); + } + + return $allExports[$id]; } } diff --git a/src/Application/Model/Exceptions/DataWizardException.php b/src/Application/Model/Exceptions/DataWizardException.php index 564f277..41f7c13 100644 --- a/src/Application/Model/Exceptions/DataWizardException.php +++ b/src/Application/Model/Exceptions/DataWizardException.php @@ -15,6 +15,8 @@ declare(strict_types=1); namespace D3\DataWizard\Application\Model\Exceptions; -interface DataWizardException +use OxidEsales\Eshop\Core\Exception\StandardException; + +class DataWizardException extends StandardException { } \ No newline at end of file diff --git a/src/Application/Model/Exceptions/DebugException.php b/src/Application/Model/Exceptions/DebugException.php index 330dc88..ba703b5 100644 --- a/src/Application/Model/Exceptions/DebugException.php +++ b/src/Application/Model/Exceptions/DebugException.php @@ -19,7 +19,7 @@ use Exception; use OxidEsales\Eshop\Core\Exception\StandardException; use OxidEsales\Eshop\Core\Registry; -class DebugException extends StandardException implements DataWizardException +class DebugException extends DataWizardException { public function __construct($sMessage = "not set", $iCode = 0, Exception $previous = null ) { diff --git a/src/Application/Model/Exceptions/InputUnvalidException.php b/src/Application/Model/Exceptions/InputUnvalidException.php new file mode 100644 index 0000000..c5a80da --- /dev/null +++ b/src/Application/Model/Exceptions/InputUnvalidException.php @@ -0,0 +1,46 @@ + + * @link https://www.oxidmodule.com + */ + +declare(strict_types=1); + +namespace D3\DataWizard\Application\Model\Exceptions; + +use D3\DataWizard\Application\Model\QueryBase; +use Exception; +use FormManager\Inputs\Input; +use OxidEsales\Eshop\Core\Exception\StandardException; + +class InputUnvalidException extends DataWizardException +{ + /** @var QueryBase */ + public $task; + + public function __construct( QueryBase $task, Input $inputElement, $iCode = 0, Exception $previous = null ) + { + $messages = []; + foreach ($inputElement->getError()->getIterator() as $item) { + $messages[] = $inputElement->label->innerHTML.' -> '.$item->getMessage(); + } + + $sMessage = implode( + ' - ', + [ + $task->getTitle(), + implode(', ', $messages) + ] + ); + parent::__construct( $sMessage, $iCode, $previous ); + + $this->task = $task; + } +} \ No newline at end of file diff --git a/src/Application/Model/Exceptions/NoSuitableRendererException.php b/src/Application/Model/Exceptions/NoSuitableRendererException.php index 0fc9b23..2ca2981 100644 --- a/src/Application/Model/Exceptions/NoSuitableRendererException.php +++ b/src/Application/Model/Exceptions/NoSuitableRendererException.php @@ -19,7 +19,7 @@ use Exception; use OxidEsales\Eshop\Core\Exception\StandardException; use OxidEsales\Eshop\Core\Registry; -class NoSuitableRendererException extends StandardException implements DataWizardException +class NoSuitableRendererException extends DataWizardException { public function __construct($sMessage = "not set", $iCode = 0, Exception $previous = null ) { diff --git a/src/Application/Model/Exceptions/RenderException.php b/src/Application/Model/Exceptions/RenderException.php index 23ef556..7745bbe 100644 --- a/src/Application/Model/Exceptions/RenderException.php +++ b/src/Application/Model/Exceptions/RenderException.php @@ -15,8 +15,6 @@ declare(strict_types=1); namespace D3\DataWizard\Application\Model\Exceptions; -use OxidEsales\Eshop\Core\Exception\StandardException; - -class RenderException extends StandardException implements DataWizardException +class RenderException extends DataWizardException { } \ No newline at end of file diff --git a/src/Application/Model/Exceptions/TaskException.php b/src/Application/Model/Exceptions/TaskException.php index 122abec..dd2ecfe 100644 --- a/src/Application/Model/Exceptions/TaskException.php +++ b/src/Application/Model/Exceptions/TaskException.php @@ -17,9 +17,8 @@ namespace D3\DataWizard\Application\Model\Exceptions; use D3\DataWizard\Application\Model\QueryBase; use Exception; -use OxidEsales\Eshop\Core\Exception\StandardException; -class TaskException extends StandardException implements DataWizardException +class TaskException extends DataWizardException { /** @var QueryBase */ public $task; diff --git a/src/Application/Model/ExportBase.php b/src/Application/Model/ExportBase.php index 08b8ea1..4e18c0b 100644 --- a/src/Application/Model/ExportBase.php +++ b/src/Application/Model/ExportBase.php @@ -15,11 +15,15 @@ declare(strict_types=1); namespace D3\DataWizard\Application\Model; +use D3\DataWizard\Application\Model\Exceptions\InputUnvalidException; use D3\DataWizard\Application\Model\ExportRenderer\RendererBridge; use D3\ModCfg\Application\Model\d3filesystem; use D3\ModCfg\Application\Model\Exception\d3_cfg_mod_exception; use D3\ModCfg\Application\Model\Exception\d3ShopCompatibilityAdapterException; use Doctrine\DBAL\DBALException; +use FormManager\Inputs\Checkbox; +use FormManager\Inputs\Input; +use FormManager\Inputs\Radio; use OxidEsales\Eshop\Core\DatabaseProvider; use OxidEsales\Eshop\Core\Exception\DatabaseConnectionException; use OxidEsales\Eshop\Core\Exception\DatabaseErrorException; @@ -28,6 +32,8 @@ use OxidEsales\Eshop\Core\Registry; abstract class ExportBase implements QueryBase { + protected $formElements = []; + /** * @return string */ @@ -50,6 +56,15 @@ abstract class ExportBase implements QueryBase */ public function run($format = RendererBridge::FORMAT_CSV) { + if ($this->hasFormElements()) { + /** @var Input $element */ + foreach ($this->getFormElements() as $element) { + if (false === $element->isValid()) { + throw oxNew(InputUnvalidException::class, $this, $element); + } + } + } + [ $rows, $fieldNames ] = $this->getExportData( $this->getQuery() ); $content = $this->renderContent($rows, $fieldNames, $format); @@ -160,4 +175,38 @@ abstract class ExportBase implements QueryBase return [ $rows, $fieldNames ]; } + + /** + * @param Input $input + */ + public function registerFormElement(Input $input) + { + switch (get_class($input)) { + case Radio::class: + case Checkbox::class: + $input->setTemplate('

{{ input }} {{ label }}

'); + $input->setAttribute('class', 'form-check-input'); + break; + default: + $input->setTemplate('

{{ label }} {{ input }}

'); + $input->setAttribute('class', 'form-control'); + } + $this->formElements[] = $input; + } + + /** + * @return bool + */ + public function hasFormElements(): bool + { + return (bool) count($this->formElements); + } + + /** + * @return array + */ + public function getFormElements(): array + { + return $this->formElements; + } } \ No newline at end of file diff --git a/src/Application/Model/Exports/KeyFigures.php b/src/Application/Model/Exports/KeyFigures.php index 831b66e..3eec246 100644 --- a/src/Application/Model/Exports/KeyFigures.php +++ b/src/Application/Model/Exports/KeyFigures.php @@ -16,15 +16,45 @@ namespace D3\DataWizard\Application\Model\Exports; use D3\DataWizard\Application\Model\ExportBase; +use FormManager\Inputs\Date; use OxidEsales\Eshop\Application\Model\Order; use OxidEsales\Eshop\Core\Registry; +use FormManager\Factory as FormFactory; class KeyFigures extends ExportBase { + const STARTDATE_NAME = 'startdate'; + const ENDDATE_NAME = 'enddate'; + /** * Shopkennzahlen */ + public function __construct() + { + /** @var Date $startDate */ + $startDateValue = Registry::getRequest()->getRequestEscapedParameter(self::STARTDATE_NAME); + $startDate = FormFactory::date( + Registry::getLang()->translateString('D3_DATAWIZARD_EXPORTS_KEYFIGURES_FIELD_STARTDATE'), + [ + 'name' => self::STARTDATE_NAME, + 'value' => $startDateValue + ] + ); + $this->registerFormElement($startDate); + + /** @var Date $endDate */ + $endDateValue = Registry::getRequest()->getRequestEscapedParameter(self::ENDDATE_NAME); + $endDate = FormFactory::date( + Registry::getLang()->translateString('D3_DATAWIZARD_EXPORTS_KEYFIGURES_FIELD_ENDDATE'), + [ + 'name' => self::ENDDATE_NAME, + 'value' => $endDateValue + ] + ); + $this->registerFormElement($endDate); + } + /** * @return string */ @@ -43,19 +73,25 @@ class KeyFigures extends ExportBase $basketsTitle = Registry::getLang()->translateString('D3_DATAWIZARD_EXPORTS_KEYFIGURES_BASKETSIZE'); $monthTitle = Registry::getLang()->translateString('D3_DATAWIZARD_EXPORTS_KEYFIGURES_MONTH'); + $startDateValue = Registry::getRequest()->getRequestEscapedParameter(self::STARTDATE_NAME) ?: '1970-01-01'; + $endDateValue = Registry::getRequest()->getRequestEscapedParameter(self::ENDDATE_NAME) ?: date('Y-m-d'); + return [ 'SELECT DATE_FORMAT(oo.oxorderdate, "%Y-%m") as :monthTitle, FORMAT(COUNT(oo.oxid), 0) AS :ordersTitle, FORMAT(SUM(oo.OXTOTALBRUTSUM / oo.oxcurrate) / COUNT(oo.oxid), 2) as :basketsTitle FROM '.$orderTable.' AS oo - GROUP BY :monthTitle - ORDER BY :monthTitle DESC + WHERE oo.oxorderdate >= :startDate AND oo.oxorderdate <= :endDate + GROUP BY DATE_FORMAT(oo.oxorderdate, "%Y-%m") + ORDER BY DATE_FORMAT(oo.oxorderdate, "%Y-%m") DESC LIMIT 30', [ - 'monthTitle' => $monthTitle, - 'ordersTitle' => $ordersTitle, - 'basketsTitle' => $basketsTitle + 'startDate' => $startDateValue, + 'endDate' => $endDateValue, + 'monthTitle' => $monthTitle, + 'ordersTitle' => $ordersTitle, + 'basketsTitle' => $basketsTitle ] ]; } diff --git a/src/Application/Model/QueryBase.php b/src/Application/Model/QueryBase.php index c17b593..c34a8a3 100644 --- a/src/Application/Model/QueryBase.php +++ b/src/Application/Model/QueryBase.php @@ -15,6 +15,8 @@ declare(strict_types=1); namespace D3\DataWizard\Application\Model; +use FormManager\Inputs\Input; + interface QueryBase { public function run(); @@ -38,4 +40,19 @@ interface QueryBase * @return array [string $query, array $parameters] */ public function getQuery() : array; + + /** + * @param Input $input + */ + public function registerFormElement(Input $input); + + /** + * @return bool + */ + public function hasFormElements(): bool; + + /** + * @return array + */ + public function getFormElements(): array; } \ No newline at end of file diff --git a/src/Application/views/admin/de/d3DataWizard_lang.php b/src/Application/views/admin/de/d3DataWizard_lang.php index e78d7f9..22fb0f6 100644 --- a/src/Application/views/admin/de/d3DataWizard_lang.php +++ b/src/Application/views/admin/de/d3DataWizard_lang.php @@ -55,6 +55,8 @@ $aLang = array( 'D3_DATAWIZARD_EXPORTS_INACTIVECATEGORIES_COUNT' => 'Anzahl', 'D3_DATAWIZARD_EXPORTS_KEYFIGURES' => 'Bestellungskennzahlen nach Monat', + 'D3_DATAWIZARD_EXPORTS_KEYFIGURES_FIELD_STARTDATE'=> 'Startdatum (optional)', + 'D3_DATAWIZARD_EXPORTS_KEYFIGURES_FIELD_ENDDATE' => 'Enddatum (optional)', 'D3_DATAWIZARD_EXPORTS_KEYFIGURES_ORDERSPERMONTH' => 'Bestellungen pro Monat', 'D3_DATAWIZARD_EXPORTS_KEYFIGURES_BASKETSIZE' => 'Warenkorbhöhe', 'D3_DATAWIZARD_EXPORTS_KEYFIGURES_MONTH' => 'Monat', diff --git a/src/Application/views/admin/tpl/d3ActionWizard.tpl b/src/Application/views/admin/tpl/d3ActionWizard.tpl index efe3469..9c6d0fa 100644 --- a/src/Application/views/admin/tpl/d3ActionWizard.tpl +++ b/src/Application/views/admin/tpl/d3ActionWizard.tpl @@ -23,6 +23,10 @@ h5.card-header { font-size: 1.1rem; } + .formElements label { + display: inline-block; + margin: .5rem 0; + } [{capture name="d3script"}][{strip}] @@ -72,9 +76,17 @@ [{$action->getTitle()}]
-

- [{$action->getDescription()}] -

+ [{if $action->getDescription()}] +

+ [{$action->getDescription()}] +

+ [{/if}] + + [{if $action->hasFormElements()}] + [{foreach from=$action->getFormElements() item="formElement"}] + [{$formElement}] + [{/foreach}] + [{/if}]