From edd7d33587aff41f5a7cada36fc92fc4d40bca61 Mon Sep 17 00:00:00 2001 From: Daniel Seifert Date: Wed, 5 May 2021 23:20:42 +0200 Subject: [PATCH 1/4] basics for actions --- .../Controller/Admin/d3ActionWizard.php | 91 +++++++++++ src/Application/Model/ActionBase.php | 142 ++++++++++++++++++ src/Application/Model/Configuration.php | 49 +++++- .../views/admin/de/d3DataWizard_lang.php | 1 + .../views/admin/tpl/d3ActionWizard.tpl | 122 +++++++++++++++ src/menu.xml | 3 +- src/metadata.php | 4 +- 7 files changed, 409 insertions(+), 3 deletions(-) create mode 100644 src/Application/Controller/Admin/d3ActionWizard.php create mode 100644 src/Application/Model/ActionBase.php create mode 100644 src/Application/views/admin/tpl/d3ActionWizard.tpl diff --git a/src/Application/Controller/Admin/d3ActionWizard.php b/src/Application/Controller/Admin/d3ActionWizard.php new file mode 100644 index 0000000..970700f --- /dev/null +++ b/src/Application/Controller/Admin/d3ActionWizard.php @@ -0,0 +1,91 @@ + + * @link https://www.oxidmodule.com + */ + +declare(strict_types=1); + +namespace D3\DataWizard\Application\Controller\Admin; + +use D3\DataWizard\Application\Model\Configuration; +use D3\DataWizard\Application\Model\Exceptions\DataWizardException; +use D3\DataWizard\Application\Model\Exceptions\DebugException; +use D3\ModCfg\Application\Model\d3database; +use D3\ModCfg\Application\Model\Exception\d3_cfg_mod_exception; +use D3\ModCfg\Application\Model\Exception\d3ShopCompatibilityAdapterException; +use Doctrine\DBAL\DBALException; +use OxidEsales\Eshop\Application\Controller\Admin\AdminDetailsController; +use OxidEsales\Eshop\Core\Exception\DatabaseConnectionException; +use OxidEsales\Eshop\Core\Exception\DatabaseErrorException; +use OxidEsales\Eshop\Core\Exception\StandardException; +use OxidEsales\Eshop\Core\Registry; + +class d3ActionWizard extends AdminDetailsController +{ + protected $_sThisTemplate = 'd3ActionWizard.tpl'; + + /** @var Configuration */ + protected $configuration; + + public function __construct() + { + parent::__construct(); + + $this->configuration = oxNew(Configuration::class); + } + + public function getGroups() + { + return $this->configuration->getGroups(); + } + + public function getGroupActions($group) + { + return $this->configuration->getActionsByGroup($group); + } + + /** + * @throws DatabaseConnectionException + * @throws StandardException + * @throws d3ShopCompatibilityAdapterException + * @throws d3_cfg_mod_exception + */ + public function doAction() + { + try { + $id = Registry::getRequest()->getRequestEscapedParameter('actionid'); + $action = $this->configuration->getActionById($id); + + [ $queryString, $parameters ] = $action->getQuery(); + + if (Registry::getConfig()->getConfigParam('d3datawizard_debug')) { + throw oxNew( + DebugException::class, + d3database::getInstance()->getPreparedStatementQuery($queryString, $parameters) + ); + } + + $action->run(); + } catch (DataWizardException|DBALException|DatabaseErrorException $e) { + Registry::getUtilsView()->addErrorToDisplay($e); + } + } + + public function getUserMessages() + { + return null; + } + + public function getHelpURL() + { + return null; + } +} \ No newline at end of file diff --git a/src/Application/Model/ActionBase.php b/src/Application/Model/ActionBase.php new file mode 100644 index 0000000..79b46aa --- /dev/null +++ b/src/Application/Model/ActionBase.php @@ -0,0 +1,142 @@ + + * @link https://www.oxidmodule.com + */ + +declare(strict_types=1); + +namespace D3\DataWizard\Application\Model; + +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 OxidEsales\Eshop\Core\DatabaseProvider; +use OxidEsales\Eshop\Core\Exception\DatabaseConnectionException; +use OxidEsales\Eshop\Core\Exception\DatabaseErrorException; +use OxidEsales\Eshop\Core\Exception\StandardException; +use OxidEsales\Eshop\Core\Registry; + +abstract class ActionBase implements QueryBase +{ + /** + * @return string + */ + public function getDescription() : string + { + return ''; + } + + /** + * @param string $format + * + * @throws DBALException + * @throws DatabaseConnectionException + * @throws DatabaseErrorException + * @throws Exceptions\NoSuitableRendererException + * @throws Exceptions\TaskException + * @throws StandardException + * @throws d3ShopCompatibilityAdapterException + * @throws d3_cfg_mod_exception + */ + public function run() + { + $rowCount = $this->getExportData( $this->getQuery() ); + } + + /** + * @return string + */ + public function getButtonText() : string + { + return "D3_DATAWIZARD_EXPORT_SUBMIT"; + } + + /** + * @param $format + * + * @return ExportRenderer\RendererInterface + * @throws Exceptions\NoSuitableRendererException + */ + public function getRenderer($format): ExportRenderer\RendererInterface + { + return oxNew(RendererBridge::class)->getRenderer($format); + } + + /** + * @param $format + * + * @return string + * @throws Exceptions\NoSuitableRendererException + */ + public function getFileExtension($format): string + { + return $this->getRenderer($format)->getFileExtension(); + } + + /** + * @param $rows + * @param $fieldnames + * @param $format + * + * @return string + * @throws Exceptions\NoSuitableRendererException + */ + public function renderContent($rows, $fieldnames, $format): string + { + $renderer = $this->getRenderer($format); + return $renderer->getContent($rows, $fieldnames); + } + + /** + * @return string + */ + public function getExportFilenameBase() : string + { + return $this->getTitle(); + } + + /** + * @param $format + * + * @return string + * @throws Exceptions\NoSuitableRendererException + */ + public function getExportFileName($format) : string + { + return $this->getExportFilenameBase().'_'.date('Y-m-d_H-i-s').'.'.$this->getFileExtension($format); + } + + /** + * @param array $query + * + * @return int + * @throws DatabaseConnectionException + * @throws DatabaseErrorException + */ + public function getExportData( array $query ): array + { + [ $queryString, $parameters ] = $query; + + $queryString = trim($queryString); + + if ( strtolower( substr( $queryString, 0, 6 ) ) === 'select' ) { + throw oxNew( + Exceptions\TaskException::class, + $this, + Registry::getLang()->translateString( 'D3_DATAWIZARD_ERR_ACTIONSELECT' ) + ); + } + + return DatabaseProvider::getDb( DatabaseProvider::FETCH_MODE_ASSOC )->execute( $queryString, $parameters ); + } +} \ No newline at end of file diff --git a/src/Application/Model/Configuration.php b/src/Application/Model/Configuration.php index a0a210b..4a44dd4 100644 --- a/src/Application/Model/Configuration.php +++ b/src/Application/Model/Configuration.php @@ -28,6 +28,7 @@ class Configuration const GROUP_ORDERS = 'D3_DATAWIZARD_GROUP_ORDERS'; const GROUP_REMARKS = 'D3_DATAWIZARD_GROUP_REMARKS'; + protected $actions = []; protected $exports = []; public function __construct() @@ -43,6 +44,15 @@ class Configuration } } + /** + * @param $group + * @param ActionBase $action + */ + public function registerAction($group, ActionBase $action) + { + $this->actions[$group][md5(serialize($action))] = $action; + } + /** * @param $group * @param ExportBase $export @@ -52,6 +62,14 @@ class Configuration $this->exports[$group][md5(serialize($export))] = $export; } + /** + * @return array + */ + public function getGroupedActions(): array + { + return $this->actions; + } + /** * @return array */ @@ -68,11 +86,30 @@ class Configuration return array_keys($this->exports); } + public function getActionsByGroup($group) + { + return $this->actions[$group]; + } + public function getExportsByGroup($group) { return $this->exports[$group]; } + /** + * @return array + */ + public function getAllActions() : array + { + $all = []; + + foreach ($this->getGroups() as $group) { + $all = array_merge($all, $this->getActionsByGroup($group)); + } + + return $all; + } + /** * @return array */ @@ -87,6 +124,16 @@ class Configuration return $all; } + /** + * @param $id + * + * @return ActionBase + */ + public function getActionById($id) : ActionBase + { + return $this->getAllExports()[$id]; + } + /** * @param $id * @@ -96,4 +143,4 @@ class Configuration { return $this->getAllExports()[$id]; } -} \ 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 2d7538d..c7e6dab 100644 --- a/src/Application/views/admin/de/d3DataWizard_lang.php +++ b/src/Application/views/admin/de/d3DataWizard_lang.php @@ -23,6 +23,7 @@ $aLang = array( 'charset' => 'UTF-8', 'd3mxDataWizard' => ' Data Wizard', 'd3mxDataWizard_Export' => 'Exporte', + 'd3mxDataWizard_Action' => 'Aktionen', 'SHOP_MODULE_GROUP_d3datawizard_general' => 'Grundeinstellungen', 'SHOP_MODULE_d3datawizard_debug' => 'zeigt Abfragen anstatt diese auszuführen', diff --git a/src/Application/views/admin/tpl/d3ActionWizard.tpl b/src/Application/views/admin/tpl/d3ActionWizard.tpl new file mode 100644 index 0000000..2239649 --- /dev/null +++ b/src/Application/views/admin/tpl/d3ActionWizard.tpl @@ -0,0 +1,122 @@ +[{include file="headitem.tpl" title="GENERAL_ADMIN_TITLE"|oxmultilangassign}] + +[{oxstyle include="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css"}] +[{oxscript include="https://code.jquery.com/jquery-3.2.1.slim.min.js"}] +[{oxscript include="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js"}] +[{oxscript include="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js"}] +[{oxstyle include="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.3/css/solid.min.css"}] + + + +[{capture name="d3script"}][{strip}] + function startExport(id, format) { + let elements = document.getElementsByClassName('errorbox'); + for (var i = 0; i < elements.length; i++){ + elements[i].style.display = 'none'; + } + setTimeout(function(){ + document.getElementById('mask').className=''; + document.getElementById('popup2').className='d3loader-2'; + }, 3000); + document.getElementById('mask').className='on'; + document.getElementById('popup2').className='d3loader-2 on'; + document.getElementById('exportid').value = id; + document.getElementById('exportformat').value = format; + document.getElementById('myedit').submit(); + } +[{/strip}][{/capture}] +[{oxscript add=$smarty.capture.d3script}] + +
+ [{$oViewConf->getHiddenSid()}] + + + + + + [{assign var="groups" value=$oView->getGroups()}] + [{if $groups|@count}] +
+ [{foreach from=$oView->getGroups() item="group"}] +
+
+

+ +

+
+ +
+
+
+ [{foreach from=$oView->getGroupActions($group) key="id" item="export"}] +
+
+
+ [{$export->getTitle()}] +
+
+

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

+ +
+ + +
+ +
+
+
+ [{/foreach}] +
+ +
+
+
+
+ + [{/foreach}] +
+ [{else}] + + [{/if}] +
+ +
+
+
+
+
+
+
+
+ +[{include file="d3_cfg_mod_inc.tpl"}] \ No newline at end of file diff --git a/src/menu.xml b/src/menu.xml index 226d1c7..00f03ae 100644 --- a/src/menu.xml +++ b/src/menu.xml @@ -3,6 +3,7 @@ + - \ No newline at end of file + diff --git a/src/metadata.php b/src/metadata.php index 29786e0..9539841 100644 --- a/src/metadata.php +++ b/src/metadata.php @@ -37,12 +37,14 @@ $aModule = [ 'email' => 'support@shopmodule.com', 'url' => 'https://www.oxidmodule.com/', 'controllers' => [ - 'd3ExportWizard' => D3\DataWizard\Application\Controller\Admin\d3ExportWizard::class + 'd3ExportWizard' => D3\DataWizard\Application\Controller\Admin\d3ExportWizard::class, + 'd3ActionWizard' => D3\DataWizard\Application\Controller\Admin\d3ActionWizard::class ], 'extend' => [], 'events' => [], 'templates' => [ 'd3ExportWizard.tpl' => 'd3/datawizard/Application/views/admin/tpl/d3ExportWizard.tpl', + 'd3ActionWizard.tpl' => 'd3/datawizard/Application/views/admin/tpl/d3ActionWizard.tpl', ], 'settings' => [ [ From eff9003b6bb499ad7390eda0460a156fd8b758e0 Mon Sep 17 00:00:00 2001 From: Daniel Seifert Date: Fri, 7 May 2021 09:08:35 +0200 Subject: [PATCH 2/4] add background for action tab --- src/Application/views/admin/tpl/d3ActionWizard.tpl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Application/views/admin/tpl/d3ActionWizard.tpl b/src/Application/views/admin/tpl/d3ActionWizard.tpl index 2239649..953d695 100644 --- a/src/Application/views/admin/tpl/d3ActionWizard.tpl +++ b/src/Application/views/admin/tpl/d3ActionWizard.tpl @@ -14,7 +14,7 @@ font-size: 0.8em; } body { - background-image: linear-gradient(339deg, rgba(47, 47, 47,0.02) 0%, rgba(47, 47, 47,0.02) 42%,transparent 42%, transparent 99%,rgba(17, 17, 17,0.02) 99%, rgba(17, 17, 17,0.02) 100%),linear-gradient(257deg, rgba(65, 65, 65,0.02) 0%, rgba(65, 65, 65,0.02) 11%,transparent 11%, transparent 92%,rgba(53, 53, 53,0.02) 92%, rgba(53, 53, 53,0.02) 100%),linear-gradient(191deg, rgba(5, 5, 5,0.02) 0%, rgba(5, 5, 5,0.02) 1%,transparent 1%, transparent 45%,rgba(19, 19, 19,0.02) 45%, rgba(19, 19, 19,0.02) 100%),linear-gradient(29deg, rgba(28, 28, 28,0.02) 0%, rgba(28, 28, 28,0.02) 33%,transparent 33%, transparent 40%,rgba(220, 220, 220,0.02) 40%, rgba(220, 220, 220,0.02) 100%),linear-gradient(90deg, rgb(255,255,255),rgb(255,255,255)); + background-image: linear-gradient(22.5deg, rgba(66, 66, 66, 0.02) 0%, rgba(66, 66, 66, 0.02) 11%,rgba(135, 135, 135, 0.02) 11%, rgba(135, 135, 135, 0.02) 24%,rgba(29, 29, 29, 0.02) 24%, rgba(29, 29, 29, 0.02) 38%,rgba(15, 15, 15, 0.02) 38%, rgba(15, 15, 15, 0.02) 50%,rgba(180, 180, 180, 0.02) 50%, rgba(180, 180, 180, 0.02) 77%,rgba(205, 205, 205, 0.02) 77%, rgba(205, 205, 205, 0.02) 100%),linear-gradient(67.5deg, rgba(10, 10, 10, 0.02) 0%, rgba(10, 10, 10, 0.02) 22%,rgba(52, 52, 52, 0.02) 22%, rgba(52, 52, 52, 0.02) 29%,rgba(203, 203, 203, 0.02) 29%, rgba(203, 203, 203, 0.02) 30%,rgba(69, 69, 69, 0.02) 30%, rgba(69, 69, 69, 0.02) 75%,rgba(231, 231, 231, 0.02) 75%, rgba(231, 231, 231, 0.02) 95%,rgba(138, 138, 138, 0.02) 95%, rgba(138, 138, 138, 0.02) 100%),linear-gradient(112.5deg, rgba(221, 221, 221, 0.02) 0%, rgba(221, 221, 221, 0.02) 17%,rgba(190, 190, 190, 0.02) 17%, rgba(190, 190, 190, 0.02) 39%,rgba(186, 186, 186, 0.02) 39%, rgba(186, 186, 186, 0.02) 66%,rgba(191, 191, 191, 0.02) 66%, rgba(191, 191, 191, 0.02) 68%,rgba(16, 16, 16, 0.02) 68%, rgba(16, 16, 16, 0.02) 70%,rgba(94, 94, 94, 0.02) 70%, rgba(94, 94, 94, 0.02) 100%),linear-gradient(90deg, #ffffff,#ffffff); } h4 .btn { font-size: 1.3rem; From 216c5a8dd59872868afa38bd6a137d65c3186c09 Mon Sep 17 00:00:00 2001 From: Daniel Seifert Date: Fri, 7 May 2021 10:19:33 +0200 Subject: [PATCH 3/4] add license informations and terms of use --- CHANGELOG.md | 0 README.en.md | 141 ++++++++++++++++++ README.md | 58 +++++-- .../views/admin/tpl/d3ActionWizard.tpl | 1 + .../views/admin/tpl/d3ExportWizard.tpl | 1 + 5 files changed, 189 insertions(+), 12 deletions(-) create mode 100644 CHANGELOG.md create mode 100644 README.en.md diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..e69de29 diff --git a/README.en.md b/README.en.md new file mode 100644 index 0000000..43270a7 --- /dev/null +++ b/README.en.md @@ -0,0 +1,141 @@ +> [deutsche Version](README.md) + +# D³ Data Wizard for OXID eShop + +The module `DataWizard` offers a framework for the simple integration of exports via the admin area of the OXID shop. + +The exports are defined via database queries or ready-made data lists. Various export formats are available. The generation is possible at any time and always recurring (within the system limits). These are offered as downloads in the browser. + +All exports are grouped together for better clarity. + +Sample exports are included in the scope of delivery. These are intended to serve as an implementation reference for individual exports. The display of the sample exports can be deactivated in the basic module settings. + +Translated with www.DeepL.com/Translator (free version) + +## Installation + +In the console in the shop root (above source and vendor), execute the following command: + +```bash +php composer require d3/datawizard:"dev-rel_1.x" +``` + +Activate in the admin area of the shop under "Extensions -> Modules". + +# Extensibility + +The module represents the technical basic framework of the exports and does not claim to be complete. In order to adapt the scope to individual requirements, the following extensions are prepared: + +- Add exports +- Use existing and new groups +- Add export formats + +Independently of this, all extension options are available that the OXID Shop provides for modules. + +## Add exports + +### Define export + +Each export is defined in a separate class. This export class must extend the class `D3\DataWizard\Application\Model\ExportBase`. All necessary functions are predefined in it. The following methods are available: + +#### mandatory method calls: +- getTitle() - defines the title in the admin area and the base of the later export file name. +- getQuery() - contains the query as a prepared statement that defines the data to be exported + +#### optional method calls: +- getDescription() - contains a short additional description of the export, this will be shown in the admin area +- getButtonText() - defines the text of the submit button in the admin area +- getExportFilenameBase() - defines the base of the later export filename +- executeQuery() - returns the compiled export data +- further methods, the adaptation of which, however, can lead to changed module behaviour and should therefore only be changed with caution + +### Register exports + +In order to be able to use the created export in the module, it must be registered. For this purpose there is the class `D3\DataWizard\Application\Model\Configuration`. This is to be overloaded with the possibilities of the OXID shop and the method `configure()` contained therein is to be supplemented. The following call is available for registering an export: + +``` +$this->registerExport(self::GROUP_CATEGORY, oxNew(myCustomExport::class)); +``` + +The first parameter contains the language identifier for the export group. Typical identifiers are already prepared in constants of the configuration class. The instance of the export class is expected as the 2nd parameter. + +## Changelog + +See [CHANGELOG](CHANGELOG.md) for further informations. + +## Licence of this software (d3/datawizard) +(status: 06.05.2021) + +``` +Copyright (c) D3 Data Development (Inh. Thomas Dartsch) + +This software is distributed under the GNU GENERAL PUBLIC LICENSE version 3. +``` + +For full copyright and licensing information, please see the [LICENSE](LICENSE.md) file distributed with this source code. + +## Further licences and terms of use + +### background gradients on src/Application/views/admin/tpl/ templates +(https://www.gradientmagic.com/licensing - status: 07.05.2021) + +``` +Image courtesy of gradientmagic.com + +Free Gradients + +Gradients available on the site are free to use on personal and commercial projects, with attribution. +``` + +------------------------------------------------------------------------------- + +The following software packages are not part of this module. However, they are required for use. The linked packages are under the following licences: + +### league/csv [MIT] +(https://github.com/thephpleague/csv - status: 06.05.2021) + +``` +Copyright (c) 2013-2017 ignace nyamagana butera + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +``` + +### mathieuviossat/arraytotexttable [MIT] +(https://github.com/viossat/arraytotexttable - status: 06.05.2021) + +``` +Copyright (c) 2015 Mathieu Viossat + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +``` diff --git a/README.md b/README.md index 3af79fe..e255a8d 100644 --- a/README.md +++ b/README.md @@ -1,14 +1,6 @@ -# Beschreibung +> [english version](README.en.md) -## Schnellinstallation - -Auf der Konsole im Shoproot (oberhalb von source und vendor) folgenden Befehl ausführen: - -```bash -php composer require d3/datawizard:"dev-rel_1.x" -``` - -# Funktion +# D³ Data Wizard für OXID eShop Das Modul `DataWizard` bietet ein Framework zur einfachen Integration von Exporten über den Adminbereich des OXID Shops. @@ -18,6 +10,16 @@ Alle Exporte sind für eine bessere Ãœbersichtlichkeit in Gruppen zusammengefass Im Lieferumfang sind Beispielexporte enthalten. Diese sollen als Implementierungsreferenz für individuelle Exporte dienen. Die Anzeige der Beispielexporte kann in den Modulgrundeinstellungen deaktiviert werden. +## Installation + +Auf der Konsole im Shoproot (oberhalb von source und vendor) folgenden Befehl ausführen: + +```bash +php composer require d3/datawizard:"dev-rel_1.x" +``` + +Im Adminbereich des Shop unter "Erweiterungen -> Module" aktivieren. + # Erweiterbarkeit Das Modul stellt das technische Grundgerüst der Exporte dar und erhebt keinen Anspruch auf Vollständigkeit. Um den Umfang an die individuellen Anforderungen anzupassen, sind folgende Erweiterungen vorbereitet: @@ -55,9 +57,40 @@ $this->registerExport(self::GROUP_CATEGORY, oxNew(myCustomExport::class)); Der erste Parameter enthält den Sprachident für die Exportgruppe. In Konstanten der configuration-Klasse sind schon typische Idents vorbereitet. Als 2. Parameter wird die Instanz der Exportklasse erwartet. -# Lizenzen +## Changelog + +Siehe [CHANGELOG](CHANGELOG.md) für weitere Informationen. + +## Lizenz dieser Software (d3/datawizard) +(Stand: 06.05.2021) + +``` +Copyright (c) D3 Data Development (Inh. Thomas Dartsch) + +Diese Software wird unter der GNU GENERAL PUBLIC LICENSE Version 3 vertrieben. +``` + +Die vollständigen Copyright- und Lizenzinformationen entnehmen Sie bitte der [LICENSE](LICENSE.md)-Datei, die mit diesem Quellcode verteilt wurde. + +## weitere Lizenzen und Nutzungsbedingungen + +### Hintergrundgradienten in src/Application/views/admin/tpl/ Templates +(https://www.gradientmagic.com/licensing - Stand: 07.05.2021) + +``` +Image courtesy of gradientmagic.com + +Free Gradients + +Gradients available on the site are free to use on personal and commercial projects, with attribution. +``` + +------------------------------------------------------------------------------- + +Die folgenden Softwarepakete sind nicht Teil dieses Moduls. Sie werden diese jedoch zur Verwendung benötigt. Die verlinkten Pakete stehen unter den folgenden Lizenzen: ### league/csv [MIT] +(https://github.com/thephpleague/csv - Stand: 06.05.2021) ``` Copyright (c) 2013-2017 ignace nyamagana butera @@ -81,6 +114,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ``` ### mathieuviossat/arraytotexttable [MIT] +(https://github.com/viossat/arraytotexttable - Stand: 06.05.2021) ``` Copyright (c) 2015 Mathieu Viossat @@ -102,4 +136,4 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -``` \ No newline at end of file +``` diff --git a/src/Application/views/admin/tpl/d3ActionWizard.tpl b/src/Application/views/admin/tpl/d3ActionWizard.tpl index 953d695..0fc6046 100644 --- a/src/Application/views/admin/tpl/d3ActionWizard.tpl +++ b/src/Application/views/admin/tpl/d3ActionWizard.tpl @@ -13,6 +13,7 @@ html { font-size: 0.8em; } + /* Image courtesy of gradientmagic.com */ body { background-image: linear-gradient(22.5deg, rgba(66, 66, 66, 0.02) 0%, rgba(66, 66, 66, 0.02) 11%,rgba(135, 135, 135, 0.02) 11%, rgba(135, 135, 135, 0.02) 24%,rgba(29, 29, 29, 0.02) 24%, rgba(29, 29, 29, 0.02) 38%,rgba(15, 15, 15, 0.02) 38%, rgba(15, 15, 15, 0.02) 50%,rgba(180, 180, 180, 0.02) 50%, rgba(180, 180, 180, 0.02) 77%,rgba(205, 205, 205, 0.02) 77%, rgba(205, 205, 205, 0.02) 100%),linear-gradient(67.5deg, rgba(10, 10, 10, 0.02) 0%, rgba(10, 10, 10, 0.02) 22%,rgba(52, 52, 52, 0.02) 22%, rgba(52, 52, 52, 0.02) 29%,rgba(203, 203, 203, 0.02) 29%, rgba(203, 203, 203, 0.02) 30%,rgba(69, 69, 69, 0.02) 30%, rgba(69, 69, 69, 0.02) 75%,rgba(231, 231, 231, 0.02) 75%, rgba(231, 231, 231, 0.02) 95%,rgba(138, 138, 138, 0.02) 95%, rgba(138, 138, 138, 0.02) 100%),linear-gradient(112.5deg, rgba(221, 221, 221, 0.02) 0%, rgba(221, 221, 221, 0.02) 17%,rgba(190, 190, 190, 0.02) 17%, rgba(190, 190, 190, 0.02) 39%,rgba(186, 186, 186, 0.02) 39%, rgba(186, 186, 186, 0.02) 66%,rgba(191, 191, 191, 0.02) 66%, rgba(191, 191, 191, 0.02) 68%,rgba(16, 16, 16, 0.02) 68%, rgba(16, 16, 16, 0.02) 70%,rgba(94, 94, 94, 0.02) 70%, rgba(94, 94, 94, 0.02) 100%),linear-gradient(90deg, #ffffff,#ffffff); } diff --git a/src/Application/views/admin/tpl/d3ExportWizard.tpl b/src/Application/views/admin/tpl/d3ExportWizard.tpl index 0a9c209..4f8fa1e 100644 --- a/src/Application/views/admin/tpl/d3ExportWizard.tpl +++ b/src/Application/views/admin/tpl/d3ExportWizard.tpl @@ -13,6 +13,7 @@ html { font-size: 0.8em; } + /* Image courtesy of gradientmagic.com */ body { background-image: linear-gradient(339deg, rgba(47, 47, 47,0.02) 0%, rgba(47, 47, 47,0.02) 42%,transparent 42%, transparent 99%,rgba(17, 17, 17,0.02) 99%, rgba(17, 17, 17,0.02) 100%),linear-gradient(257deg, rgba(65, 65, 65,0.02) 0%, rgba(65, 65, 65,0.02) 11%,transparent 11%, transparent 92%,rgba(53, 53, 53,0.02) 92%, rgba(53, 53, 53,0.02) 100%),linear-gradient(191deg, rgba(5, 5, 5,0.02) 0%, rgba(5, 5, 5,0.02) 1%,transparent 1%, transparent 45%,rgba(19, 19, 19,0.02) 45%, rgba(19, 19, 19,0.02) 100%),linear-gradient(29deg, rgba(28, 28, 28,0.02) 0%, rgba(28, 28, 28,0.02) 33%,transparent 33%, transparent 40%,rgba(220, 220, 220,0.02) 40%, rgba(220, 220, 220,0.02) 100%),linear-gradient(90deg, rgb(255,255,255),rgb(255,255,255)); } From af9cc1759d74af344af1fefc28019330ad79b692 Mon Sep 17 00:00:00 2001 From: Daniel Seifert Date: Tue, 22 Jun 2021 13:26:51 +0200 Subject: [PATCH 4/4] implement action runner --- .../Controller/Admin/d3ActionWizard.php | 2 +- .../Controller/Admin/d3ExportWizard.php | 2 +- src/Application/Model/ActionBase.php | 104 ++++-------------- .../Model/Actions/FixArtextendsItems.php | 89 +++++++++++++++ src/Application/Model/Configuration.php | 29 ++++- src/Application/Model/QueryBase.php | 5 - .../views/admin/de/d3DataWizard_lang.php | 10 +- .../views/admin/tpl/d3ActionWizard.tpl | 24 ++-- 8 files changed, 154 insertions(+), 111 deletions(-) create mode 100644 src/Application/Model/Actions/FixArtextendsItems.php diff --git a/src/Application/Controller/Admin/d3ActionWizard.php b/src/Application/Controller/Admin/d3ActionWizard.php index 970700f..caca3aa 100644 --- a/src/Application/Controller/Admin/d3ActionWizard.php +++ b/src/Application/Controller/Admin/d3ActionWizard.php @@ -44,7 +44,7 @@ class d3ActionWizard extends AdminDetailsController public function getGroups() { - return $this->configuration->getGroups(); + return $this->configuration->getActionGroups(); } public function getGroupActions($group) diff --git a/src/Application/Controller/Admin/d3ExportWizard.php b/src/Application/Controller/Admin/d3ExportWizard.php index ef8d555..236c97c 100644 --- a/src/Application/Controller/Admin/d3ExportWizard.php +++ b/src/Application/Controller/Admin/d3ExportWizard.php @@ -44,7 +44,7 @@ class d3ExportWizard extends AdminDetailsController public function getGroups() { - return $this->configuration->getGroups(); + return $this->configuration->getExportGroups(); } public function getGroupExports($group) diff --git a/src/Application/Model/ActionBase.php b/src/Application/Model/ActionBase.php index 79b46aa..20c9e43 100644 --- a/src/Application/Model/ActionBase.php +++ b/src/Application/Model/ActionBase.php @@ -15,15 +15,9 @@ declare(strict_types=1); namespace D3\DataWizard\Application\Model; -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 OxidEsales\Eshop\Core\DatabaseProvider; use OxidEsales\Eshop\Core\Exception\DatabaseConnectionException; use OxidEsales\Eshop\Core\Exception\DatabaseErrorException; -use OxidEsales\Eshop\Core\Exception\StandardException; use OxidEsales\Eshop\Core\Registry; abstract class ActionBase implements QueryBase @@ -35,85 +29,14 @@ abstract class ActionBase implements QueryBase { return ''; } - + /** - * @param string $format - * - * @throws DBALException * @throws DatabaseConnectionException * @throws DatabaseErrorException - * @throws Exceptions\NoSuitableRendererException - * @throws Exceptions\TaskException - * @throws StandardException - * @throws d3ShopCompatibilityAdapterException - * @throws d3_cfg_mod_exception */ public function run() { - $rowCount = $this->getExportData( $this->getQuery() ); - } - - /** - * @return string - */ - public function getButtonText() : string - { - return "D3_DATAWIZARD_EXPORT_SUBMIT"; - } - - /** - * @param $format - * - * @return ExportRenderer\RendererInterface - * @throws Exceptions\NoSuitableRendererException - */ - public function getRenderer($format): ExportRenderer\RendererInterface - { - return oxNew(RendererBridge::class)->getRenderer($format); - } - - /** - * @param $format - * - * @return string - * @throws Exceptions\NoSuitableRendererException - */ - public function getFileExtension($format): string - { - return $this->getRenderer($format)->getFileExtension(); - } - - /** - * @param $rows - * @param $fieldnames - * @param $format - * - * @return string - * @throws Exceptions\NoSuitableRendererException - */ - public function renderContent($rows, $fieldnames, $format): string - { - $renderer = $this->getRenderer($format); - return $renderer->getContent($rows, $fieldnames); - } - - /** - * @return string - */ - public function getExportFilenameBase() : string - { - return $this->getTitle(); - } - - /** - * @param $format - * - * @return string - * @throws Exceptions\NoSuitableRendererException - */ - public function getExportFileName($format) : string - { - return $this->getExportFilenameBase().'_'.date('Y-m-d_H-i-s').'.'.$this->getFileExtension($format); + $this->executeAction( $this->getQuery() ); } /** @@ -123,7 +46,7 @@ abstract class ActionBase implements QueryBase * @throws DatabaseConnectionException * @throws DatabaseErrorException */ - public function getExportData( array $query ): array + public function executeAction( array $query ): int { [ $queryString, $parameters ] = $query; @@ -137,6 +60,25 @@ abstract class ActionBase implements QueryBase ); } - return DatabaseProvider::getDb( DatabaseProvider::FETCH_MODE_ASSOC )->execute( $queryString, $parameters ); + $affected = DatabaseProvider::getDb( DatabaseProvider::FETCH_MODE_ASSOC )->execute( $queryString, $parameters ); + + throw oxNew( + Exceptions\TaskException::class, + $this, + sprintf( + Registry::getLang()->translateString( + $affected === 1 ? 'D3_DATAWIZARD_ERR_ACTIONRESULT' : 'D3_DATAWIZARD_ERR_ACTIONRESULTS' + ), + $affected + ) + ); + } + + /** + * @return string + */ + public function getButtonText() : string + { + return "D3_DATAWIZARD_ACTION_SUBMIT"; } } \ No newline at end of file diff --git a/src/Application/Model/Actions/FixArtextendsItems.php b/src/Application/Model/Actions/FixArtextendsItems.php new file mode 100644 index 0000000..4a7f571 --- /dev/null +++ b/src/Application/Model/Actions/FixArtextendsItems.php @@ -0,0 +1,89 @@ + + * @link http://www.oxidmodule.com + */ + +declare(strict_types=1); + +namespace D3\DataWizard\Application\Model\Actions; + +use D3\DataWizard\Application\Model\ActionBase; +use OxidEsales\Eshop\Core\Model\BaseModel; +use OxidEsales\Eshop\Core\Model\MultiLanguageModel; +use OxidEsales\Eshop\Core\Registry; + +class FixArtextendsItems extends ActionBase +{ + /** + * fehlende oxartextends-Einträge nachtragen + */ + + /** + * @return string + */ + public function getTitle() : string + { + return Registry::getLang()->translateString('D3_DATAWIZARD_ACTIONS_FIXARTEXTENDSITEMS'); + } + + /** + * @return array + */ + public function getQuery() : array + { + $aDefaultValueFields = array( + 'oxtimestamp' => "''", + ); + + $aNonArtExtendsFields = array( + 'oxid' => 'oxarticles.oxid', + ); + + $aArtExtendsFields = array_fill_keys($this->getArtExtendsFields(), "''"); + $aMergedFields = array_merge($aNonArtExtendsFields, $aArtExtendsFields); + $aQueryFields = array_diff_key($aMergedFields, $aDefaultValueFields); + + $sArtExtendsFields = implode(', ', array_keys($aQueryFields)); + + $select = "SELECT ".implode(', ', $aQueryFields). + " FROM oxarticles". + " LEFT JOIN oxartextends AS arx ON oxarticles.oxid = arx.oxid". + " WHERE arx.oxid IS NULL"; + + $query = "INSERT INTO oxartextends ($sArtExtendsFields) ". + $select; + + return [$query, []]; + } + + /** + * @return array + */ + public function getArtExtendsFields(): array + { + /** @var $oArtExtends MultiLanguageModel */ + $oArtExtends = oxNew(BaseModel::class); + $oArtExtends->init('oxartextends', false); + + $aFieldNames = $oArtExtends->getFieldNames(); + + if (false == $aFieldNames) { + $oArtExtends->disableLazyLoading(); + $aFieldNames = $oArtExtends->getFieldNames(); + } + + unset($aFieldNames[array_search('oxid', $aFieldNames)]); + + return $aFieldNames; + } +} \ No newline at end of file diff --git a/src/Application/Model/Configuration.php b/src/Application/Model/Configuration.php index 4a44dd4..c565431 100644 --- a/src/Application/Model/Configuration.php +++ b/src/Application/Model/Configuration.php @@ -15,6 +15,7 @@ declare(strict_types=1); namespace D3\DataWizard\Application\Model; +use D3\DataWizard\Application\Model\Actions\FixArtextendsItems; use D3\DataWizard\Application\Model\Exports\InactiveCategories; use D3\DataWizard\Application\Model\Exports\KeyFigures; use OxidEsales\Eshop\Core\Registry; @@ -39,6 +40,8 @@ class Configuration public function configure() { if (false === Registry::getConfig()->getConfigParam('d3datawizard_hideexamples', false)) { + $this->registerAction(self::GROUP_ARTICLES, oxNew(FixArtextendsItems::class)); + $this->registerExport(self::GROUP_CATEGORY, oxNew(InactiveCategories::class)); $this->registerExport(self::GROUP_SHOP, oxNew(KeyFigures::class)); } @@ -81,16 +84,34 @@ class Configuration /** * @return array */ - public function getGroups(): array + public function getActionGroups(): array + { + return array_keys($this->actions); + } + + /** + * @return array + */ + public function getExportGroups(): array { return array_keys($this->exports); } + /** + * @param $group + * + * @return mixed + */ public function getActionsByGroup($group) { return $this->actions[$group]; } + /** + * @param $group + * + * @return mixed + */ public function getExportsByGroup($group) { return $this->exports[$group]; @@ -103,7 +124,7 @@ class Configuration { $all = []; - foreach ($this->getGroups() as $group) { + foreach ($this->getActionGroups() as $group) { $all = array_merge($all, $this->getActionsByGroup($group)); } @@ -117,7 +138,7 @@ class Configuration { $all = []; - foreach ($this->getGroups() as $group) { + foreach ($this->getExportGroups() as $group) { $all = array_merge($all, $this->getExportsByGroup($group)); } @@ -131,7 +152,7 @@ class Configuration */ public function getActionById($id) : ActionBase { - return $this->getAllExports()[$id]; + return $this->getAllActions()[$id]; } /** diff --git a/src/Application/Model/QueryBase.php b/src/Application/Model/QueryBase.php index b034dd8..c17b593 100644 --- a/src/Application/Model/QueryBase.php +++ b/src/Application/Model/QueryBase.php @@ -19,11 +19,6 @@ interface QueryBase { public function run(); - /** - * @return string - */ - public function getExportFilenameBase() : string; - /** * @return string */ diff --git a/src/Application/views/admin/de/d3DataWizard_lang.php b/src/Application/views/admin/de/d3DataWizard_lang.php index c7e6dab..e78d7f9 100644 --- a/src/Application/views/admin/de/d3DataWizard_lang.php +++ b/src/Application/views/admin/de/d3DataWizard_lang.php @@ -40,6 +40,8 @@ $aLang = array( 'D3_DATAWIZARD_EXPORT_FORMAT_CSV' => 'CSV-Format', 'D3_DATAWIZARD_EXPORT_FORMAT_PRETTY' => 'Pretty-Format', + 'D3_DATAWIZARD_ACTION_SUBMIT' => 'Aktion starten', + 'D3_DATAWIZARD_DEBUG' => 'Debug: %1$s', 'D3_DATAWIZARD_ERR_NOEXPORTSELECT' => 'Export kann nicht ausgeführt werden. Exporte erfordern SELECT Query.', @@ -57,7 +59,9 @@ $aLang = array( 'D3_DATAWIZARD_EXPORTS_KEYFIGURES_BASKETSIZE' => 'Warenkorbhöhe', 'D3_DATAWIZARD_EXPORTS_KEYFIGURES_MONTH' => 'Monat', -// Abracadata -// Harry Potter -// Magic + 'D3_DATAWIZARD_ERR_ACTIONSELECT' => 'Aktion kann nicht ausgeführt werden. Aktionen können keine SELECTs exportieren.', + 'D3_DATAWIZARD_ERR_NOACTION_INSTALLED' => 'Es sind keine Aktionen installiert oder aktiviert.', + 'D3_DATAWIZARD_ERR_ACTIONRESULT' => '%1$s Eintrag verändert', + 'D3_DATAWIZARD_ERR_ACTIONRESULTS' => '%1$s Einträge verändert', + 'D3_DATAWIZARD_ACTIONS_FIXARTEXTENDSITEMS' => 'fehlende oxartextends-Einträge nachtragen', ); diff --git a/src/Application/views/admin/tpl/d3ActionWizard.tpl b/src/Application/views/admin/tpl/d3ActionWizard.tpl index 0fc6046..efe3469 100644 --- a/src/Application/views/admin/tpl/d3ActionWizard.tpl +++ b/src/Application/views/admin/tpl/d3ActionWizard.tpl @@ -26,7 +26,7 @@ [{capture name="d3script"}][{strip}] - function startExport(id, format) { + function startAction(id) { let elements = document.getElementsByClassName('errorbox'); for (var i = 0; i < elements.length; i++){ elements[i].style.display = 'none'; @@ -37,8 +37,7 @@ }, 3000); document.getElementById('mask').className='on'; document.getElementById('popup2').className='d3loader-2 on'; - document.getElementById('exportid').value = id; - document.getElementById('exportformat').value = format; + document.getElementById('actionid').value = id; document.getElementById('myedit').submit(); } [{/strip}][{/capture}] @@ -47,9 +46,8 @@
[{$oViewConf->getHiddenSid()}] - - - + + [{assign var="groups" value=$oView->getGroups()}] [{if $groups|@count}] @@ -67,27 +65,21 @@
- [{foreach from=$oView->getGroupActions($group) key="id" item="export"}] + [{foreach from=$oView->getGroupActions($group) key="id" item="action"}]
- [{$export->getTitle()}] + [{$action->getTitle()}]

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

-