Compare commits

...

64 Commits

Author SHA1 Message Date
Daniel Seifert 445a58a819 add ViewId tests 2024-05-13 16:24:34 +02:00
Daniel Seifert 957de3ac0f adjust changelog 2024-05-13 16:04:56 +02:00
Daniel Seifert 9f2a97c560 fix assignment in template 2024-05-13 15:45:25 +02:00
Daniel Seifert 76d72c8546 align test fixtures to strict types 2024-05-13 15:45:25 +02:00
Daniel Seifert 76fd879554 adjust tests 2024-05-13 15:45:25 +02:00
Daniel Seifert be873efb32 set argument types 2024-05-13 15:45:25 +02:00
Daniel Seifert 201b01db4c fix unicode char issues 2024-05-13 15:45:24 +02:00
Daniel Seifert 185caeeac3 refactor CSV format class
- add column consistency check
- can force enclosure optionally
2024-05-13 15:45:24 +02:00
Daniel Seifert 760b7b2509 assert right argument types 2024-05-13 15:45:24 +02:00
Daniel Seifert f730a380ec use current module setting service 2024-05-13 15:45:24 +02:00
Daniel Seifert 4cfcfb6d44 fix type in Twig template 2024-05-13 15:45:23 +02:00
Daniel Seifert 69b33d3538 fix tests 2024-05-13 15:45:23 +02:00
Daniel Seifert 36ee1a5957 fix tests 2024-05-13 15:45:23 +02:00
Daniel Seifert 3fd5f2dc98 fix test issues 2024-05-13 15:45:23 +02:00
Daniel Seifert bb7b9c2025 add Twig templates and translations, move Smarty templates to appropriate folder 2024-05-13 15:45:23 +02:00
Daniel Seifert 7ed3a7be0e make installable in OXID 7.1 2024-05-13 15:45:22 +02:00
Daniel Seifert baeb293048 add module dependency
available from OXID 7.1
2024-05-13 15:45:22 +02:00
Daniel Seifert 908068abfa improve code 2024-05-13 15:45:22 +02:00
Daniel Seifert 4548be2986 retrieve module settings from settings service instead from outdated configuration 2024-05-13 15:45:21 +02:00
Daniel Seifert 42fe5c8ca2 adjust translation file structure 2024-05-13 15:45:21 +02:00
Daniel Seifert 58dcf94255 adjust translation file structure 2024-05-13 15:45:21 +02:00
Daniel Seifert 34f04b8835 refactor Smarty template integration 2024-05-13 15:45:21 +02:00
Daniel Seifert b77642666b improve code for PHP 8 2024-05-13 15:44:15 +02:00
Daniel Seifert 220f8a1c7c adjust composer file 2024-05-13 15:44:15 +02:00
Daniel Seifert 4b726bb678
use vector module icon 2023-12-05 23:27:49 +01:00
Markus Gärtner c414eb3683 Tag version 2.1.1.3, make installable in OXID 6.5.3 2023-09-12 13:54:03 +02:00
Markus Gärtner 5ddd1a3923 make installable in OXID 6.5.3 2023-09-12 13:43:59 +02:00
Daniel Seifert aac67d8550
add product logo 2023-06-09 12:18:36 +02:00
Daniel Seifert 3debde96c9
apply roles and rights 2023-05-23 10:59:44 +02:00
Daniel Seifert 03f31f3e8b
adjust documentation 2023-03-30 13:33:39 +02:00
Daniel Seifert 3d83650f7c
fix JS for multiforms 2023-03-30 13:30:04 +02:00
Daniel Seifert cf6dd76aa9
adjust documentation 2023-03-22 16:00:53 +01:00
Daniel Seifert 0213f2e6b3
fix cascaded HTML elements to prevent form issues 2023-03-22 15:58:02 +01:00
Daniel Seifert 1fd00635f9
define code coverage exclusions 2022-12-24 23:39:45 +01:00
Daniel Seifert 640152b6a6
adjust version informations 2022-12-24 23:28:33 +01:00
Daniel Seifert 7d8ed628eb
make installable in OXID 6.5.1 2022-12-19 11:22:50 +01:00
Daniel Seifert 8356ff3a62
make installable in OXID 6.5 (CE 6.12) 2022-08-30 00:23:18 +02:00
Daniel Seifert 7c479d02c8
improve changelog 2022-07-28 11:08:54 +02:00
Daniel Seifert b1e3bd98f0
Merge branch 'rel_2.x' of git.d3data.de:D3Public/DataWizard into rel_2.x 2022-07-13 13:46:17 +02:00
Daniel Seifert 72478c06e7
fix typo 2022-07-13 13:45:55 +02:00
Daniel Seifert bd4dfaf36c
0010966 execute action after confirmation 2022-02-27 22:56:00 +01:00
Daniel Seifert 7e1e65cb37
prevent commiting CS-Fixer cache file 2022-01-17 11:09:16 +01:00
Daniel Seifert 0c0d564554
add CS-fixed files 2022-01-17 10:59:18 +01:00
Daniel Seifert 51642b57c7
add CS-Fixer configuration 2022-01-17 10:58:46 +01:00
Daniel Seifert d0464d4a20
enhance README file 2021-12-29 23:41:51 +01:00
Daniel Seifert 6aa028fb8c
improve package description 2021-12-23 14:46:43 +01:00
Daniel Seifert 143173be2f
set Modcfg as dependency 2021-12-22 15:10:24 +01:00
Daniel Seifert f3b80607b0
adjust version informations 2021-12-21 13:50:40 +01:00
Daniel Seifert e05278da19
extract content rendering into separate method 2021-12-21 13:38:53 +01:00
Daniel Seifert 69bf942608
remove outdated version from form manager dependency 2021-12-20 14:09:57 +01:00
Daniel Seifert bcd91cf709
remove unused dev dependency 2021-12-20 13:54:55 +01:00
Daniel Seifert e604b84849
improve code 2021-12-20 13:41:24 +01:00
Daniel Seifert 67c462ccda
Merge branch 'dev_2.x_PHP73' of git.d3data.de:D3Public/DataWizard into dev_2.x_PHP73 2021-12-20 12:06:15 +01:00
Daniel Seifert 2549003c71
adjust version informations 2021-12-20 12:05:55 +01:00
Daniel Seifert f86e3a9daf
make installable in OXID 6.4 2021-12-20 11:53:55 +01:00
Daniel Seifert 91b18a9196
Merge branch 'rel_1.x' into dev_2.x_PHP73 2021-11-28 23:09:15 +01:00
Daniel Seifert 675b18aaa8
define test dependencies 2021-11-28 23:05:04 +01:00
Daniel Seifert a0788ba666
add missing tests 2021-11-28 23:02:15 +01:00
Daniel Seifert 3aa64f8f63
add tests for configuration class 2021-11-28 01:04:46 +01:00
Daniel Seifert b1946c4aae
improve tests for EE 2021-11-27 00:59:02 +01:00
Daniel Seifert 61827e7825
add tests for renderers 2021-11-25 23:42:41 +01:00
Daniel Seifert 5fda1baecb
add tests for admin controller classes 2021-11-24 23:38:28 +01:00
Daniel Seifert e0bd9f02b6
Merge branch 'rel_1.x' into dev_2.x_PHP73 2021-11-11 11:18:16 +01:00
Daniel Seifert 5251490b74
handle JSON exception 2021-11-11 09:41:36 +01:00
69 changed files with 4256 additions and 397 deletions

5
.gitattributes vendored Normal file
View File

@ -0,0 +1,5 @@
* text=auto
/.gitattributes export-ignore
/.gitignore export-ignore
/.php-cs-fixer.php export-ignore

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
.php-cs-fixer.cache

13
.php-cs-fixer.php Normal file
View File

@ -0,0 +1,13 @@
<?php
$finder = PhpCsFixer\Finder::create()
->in(__DIR__)
;
$config = new PhpCsFixer\Config();
return $config->setRules([
'@PHP73Migration' => true,
'@PSR12' => true
])
->setFinder($finder)
;

View File

@ -3,7 +3,7 @@
/**
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
*
* https://www.d3data.de
*
* @copyright (C) D3 Data Development (Inh. Thomas Dartsch)
@ -16,24 +16,26 @@ declare(strict_types=1);
namespace D3\DataWizard\Application\Controller\Admin;
use D3\DataWizard\Application\Model\Configuration;
use D3\DataWizard\Application\Model\Constants;
use D3\DataWizard\Application\Model\Exceptions\DataWizardException;
use D3\DataWizard\Application\Model\Exceptions\DebugException;
use D3\DataWizard\Application\Model\Exceptions\InputUnvalidException;
use D3\DataWizard\Application\Model\Exceptions\TaskException;
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 Doctrine\DBAL\Exception as 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;
use OxidEsales\EshopCommunity\Internal\Container\ContainerFactory;
use OxidEsales\EshopCommunity\Internal\Framework\Module\Facade\ModuleSettingService;
use OxidEsales\EshopCommunity\Internal\Framework\Module\Facade\ModuleSettingServiceInterface;
use Psr\Container\ContainerExceptionInterface;
use Psr\Container\NotFoundExceptionInterface;
class d3ActionWizard extends AdminDetailsController
{
protected $_sThisTemplate = 'd3ActionWizard.tpl';
protected $_sThisTemplate = '@'. Constants::OXID_MODULE_ID .'/admin/d3ActionWizard';
/** @var Configuration */
protected $configuration;
protected Configuration $configuration;
public function __construct()
{
@ -42,60 +44,79 @@ class d3ActionWizard extends AdminDetailsController
$this->configuration = oxNew(Configuration::class);
}
public function getGroups()
public function getViewId(): string
{
return 'd3mxDataWizard_Action';
}
public function getGroups(): array
{
return $this->configuration->getActionGroups();
}
public function getGroupTasks($group)
public function getGroupTasks($group): array
{
return $this->configuration->getActionsByGroup($group);
}
/**
* @throws DatabaseConnectionException
* @throws StandardException
* @throws d3ShopCompatibilityAdapterException
* @throws d3_cfg_mod_exception
* @throws ContainerExceptionInterface
* @throws NotFoundExceptionInterface
*/
public function runTask()
public function runTask(): void
{
try {
$this->execute();
} catch (DataWizardException|DBALException|DatabaseErrorException $e) {
} catch (DataWizardException|DBALException $e) {
Registry::getLogger()->error($e->getMessage());
Registry::getUtilsView()->addErrorToDisplay($e);
}
}
/**
* @throws DatabaseConnectionException
* @throws DatabaseErrorException
* @throws ContainerExceptionInterface
* @throws DBALException
* @throws DebugException
* @throws InputUnvalidException
* @throws NotFoundExceptionInterface
* @throws TaskException
*/
protected function execute()
protected function execute(): void
{
$id = Registry::getRequest()->getRequestEscapedParameter('taskid');
$action = $this->configuration->getActionById($id);
[ $queryString, $parameters ] = $action->getQuery();
if (Registry::getConfig()->getConfigParam('d3datawizard_debug')) {
throw oxNew(
if ($this->getSettingsService()->getBoolean('d3datawizard_debug', Constants::OXID_MODULE_ID)) {
/** @var DebugException $debug */
$debug = oxNew(
DebugException::class,
d3database::getInstance()->getPreparedStatementQuery($queryString, $parameters)
);
throw $debug;
}
$action->run();
}
public function getUserMessages()
/**
* @return ModuleSettingService
* @throws ContainerExceptionInterface
* @throws NotFoundExceptionInterface
*/
public function getSettingsService(): ModuleSettingServiceInterface
{
return ContainerFactory::getInstance()->getContainer()->get(ModuleSettingServiceInterface::class);
}
public function getUserMessages(): ?string
{
return null;
}
public function getHelpURL()
public function getHelpURL(): ?string
{
return null;
}
}
}

View File

@ -3,7 +3,7 @@
/**
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
*
* https://www.d3data.de
*
* @copyright (C) D3 Data Development (Inh. Thomas Dartsch)
@ -16,26 +16,31 @@ declare(strict_types=1);
namespace D3\DataWizard\Application\Controller\Admin;
use D3\DataWizard\Application\Model\Configuration;
use D3\DataWizard\Application\Model\Constants;
use D3\DataWizard\Application\Model\Exceptions\DataWizardException;
use D3\DataWizard\Application\Model\Exceptions\DebugException;
use D3\DataWizard\Application\Model\Exceptions\NoSuitableRendererException;
use D3\DataWizard\Application\Model\Exceptions\TaskException;
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 Doctrine\DBAL\Driver\Exception;
use Doctrine\DBAL\Exception as 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;
use OxidEsales\EshopCommunity\Internal\Container\ContainerFactory;
use OxidEsales\EshopCommunity\Internal\Framework\Module\Facade\ModuleSettingService;
use OxidEsales\EshopCommunity\Internal\Framework\Module\Facade\ModuleSettingServiceInterface;
use Psr\Container\ContainerExceptionInterface;
use Psr\Container\NotFoundExceptionInterface;
class d3ExportWizard extends AdminDetailsController
{
protected $_sThisTemplate = 'd3ExportWizard.tpl';
protected $_sThisTemplate = '@'. Constants::OXID_MODULE_ID .'/admin/d3ExportWizard';
/** @var Configuration */
protected $configuration;
protected Configuration $configuration;
public function __construct()
{
@ -44,23 +49,31 @@ class d3ExportWizard extends AdminDetailsController
$this->configuration = oxNew(Configuration::class);
}
public function getGroups()
public function getViewId(): string
{
return 'd3mxDataWizard_Export';
}
public function getGroups(): array
{
return $this->configuration->getExportGroups();
}
public function getGroupTasks($group)
public function getGroupTasks($group): array
{
return $this->configuration->getExportsByGroup($group);
}
/**
* @throws ContainerExceptionInterface
* @throws DatabaseConnectionException
* @throws Exception
* @throws NotFoundExceptionInterface
* @throws StandardException
* @throws d3ShopCompatibilityAdapterException
* @throws d3_cfg_mod_exception
*/
public function runTask()
public function runTask(): void
{
try {
$this->execute();
@ -74,20 +87,22 @@ class d3ExportWizard extends AdminDetailsController
* @throws DBALException
* @throws DatabaseConnectionException
* @throws DatabaseErrorException
* @throws StandardException
* @throws NoSuitableRendererException
* @throws TaskException
* @throws StandardException
* @throws Exception
* @throws ContainerExceptionInterface
* @throws NotFoundExceptionInterface
* @throws d3ShopCompatibilityAdapterException
* @throws d3_cfg_mod_exception
*/
protected function execute()
protected function execute(): void
{
$id = Registry::getRequest()->getRequestEscapedParameter('taskid');
$export = $this->configuration->getExportById($id);
[ $queryString, $parameters ] = $export->getQuery();
if (Registry::getConfig()->getConfigParam('d3datawizard_debug')) {
if ($this->getSettingsService()->getBoolean('d3datawizard_debug', Constants::OXID_MODULE_ID)) {
throw oxNew(
DebugException::class,
d3database::getInstance()->getPreparedStatementQuery($queryString, $parameters)
@ -97,13 +112,23 @@ class d3ExportWizard extends AdminDetailsController
$export->run(Registry::getRequest()->getRequestEscapedParameter('format'));
}
public function getUserMessages()
/**
* @return ModuleSettingService
* @throws ContainerExceptionInterface
* @throws NotFoundExceptionInterface
*/
public function getSettingsService(): ModuleSettingServiceInterface
{
return ContainerFactory::getInstance()->getContainer()->get(ModuleSettingServiceInterface::class);
}
public function getUserMessages(): ?string
{
return null;
}
public function getHelpURL()
public function getHelpURL(): ?string
{
return null;
}
}
}

View File

@ -3,7 +3,7 @@
/**
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
*
* https://www.d3data.de
*
* @copyright (C) D3 Data Development (Inh. Thomas Dartsch)
@ -16,70 +16,84 @@ declare(strict_types=1);
namespace D3\DataWizard\Application\Model;
use D3\DataWizard\Application\Model\Exceptions\InputUnvalidException;
use D3\DataWizard\Application\Model\Exceptions\TaskException;
use Doctrine\DBAL\Connection;
use Doctrine\DBAL\Exception as 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;
use OxidEsales\Eshop\Core\Registry;
use OxidEsales\EshopCommunity\Internal\Container\ContainerFactory;
use OxidEsales\EshopCommunity\Internal\Framework\Database\ConnectionProviderInterface;
use Psr\Container\ContainerExceptionInterface;
use Psr\Container\NotFoundExceptionInterface;
abstract class ActionBase implements QueryBase
{
protected $formElements = [];
protected array $formElements = [];
/**
* Ensure that the translations are equally available in the frontend and the backend
* @return string
*/
public function getDescription() : string
public function getDescription(): string
{
return '';
}
/**
* @throws DatabaseConnectionException
* @throws DatabaseErrorException
* @throws ContainerExceptionInterface
* @throws DBALException
* @throws InputUnvalidException
* @throws NotFoundExceptionInterface
* @throws TaskException
*/
public function run()
public function run(): void
{
if ($this->hasFormElements()) {
/** @var Input $element */
foreach ($this->getFormElements() as $element) {
if (false === $element->isValid()) {
throw oxNew(InputUnvalidException::class, $this, $element);
/** @var InputUnvalidException $exception */
$exception = oxNew(InputUnvalidException::class, $this, $element);
throw $exception;
}
}
}
$this->executeAction( $this->getQuery() );
$this->executeAction($this->getQuery());
}
/**
* @param array $query
*
* @return int
* @throws DatabaseConnectionException
* @throws DatabaseErrorException
* @return void
* @throws ContainerExceptionInterface
* @throws NotFoundExceptionInterface
* @throws TaskException
* @throws DBALException
*/
public function executeAction( array $query ): int
public function executeAction(array $query): void
{
[ $queryString, $parameters ] = $query;
$queryString = trim($queryString);
if ( strtolower( substr( $queryString, 0, 6 ) ) === 'select' ) {
throw oxNew(
Exceptions\TaskException::class,
if (strtolower(substr($queryString, 0, 6)) === 'select') {
/** @var TaskException $exception */
$exception = oxNew(
TaskException::class,
$this,
Registry::getLang()->translateString( 'D3_DATAWIZARD_ERR_ACTIONSELECT' )
Registry::getLang()->translateString('D3_DATAWIZARD_ERR_ACTIONSELECT')
);
throw $exception;
}
$affected = DatabaseProvider::getDb( DatabaseProvider::FETCH_MODE_ASSOC )->execute( $queryString, $parameters );
$affected = (int) $this->getConnection()->executeStatement($queryString, $parameters);
throw oxNew(
Exceptions\TaskException::class,
/** @var TaskException $exception */
$exception = oxNew(
TaskException::class,
$this,
sprintf(
Registry::getLang()->translateString(
@ -88,12 +102,18 @@ abstract class ActionBase implements QueryBase
$affected
)
);
throw $exception;
}
protected function getConnection(): Connection
{
return ContainerFactory::getInstance()->getContainer()->get(ConnectionProviderInterface::class)->get();
}
/**
* @return string
*/
public function getButtonText() : string
public function getButtonText(): string
{
return "D3_DATAWIZARD_ACTION_SUBMIT";
}
@ -101,17 +121,14 @@ abstract class ActionBase implements QueryBase
/**
* @param Input $input
*/
public function registerFormElement(Input $input)
public function registerFormElement(Input $input): void
{
switch (get_class($input)) {
case Radio::class:
case Checkbox::class:
$input->setTemplate('<p class="form-check">{{ input }} {{ label }}</p>');
$input->setAttribute('class', 'form-check-input');
break;
default:
$input->setTemplate('<p class="formElements">{{ label }} {{ input }}</p>');
$input->setAttribute('class', 'form-control');
if ($input instanceof Radio || $input instanceof Checkbox) {
$input->setTemplate('<p class="form-check">{{ input }} {{ label }}</p>');
$input->setAttribute('class', 'form-check-input');
} else {
$input->setTemplate('<p class="formElements">{{ label }} {{ input }}</p>');
$input->setAttribute('class', 'form-control');
}
$this->formElements[] = $input;
}
@ -131,4 +148,4 @@ abstract class ActionBase implements QueryBase
{
return $this->formElements;
}
}
}

View File

@ -3,7 +3,7 @@
/**
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
*
* https://www.d3data.de
*
* @copyright (C) D3 Data Development (Inh. Thomas Dartsch)
@ -15,24 +15,20 @@ 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;
class Configuration
{
const GROUP_SHOP = 'D3_DATAWIZARD_GROUP_SHOP';
const GROUP_CATEGORY = 'D3_DATAWIZARD_GROUP_CATEGORIES';
const GROUP_ARTICLES = 'D3_DATAWIZARD_GROUP_ARTICLES';
const GROUP_USERS = 'D3_DATAWIZARD_GROUP_USERS';
const GROUP_ORDERS = 'D3_DATAWIZARD_GROUP_ORDERS';
const GROUP_REMARKS = 'D3_DATAWIZARD_GROUP_REMARKS';
const GROUP_CMS = 'D3_DATAWIZARD_GROUP_CMS';
public const GROUP_SHOP = 'D3_DATAWIZARD_GROUP_SHOP';
public const GROUP_CATEGORY = 'D3_DATAWIZARD_GROUP_CATEGORIES';
public const GROUP_ARTICLES = 'D3_DATAWIZARD_GROUP_ARTICLES';
public const GROUP_USERS = 'D3_DATAWIZARD_GROUP_USERS';
public const GROUP_ORDERS = 'D3_DATAWIZARD_GROUP_ORDERS';
public const GROUP_REMARKS = 'D3_DATAWIZARD_GROUP_REMARKS';
public const GROUP_CMS = 'D3_DATAWIZARD_GROUP_CMS';
protected $actions = [];
protected $exports = [];
protected array $actions = [];
protected array $exports = [];
public function __construct()
{
@ -48,7 +44,7 @@ class Configuration
* @param $group
* @param ActionBase $action
*/
public function registerAction($group, ActionBase $action)
public function registerAction($group, ActionBase $action): void
{
$this->actions[$group][md5(get_class($action))] = $action;
}
@ -57,7 +53,7 @@ class Configuration
* @param $group
* @param ExportBase $export
*/
public function registerExport($group, ExportBase $export)
public function registerExport($group, ExportBase $export): void
{
$this->exports[$group][md5(get_class($export))] = $export;
}
@ -97,9 +93,9 @@ class Configuration
/**
* @param $group
*
* @return mixed
* @return array
*/
public function getActionsByGroup($group)
public function getActionsByGroup($group): array
{
return $this->actions[$group];
}
@ -107,9 +103,9 @@ class Configuration
/**
* @param $group
*
* @return mixed
* @return array
*/
public function getExportsByGroup($group)
public function getExportsByGroup($group): array
{
return $this->exports[$group];
}
@ -117,7 +113,7 @@ class Configuration
/**
* @return array
*/
public function getAllActions() : array
public function getAllActions(): array
{
$all = [];
@ -131,7 +127,7 @@ class Configuration
/**
* @return array
*/
public function getAllExports() : array
public function getAllExports(): array
{
$all = [];
@ -147,9 +143,15 @@ class Configuration
*
* @return ActionBase
*/
public function getActionById($id) : ActionBase
public function getActionById($id): ActionBase
{
return $this->getAllActions()[$id];
$allActions = $this->getAllActions();
if ( ! $allActions[ $id ] ) {
throw oxNew(DataWizardException::class, 'no action with id '.$id);
}
return $allActions[$id];
}
/**
@ -157,11 +159,11 @@ class Configuration
*
* @return ExportBase
*/
public function getExportById($id) : ExportBase
public function getExportById($id): ExportBase
{
$allExports = $this->getAllExports();
if (false == $allExports[$id]) {
if ( ! $allExports[ $id ] ) {
throw oxNew(DataWizardException::class, 'no export with id '.$id);
}

View File

@ -0,0 +1,21 @@
<?php
/**
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* https://www.d3data.de
*
* @copyright (C) D3 Data Development (Inh. Thomas Dartsch)
* @author D3 Data Development - Daniel Seifert <support@shopmodule.com>
* @link https://www.oxidmodule.com
*/
declare(strict_types=1);
namespace D3\DataWizard\Application\Model;
class Constants
{
public const OXID_MODULE_ID = 'd3datawizard';
}

View File

@ -3,7 +3,7 @@
/**
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
*
* https://www.d3data.de
*
* @copyright (C) D3 Data Development (Inh. Thomas Dartsch)
@ -19,4 +19,4 @@ use OxidEsales\Eshop\Core\Exception\StandardException;
class DataWizardException extends StandardException
{
}
}

View File

@ -3,7 +3,7 @@
/**
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
*
* https://www.d3data.de
*
* @copyright (C) D3 Data Development (Inh. Thomas Dartsch)
@ -20,13 +20,13 @@ use OxidEsales\Eshop\Core\Registry;
class DebugException extends DataWizardException
{
public function __construct($sMessage = "not set", $iCode = 0, Exception $previous = null )
public function __construct($sMessage = "not set", $iCode = 0, Exception $previous = null)
{
$sMessage = sprintf(
Registry::getLang()->translateString('D3_DATAWIZARD_DEBUG'),
$sMessage
);
parent::__construct($sMessage, $iCode, $previous );
parent::__construct($sMessage, $iCode, $previous);
}
}
}

View File

@ -3,7 +3,7 @@
/**
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
*
* https://www.d3data.de
*
* @copyright (C) D3 Data Development (Inh. Thomas Dartsch)
@ -20,13 +20,13 @@ use OxidEsales\Eshop\Core\Registry;
class ExportFileException extends DataWizardException
{
public function __construct($sMessage = "not set", $iCode = 0, Exception $previous = null )
public function __construct($sMessage = "not set", $iCode = 0, Exception $previous = null)
{
$sMessage = sprintf(
Registry::getLang()->translateString('D3_DATAWIZARD_ERR_EXPORTFILEERROR'),
$sMessage
);
parent::__construct($sMessage, $iCode, $previous );
parent::__construct($sMessage, $iCode, $previous);
}
}
}

View File

@ -3,7 +3,7 @@
/**
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
*
* https://www.d3data.de
*
* @copyright (C) D3 Data Development (Inh. Thomas Dartsch)
@ -21,8 +21,7 @@ use FormManager\Inputs\Input;
class InputUnvalidException extends DataWizardException
{
/** @var QueryBase */
public $task;
public QueryBase $task;
/**
* InputUnvalidException constructor.
@ -32,7 +31,7 @@ class InputUnvalidException extends DataWizardException
* @param Exception|null $previous
* @throws Exception
*/
public function __construct( QueryBase $task, Input $inputElement, $iCode = 0, Exception $previous = null )
public function __construct(QueryBase $task, Input $inputElement, $iCode = 0, Exception $previous = null)
{
$messages = [];
foreach ($inputElement->getError()->getIterator() as $item) {
@ -43,11 +42,11 @@ class InputUnvalidException extends DataWizardException
' - ',
[
$task->getTitle(),
implode(', ', $messages)
implode(', ', $messages),
]
);
parent::__construct( $sMessage, $iCode, $previous );
parent::__construct($sMessage, $iCode, $previous);
$this->task = $task;
}
}
}

View File

@ -3,7 +3,7 @@
/**
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
*
* https://www.d3data.de
*
* @copyright (C) D3 Data Development (Inh. Thomas Dartsch)
@ -20,13 +20,13 @@ use OxidEsales\Eshop\Core\Registry;
class NoSuitableRendererException extends DataWizardException
{
public function __construct($sMessage = "not set", $iCode = 0, Exception $previous = null )
public function __construct($sMessage = "not set", $iCode = 0, Exception $previous = null)
{
$sMessage = sprintf(
Registry::getLang()->translateString('D3_DATAWIZARD_ERR_NOSUITABLERENDERER'),
$sMessage
);
parent::__construct($sMessage, $iCode, $previous );
parent::__construct($sMessage, $iCode, $previous);
}
}
}

View File

@ -3,7 +3,7 @@
/**
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
*
* https://www.d3data.de
*
* @copyright (C) D3 Data Development (Inh. Thomas Dartsch)
@ -17,4 +17,4 @@ namespace D3\DataWizard\Application\Model\Exceptions;
class RenderException extends DataWizardException
{
}
}

View File

@ -3,7 +3,7 @@
/**
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
*
* https://www.d3data.de
*
* @copyright (C) D3 Data Development (Inh. Thomas Dartsch)
@ -20,20 +20,19 @@ use Exception;
class TaskException extends DataWizardException
{
/** @var QueryBase */
public $task;
public QueryBase $task;
public function __construct( QueryBase $task, $sMessage = "not set", $iCode = 0, Exception $previous = null )
public function __construct(QueryBase $task, $sMessage = "not set", $iCode = 0, Exception $previous = null)
{
$sMessage = implode(
' - ',
[
$task->getTitle(),
$sMessage
$sMessage,
]
);
parent::__construct( $sMessage, $iCode, $previous );
parent::__construct($sMessage, $iCode, $previous);
$this->task = $task;
}
}
}

View File

@ -3,7 +3,7 @@
/**
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
*
* https://www.d3data.de
*
* @copyright (C) D3 Data Development (Inh. Thomas Dartsch)
@ -15,50 +15,60 @@ declare(strict_types=1);
namespace D3\DataWizard\Application\Model;
use Assert\Assert;
use D3\DataWizard\Application\Model\Exceptions\ExportFileException;
use D3\DataWizard\Application\Model\Exceptions\InputUnvalidException;
use D3\DataWizard\Application\Model\Exceptions\NoSuitableRendererException;
use D3\DataWizard\Application\Model\ExportRenderer\RendererBridge;
use D3\DataWizard\Application\Model\ExportRenderer\RendererInterface;
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 Doctrine\DBAL\Connection;
use Doctrine\DBAL\Driver\Exception;
use Doctrine\DBAL\Exception as 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;
use OxidEsales\Eshop\Core\Exception\StandardException;
use OxidEsales\Eshop\Core\Registry;
use OxidEsales\EshopCommunity\Internal\Container\ContainerFactory;
use OxidEsales\EshopCommunity\Internal\Framework\Database\ConnectionProviderInterface;
use Psr\Container\ContainerExceptionInterface;
use Psr\Container\NotFoundExceptionInterface;
abstract class ExportBase implements QueryBase
{
protected $formElements = [];
protected array $formElements = [];
/**
* Ensure that the translations are equally available in the frontend and the backend
* @return string
*/
public function getDescription() : string
public function getDescription(): string
{
return '';
}
/**
* @param string $format
* @param $path
* @param null $path
*
* @return string
* @throws ContainerExceptionInterface
* @throws DBALException
* @throws DatabaseConnectionException
* @throws DatabaseErrorException
* @throws Exceptions\NoSuitableRendererException
* @throws Exceptions\TaskException
* @throws Exception
* @throws NoSuitableRendererException
* @throws NotFoundExceptionInterface
* @throws StandardException
* @throws d3ShopCompatibilityAdapterException
* @throws d3_cfg_mod_exception
* @return string
*/
public function run( string $format = RendererBridge::FORMAT_CSV, $path = null): string
public function run(string $format = RendererBridge::FORMAT_CSV, $path = null): string
{
if ($this->hasFormElements()) {
/** @var Input $element */
@ -69,59 +79,34 @@ abstract class ExportBase implements QueryBase
}
}
[ $rows, $fieldNames ] = $this->getExportData( $this->getQuery() );
$content = $this->renderContent($rows, $fieldNames, $format);
/** @var $oFS d3filesystem */
$oFS = oxNew( d3filesystem::class );
if (is_null($path)) {
$oFS->startDirectDownload( $oFS->filterFilename( $this->getExportFileName( $format ) ), $content );
} else {
$filePath = $oFS->trailingslashit($path).$oFS->filterFilename( $this->getExportFileName( $format ) );
if (false === $oFS->createFile($filePath, $content,true)) {
throw oxNew(ExportFileException::class, $filePath);
}
return $filePath;
}
return '';
return $this->executeExport($format, $path);
}
/**
* @return string
*/
public function getButtonText() : string
public function getButtonText(): string
{
return "D3_DATAWIZARD_EXPORT_SUBMIT";
}
/**
* @param $format
*
* @return ExportRenderer\RendererInterface
* @throws Exceptions\NoSuitableRendererException
* @throws NoSuitableRendererException
*/
public function getRenderer($format): ExportRenderer\RendererInterface
public function getRenderer(string $format): RendererInterface
{
return $this->getRendererBridge()->getRenderer($format);
}
/**
* @return RendererBridge
*/
public function getRendererBridge()
public function getRendererBridge(): RendererBridge
{
return oxNew(RendererBridge::class);
}
/**
* @param $format
*
* @return string
* @throws Exceptions\NoSuitableRendererException
* @throws NoSuitableRendererException
*/
public function getFileExtension($format): string
public function getFileExtension(string $format): string
{
return $this->getRenderer($format)->getFileExtension();
}
@ -143,7 +128,7 @@ abstract class ExportBase implements QueryBase
/**
* @return string
*/
public function getExportFilenameBase() : string
public function getExportFilenameBase(): string
{
return $this->getTitle();
}
@ -154,7 +139,7 @@ abstract class ExportBase implements QueryBase
* @return string
* @throws Exceptions\NoSuitableRendererException
*/
public function getExportFileName($format) : string
public function getExportFileName($format): string
{
return $this->getExportFilenameBase().'_'.date('Y-m-d_H-i-s').'.'.$this->getFileExtension($format);
}
@ -163,52 +148,54 @@ abstract class ExportBase implements QueryBase
* @param array $query
*
* @return array
* @throws DatabaseConnectionException
* @throws DatabaseErrorException
* @throws DBALException
* @throws Exception
*/
public function getExportData( array $query ): array
public function getExportData(array $query): array
{
[ $queryString, $parameters ] = $query;
Assert::that($queryString)->string();
Assert::that($parameters)->isArray();
$queryString = trim($queryString);
if ( strtolower( substr( $queryString, 0, 6 ) ) !== 'select' ) {
if (strtolower(substr($queryString, 0, 6)) !== 'select') {
throw oxNew(
Exceptions\TaskException::class,
$this,
Registry::getLang()->translateString( 'D3_DATAWIZARD_ERR_NOEXPORTSELECT' )
Registry::getLang()->translateString('D3_DATAWIZARD_ERR_NOEXPORTSELECT')
);
}
$rows = DatabaseProvider::getDb( DatabaseProvider::FETCH_MODE_ASSOC )->getAll( $queryString, $parameters );
$rows = $this->getConnection()->executeQuery($queryString, $parameters)->fetchAllAssociative();
if ( count( $rows ) <= 0 ) {
if (count($rows) <= 0) {
throw oxNew(
Exceptions\TaskException::class,
$this,
Registry::getLang()->translateString( 'D3_DATAWIZARD_ERR_NOEXPORTCONTENT', null, true )
Registry::getLang()->translateString('D3_DATAWIZARD_ERR_NOEXPORTCONTENT', null, true)
);
}
$fieldNames = array_keys( $rows[0] );
$fieldNames = array_keys($rows[0]);
return [ $rows, $fieldNames ];
}
/**
* @param Input $input
*/
public function registerFormElement(Input $input)
protected function getConnection(): Connection
{
switch (get_class($input)) {
case Radio::class:
case Checkbox::class:
$input->setTemplate('<p class="form-check">{{ input }} {{ label }}</p>');
$input->setAttribute('class', 'form-check-input');
break;
default:
$input->setTemplate('<p class="formElements">{{ label }} {{ input }}</p>');
$input->setAttribute('class', 'form-control');
return ContainerFactory::getInstance()->getContainer()->get(ConnectionProviderInterface::class)->get();
}
public function registerFormElement(Input $input): void
{
if ($input instanceof Radio || $input instanceof Checkbox) {
$input->setTemplate('<p class="form-check">{{ input }} {{ label }}</p>');
$input->setAttribute('class', 'form-check-input');
} else {
$input->setTemplate('<p class="formElements">{{ label }} {{ input }}</p>');
$input->setAttribute('class', 'form-control');
}
$this->formElements[] = $input;
}
@ -228,4 +215,60 @@ abstract class ExportBase implements QueryBase
{
return $this->formElements;
}
}
/**
* @param string $format
* @param $path
*
* @return string
* @throws ContainerExceptionInterface
* @throws DBALException
* @throws DatabaseConnectionException
* @throws DatabaseErrorException
* @throws Exception
* @throws NoSuitableRendererException
* @throws NotFoundExceptionInterface
* @throws StandardException
* @throws d3ShopCompatibilityAdapterException
* @throws d3_cfg_mod_exception
*/
protected function executeExport(string $format, $path): string
{
$content = $this->getContent($format);
$oFS = $this->getFileSystem();
if (is_null($path)) {
$oFS->startDirectDownload($oFS->filterFilename($this->getExportFileName($format)), $content);
} else {
$filePath = $oFS->trailingslashit($path) . $oFS->filterFilename($this->getExportFileName($format));
if (false === $oFS->createFile($filePath, $content)) {
throw oxNew(ExportFileException::class, $filePath);
}
return $filePath;
}
return '';
}
protected function getFileSystem(): d3filesystem
{
return oxNew(d3filesystem::class);
}
/**
* @param string $format
*
* @return string
* @throws ContainerExceptionInterface
* @throws DBALException
* @throws Exception
* @throws NoSuitableRendererException
* @throws NotFoundExceptionInterface
*/
public function getContent(string $format): string
{
[ $rows, $fieldNames ] = $this->getExportData($this->getQuery());
return $this->renderContent($rows, $fieldNames, $format);
}
}

View File

@ -3,7 +3,7 @@
/**
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
*
* https://www.d3data.de
*
* @copyright (C) D3 Data Development (Inh. Thomas Dartsch)
@ -16,30 +16,35 @@ declare(strict_types=1);
namespace D3\DataWizard\Application\Model\ExportRenderer;
use D3\DataWizard\Application\Model\Exceptions\RenderException;
use League\Csv\EncloseField;
use League\Csv\ColumnConsistency;
use League\Csv\Exception;
use League\Csv\Writer;
use OxidEsales\Eshop\Core\Config;
use OxidEsales\Eshop\Core\Registry;
class Csv implements RendererInterface
{
public function __construct(protected bool $forceEnclose = false)
{}
/**
* @param $rows
* @param $fieldNames
* @param iterable $rows
* @param iterable $fieldNames
*
* @return string
* @throws RenderException
*/
public function getContent($rows, $fieldNames): string
public function getContent(iterable $rows, iterable $fieldNames): string
{
try {
$csv = $this->getCsv();
$csv->insertOne( $fieldNames );
$csv->insertAll( $rows );
return method_exists($csv, 'getContent') ? $csv->getContent() : (string) $csv;
$this->forceEnclose ? $csv->forceEnclosure() : $csv->relaxEnclosure();
$csv->insertOne((array) $fieldNames);
$csv->insertAll($rows);
return (string) $csv;
} catch (Exception $e) {
/** @var RenderException $newException */
$newException = oxNew(RenderException::class, $e->getMessage(), $e->getCode(), $e );
$newException = oxNew(RenderException::class, $e->getMessage(), $e->getCode(), $e);
throw $newException;
}
}
@ -57,20 +62,14 @@ class Csv implements RendererInterface
{
$csv = Writer::createFromString();
EncloseField::addTo($csv, "\t\x1f");
$sEncloser = Registry::getConfig()->getConfigParam('sGiCsvFieldEncloser');
if (false == $sEncloser) {
$sEncloser = '"';
}
$sEncloser = $this->d3GetConfig()->getConfigParam('sGiCsvFieldEncloser') ?? '"';
$csv->setEnclosure($sEncloser);
$sDelimiter = Registry::getConfig()->getConfigParam('sCSVSign');
if (false == $sDelimiter) {
$sDelimiter = ';';
}
$sDelimiter = $this->d3GetConfig()->getConfigParam('sCSVSign') ?? ';';
$csv->setDelimiter($sDelimiter);
$csv->addValidator(new ColumnConsistency(), 'columns_consistency');
return $csv;
}
@ -81,4 +80,12 @@ class Csv implements RendererInterface
{
return 'D3_DATAWIZARD_EXPORT_FORMAT_CSV';
}
}
/**
* @return Config
*/
public function d3GetConfig(): Config
{
return Registry::getConfig();
}
}

View File

@ -3,7 +3,7 @@
/**
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
*
* https://www.d3data.de
*
* @copyright (C) D3 Data Development (Inh. Thomas Dartsch)
@ -16,24 +16,27 @@ declare(strict_types=1);
namespace D3\DataWizard\Application\Model\ExportRenderer;
use D3\DataWizard\Application\Model\Exceptions\RenderException;
use JsonException;
class Json implements RendererInterface
{
/**
* @param $rows
* @param $fieldNames
* @param iterable $rows
* @param iterable $fieldNames
*
* @return string
* @throws RenderException
*/
public function getContent($rows, $fieldNames): string
public function getContent( iterable $rows, iterable $fieldNames): string
{
$flags = JSON_PRETTY_PRINT;
$json = json_encode( $rows, $flags );
if ( $json === false ) {
throw oxNew( RenderException::class, json_last_error_msg(), json_last_error());
try {
$flags = JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES;
return json_encode($rows, $flags);
} catch (JsonException $e) {
/** @var RenderException $newException */
$newException = oxNew(RenderException::class, $e->getMessage(), $e->getCode(), $e);
throw $newException;
}
return $json;
}
public function getFileExtension(): string
@ -48,4 +51,4 @@ class Json implements RendererInterface
{
return "D3_DATAWIZARD_EXPORT_FORMAT_JSON";
}
}
}

View File

@ -3,7 +3,7 @@
/**
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
*
* https://www.d3data.de
*
* @copyright (C) D3 Data Development (Inh. Thomas Dartsch)
@ -20,17 +20,26 @@ use MathieuViossat\Util\ArrayToTextTable;
class Pretty implements RendererInterface
{
/**
* @param $rows
* @param $fieldNames
* @param iterable $rows
* @param iterable $fieldNames
*
* @return string
*/
public function getContent($rows, $fieldNames) : string
public function getContent(iterable $rows, iterable $fieldNames): string
{
$renderer = oxNew(ArrayToTextTable::class, $rows);
$renderer = $this->getArrayToTextTableInstance($rows);
return $renderer->getTable();
}
/**
* @param $rows
* @return ArrayToTextTable
*/
public function getArrayToTextTableInstance($rows): ArrayToTextTable
{
return oxNew(ArrayToTextTable::class, $rows);
}
/**
* @return string
*/
@ -46,4 +55,4 @@ class Pretty implements RendererInterface
{
return "D3_DATAWIZARD_EXPORT_FORMAT_PRETTY";
}
}
}

View File

@ -3,7 +3,7 @@
/**
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
*
* https://www.d3data.de
*
* @copyright (C) D3 Data Development (Inh. Thomas Dartsch)
@ -19,9 +19,9 @@ use D3\DataWizard\Application\Model\Exceptions\NoSuitableRendererException;
class RendererBridge
{
const FORMAT_CSV = 'CSV';
const FORMAT_PRETTY = 'Pretty';
const FORMAT_JSON = 'JSON';
public const FORMAT_CSV = 'CSV';
public const FORMAT_PRETTY = 'Pretty';
public const FORMAT_JSON = 'JSON';
/**
* @return array
@ -31,11 +31,11 @@ class RendererBridge
return [
self::FORMAT_CSV => oxNew(Csv::class),
self::FORMAT_PRETTY => oxNew(Pretty::class),
self::FORMAT_JSON => oxNew(Json::class)
self::FORMAT_JSON => oxNew(Json::class),
];
}
public function getTranslatedRendererIdList()
public function getTranslatedRendererIdList(): array
{
$rendererList = $this->getRendererList();
array_walk($rendererList, [$this, 'translateRendererId']);
@ -45,7 +45,7 @@ class RendererBridge
/**
* @param RendererInterface $instance
*/
protected function translateRendererId(RendererInterface &$instance)
protected function translateRendererId(RendererInterface &$instance): void
{
$instance = $instance->getTitleTranslationId();
}
@ -60,8 +60,8 @@ class RendererBridge
{
$format = strtolower($format);
$rendererList = array_change_key_case($this->getRendererList(), CASE_LOWER);
$rendererListTypes = array_keys(array_change_key_case($rendererList, CASE_LOWER));
$rendererList = array_change_key_case($this->getRendererList());
$rendererListTypes = array_keys(array_change_key_case($rendererList));
if (in_array($format, $rendererListTypes, true)) {
return $rendererList[$format];
@ -71,4 +71,4 @@ class RendererBridge
$e = oxNew(NoSuitableRendererException::class, $format);
throw $e;
}
}
}

View File

@ -3,7 +3,7 @@
/**
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
*
* https://www.d3data.de
*
* @copyright (C) D3 Data Development (Inh. Thomas Dartsch)
@ -18,20 +18,20 @@ namespace D3\DataWizard\Application\Model\ExportRenderer;
interface RendererInterface
{
/**
* @param $rows
* @param $fieldNames
* @param iterable $rows
* @param iterable $fieldNames
*
* @return string
*/
public function getContent($rows, $fieldNames) : string;
public function getContent(iterable $rows, iterable $fieldNames): string;
/**
* @return string
*/
public function getFileExtension() : string;
public function getFileExtension(): string;
/**
* @return string
*/
public function getTitleTranslationId() : string;
}
public function getTitleTranslationId(): string;
}

View File

@ -3,7 +3,7 @@
/**
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
*
* https://www.d3data.de
*
* @copyright (C) D3 Data Development (Inh. Thomas Dartsch)
@ -25,23 +25,23 @@ interface QueryBase
* Ensure that the translations are equally available in the frontend and the backend
* @return string
*/
public function getTitle() : string;
public function getTitle(): string;
/**
* Ensure that the translations are equally available in the frontend and the backend
* @return string
*/
public function getDescription() : string;
public function getDescription(): string;
/**
* @return string
*/
public function getButtonText() : string;
public function getButtonText(): string;
/**
* @return array [string $query, array $parameters]
*/
public function getQuery() : array;
public function getQuery(): array;
/**
* @param Input $input
@ -57,4 +57,4 @@ interface QueryBase
* @return array
*/
public function getFormElements(): array;
}
}

View File

@ -1,8 +0,0 @@
[{block name="submitElements"}]
<div class="btn-group">
<button type="button" class="btn btn-primary" onclick="startTask('[{$id}]')">
<i class="fas fa-fw fa-magic"></i>
[{oxmultilang ident=$item->getButtonText()}]
</button>
</div>
[{/block}]

View File

@ -0,0 +1,25 @@
<?php
/**
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* https://www.d3data.de
*
* @copyright (C) D3 Data Development (Inh. Thomas Dartsch)
* @author D3 Data Development - Daniel Seifert <info@shopmodule.com>
* @link https://www.oxidmodule.com
*/
// @codeCoverageIgnoreStart
declare(strict_types=1);
$sLangName = 'Deutsch';
// -------------------------------
// RESOURCE IDENTITFIER = STRING
// -------------------------------
$aLang = include __DIR__."/../../de/d3DataWizard_translations.php";
// @codeCoverageIgnoreEnd

View File

@ -0,0 +1,25 @@
<?php
/**
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* https://www.d3data.de
*
* @copyright (C) D3 Data Development (Inh. Thomas Dartsch)
* @author D3 Data Development - Daniel Seifert <info@shopmodule.com>
* @link https://www.oxidmodule.com
*/
// @codeCoverageIgnoreStart
declare(strict_types=1);
$sLangName = 'English';
// -------------------------------
// RESOURCE IDENTITFIER = STRING
// -------------------------------
$aLang = include __DIR__."/../../en/d3DataWizard_translations.php";
// @codeCoverageIgnoreEnd

View File

@ -0,0 +1,25 @@
<?php
/**
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* https://www.d3data.de
*
* @copyright (C) D3 Data Development (Inh. Thomas Dartsch)
* @author D3 Data Development - Daniel Seifert <info@shopmodule.com>
* @link https://www.oxidmodule.com
*/
// @codeCoverageIgnoreStart
declare(strict_types=1);
$sLangName = 'Deutsch';
// -------------------------------
// RESOURCE IDENTITFIER = STRING
// -------------------------------
$aLang = include __DIR__."/../../de/d3DataWizard_translations.php";
// @codeCoverageIgnoreEnd

View File

@ -0,0 +1,25 @@
<?php
/**
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* https://www.d3data.de
*
* @copyright (C) D3 Data Development (Inh. Thomas Dartsch)
* @author D3 Data Development - Daniel Seifert <info@shopmodule.com>
* @link https://www.oxidmodule.com
*/
// @codeCoverageIgnoreStart
declare(strict_types=1);
$sLangName = 'English';
// -------------------------------
// RESOURCE IDENTITFIER = STRING
// -------------------------------
$aLang = include __DIR__."/../../en/d3DataWizard_translations.php";
// @codeCoverageIgnoreEnd

View File

@ -3,7 +3,7 @@
/**
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
*
* https://www.d3data.de
*
* @copyright (C) D3 Data Development (Inh. Thomas Dartsch)
@ -11,14 +11,10 @@
* @link https://www.oxidmodule.com
*/
// @codeCoverageIgnoreStart
declare(strict_types=1);
$sLangName = "Deutsch";
// -------------------------------
// RESOURCE IDENTITFIER = STRING
// -------------------------------
$aLang = array(
return [
//Navigation
'charset' => 'UTF-8',
'd3mxDataWizard' => '<i class="fas fa-fw fa-hat-wizard"></i> Data Wizard',
@ -42,6 +38,7 @@ $aLang = array(
'D3_DATAWIZARD_EXPORT_FORMAT_JSON' => 'JSON-Format',
'D3_DATAWIZARD_ACTION_SUBMIT' => 'Aktion starten',
'D3_DATAWIZARD_ACTION_SUBMIT_CONFIRM' => 'Soll die Aktion gestartet werden?',
'D3_DATAWIZARD_DEBUG' => 'Debug: %1$s',
@ -55,4 +52,5 @@ $aLang = array(
'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',
);
];
// @codeCoverageIgnoreEnd

View File

@ -3,7 +3,7 @@
/**
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
*
* https://www.d3data.de
*
* @copyright (C) D3 Data Development (Inh. Thomas Dartsch)
@ -11,13 +11,10 @@
* @link https://www.oxidmodule.com
*/
// @codeCoverageIgnoreStart
declare(strict_types=1);
$sLangName = "English";
// -------------------------------
// RESOURCE IDENTITFIER = STRING
// -------------------------------
$aLang = array(
return [
//Navigation
'charset' => 'UTF-8',
@ -42,6 +39,7 @@ $aLang = array(
'D3_DATAWIZARD_EXPORT_FORMAT_JSON' => 'JSON format',
'D3_DATAWIZARD_ACTION_SUBMIT' => 'run action',
'D3_DATAWIZARD_ACTION_SUBMIT_CONFIRM' => 'Should the action be executed?',
'D3_DATAWIZARD_DEBUG' => 'Debug: %1$s',
@ -55,4 +53,5 @@ $aLang = array(
'D3_DATAWIZARD_ERR_NOACTION_INSTALLED' => 'No actions are installed or activated.',
'D3_DATAWIZARD_ERR_ACTIONRESULT' => '%1$s entry changed',
'D3_DATAWIZARD_ERR_ACTIONRESULTS' => '%1$s entries changed',
);
];
// @codeCoverageIgnoreEnd

View File

@ -1,46 +1,85 @@
# Changelog
All notable changes to this project will be documented in this file.
## 1.4.0.0 (2021-11-11)
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
#### Added
## [unreleased](https://git.d3data.de/D3Public/DataWizard/compare/3.0.0.0...rel_3.x) - 2023-09-12
## [3.0.0.0](https://git.d3data.de/D3Public/DataWizard/compare/2.1.1.3...3.0.0.0) - 2024-05-13
### Added
- installable in OXID 7.0 + 7.1
- Twig support
### Removed
- support for OXID < 7
## [2.1.1.3](https://git.d3data.de/D3Public/DataWizard/compare/2.1.1.2...2.1.1.3) - 2023-09-12
### Added
- apply roles and rights
## [2.1.1.2](https://git.d3data.de/D3Public/DataWizard/compare/2.1.1.1...2.1.1.2) - 2023-03-30
### Fixed
- fix JavaScript for multiple forms
## [2.1.1.1](https://git.d3data.de/D3Public/DataWizard/compare/2.1.1.0...2.1.1.1) - 2023-03-22
### Fixed
- wrong cascaded HTML elements
## [2.1.1.0](https://git.d3data.de/D3Public/DataWizard/compare/2.1.0.0...2.1.1.0) - 2022-12-24
### Added
- installable in OXID 6.5.0 and 6.5.1
- request confirmation before execute action
### Changed
- documentation extended
## [2.1.0.0](https://git.d3data.de/D3Public/DataWizard/compare/2.0.0.0...2.1.0.0) - 2021-12-21
### Changed
- adjust to CLI extension which can export to STDOUT
## [2.0.0.0](https://git.d3data.de/D3Public/DataWizard/compare/1.4.0.0...2.0.0.0) - 2021-12-20
### Added
- add tests
- make installable in OXID 6.4
### Changed
- adjust code to PHP 7.3 and up
## [1.4.0.0](https://git.d3data.de/D3Public/DataWizard/compare/1.3.1.0...1.4.0.0) - 2021-11-11
### Added
- add JSON export renderer
- add tpl block for easier extension
- enable controller based exception handling
#### Changed
### Changed
- change deprecated CSV export code
- show registered export renderers in admin submit without required tpl block extension
- force get translations from admin
---
## 1.3.1.0 (2021-09-10)
## [1.3.1.0](https://git.d3data.de/D3Public/DataWizard/compare/1.2.0.0...1.3.0.0) - 2021-09-10
### Added
- installable in OXID 6.3.1
---
## 1.3.0.0 (2021-07-29)
## [1.3.0.0](https://git.d3data.de/D3Public/DataWizard/compare/1.2.0.0...1.3.0.0) - 2021-07-29
### Changed
- can handle long task description text
- has more generic admin controller templates
---
## 1.2.0.0 (2021-07-27)
## [1.2.0.0](https://git.d3data.de/D3Public/DataWizard/compare/1.1.0.0...1.2.0.0) - 2021-07-27
### Added
- adjustments for CLI extension
### Fixed
- fix OXID 6.1 incompatibilities
---
## 1.1.0.0 (2021-06-25)
## [1.1.0.0](https://git.d3data.de/D3Public/DataWizard/compare/1.0.0.0...1.1.0.0) - 2021-06-25
### Added
- implement form builder
### Fixed
- fix key figures export
---
## 1.0.0.0 (2021-06-22)
## [1.0.0.0](https://git.d3data.de/D3Public/DataWizard/releases/tag/1.0.0.0) - 2021-06-22
### Added
- initial implementation

View File

@ -9,20 +9,39 @@ The exports are defined via database queries or ready-made data lists. Various e
All exports and tasks are grouped together for better clarity.
Sample exports are included in the package d3/datawizardtasks. These are intended to serve as an implementation reference for individual exports.
Sample exports are included in the package `d3/datawizardtasks`. These are intended to serve as an implementation reference for individual exports.
![administration area](assets/administration_exports.jpg "administration area")
## Table of content
- [Installation](#installation)
- [Usage](#usage)
- [Extensibility](#extensibility)
- [Extension packages](#extension-packages)
- [Changelog](#changelog)
- [Contributing](#contributing)
- [License](#license)
- [Further licences and terms of use](#further-licences-and-terms-of-use)
## Installation
In the console in the shop root (above source and vendor), execute the following command:
This package requires an Composer installed OXID eShop as defined in [composer.json](composer.json).
Open a command line interface and navigate to the shop root directory (parent of source and vendor). Execute the following command. Adapt the paths to your environment.
```bash
php composer require d3/datawizard
php composer require d3/datawizard:^2.0
```
Activate the module in the admin area of the shop in "Extensions -> Modules".
## Usage
These package doesn't contain any export or action items. See [Extension packages](#extension_packages) for installable example items.
Log in to the admin area of your shop and navigate to "DÂł Modules -> Data Wizard". Go to "Exports" or "Actions" (as desired). Choose your desired item and export or execute it.
## 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:
@ -33,7 +52,7 @@ The module represents the technical basic framework of the exports and does not
Independently of this, all extension options are available that the OXID Shop provides for modules.
## Extension packages
### Extension packages
- `d3/datawizardtasks` - provides sample exports and their implementation reference
- `d3/datawizardcli` - provides the execution of exports or tasks via the command prompt (e.g. as cronjobs)
@ -43,9 +62,21 @@ Independently of this, all extension options are available that the OXID Shop pr
See [CHANGELOG](CHANGELOG.md) for further informations.
## Licence of this software (d3/datawizard)
## Contributing
If you have a suggestion that would make this better, please fork the repo and create a pull request. You can also simply open an issue. Don't forget to give the project a star! Thanks again!
- Fork the Project
- Create your Feature Branch (git checkout -b feature/AmazingFeature)
- Commit your Changes (git commit -m 'Add some AmazingFeature')
- Push to the Branch (git push origin feature/AmazingFeature)
- Open a Pull Request
## License
(status: 2021-05-06)
Distributed under the GPLv3 license.
```
Copyright (c) D3 Data Development (Inh. Thomas Dartsch)
@ -118,4 +149,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.
```
```

View File

@ -9,20 +9,40 @@ Die Exporte werden ĂĽber Datenbankabfragen oder fertige Datenlisten definiert. E
Alle Exporte bzw. Tasks sind fĂĽr eine bessere Ăśbersichtlichkeit in Gruppen zusammengefasst.
Im Paket d3/datawizardtasks sind Beispielexporte enthalten. Diese sollen als Implementierungsreferenz fĂĽr individuelle Exporte dienen.
Im Paket `d3/datawizardtasks` sind Beispielexporte enthalten. Diese sollen als Implementierungsreferenz fĂĽr individuelle Exporte dienen.
![Adminbereich](assets/administration_exports.jpg "Adminbereich")
## Schnellinstallation
## Inhaltsverzeichnis
- [Installation](#installation)
- [Verwendung](#verwendung)
- [Erweiterbarkeit](#erweiterbarkeit)
- [Erweiterungspakete](#erweiterungspakete)
- [Changelog](#changelog)
- [Beitragen](#beitragen)
- [Lizenz](#lizenz)
- [weitere Lizenzen und Nutzungsbedingungen](#weitere-lizenzen-und-nutzungsbedingungen)
## Installation
Dieses Paket erfordert einen mit Composer installierten OXID eShop in einer in der [composer.json](composer.json) definierten Version.
Ă–ffnen Sie eine Kommandozeile und navigieren Sie zum Stammverzeichnis des Shops (Elternverzeichnis von source und vendor). FĂĽhren Sie den folgenden Befehl aus. Passen Sie die Pfadangaben an Ihre Installationsumgebung an.
Auf der Konsole im Shoproot (oberhalb von source und vendor) folgenden Befehl ausfĂĽhren:
```bash
php composer require d3/datawizard
php composer require d3/datawizard:^2.0
```
Aktivieren Sie das Modul im Shopadmin unter "Erweiterungen -> Module".
## Verwendung
Dieses Paket enthält keine Exporte oder Aktionen. In [Erweiterungspakete](#erweiterungspakete) finden Sie installierbare Beispieleinträge.
Melden Sie sich im Adminbereich Ihres Shops an und navigieren Sie zu "D³ Module -> Data Wizard". Wechseln Sie je nach Wunsch zu "Exporte" oder "Aktionen". Wählen Sie den gewünschten Eintrag und starten Sie den Export bzw. die Aktion.
## 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:
@ -33,7 +53,7 @@ Das Modul stellt das technische GrundgerĂĽst der Exporte dar und erhebt keinen A
Unabhängig dessen stehen alle Erweiterungsmöglichkeiten zur Verfügung, die der OXID Shop für Module bereitstellt.
## Erweiterungspakete
### Erweiterungspakete
- `d3/datawizardtasks` - liefert Beispielexporte und deren Implementierungsreferenz
- `d3/datawizardcli` - ermöglicht die Ausführung der Exporte oder Tasks über die Eingabeaufforderung (z.B. als Cronjobs)
@ -43,9 +63,21 @@ Unabhängig dessen stehen alle Erweiterungsmöglichkeiten zur Verfügung, die de
Siehe [CHANGELOG](CHANGELOG.md) fĂĽr weitere Informationen.
## Lizenz dieser Software (d3/datawizard)
## Beitragen
Wenn Sie eine Verbesserungsvorschlag haben, legen Sie einen Fork des Repositories an und erstellen Sie einen Pull Request. Alternativ können Sie einfach ein Issue erstellen. Fügen Sie das Projekt zu Ihren Favoriten hinzu. Vielen Dank.
- Erstellen Sie einen Fork des Projekts
- Erstellen Sie einen Feature Branch (git checkout -b feature/AmazingFeature)
- FĂĽgen Sie Ihre Ă„nderungen hinzu (git commit -m 'Add some AmazingFeature')
- Ăśbertragen Sie den Branch (git push origin feature/AmazingFeature)
- Ă–ffnen Sie einen Pull Request
## Lizenz
(Stand: 06.05.2021)
Vertrieben unter der GPLv3 Lizenz.
```
Copyright (c) D3 Data Development (Inh. Thomas Dartsch)

View File

@ -1,6 +1,6 @@
{
"name": "d3/datawizard",
"description": "das magische Datenwerkzeug",
"description": "the magical data tool /\n das magische Datenwerkzeug",
"type": "oxideshop-module",
"keywords": [
"oxid",
@ -25,20 +25,17 @@
"GPL-3.0-or-later"
],
"require": {
"php": ">=7.1",
"oxid-esales/oxideshop-ce": "6.3 - 6.9",
"php": "^8.0",
"oxid-esales/oxideshop-ce": "7.0 - 7.1",
"league/csv": "^9.0",
"mathieuviossat/arraytotexttable": "^1.0",
"form-manager/form-manager": "^5.1 || ^6.1"
"form-manager/form-manager": "^6.1",
"d3/modcfg": "^7.0",
"beberlei/assert": "^3.3.2"
},
"extra": {
"oxideshop": {
"blacklist-filter": [
"*.md",
"composer.json"
],
"target-directory": "d3/datawizard"
}
"require-dev": {
"d3/testingtools": "^1.2.0.0",
"phpunit/phpunit": "^9.1.1"
},
"suggest": {
"d3/datawizardtasks": "useful example tasks for Data Wizard",
@ -47,7 +44,11 @@
},
"autoload": {
"psr-4": {
"D3\\DataWizard\\": "../../../source/modules/d3/datawizard"
"D3\\DataWizard\\": "./"
}
},
"scripts": {
"phpunit": "XDEBUG_MODE=coverage ./vendor/bin/phpunit --config=vendor/d3/datawizard/ --no-coverage",
"phpunit-coverage": "XDEBUG_MODE=coverage ./vendor/bin/phpunit --config=vendor/d3/datawizard/ --coverage-html=vendor/d3/datawizard/tests/result/coverage"
}
}

2
dependencies.yaml Normal file
View File

@ -0,0 +1,2 @@
modules:
- d3modcfg_lib

View File

@ -13,12 +13,11 @@
declare(strict_types=1);
/**
* Metadata version
*/
use D3\DataWizard\Application\Model\Constants;
$sMetadataVersion = '2.1';
$sModuleId = 'd3datawizard';
$sModuleId = Constants::OXID_MODULE_ID;
$logo = '<img src="https://logos.oxidmodule.com/d3logo.svg" alt="(D3)" style="height:1em;width:1em">';
/**
@ -31,31 +30,31 @@ $aModule = [
'de' => '',
'en' => '',
],
'thumbnail' => '',
'version' => '1.4.0.0',
'thumbnail' => 'picture.svg',
'version' => '3.0.0.0',
'author' => 'D&sup3; Data Development (Inh.: Thomas Dartsch)',
'email' => 'support@shopmodule.com',
'url' => 'https://www.oxidmodule.com/',
'controllers' => [
'd3ExportWizard' => D3\DataWizard\Application\Controller\Admin\d3ExportWizard::class,
'd3ActionWizard' => D3\DataWizard\Application\Controller\Admin\d3ActionWizard::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',
'd3Wizards.tpl' => 'd3/datawizard/Application/views/admin/tpl/inc/Wizards.tpl',
'd3ExportSubmit.tpl' => 'd3/datawizard/Application/views/admin/tpl/inc/exportSubmit.tpl',
'd3ActionSubmit.tpl' => 'd3/datawizard/Application/views/admin/tpl/inc/actionSubmit.tpl',
'@' . Constants::OXID_MODULE_ID . '/admin/d3ExportWizard.tpl' => 'views/smarty/admin/d3ExportWizard.tpl',
'@' . Constants::OXID_MODULE_ID . '/admin/d3ActionWizard.tpl' => 'views/smarty/admin/d3ActionWizard.tpl',
'@' . Constants::OXID_MODULE_ID . '/admin/inc/d3Wizards.tpl' => 'views/smarty/admin/inc/Wizards.tpl',
'@' . Constants::OXID_MODULE_ID . '/admin/inc/d3ExportSubmit.tpl' => 'views/smarty/admin/inc/exportSubmit.tpl',
'@' . Constants::OXID_MODULE_ID . '/admin/inc/d3ActionSubmit.tpl' => 'views/smarty/admin/inc/actionSubmit.tpl',
],
'settings' => [
[
'group' => $sModuleId.'_general',
'name' => $sModuleId.'_debug',
'type' => 'bool',
'value' => false
]
'value' => false,
],
],
'blocks' => []
'blocks' => [],
];

36
phpunit.xml Normal file
View File

@ -0,0 +1,36 @@
<?xml version="1.0"?>
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
backupGlobals="true"
bootstrap="../../../source/bootstrap.php"
colors="false"
backupStaticAttributes="false"
convertErrorsToExceptions="true"
convertNoticesToExceptions="false"
convertWarningsToExceptions="true"
forceCoversAnnotation="false"
processIsolation="false"
stopOnError="false"
stopOnFailure="false"
stopOnIncomplete="false"
stopOnSkipped="false"
beStrictAboutTestsThatDoNotTestAnything="false"
verbose="false"
xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/9.3/phpunit.xsd">
<testsuites>
<testsuite name="Unit">
<directory>tests/unit</directory>
</testsuite>
</testsuites>
<coverage includeUncoveredFiles="true" processUncoveredFiles="true">
<include>
<directory suffix=".php">Application</directory>
</include>
<exclude>
<file>../.php-cs-fixer.php</file>
<file>../IntelliSenseHelper.php</file>
</exclude>
</coverage>
<php>
<const name="OXID_PHP_UNIT" value="true"/>
</php>
</phpunit>

84
picture.svg Normal file
View File

@ -0,0 +1,84 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 14.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 43363) -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" id="Ebene_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
width="201px" height="124px" viewBox="0 0 201 124" enable-background="new 0 0 201 124" xml:space="preserve">
<g>
<linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="47.0591" y1="67.5117" x2="47.0591" y2="54.6143">
<stop offset="0.0056" style="stop-color:#3266A9"/>
<stop offset="1" style="stop-color:#0099FF"/>
</linearGradient>
<path fill="url(#SVGID_1_)" d="M50.282,55.502c-0.784-0.592-2.104-0.888-3.961-0.888h-1.376l-2.283,12.898h1.779
c3.76,0,6.032-2.245,6.815-6.733c0.134-0.871,0.202-1.642,0.202-2.313C51.457,57.081,51.064,56.093,50.282,55.502z"/>
<linearGradient id="SVGID_2_" gradientUnits="userSpaceOnUse" x1="65.9609" y1="49.104" x2="65.9609" y2="36.9434">
<stop offset="0.0056" style="stop-color:#3266A9"/>
<stop offset="1" style="stop-color:#0099FF"/>
</linearGradient>
<path fill="url(#SVGID_2_)" d="M65.72,40.482c1.074,0,1.611,0.381,1.611,1.143c0,0.701-0.321,1.201-0.962,1.5
c-0.209,0.119-0.366,0.194-0.471,0.224c-0.065,0.019-0.158,0.037-0.271,0.056c1.98,1.621,3.702,3.544,5.097,5.699
c0.117-0.321,0.21-0.658,0.277-1.013l0.09-1.008c0-1.223-0.568-2.081-1.701-2.574c0.776-0.402,1.376-0.94,1.801-1.611
c0.425-0.672,0.638-1.418,0.638-2.239c0-0.642-0.198-1.265-0.593-1.868c-0.396-0.605-0.98-1.049-1.757-1.333
c-0.433-0.193-0.876-0.328-1.332-0.402c-0.456-0.075-1.003-0.113-1.645-0.113c-0.82,0-1.663,0.124-2.529,0.37
c-0.865,0.246-1.6,0.563-2.204,0.952s-1.13,0.907-1.578,1.557c-0.036,0.052-0.066,0.109-0.101,0.163
c1.196,0.534,2.341,1.163,3.426,1.874C63.947,40.943,64.68,40.482,65.72,40.482z"/>
<linearGradient id="SVGID_3_" gradientUnits="userSpaceOnUse" x1="50.0576" y1="87.0566" x2="50.0576" y2="37.8525">
<stop offset="0.0056" style="stop-color:#3266A9"/>
<stop offset="1" style="stop-color:#0099FF"/>
</linearGradient>
<path fill="url(#SVGID_3_)" d="M70.725,49.104c-0.433,1.189-1.208,2.147-2.331,2.871c-1.425,0.918-3.182,1.377-5.271,1.377
c-1.179,0-2.175-0.176-2.988-0.525c-0.813-0.35-1.444-0.864-1.891-1.543c-0.448-0.678-0.671-1.481-0.671-2.405l0.022-0.694
l0.156-0.693h4.367l-0.028,0.179v0.179v0.246c0,1.164,0.628,1.746,1.884,1.746c0.635,0,1.201-0.217,1.696-0.649
c0.495-0.434,0.742-0.94,0.742-1.522c0-0.522-0.194-0.887-0.582-1.097c-0.329-0.208-1.007-0.313-2.036-0.313l0.47-2.754
l1.141-0.067c0.083-0.011,0.154-0.022,0.221-0.033c-0.674-0.551-1.378-1.067-2.11-1.546c-0.044,0.096-0.087,0.195-0.125,0.302
h-4.185c0.192-0.837,0.49-1.56,0.884-2.175c-3.064-1.372-6.46-2.133-10.034-2.133c-13.588,0-24.603,11.014-24.603,24.601
c0,13.59,11.015,24.604,24.603,24.604S74.66,76.043,74.66,62.453C74.66,57.532,73.214,52.949,70.725,49.104z M59.413,59.233
l-0.168,1.275c-0.538,2.953-1.511,5.404-2.921,7.35c-1.298,1.835-3.016,3.179-5.153,4.028c-2.138,0.851-4.494,1.274-7.067,1.274
H33.731l4.264-24.198h10.441c1.141,0,2.204,0.073,3.189,0.218c0.984,0.146,1.868,0.364,2.651,0.655
c1.611,0.537,2.887,1.471,3.827,2.802c0.94,1.332,1.41,2.992,1.41,4.984L59.413,59.233z"/>
</g>
<linearGradient id="SVGID_4_" gradientUnits="userSpaceOnUse" x1="107.3027" y1="105.8555" x2="93.0727" y2="16.0106">
<stop offset="0" style="stop-color:#B2B2B2;stop-opacity:0"/>
<stop offset="0.2" style="stop-color:#B2B2B2"/>
<stop offset="0.8" style="stop-color:#B2B2B2"/>
<stop offset="1" style="stop-color:#B2B2B2;stop-opacity:0"/>
</linearGradient>
<rect x="99.875" y="14.933" fill="url(#SVGID_4_)" width="0.625" height="92"/>
<script xmlns=""></script>
<g>
<g>
<path fill="none" d="M153.855,40.748H140.76v9.354c0,1.034-0.839,1.872-1.871,1.872h-9.354v20.582
c0,1.031,0.838,1.869,1.871,1.869h22.45c0.083,0,0.159-0.014,0.239-0.023l-5.59-5.588h-13.358c-1.032,0-1.871-0.84-1.871-1.871
c0-1.033,0.839-1.871,1.871-1.871h9.617l-3.742-3.743h-5.875c-1.032,0-1.871-0.837-1.871-1.871c0-1.034,0.839-1.871,1.871-1.871
h3.215c-0.183-1.584,0.68-3.495,2.505-5.326c0.765-0.765,2.763-2.533,4.869-2.533c0.546,0,1.063,0.117,1.527,0.339
c0.346,0.133,0.668,0.338,0.945,0.615l7.52,7.517V42.618C155.728,41.585,154.889,40.748,153.855,40.748z"/>
<polygon fill="none" points="137.018,43.393 132.18,48.231 137.018,48.231 "/>
<path d="M133.275,66.941c0,1.031,0.839,1.871,1.871,1.871h13.358l-3.741-3.742h-9.617
C134.114,65.07,133.275,65.908,133.275,66.941z"/>
<path d="M133.275,59.457c0,1.033,0.839,1.871,1.871,1.871h5.875l-1.73-1.73c-0.272-0.272-0.476-0.587-0.613-0.923
c-0.169-0.339-0.272-0.705-0.316-1.089h-3.215C134.114,57.585,133.275,58.423,133.275,59.457z"/>
<path d="M153.855,74.424h-22.45c-1.033,0-1.871-0.838-1.871-1.869V51.973h9.354c1.032,0,1.871-0.838,1.871-1.872v-9.354h13.096
c1.033,0,1.872,0.837,1.872,1.871v15.579l1.419,1.42l1.301-1.736l-0.989-2.9c-0.358-1.065-0.215-2.155,0.394-3.001
c0.401-0.559,0.971-0.953,1.617-1.147v-8.215c0-3.1-2.514-5.613-5.613-5.613h-14.967c-0.496,0-0.973,0.197-1.322,0.548
L126.34,48.779c-0.351,0.352-0.548,0.827-0.548,1.323v22.453c0,3.1,2.514,5.611,5.613,5.611h22.45
c1.139,0,2.196-0.342,3.081-0.924l-2.842-2.842C154.015,74.41,153.938,74.424,153.855,74.424z M137.018,43.393v4.838h-4.838
L137.018,43.393z"/>
</g>
<g>
<g>
<g>
<path fill="#010002" d="M159.092,62.488l3.655-0.048c0.479-0.006,1.107,0.314,1.388,0.71l2.109,2.982
c0.281,0.393,0.624,0.34,0.769-0.125l1.089-3.486c0.14-0.466,0.636-0.96,1.098-1.103l3.487-1.084
c0.465-0.142,0.52-0.488,0.126-0.768l-2.985-2.112c-0.396-0.281-0.716-0.903-0.705-1.385l0.044-3.656
c0.006-0.479-0.305-0.644-0.694-0.352l-2.929,2.186c-0.385,0.289-1.076,0.397-1.536,0.246l-3.46-1.177
c-0.459-0.153-0.709,0.093-0.555,0.549l1.179,3.46c0.15,0.455,0.043,1.149-0.24,1.539l-2.19,2.926
C158.447,62.182,158.61,62.492,159.092,62.488z"/>
<path fill="#010002" d="M175.635,82.078l0.061-0.063l-29.578-29.571l-0.033,0.032c-0.005-0.002-0.005-0.006-0.009-0.007
c-0.489-0.496-1.99,0.201-3.343,1.552c-1.348,1.353-2.045,2.848-1.553,3.343c0.003,0.005,0.009,0.005,0.01,0.006l-0.033,0.036
l29.575,29.578l0.059-0.064c0.587,0.313,1.962-0.367,3.215-1.625C175.267,84.037,175.943,82.662,175.635,82.078z
M149.582,60.874c-0.715,0.715-1.469,1.239-2.096,1.51l-4.374-4.4c0.624-0.272,1.368-0.795,2.08-1.503
c0.705-0.708,1.222-1.446,1.497-2.066l4.385,4.41C150.801,59.443,150.28,60.174,149.582,60.874z"/>
</g>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 6.4 KiB

2
tests/.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
reports
.phpunit.result.cache

15
tests/README.md Normal file
View File

@ -0,0 +1,15 @@
# D3 Datawizard Tests
## Requirements
Please install the packages listed in the composer.json in "require-dev". Unfortunately Composer does not provide an automatic installation.
missing ext-sockets
### Configuration
Make sure the module has been activated with a valid license key.
Configure the error reporting to `error_reporting(E_ALL & ~E_DEPRECATED & ~E_USER_DEPRECATED);` in the `config.inc.php` due some deprecation issues in original OXID code
## Unit Tests
commands are described in composer.json scripts section

41
tests/additional.inc.php Executable file
View File

@ -0,0 +1,41 @@
<?php
/**
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* https://www.d3data.de
*
* @copyright (C) D3 Data Development (Inh. Thomas Dartsch)
* @author D3 Data Development - Daniel Seifert <info@shopmodule.com>
* @link https://www.oxidmodule.com
*/
// Include datawizard test config
namespace D3\DataWizard\tests;
use D3\ModCfg\Tests\additional_abstract;
use Exception;
use OxidEsales\Eshop\Core\Exception\StandardException;
include(dirname(__FILE__) . DIRECTORY_SEPARATOR . 'd3datawizard_config.php');
class additional extends additional_abstract
{
/**
* additional constructor.
* @throws StandardException
*/
public function __construct()
{
if (D3DATAWIZARD_REQUIRE_MODCFG) {
$this->reactivateModCfg();
}
}
}
try {
d3GetOxidDIC()->get(additional::class);
} catch (Exception) {
}

14
tests/d3datawizard_config.php Executable file
View File

@ -0,0 +1,14 @@
<?php
/**
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* https://www.d3data.de
*
* @copyright (C) D3 Data Development (Inh. Thomas Dartsch)
* @author D3 Data Development - Daniel Seifert <info@shopmodule.com>
* @link https://www.oxidmodule.com
*/
const D3DATAWIZARD_REQUIRE_MODCFG = true;

View File

@ -0,0 +1,18 @@
<?php
namespace D3\DataWizard\tests\tools;
use D3\DataWizard\Application\Model\ActionBase;
class d3TestAction extends ActionBase
{
public function getTitle(): string
{
return 'TestTitle';
}
public function getQuery(): array
{
return ["UPDATE 1"];
}
}

View File

@ -0,0 +1,18 @@
<?php
namespace D3\DataWizard\tests\tools;
use D3\DataWizard\Application\Model\ExportBase;
class d3TestExport extends ExportBase
{
public function getTitle(): string
{
return 'TestTitle';
}
public function getQuery(): array
{
return ["SELECT 1"];
}
}

View File

@ -0,0 +1,199 @@
<?php
/**
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* https://www.d3data.de
*
* @copyright (C) D3 Data Development (Inh. Thomas Dartsch)
* @author D3 Data Development - Daniel Seifert <info@shopmodule.com>
* @link https://www.oxidmodule.com
*/
declare(strict_types=1);
namespace D3\DataWizard\tests\unit\Application\Controller\Admin;
use D3\DataWizard\Application\Controller\Admin\d3ActionWizard;
use D3\DataWizard\Application\Model\Configuration;
use D3\DataWizard\Application\Model\Constants;
use D3\DataWizard\Application\Model\Exceptions\DataWizardException;
use D3\DataWizard\Application\Model\Exceptions\DebugException;
use D3\DataWizard\Application\Model\ExportRenderer\RendererBridge;
use D3\DataWizard\tests\tools\d3TestAction;
use Doctrine\DBAL\Exception as DBALException;
use OxidEsales\Eshop\Core\Registry;
use OxidEsales\Eshop\Core\Request;
use OxidEsales\EshopCommunity\Internal\Framework\Module\Facade\ModuleSettingService;
use PHPUnit\Framework\MockObject\MockObject;
use ReflectionException;
class d3ActionWizardTest extends d3AdminController
{
/** @var d3ActionWizard */
protected $_oController;
protected $testClassName = d3ActionWizard::class;
public function setUp(): void
{
parent::setUp();
$this->_oController = oxNew($this->testClassName);
}
/**
* @covers \D3\DataWizard\Application\Controller\Admin\d3ActionWizard::getGroups()
* @test
* @throws ReflectionException
*/
public function canGetGroups()
{
$expected = ['expected' => 'array'];
/** @var Configuration|MockObject $configurationMock */
$configurationMock = $this->getMockBuilder(Configuration::class)
->onlyMethods(['getActionGroups'])
->getMock();
$configurationMock->expects($this->atLeastOnce())->method('getActionGroups')->willReturn($expected);
$this->setValue($this->_oController, 'configuration', $configurationMock);
$this->assertSame(
$expected,
$this->callMethod(
$this->_oController,
'getGroups'
)
);
}
/**
* @covers \D3\DataWizard\Application\Controller\Admin\d3ActionWizard::getGroupTasks()
* @test
* @throws ReflectionException
* @dataProvider canGetGroupTasksDataProvider
*/
public function canGetGroupTasks($argument)
{
$expected = ['expected' => 'array'];
/** @var Configuration|MockObject $configurationMock */
$configurationMock = $this->getMockBuilder(Configuration::class)
->onlyMethods(['getActionsByGroup'])
->getMock();
$configurationMock->expects($this->atLeastOnce())->method('getActionsByGroup')->with($argument)->willReturn($expected);
$this->setValue($this->_oController, 'configuration', $configurationMock);
$this->assertSame(
$expected,
$this->callMethod(
$this->_oController,
'getGroupTasks',
[$argument]
)
);
}
/**
* @return array
*/
public function canGetGroupTasksDataProvider(): array
{
return [
['test1'],
['test2'],
];
}
/**
* @covers \D3\DataWizard\Application\Controller\Admin\d3ActionWizard::execute()
* @test
* @throws ReflectionException
* @dataProvider executePassDataProvider
*/
public function executePass($blDebug)
{
/** @var Request|MockObject $requestMock */
$requestMock = $this->getMockBuilder(get_class(Registry::getRequest()))
->onlyMethods(['getRequestEscapedParameter'])
->getMock();
$requestMock->expects($this->any())->method('getRequestEscapedParameter')->willReturnCallback([$this, 'executePassRequestCallback']);
Registry::set(Request::class, $requestMock);
/** @var ModuleSettingService $settingsServiceMock */
$settingsServiceMock = $this->getMockBuilder(ModuleSettingService::class)
->disableOriginalConstructor()
->onlyMethods(['getBoolean'])
->getMock();
$settingsServiceMock->expects($this->once())->method('getBoolean')->with(
$this->identicalTo('d3datawizard_debug'),
$this->identicalTo(Constants::OXID_MODULE_ID)
)->willReturn($blDebug);
/** @var d3ActionWizard|MockObject $controllerMock */
$controllerMock = $this->getMockBuilder(d3ActionWizard::class)
->onlyMethods(['getSettingsService'])
->getMock();
$controllerMock->method('getSettingsService')->willReturn($settingsServiceMock);
$this->_oController = $controllerMock;
/** @var d3TestAction|MockObject $actionMock */
$actionMock = $this->getMockBuilder(d3TestAction::class)
->onlyMethods([
'getQuery',
'run',
])
->getMock();
$actionMock->expects($this->atLeastOnce())->method('getQuery')->willReturn(['SELECT 1', ['1']]);
$actionMock->expects($this->exactly((int) !$blDebug))->method('run');
/** @var Configuration|MockObject $configurationMock */
$configurationMock = $this->getMockBuilder(Configuration::class)
->onlyMethods(['getActionById'])
->disableOriginalConstructor()
->getMock();
$configurationMock->expects($this->atLeastOnce())->method('getActionById')->with('testTaskId')->willReturn($actionMock);
$this->setValue($this->_oController, 'configuration', $configurationMock);
if ($blDebug) {
$this->expectException(DebugException::class);
}
$this->callMethod(
$this->_oController,
'execute'
);
}
public function executePassRequestCallback($varName)
{
return match ( $varName ) {
'taskid' => 'testTaskId',
'format' => RendererBridge::FORMAT_CSV,
default => oxNew( Request::class )->getRequestEscapedParameter( $varName ),
};
}
/**
* @return array
*/
public function executePassDataProvider(): array
{
return [
'no debug' => [false],
'debug' => [true],
];
}
/**
* @return string[][]
*/
public function runTaskFailedDataProvider(): array
{
return [
[DataWizardException::class],
[DBALException::class],
];
}
}

View File

@ -0,0 +1,267 @@
<?php
/**
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* https://www.d3data.de
*
* @copyright (C) D3 Data Development (Inh. Thomas Dartsch)
* @author D3 Data Development - Daniel Seifert <info@shopmodule.com>
* @link https://www.oxidmodule.com
*/
declare(strict_types=1);
namespace D3\DataWizard\tests\unit\Application\Controller\Admin;
use D3\DataWizard\Application\Controller\Admin\d3ActionWizard;
use D3\DataWizard\Application\Controller\Admin\d3ExportWizard;
use D3\DataWizard\Application\Model\Configuration;
use D3\DataWizard\Application\Model\Exceptions\DataWizardException;
use D3\DataWizard\Application\Model\Exceptions\DebugException;
use D3\DataWizard\tests\tools\d3TestAction;
use D3\ModCfg\Tests\unit\d3ModCfgUnitTestCase;
use Doctrine\DBAL\Exception as DBALException;
use Exception;
use OxidEsales\Eshop\Core\Config;
use OxidEsales\Eshop\Core\Exception\DatabaseErrorException;
use OxidEsales\Eshop\Core\Registry;
use OxidEsales\Eshop\Core\Request;
use OxidEsales\Eshop\Core\UtilsView;
use OxidEsales\EshopCommunity\Internal\Framework\Module\Facade\ModuleSettingService;
use PHPUnit\Framework\MockObject\MockObject;
use Psr\Log\LoggerInterface;
use ReflectionException;
abstract class d3AdminController extends d3ModCfgUnitTestCase
{
/** @var d3ActionWizard|d3ExportWizard */
protected $_oController;
protected $testClassName;
public function tearDown(): void
{
parent::tearDown();
unset($this->_oController);
}
/**
* @covers \D3\DataWizard\Application\Controller\Admin\d3ActionWizard::__construct
* @covers \D3\DataWizard\Application\Controller\Admin\d3ExportWizard::__construct
* @test
* @throws ReflectionException
*/
public function testConstructor()
{
$this->setValue($this->_oController, 'configuration', oxNew(Configuration::class));
$this->callMethod(
$this->_oController,
'__construct'
);
$this->assertInstanceOf(
Configuration::class,
$this->getValue(
$this->_oController,
'configuration'
)
);
}
/**
* @test
* @return void
* @throws ReflectionException
* @covers \D3\DataWizard\Application\Controller\Admin\d3ActionWizard::getViewId
* @covers \D3\DataWizard\Application\Controller\Admin\d3ExportWizard::getViewId
*/
public function canGetViewId(): void
{
$viewId = $this->callMethod($this->_oController, 'getViewId');
$this->assertIsString($viewId);
$this->assertStringStartsWith('d3mxDataWizard', $viewId);
}
/**
* @covers \D3\DataWizard\Application\Controller\Admin\d3ActionWizard::runTask()
* @covers \D3\DataWizard\Application\Controller\Admin\d3ExportWizard::runTask()
* @test
* @throws ReflectionException
*/
public function runTaskPass()
{
/** @var d3ActionWizard|d3ExportWizard|MockObject $controllerMock */
$controllerMock = $this->getMockBuilder($this->testClassName)
->onlyMethods(['execute'])
->getMock();
$controllerMock->expects($this->once())->method('execute');
$this->_oController = $controllerMock;
$this->callMethod(
$this->_oController,
'runTask'
);
}
/**
* @covers \D3\DataWizard\Application\Controller\Admin\d3ActionWizard::runTask()
* @covers \D3\DataWizard\Application\Controller\Admin\d3ExportWizard::runTask()
* @test
* @param $exceptionClass
* @throws ReflectionException
* @dataProvider runTaskFailedDataProvider
*/
public function runTaskFailed($exceptionClass)
{
/** @var DataWizardException|DBALException|DatabaseErrorException|MockObject $exceptionMock */
$exceptionMock = $this->getMockBuilder($exceptionClass)
->setConstructorArgs(['exc_msg', 20, new Exception()])
->getMock();
/** @var d3ActionWizard|d3ExportWizard|MockObject $controllerMock */
$controllerMock = $this->getMockBuilder($this->testClassName)
->onlyMethods(['execute'])
->getMock();
$controllerMock->expects($this->once())->method('execute')->willThrowException($exceptionMock);
/** @var LoggerInterface|MockObject $loggerMock */
$loggerMock = $this->getMockBuilder(get_class(Registry::getLogger()))
->onlyMethods(['error'])
->disableOriginalConstructor()
->getMock();
$loggerMock->expects($this->atLeastOnce())->method('error')->with('exc_msg')->willReturn(true);
Registry::set('logger', $loggerMock);
/** @var UtilsView|MockObject $utilsViewMock */
$utilsViewMock = $this->getMockBuilder(get_class(Registry::getUtilsView()))
->onlyMethods(['addErrorToDisplay'])
->getMock();
$utilsViewMock->expects($this->atLeastOnce())->method('addErrorToDisplay')->with($exceptionMock)->willReturn(true);
Registry::set(UtilsView::class, $utilsViewMock);
$this->_oController = $controllerMock;
$this->callMethod(
$this->_oController,
'runTask'
);
}
/**
* @covers \D3\DataWizard\Application\Controller\Admin\d3ActionWizard::execute()
* @covers \D3\DataWizard\Application\Controller\Admin\d3ExportWizard::execute()
* @test
* @throws ReflectionException
* @dataProvider executePassDataProvider
*/
public function executePass($blDebug)
{
/** @var Request|MockObject $requestMock */
$requestMock = $this->getMockBuilder(get_class(Registry::getRequest()))
->onlyMethods(['getRequestEscapedParameter'])
->getMock();
$requestMock->expects($this->atLeastOnce())->method('getRequestEscapedParameter')->with('taskid')->willReturn('testTaskId');
Registry::set(Request::class, $requestMock);
/** @var d3TestAction|MockObject $actionMock */
$actionMock = $this->getMockBuilder(d3TestAction::class)
->onlyMethods([
'getQuery',
'run',
])
->getMock();
$actionMock->expects($this->atLeastOnce())->method('getQuery')->willReturn(['SELECT 1', ['1']]);
$actionMock->expects($this->exactly((int) !$blDebug))->method('run')->willReturn(true);
/** @var Configuration|MockObject $configurationMock */
$configurationMock = $this->getMockBuilder(Configuration::class)
->onlyMethods(['getActionById'])
->disableOriginalConstructor()
->getMock();
$configurationMock->expects($this->atLeastOnce())->method('getActionById')->with('testTaskId')->willReturn($actionMock);
$this->setValue($this->_oController, 'configuration', $configurationMock);
/** @var Config|MockObject $configMock */
$configMock = $this->getMockBuilder(Config::class)
->onlyMethods(['getConfigParam'])
->getMock();
$configMock->expects($this->atLeastOnce())->method('getConfigParam')->willReturn($blDebug);
Registry::set(Config::class, $configMock);
if ($blDebug) {
$this->expectException(DebugException::class);
}
$this->callMethod(
$this->_oController,
'execute'
);
}
/**
* @return array
*/
public function executePassDataProvider(): array
{
return [
'no debug' => [false],
'debug' => [true],
];
}
/**
* @covers \D3\DataWizard\Application\Controller\Admin\d3ActionWizard::getUserMessages()
* @covers \D3\DataWizard\Application\Controller\Admin\d3ExportWizard::getUserMessages()
* @test
* @throws ReflectionException
*/
public function canGetUserMessages()
{
$this->assertNull(
$this->callMethod(
$this->_oController,
'getUserMessages'
)
);
}
/**
* @covers \D3\DataWizard\Application\Controller\Admin\d3ActionWizard::getHelpURL()
* @covers \D3\DataWizard\Application\Controller\Admin\d3ExportWizard::getHelpURL()
* @test
* @throws ReflectionException
*/
public function canGetHelpUrl()
{
$this->assertNull(
$this->callMethod(
$this->_oController,
'getHelpURL'
)
);
}
/**
* @test
* @return void
* @throws ReflectionException
* @covers \D3\DataWizard\Application\Controller\Admin\d3ActionWizard::getSettingsService()
* @covers \D3\DataWizard\Application\Controller\Admin\d3ExportWizard::getSettingsService()
*/
public function canGetSettingsService(): void
{
$this->assertInstanceOf(
ModuleSettingService::class,
$this->callMethod(
$this->_oController,
'getSettingsService'
)
);
}
}

View File

@ -0,0 +1,206 @@
<?php
/**
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* https://www.d3data.de
*
* @copyright (C) D3 Data Development (Inh. Thomas Dartsch)
* @author D3 Data Development - Daniel Seifert <info@shopmodule.com>
* @link https://www.oxidmodule.com
*/
declare(strict_types=1);
namespace D3\DataWizard\tests\unit\Application\Controller\Admin;
use D3\DataWizard\Application\Controller\Admin\d3ExportWizard;
use D3\DataWizard\Application\Model\Configuration;
use D3\DataWizard\Application\Model\Constants;
use D3\DataWizard\Application\Model\Exceptions\DataWizardException;
use D3\DataWizard\Application\Model\Exceptions\DebugException;
use D3\DataWizard\Application\Model\ExportRenderer\RendererBridge;
use D3\DataWizard\tests\tools\d3TestAction;
use D3\DataWizard\tests\tools\d3TestExport;
use Doctrine\DBAL\Exception as DBALException;
use OxidEsales\Eshop\Core\Exception\DatabaseErrorException;
use OxidEsales\Eshop\Core\Registry;
use OxidEsales\Eshop\Core\Request;
use OxidEsales\EshopCommunity\Internal\Framework\Module\Facade\ModuleSettingService;
use PHPUnit\Framework\MockObject\MockObject;
use ReflectionException;
class d3ExportWizardTest extends d3AdminController
{
/** @var d3ExportWizard */
protected $_oController;
protected $testClassName = d3ExportWizard::class;
public function setUp(): void
{
parent::setUp();
$this->_oController = oxNew($this->testClassName);
}
/**
* @covers \D3\DataWizard\Application\Controller\Admin\d3ExportWizard::getGroups()
* @test
* @throws ReflectionException
*/
public function canGetGroups()
{
$expected = ['expected' => 'array'];
/** @var Configuration|MockObject $configurationMock */
$configurationMock = $this->getMockBuilder(Configuration::class)
->onlyMethods(['getExportGroups'])
->getMock();
$configurationMock->expects($this->atLeastOnce())->method('getExportGroups')->willReturn($expected);
$this->setValue($this->_oController, 'configuration', $configurationMock);
$this->assertSame(
$expected,
$this->callMethod(
$this->_oController,
'getGroups'
)
);
}
/**
* @covers \D3\DataWizard\Application\Controller\Admin\d3ExportWizard::getGroupTasks()
* @test
* @throws ReflectionException
* @dataProvider canGetGroupTasksDataProvider
*/
public function canGetGroupTasks($argument)
{
$expected = ['expected' => 'array'];
/** @var Configuration|MockObject $configurationMock */
$configurationMock = $this->getMockBuilder(Configuration::class)
->onlyMethods(['getExportsByGroup'])
->getMock();
$configurationMock->expects($this->atLeastOnce())->method('getExportsByGroup')->with($argument)->willReturn($expected);
$this->setValue($this->_oController, 'configuration', $configurationMock);
$this->assertSame(
$expected,
$this->callMethod(
$this->_oController,
'getGroupTasks',
[$argument]
)
);
}
/**
* @return array
*/
public function canGetGroupTasksDataProvider(): array
{
return [
['test1'],
['test2'],
];
}
/**
* @covers \D3\DataWizard\Application\Controller\Admin\d3ExportWizard::execute()
* @test
* @throws ReflectionException
* @dataProvider executePassDataProvider
*/
public function executePass($blDebug)
{
/** @var Request|MockObject $requestMock */
$requestMock = $this->getMockBuilder(get_class(Registry::getRequest()))
->onlyMethods(['getRequestEscapedParameter'])
->getMock();
$requestMock->expects($this->any())->method('getRequestEscapedParameter')->willReturnCallback([$this, 'executePassRequestCallback']);
//OnConsecutiveCalls('testTaskId', 'CSV');
Registry::set(Request::class, $requestMock);
/** @var ModuleSettingService $settingsServiceMock */
$settingsServiceMock = $this->getMockBuilder(ModuleSettingService::class)
->disableOriginalConstructor()
->onlyMethods(['getBoolean'])
->getMock();
$settingsServiceMock->expects($this->once())->method('getBoolean')->with(
$this->identicalTo('d3datawizard_debug'),
$this->identicalTo(Constants::OXID_MODULE_ID)
)->willReturn($blDebug);
/** @var d3ExportWizard|MockObject $controllerMock */
$controllerMock = $this->getMockBuilder(d3ExportWizard::class)
->onlyMethods(['getSettingsService'])
->getMock();
$controllerMock->method('getSettingsService')->willReturn($settingsServiceMock);
$this->_oController = $controllerMock;
/** @var d3TestAction|MockObject $exportMock */
$exportMock = $this->getMockBuilder(d3TestExport::class)
->onlyMethods([
'getQuery',
'run',
])
->getMock();
$exportMock->expects($this->atLeastOnce())->method('getQuery')->willReturn(['SELECT 1', ['1']]);
$exportMock->expects($this->exactly((int) !$blDebug))->method('run')->willReturn('');
/** @var Configuration|MockObject $configurationMock */
$configurationMock = $this->getMockBuilder(Configuration::class)
->onlyMethods(['getExportById'])
->disableOriginalConstructor()
->getMock();
$configurationMock->expects($this->atLeastOnce())->method('getExportById')->with('testTaskId')->willReturn($exportMock);
$this->setValue($this->_oController, 'configuration', $configurationMock);
if ($blDebug) {
$this->expectException(DebugException::class);
}
$this->callMethod(
$this->_oController,
'execute'
);
}
public function executePassRequestCallback($varName)
{
switch ($varName) {
case 'taskid':
return 'testTaskId';
case 'format':
return RendererBridge::FORMAT_CSV;
default:
return oxNew(Request::class)->getRequestEscapedParameter($varName);
}
}
/**
* @return array
*/
public function executePassDataProvider(): array
{
return [
'no debug' => [false],
'debug' => [true],
];
}
/**
* @return string[][]
*/
public function runTaskFailedDataProvider(): array
{
return [
[DataWizardException::class],
[DBALException::class],
[DatabaseErrorException::class],
];
}
}

View File

@ -0,0 +1,318 @@
<?php
/**
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* https://www.d3data.de
*
* @copyright (C) D3 Data Development (Inh. Thomas Dartsch)
* @author D3 Data Development - Daniel Seifert <info@shopmodule.com>
* @link https://www.oxidmodule.com
*/
declare(strict_types=1);
namespace D3\DataWizard\tests\unit\Application\Model;
use D3\DataWizard\Application\Model\Exceptions\TaskException;
use D3\DataWizard\tests\tools\d3TestAction;
use D3\ModCfg\Tests\unit\d3ModCfgUnitTestCase;
use Doctrine\DBAL\Connection;
use FormManager\Inputs\Hidden;
use FormManager\Inputs\Number;
use FormManager\Inputs\Radio;
use OxidEsales\Eshop\Core\Database\Adapter\Doctrine\Database;
use OxidEsales\Eshop\Core\Exception\StandardException;
use PHPUnit\Framework\MockObject\MockObject;
use ReflectionException;
class ActionBaseTest extends d3ModCfgUnitTestCase
{
/** @var d3TestAction */
protected $_oModel;
public function setUp(): void
{
parent::setUp();
$this->_oModel = oxNew(d3TestAction::class);
}
public function tearDown(): void
{
parent::tearDown();
unset($this->_oModel);
}
/**
* @covers \D3\DataWizard\Application\Model\ActionBase::getDescription
* @test
* @throws ReflectionException
*/
public function canGetDescription()
{
$this->assertIsString(
$this->callMethod(
$this->_oModel,
'getDescription'
)
);
}
/**
* @covers \D3\DataWizard\Application\Model\ActionBase::getButtonText
* @test
* @throws ReflectionException
*/
public function canGetButtonText()
{
$this->assertIsString(
$this->callMethod(
$this->_oModel,
'getButtonText'
)
);
}
/**
* @covers \D3\DataWizard\Application\Model\ActionBase::hasFormElements
* @test
* @throws ReflectionException
* @dataProvider canGetHasFormElementsDataProvider
*/
public function canGetHasFormElements($formElements, $expected)
{
$this->setValue($this->_oModel, 'formElements', $formElements);
$this->assertSame(
$expected,
$this->callMethod(
$this->_oModel,
'hasFormElements'
)
);
}
public function canGetHasFormElementsDataProvider(): array
{
return [
'hasFormElements' => [['abc', 'def'], true],
'hasNoFormElements' => [[], false],
];
}
/**
* @covers \D3\DataWizard\Application\Model\ActionBase::getFormElements
* @test
* @throws ReflectionException
* @dataProvider canGetHasFormElementsDataProvider
*/
public function canGetFormElements($formElements)
{
$this->setValue($this->_oModel, 'formElements', $formElements);
$this->assertSame(
$formElements,
$this->callMethod(
$this->_oModel,
'getFormElements'
)
);
}
/**
* @covers \D3\DataWizard\Application\Model\ActionBase::registerFormElement
* @test
* @throws ReflectionException
* @dataProvider canRegisterFormElementDataProvider
*/
public function canRegisterFormElement($inputClass)
{
$oldCount = count($this->getValue($this->_oModel, 'formElements'));
/** @var Radio|MockObject $inputMock */
$inputMock = $this->getMockBuilder($inputClass)
->onlyMethods([
'setTemplate',
'setAttribute',
])
->getMock();
$inputMock->expects($this->atLeastOnce())->method('setTemplate');
$inputMock->expects($this->atLeastOnce())->method('setAttribute');
$this->callMethod(
$this->_oModel,
'registerFormElement',
[$inputMock]
);
$newCount = count($this->getValue($this->_oModel, 'formElements'));
$this->assertGreaterThan($oldCount, $newCount);
}
/**
* @return \string[][]
*/
public function canRegisterFormElementDataProvider(): array
{
return [
'Radio' => [Radio::class],
'Checkbox' => [Radio::class],
'Hidden' => [Hidden::class],
];
}
/**
* @covers \D3\DataWizard\Application\Model\ActionBase::run
* @test
* @throws ReflectionException
*/
public function canRunWithoutFormElements()
{
$modelMock = $this->getMockBuilder(d3TestAction::class)
->onlyMethods([
'hasFormElements',
'executeAction',
'getQuery',
])
->getMock();
$modelMock->expects($this->atLeastOnce())->method('hasFormElements')->willReturn(false);
$modelMock->expects($this->atLeastOnce())->method('executeAction');
$modelMock->expects($this->atLeastOnce())->method('getQuery')->willReturn([]);
$this->_oModel = $modelMock;
$this->callMethod(
$this->_oModel,
'run'
);
}
/**
* @covers \D3\DataWizard\Application\Model\ActionBase::run
* @test
* @throws ReflectionException
* @dataProvider canRunWithFormElementsDataProvider
*/
public function canRunWithFormElements($elements, $blThrowException)
{
$expectedException = oxNew(StandardException::class);
$modelMock = $this->getMockBuilder(d3TestAction::class)
->onlyMethods([
'hasFormElements',
'executeAction',
'getQuery',
'getFormElements',
])
->getMock();
$modelMock->expects($this->atLeastOnce())->method('hasFormElements')->willReturn(true);
$modelMock->expects($this->exactly((int) !$blThrowException))->method('executeAction');
$modelMock->expects($this->exactly((int) !$blThrowException))->method('getQuery')->willReturn([]);
$modelMock->expects($this->atLeastOnce())->method('getFormElements')->willReturn($elements);
$this->_oModel = $modelMock;
if ($blThrowException) {
$this->expectException(get_class($expectedException));
}
$this->callMethod(
$this->_oModel,
'run'
);
}
/**
* @return array[]
*/
public function canRunWithFormElementsDataProvider(): array
{
/** @var Radio|MockObject $validMock */
$validMock = $this->getMockBuilder(Radio::class)
->onlyMethods(['isValid'])
->getMock();
$validMock->expects($this->atLeastOnce())->method('isValid')->willReturn(true);
$invalidField = new Number(null, [
'required' => true,
'min' => 1,
'max' => 10,
'step' => 5,
]);
$invalidField
->setValue(20)
->setErrorMessages(['errorMsgs']);
return [
'validElements' => [[$validMock, $validMock], false],
'invalidElements' => [[$validMock, $invalidField], true],
];
}
/**
* @covers \D3\DataWizard\Application\Model\ActionBase::executeAction
* @test
* @throws ReflectionException
* @dataProvider canExecuteActionDataProvider
*/
public function canExecuteAction($query, $throwsException)
{
/** @var Database|MockObject $connectionMock */
$connectionMock = $this->getMockBuilder(Connection::class)
->disableOriginalConstructor()
->onlyMethods(['executeStatement'])
->getMock();
$connectionMock->expects($this->exactly((int) !$throwsException))->method('executeStatement')->willReturn(1);
/** @var d3TestAction|MockObject $modelMock */
$modelMock = $this->getMockBuilder(d3TestAction::class)
->onlyMethods(['getConnection'])
->getMock();
$modelMock->expects($this->exactly((int) !$throwsException))->method('getConnection')->willReturn($connectionMock);
$this->_oModel = $modelMock;
try {
$this->callMethod(
$this->_oModel,
'executeAction',
[[$query, ['parameters']]]
);
} catch (TaskException $e) {
if ($throwsException) {
$this->assertStringContainsString('keine SELECTs exportieren', $e->getMessage());
} else {
$this->assertStringContainsString('1 Eintrag verändert', $e->getMessage());
}
}
}
/**
* @return array[]
*/
public function canExecuteActionDataProvider(): array
{
return [
'Select throws exception' => ['SELECT 1', true],
'Update dont throws exception' => ['UPDATE 1', false],
];
}
/**
* @covers \D3\DataWizard\Application\Model\ActionBase::getConnection
* @test
* @throws ReflectionException
*/
public function canGetConnection()
{
$this->assertInstanceOf(
Connection::class,
$this->callMethod(
$this->_oModel,
'getConnection'
)
);
}
}

View File

@ -0,0 +1,455 @@
<?php
/**
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* https://www.d3data.de
*
* @copyright (C) D3 Data Development (Inh. Thomas Dartsch)
* @author D3 Data Development - Daniel Seifert <info@shopmodule.com>
* @link https://www.oxidmodule.com
*/
declare(strict_types=1);
namespace D3\DataWizard\tests\unit\Application\Model;
use D3\DataWizard\Application\Model\Configuration;
use D3\DataWizard\Application\Model\Exceptions\DataWizardException;
use D3\DataWizard\tests\tools\d3TestAction;
use D3\DataWizard\tests\tools\d3TestExport;
use D3\ModCfg\Tests\unit\d3ModCfgUnitTestCase;
use PHPUnit\Framework\MockObject\MockObject;
use ReflectionException;
class ConfigurationTest extends d3ModCfgUnitTestCase
{
/** @var Configuration */
protected $_oModel;
public function setUp(): void
{
parent::setUp();
$this->_oModel = oxNew(Configuration::class);
}
public function tearDown(): void
{
parent::tearDown();
unset($this->_oModel);
}
/**
* @covers \D3\DataWizard\Application\Model\Configuration::__construct
* @test
* @throws ReflectionException
*/
public function canConstruct()
{
/** @var Configuration|MockObject $modelMock */
$modelMock = $this->getMockBuilder(Configuration::class)
->disableOriginalConstructor()
->onlyMethods(['configure'])
->getMock();
$modelMock->expects($this->once())->method('configure');
$this->_oModel = $modelMock;
$this->callMethod(
$this->_oModel,
'__construct'
);
}
/**
* @covers \D3\DataWizard\Application\Model\Configuration::configure()
* @test
* @throws ReflectionException
*/
public function canConfigure()
{
$this->assertEmpty(
$this->callMethod(
$this->_oModel,
'configure'
)
);
}
/**
* @covers \D3\DataWizard\Application\Model\Configuration::registerAction
* @test
* @throws ReflectionException
*/
public function canRegisterAction()
{
$action = oxNew(d3TestAction::class);
$oldCount = count($this->getValue(
$this->_oModel,
'actions'
));
$this->callMethod(
$this->_oModel,
'registerAction',
['testGroup', $action]
);
$actions = $this->getValue(
$this->_oModel,
'actions'
);
$newCount = count($actions);
$flattedActions = $this->array_flatten($actions);
$this->assertGreaterThan($oldCount, $newCount);
$this->assertContains($action, $flattedActions);
}
/**
* @covers \D3\DataWizard\Application\Model\Configuration::registerExport
* @test
* @throws ReflectionException
*/
public function canRegisterExport()
{
$export = oxNew(d3TestExport::class);
$oldCount = count($this->getValue(
$this->_oModel,
'exports'
));
$this->callMethod(
$this->_oModel,
'registerExport',
['testGroup', $export]
);
$exports = $this->getValue(
$this->_oModel,
'exports'
);
$newCount = count($exports);
$flattedExports = $this->array_flatten($exports);
$this->assertGreaterThan($oldCount, $newCount);
$this->assertContains($export, $flattedExports);
}
/**
* @param $array
* @return array|false
*/
public function array_flatten($array)
{
if (!is_array($array)) {
return false;
}
$result = [];
foreach ($array as $key => $value) {
if (is_array($value)) {
$result = array_merge($result, $this->array_flatten($value));
} else {
$result[$key] = $value;
}
}
return $result;
}
/**
* @covers \D3\DataWizard\Application\Model\Configuration::getGroupedActions()
* @test
* @throws ReflectionException
*/
public function canGetGroupedActions()
{
$actionList = ['abc', 'def'];
$this->setValue(
$this->_oModel,
'actions',
$actionList
);
$this->assertSame(
$actionList,
$this->callMethod(
$this->_oModel,
'getGroupedActions'
)
);
}
/**
* @covers \D3\DataWizard\Application\Model\Configuration::getGroupedExports()
* @test
* @throws ReflectionException
*/
public function canGetGroupedExports()
{
$exportList = ['abc', 'def'];
$this->setValue(
$this->_oModel,
'exports',
$exportList
);
$this->assertSame(
$exportList,
$this->callMethod(
$this->_oModel,
'getGroupedExports'
)
);
}
/**
* @covers \D3\DataWizard\Application\Model\Configuration::getActionGroups()
* @test
* @throws ReflectionException
*/
public function canGetActionGroups()
{
$actionList = ['abc' => '123', 'def' => '456'];
$this->setValue(
$this->_oModel,
'actions',
$actionList
);
$this->assertSame(
['abc', 'def'],
$this->callMethod(
$this->_oModel,
'getActionGroups'
)
);
}
/**
* @covers \D3\DataWizard\Application\Model\Configuration::getExportGroups()
* @test
* @throws ReflectionException
*/
public function canGetExportGroups()
{
$exportList = ['abc' => '123', 'def' => '456'];
$this->setValue(
$this->_oModel,
'exports',
$exportList
);
$this->assertSame(
['abc', 'def'],
$this->callMethod(
$this->_oModel,
'getExportGroups'
)
);
}
/**
* @covers \D3\DataWizard\Application\Model\Configuration::getActionsByGroup()
* @test
* @throws ReflectionException
*/
public function canGetActionsByGroup()
{
$actionList = ['abc' => ['123'], 'def' => ['456']];
$this->setValue(
$this->_oModel,
'actions',
$actionList
);
$this->assertSame(
['456'],
$this->callMethod(
$this->_oModel,
'getActionsByGroup',
['def']
)
);
}
/**
* @covers \D3\DataWizard\Application\Model\Configuration::getExportsByGroup()
* @test
* @throws ReflectionException
*/
public function canGetExportsByGroup()
{
$exportList = ['abc' => ['123'], 'def' => ['456']];
$this->setValue(
$this->_oModel,
'exports',
$exportList
);
$this->assertSame(
['456'],
$this->callMethod(
$this->_oModel,
'getExportsByGroup',
['def']
)
);
}
/**
* @covers \D3\DataWizard\Application\Model\Configuration::getAllActions()
* @test
* @throws ReflectionException
*/
public function canGetAllActions()
{
/** @var Configuration|MockObject $modelMock */
$modelMock = $this->getMockBuilder(Configuration::class)
->onlyMethods([
'getActionGroups',
'getActionsByGroup',
])
->getMock();
$modelMock->expects($this->once())->method('getActionGroups')->willReturn(['123', '456']);
$modelMock->expects($this->exactly(2))->method('getActionsByGroup')->willReturnOnConsecutiveCalls(
['123', '456'],
['789', '012']
);
$this->_oModel = $modelMock;
$this->assertSame(
['123','456', '789', '012'],
$this->callMethod(
$this->_oModel,
'getAllActions'
)
);
}
/**
* @covers \D3\DataWizard\Application\Model\Configuration::getAllExports()
* @test
* @throws ReflectionException
*/
public function canGetAllExports()
{
/** @var Configuration|MockObject $modelMock */
$modelMock = $this->getMockBuilder(Configuration::class)
->onlyMethods([
'getExportGroups',
'getExportsByGroup',
])
->getMock();
$modelMock->expects($this->once())->method('getExportGroups')->willReturn(['123', '456']);
$modelMock->expects($this->exactly(2))->method('getExportsByGroup')->willReturnOnConsecutiveCalls(
['123', '456'],
['789', '012']
);
$this->_oModel = $modelMock;
$this->assertSame(
['123', '456', '789', '012'],
$this->callMethod(
$this->_oModel,
'getAllExports'
)
);
}
/**
* @covers \D3\DataWizard\Application\Model\Configuration::getActionById()
* @test
* @throws ReflectionException
* @dataProvider canGetActionByIdDataProvider
*/
public function canGetActionById($id, $throwException)
{
$expected = oxNew(d3TestAction::class);
/** @var Configuration|MockObject $modelMock */
$modelMock = $this->getMockBuilder(Configuration::class)
->onlyMethods(['getAllActions'])
->getMock();
$modelMock->expects($this->once())->method('getAllActions')->willReturn(['123' => oxNew(d3TestAction::class), '456' => $expected]);
$this->_oModel = $modelMock;
if ($throwException) {
$this->expectException(DataWizardException::class);
}
$return = $this->callMethod(
$this->_oModel,
'getActionById',
[$id]
);
if (!$throwException) {
$this->assertSame(
$expected,
$return
);
}
}
/**
* @covers \D3\DataWizard\Application\Model\Configuration::getExportById()
* @test
* @throws ReflectionException
* @dataProvider canGetActionByIdDataProvider
*/
public function canGetExportById($id, $throwException)
{
$expected = oxNew(d3TestExport::class);
/** @var Configuration|MockObject $modelMock */
$modelMock = $this->getMockBuilder(Configuration::class)
->onlyMethods(['getAllExports'])
->getMock();
$modelMock->expects($this->once())->method('getAllExports')->willReturn(['123' => oxNew(d3TestExport::class), '456' => $expected]);
$this->_oModel = $modelMock;
if ($throwException) {
$this->expectException(DataWizardException::class);
}
$return = $this->callMethod(
$this->_oModel,
'getExportById',
[$id]
);
if (!$throwException) {
$this->assertSame(
$expected,
$return
);
}
}
/**
* @return array[]
*/
public function canGetActionByIdDataProvider(): array
{
return [
'unset id' => ['987', true],
'set id' => ['456', false],
];
}
}

View File

@ -0,0 +1,78 @@
<?php
/**
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* https://www.d3data.de
*
* @copyright (C) D3 Data Development (Inh. Thomas Dartsch)
* @author D3 Data Development - Daniel Seifert <info@shopmodule.com>
* @link https://www.oxidmodule.com
*/
declare(strict_types=1);
namespace D3\DataWizard\tests\unit\Application\Model\Exceptions;
use D3\DataWizard\Application\Model\Exceptions\DebugException;
use D3\ModCfg\Tests\unit\d3ModCfgUnitTestCase;
use Exception;
use OxidEsales\Eshop\Core\Registry;
use PHPUnit\Framework\MockObject\MockObject;
use ReflectionException;
class DebugExceptionTest extends d3ModCfgUnitTestCase
{
/** @var DebugException */
protected $_oModel;
/**
* @covers \D3\DataWizard\Application\Model\Exceptions\DebugException::__construct
* @test
* @throws ReflectionException
*/
public function canConstruct()
{
$code = '500';
$exception = oxNew(Exception::class);
/** @var DebugException|MockObject $modelMock */
$modelMock = $this->getMockBuilder(DebugException::class)
->disableOriginalConstructor()
->getMock();
$this->_oModel = $modelMock;
$this->callMethod(
$this->_oModel,
'__construct',
['testMessage', $code, $exception]
);
$this->assertStringContainsString(
'Debug: testMessage',
$this->callMethod(
$this->_oModel,
'getMessage'
)
);
$this->assertEquals(
$code,
$this->callMethod(
$this->_oModel,
'getCode'
)
);
$this->assertSame(
$exception,
$this->callMethod(
$this->_oModel,
'getPrevious'
)
);
}
}

View File

@ -0,0 +1,78 @@
<?php
/**
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* https://www.d3data.de
*
* @copyright (C) D3 Data Development (Inh. Thomas Dartsch)
* @author D3 Data Development - Daniel Seifert <info@shopmodule.com>
* @link https://www.oxidmodule.com
*/
declare(strict_types=1);
namespace D3\DataWizard\tests\unit\Application\Model\Exceptions;
use D3\DataWizard\Application\Model\Exceptions\ExportFileException;
use D3\ModCfg\Tests\unit\d3ModCfgUnitTestCase;
use Exception;
use OxidEsales\Eshop\Core\Registry;
use PHPUnit\Framework\MockObject\MockObject;
use ReflectionException;
class ExportFileExceptionTest extends d3ModCfgUnitTestCase
{
/** @var ExportFileException */
protected $_oModel;
/**
* @covers \D3\DataWizard\Application\Model\Exceptions\ExportFileException::__construct
* @test
* @throws ReflectionException
*/
public function canConstruct()
{
$code = '500';
$exception = oxNew(Exception::class);
/** @var ExportFileException|MockObject $modelMock */
$modelMock = $this->getMockBuilder(ExportFileException::class)
->disableOriginalConstructor()
->getMock();
$this->_oModel = $modelMock;
$this->callMethod(
$this->_oModel,
'__construct',
['testMessage', $code, $exception]
);
$this->assertStringContainsString(
'kann nicht angelegt werden',
$this->callMethod(
$this->_oModel,
'getMessage'
)
);
$this->assertEquals(
$code,
$this->callMethod(
$this->_oModel,
'getCode'
)
);
$this->assertSame(
$exception,
$this->callMethod(
$this->_oModel,
'getPrevious'
)
);
}
}

View File

@ -0,0 +1,96 @@
<?php
/**
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* https://www.d3data.de
*
* @copyright (C) D3 Data Development (Inh. Thomas Dartsch)
* @author D3 Data Development - Daniel Seifert <info@shopmodule.com>
* @link https://www.oxidmodule.com
*/
declare(strict_types=1);
namespace D3\DataWizard\tests\unit\Application\Model\Exceptions;
use D3\DataWizard\Application\Model\Exceptions\InputUnvalidException;
use D3\DataWizard\Application\Model\ExportBase;
use D3\DataWizard\tests\tools\d3TestExport;
use D3\ModCfg\Tests\unit\d3ModCfgUnitTestCase;
use Exception;
use FormManager\Inputs\Number;
use PHPUnit\Framework\MockObject\MockObject;
use ReflectionException;
class InputUnvalidExceptionTest extends d3ModCfgUnitTestCase
{
/** @var InputUnvalidException */
protected $_oModel;
/**
* @covers \D3\DataWizard\Application\Model\Exceptions\InputUnvalidException::__construct
* @test
* @throws ReflectionException
*/
public function canConstruct()
{
$code = '500';
$exception = oxNew(Exception::class);
$invalidField = new Number(null, [
'required' => true,
'min' => 1,
'max' => 10,
'step' => 5,
]);
$invalidField
->setValue(20)
->setErrorMessages(['errorMsgs']);
/** @var ExportBase|MockObject $taskMock */
$taskMock = $this->getMockBuilder(d3TestExport::class)
->onlyMethods(['getTitle'])
->getMock();
$taskMock->expects($this->atLeastOnce())->method('getTitle')->willReturn('testTitle');
/** @var InputUnvalidException|MockObject $modelMock */
$modelMock = $this->getMockBuilder(InputUnvalidException::class)
->disableOriginalConstructor()
->getMock();
$this->_oModel = $modelMock;
$this->callMethod(
$this->_oModel,
'__construct',
[$taskMock, $invalidField, $code, $exception]
);
$this->assertMatchesRegularExpression(
'/^testTitle\s-\s*->\s.*\sless\s/m',
$this->callMethod(
$this->_oModel,
'getMessage'
)
);
$this->assertEquals(
$code,
$this->callMethod(
$this->_oModel,
'getCode'
)
);
$this->assertSame(
$exception,
$this->callMethod(
$this->_oModel,
'getPrevious'
)
);
}
}

View File

@ -0,0 +1,78 @@
<?php
/**
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* https://www.d3data.de
*
* @copyright (C) D3 Data Development (Inh. Thomas Dartsch)
* @author D3 Data Development - Daniel Seifert <info@shopmodule.com>
* @link https://www.oxidmodule.com
*/
declare(strict_types=1);
namespace D3\DataWizard\tests\unit\Application\Model\Exceptions;
use D3\DataWizard\Application\Model\Exceptions\NoSuitableRendererException;
use D3\ModCfg\Tests\unit\d3ModCfgUnitTestCase;
use Exception;
use OxidEsales\Eshop\Core\Registry;
use PHPUnit\Framework\MockObject\MockObject;
use ReflectionException;
class NoSuitableRendererExceptionTest extends d3ModCfgUnitTestCase
{
/** @var NoSuitableRendererException */
protected $_oModel;
/**
* @covers \D3\DataWizard\Application\Model\Exceptions\NoSuitableRendererException::__construct
* @test
* @throws ReflectionException
*/
public function canConstruct()
{
$code = '500';
$exception = oxNew(Exception::class);
/** @var NoSuitableRendererException|MockObject $modelMock */
$modelMock = $this->getMockBuilder(NoSuitableRendererException::class)
->disableOriginalConstructor()
->getMock();
$this->_oModel = $modelMock;
$this->callMethod(
$this->_oModel,
'__construct',
['testMessage', $code, $exception]
);
$this->assertStringContainsString(
'kein Renderer f',
$this->callMethod(
$this->_oModel,
'getMessage'
)
);
$this->assertEquals(
$code,
$this->callMethod(
$this->_oModel,
'getCode'
)
);
$this->assertSame(
$exception,
$this->callMethod(
$this->_oModel,
'getPrevious'
)
);
}
}

View File

@ -0,0 +1,85 @@
<?php
/**
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* https://www.d3data.de
*
* @copyright (C) D3 Data Development (Inh. Thomas Dartsch)
* @author D3 Data Development - Daniel Seifert <info@shopmodule.com>
* @link https://www.oxidmodule.com
*/
declare(strict_types=1);
namespace D3\DataWizard\tests\unit\Application\Model\Exceptions;
use D3\DataWizard\Application\Model\Exceptions\TaskException;
use D3\DataWizard\Application\Model\ExportBase;
use D3\DataWizard\tests\tools\d3TestExport;
use D3\ModCfg\Tests\unit\d3ModCfgUnitTestCase;
use Exception;
use PHPUnit\Framework\MockObject\MockObject;
use ReflectionException;
class TaskExceptionTest extends d3ModCfgUnitTestCase
{
/** @var TaskException */
protected $_oModel;
/**
* @covers \D3\DataWizard\Application\Model\Exceptions\TaskException::__construct
* @test
* @throws ReflectionException
*/
public function canConstruct()
{
$code = '500';
$exception = oxNew(Exception::class);
/** @var ExportBase|MockObject $taskMock */
$taskMock = $this->getMockBuilder(d3TestExport::class)
->onlyMethods(['getTitle'])
->getMock();
$taskMock->expects($this->atLeastOnce())->method('getTitle')->willReturn('testTitle');
/** @var TaskException|MockObject $modelMock */
$modelMock = $this->getMockBuilder(TaskException::class)
->disableOriginalConstructor()
->getMock();
$this->_oModel = $modelMock;
$this->callMethod(
$this->_oModel,
'__construct',
[$taskMock, 'testMessage', $code, $exception]
);
$this->assertSame(
'testTitle - testMessage',
$this->callMethod(
$this->_oModel,
'getMessage'
)
);
$this->assertEquals(
$code,
$this->callMethod(
$this->_oModel,
'getCode'
)
);
$this->assertSame(
$exception,
$this->callMethod(
$this->_oModel,
'getPrevious'
)
);
}
}

View File

@ -0,0 +1,644 @@
<?php
/**
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* https://www.d3data.de
*
* @copyright (C) D3 Data Development (Inh. Thomas Dartsch)
* @author D3 Data Development - Daniel Seifert <info@shopmodule.com>
* @link https://www.oxidmodule.com
*/
declare(strict_types=1);
namespace D3\DataWizard\tests\unit\Application\Model;
use D3\DataWizard\Application\Model\Exceptions\ExportFileException;
use D3\DataWizard\Application\Model\Exceptions\TaskException;
use D3\DataWizard\Application\Model\ExportRenderer\Csv;
use D3\DataWizard\Application\Model\ExportRenderer\RendererBridge;
use D3\DataWizard\Application\Model\ExportRenderer\RendererInterface;
use D3\DataWizard\tests\tools\d3TestExport;
use D3\ModCfg\Application\Model\d3filesystem;
use D3\ModCfg\Tests\unit\d3ModCfgUnitTestCase;
use Doctrine\DBAL\Connection;
use Doctrine\DBAL\Driver\Result;
use FormManager\Inputs\Hidden;
use FormManager\Inputs\Number;
use FormManager\Inputs\Radio;
use OxidEsales\Eshop\Core\Database\Adapter\Doctrine\Database;
use OxidEsales\Eshop\Core\Exception\StandardException;
use OxidEsales\Eshop\Core\Registry;
use PHPUnit\Framework\MockObject\MockObject;
use ReflectionException;
class ExportBaseTest extends d3ModCfgUnitTestCase
{
/** @var d3TestExport */
protected $_oModel;
public function setUp(): void
{
parent::setUp();
$this->_oModel = oxNew(d3TestExport::class);
}
public function tearDown(): void
{
parent::tearDown();
unset($this->_oModel);
}
/**
* @covers \D3\DataWizard\Application\Model\ExportBase::getDescription
* @test
* @throws ReflectionException
*/
public function canGetDescription()
{
$this->assertIsString(
$this->callMethod(
$this->_oModel,
'getDescription'
)
);
}
/**
* @covers \D3\DataWizard\Application\Model\ExportBase::getButtonText
* @test
* @throws ReflectionException
*/
public function canGetButtonText()
{
$this->assertIsString(
$this->callMethod(
$this->_oModel,
'getButtonText'
)
);
}
/**
* @covers \D3\DataWizard\Application\Model\ExportBase::hasFormElements
* @test
* @throws ReflectionException
* @dataProvider canGetHasFormElementsDataProvider
*/
public function canGetHasFormElements($formElements, $expected)
{
$this->setValue($this->_oModel, 'formElements', $formElements);
$this->assertSame(
$expected,
$this->callMethod(
$this->_oModel,
'hasFormElements'
)
);
}
public function canGetHasFormElementsDataProvider(): array
{
return [
'hasFormElements' => [['abc', 'def'], true],
'hasNoFormElements' => [[], false],
];
}
/**
* @covers \D3\DataWizard\Application\Model\ExportBase::getFormElements
* @test
* @throws ReflectionException
* @dataProvider canGetHasFormElementsDataProvider
*/
public function canGetFormElements($formElements)
{
$this->setValue($this->_oModel, 'formElements', $formElements);
$this->assertSame(
$formElements,
$this->callMethod(
$this->_oModel,
'getFormElements'
)
);
}
/**
* @covers \D3\DataWizard\Application\Model\ExportBase::registerFormElement
* @test
* @throws ReflectionException
* @dataProvider canRegisterFormElementDataProvider
*/
public function canRegisterFormElement($inputClass)
{
$oldCount = count($this->getValue($this->_oModel, 'formElements'));
/** @var Radio|MockObject $inputMock */
$inputMock = $this->getMockBuilder($inputClass)
->onlyMethods([
'setTemplate',
'setAttribute',
])
->getMock();
$inputMock->expects($this->atLeastOnce())->method('setTemplate');
$inputMock->expects($this->atLeastOnce())->method('setAttribute');
$this->callMethod(
$this->_oModel,
'registerFormElement',
[$inputMock]
);
$newCount = count($this->getValue($this->_oModel, 'formElements'));
$this->assertGreaterThan($oldCount, $newCount);
}
/**
* @return \string[][]
*/
public function canRegisterFormElementDataProvider(): array
{
return [
'Radio' => [Radio::class],
'Checkbox' => [Radio::class],
'Hidden' => [Hidden::class],
];
}
/**
* @covers \D3\DataWizard\Application\Model\ExportBase::run
* @test
* @throws ReflectionException
*/
public function canRunWithoutFormElements()
{
$format = 'myFormat';
$path = 'myPath';
/** @var d3TestExport|MockObject $modelMock */
$modelMock = $this->getMockBuilder(d3TestExport::class)
->onlyMethods([
'hasFormElements',
'executeExport',
])
->getMock();
$modelMock->expects($this->atLeastOnce())->method('hasFormElements')->willReturn(false);
$modelMock->expects($this->atLeastOnce())->method('executeExport')->with($format, $path)->willReturn('some content');
$this->_oModel = $modelMock;
$this->callMethod(
$this->_oModel,
'run',
[$format, $path]
);
}
/**
* @covers \D3\DataWizard\Application\Model\ExportBase::run
* @test
* @throws ReflectionException
* @dataProvider canRunWithFormElementsDataProvider
*/
public function canRunWithFormElements($elements, $blThrowException)
{
$format = 'myFormat';
$path = 'myPath';
$expectedException = oxNew(StandardException::class);
$modelMock = $this->getMockBuilder(d3TestExport::class)
->onlyMethods([
'hasFormElements',
'executeExport',
'getFormElements',
])
->getMock();
$modelMock->expects($this->atLeastOnce())->method('hasFormElements')->willReturn(true);
$modelMock->expects($this->exactly((int) !$blThrowException))->method('executeExport')->with($format, $path)->willReturn('some content');
$modelMock->expects($this->atLeastOnce())->method('getFormElements')->willReturn($elements);
$this->_oModel = $modelMock;
if ($blThrowException) {
$this->expectException(get_class($expectedException));
}
$this->callMethod(
$this->_oModel,
'run',
[$format, $path]
);
}
/**
* @return array[]
*/
public function canRunWithFormElementsDataProvider(): array
{
/** @var Radio|MockObject $validMock */
$validMock = $this->getMockBuilder(Radio::class)
->onlyMethods(['isValid'])
->getMock();
$validMock->expects($this->atLeastOnce())->method('isValid')->willReturn(true);
$invalidField = new Number(null, [
'required' => true,
'min' => 1,
'max' => 10,
'step' => 5,
]);
$invalidField
->setValue(20)
->setErrorMessages(['errorMsgs']);
return [
'validElements' => [[$validMock, $validMock], false],
'invalidElements' => [[$validMock, $invalidField], true],
];
}
/**
* @covers \D3\DataWizard\Application\Model\ExportBase::executeExport
* @test
* @throws ReflectionException
* @dataProvider canExecuteExportDataProvider
*/
public function canExecuteExport($path, $throwsException)
{
/** @var d3filesystem|MockObject $fsMock */
$fsMock = $this->getMockBuilder(d3filesystem::class)
->onlyMethods([
'startDirectDownload',
'filterFilename',
'trailingslashit',
'createFile',
])
->getMock();
$fsMock->expects($this->exactly((int) !isset($path)))->method('startDirectDownload')->willReturn(true);
$fsMock->method('filterFilename')->willReturnArgument(0);
$fsMock->expects($this->exactly((int) isset($path)))->method('trailingslashit')->willReturnArgument(0);
$fsMock->expects($this->exactly((int) isset($path)))->method('createFile')->willReturn((bool) !$throwsException);
/** @var d3TestExport|MockObject $modelMock */
$modelMock = $this->getMockBuilder(d3TestExport::class)
->onlyMethods([
'getContent',
'getFileSystem',
'getExportFileName',
])
->getMock();
$modelMock->expects($this->atLeastOnce())->method('getContent')->willReturn('some content');
$modelMock->expects($this->atLeastOnce())->method('getFileSystem')->willReturn($fsMock);
$modelMock->expects($this->atLeastOnce())->method('getExportFileName')->willReturn('exportFileName');
$this->_oModel = $modelMock;
if ($path && $throwsException) {
$this->expectException(ExportFileException::class);
}
$this->callMethod(
$this->_oModel,
'executeExport',
['CSV', $path]
);
}
/**
* @return array[]
*/
public function canExecuteExportDataProvider(): array
{
return [
'unable to create path for saving file' => ['myPath', true],
'can create path for saving file' => ['myPath', false],
'no path for download' => [null, false],
];
}
/**
* @covers \D3\DataWizard\Application\Model\ExportBase::getConnection
* @test
* @throws ReflectionException
*/
public function canGetConnection()
{
$this->assertInstanceOf(
Connection::class,
$this->callMethod(
$this->_oModel,
'getConnection'
)
);
}
/**
* @covers \D3\DataWizard\Application\Model\ExportBase::getFileSystem
* @test
* @throws ReflectionException
*/
public function canGetFileSystem()
{
$this->assertInstanceOf(
d3filesystem::class,
$this->callMethod(
$this->_oModel,
'getFileSystem'
)
);
}
/**
* @covers \D3\DataWizard\Application\Model\ExportBase::getRenderer
* @test
* @throws ReflectionException
*/
public function canGetRenderer()
{
/** @var RendererInterface|MockObject $rendererMock */
$rendererMock = $this->getMockBuilder(Csv::class)
->getMock();
/** @var RendererBridge|MockObject $rendererBridgeMock */
$rendererBridgeMock = $this->getMockBuilder(RendererBridge::class)
->onlyMethods(['getRenderer'])
->getMock();
$rendererBridgeMock->expects($this->atLeastOnce())->method('getRenderer')->willReturn($rendererMock);
/** @var d3TestExport|MockObject $modelMock */
$modelMock = $this->getMockBuilder(d3TestExport::class)
->onlyMethods([
'getRendererBridge',
])
->getMock();
$modelMock->expects($this->atLeastOnce())->method('getRendererBridge')->willReturn($rendererBridgeMock);
$this->_oModel = $modelMock;
$this->assertSame(
$rendererMock,
$this->callMethod(
$this->_oModel,
'getRenderer',
[RendererBridge::FORMAT_CSV]
)
);
}
/**
* @covers \D3\DataWizard\Application\Model\ExportBase::getRendererBridge
* @test
* @throws ReflectionException
*/
public function canGetRendererBridge()
{
$this->assertInstanceOf(
RendererBridge::class,
$this->callMethod(
$this->_oModel,
'getRendererBridge'
)
);
}
/**
* @covers \D3\DataWizard\Application\Model\ExportBase::getFileExtension
* @test
* @throws ReflectionException
*/
public function canGetFileExtension()
{
$format = RendererBridge::FORMAT_CSV;
$expected = 'myFileExtension';
/** @var RendererInterface|MockObject $rendererMock */
$rendererMock = $this->getMockBuilder(Csv::class)
->onlyMethods(['getFileExtension'])
->getMock();
$rendererMock->expects($this->atLeastOnce())->method('getFileExtension')->willReturn($expected);
/** @var d3TestExport|MockObject $modelMock */
$modelMock = $this->getMockBuilder(d3TestExport::class)
->onlyMethods([
'getRenderer',
])
->getMock();
$modelMock->expects($this->atLeastOnce())->method('getRenderer')->with($format)->willReturn($rendererMock);
$this->_oModel = $modelMock;
$this->assertSame(
$expected,
$this->callMethod(
$this->_oModel,
'getFileExtension',
[$format]
)
);
}
/**
* @covers \D3\DataWizard\Application\Model\ExportBase::renderContent
* @test
* @throws ReflectionException
*/
public function canRenderContent()
{
$rows = ['row1', 'row2'];
$fieldnames = ['fieldname1', 'fieldname2'];
$format = RendererBridge::FORMAT_CSV;
$expected = 'myContent';
/** @var RendererInterface|MockObject $rendererMock */
$rendererMock = $this->getMockBuilder(Csv::class)
->onlyMethods(['getContent'])
->getMock();
$rendererMock->expects($this->atLeastOnce())->method('getContent')->with($rows, $fieldnames)->willReturn($expected);
/** @var d3TestExport|MockObject $modelMock */
$modelMock = $this->getMockBuilder(d3TestExport::class)
->onlyMethods([
'getRenderer',
])
->getMock();
$modelMock->expects($this->atLeastOnce())->method('getRenderer')->with($format)->willReturn($rendererMock);
$this->_oModel = $modelMock;
$this->assertSame(
$expected,
$this->callMethod(
$this->_oModel,
'renderContent',
[$rows, $fieldnames, $format]
)
);
}
/**
* @covers \D3\DataWizard\Application\Model\ExportBase::getExportFilenameBase
* @test
* @throws ReflectionException
*/
public function canGetExportFilenameBase()
{
/** @var d3TestExport|MockObject $modelMock */
$modelMock = $this->getMockBuilder(d3TestExport::class)
->onlyMethods([
'getTitle',
])
->getMock();
$modelMock->expects($this->atLeastOnce())->method('getTitle')->willReturn('someTitle');
$this->_oModel = $modelMock;
$this->callMethod(
$this->_oModel,
'getExportFilenameBase'
);
}
/**
* @covers \D3\DataWizard\Application\Model\ExportBase::getExportFileName
* @test
* @throws ReflectionException
*/
public function canGetExportFileName()
{
$format = RendererBridge::FORMAT_CSV;
/** @var d3TestExport|MockObject $modelMock */
$modelMock = $this->getMockBuilder(d3TestExport::class)
->onlyMethods([
'getExportFilenameBase',
'getFileExtension',
])
->getMock();
$modelMock->expects($this->atLeastOnce())->method('getExportFilenameBase')->willReturn('base');
$modelMock->expects($this->atLeastOnce())->method('getFileExtension')->with($format)->willReturn('extension');
$this->_oModel = $modelMock;
$this->assertMatchesRegularExpression(
'/^base_(\d{4})-(\d{2})-(\d{2})_(\d{2})-(\d{2})-(\d{2})\.extension$/m',
$this->callMethod(
$this->_oModel,
'getExportFileName',
[$format]
)
);
}
/**
* @covers \D3\DataWizard\Application\Model\ExportBase::getExportData
* @test
* @throws ReflectionException
* @dataProvider canGetExportDataDataProvider
*/
public function canGetExportData($query, $throwsException, $dbResult)
{
/** @var Result|MockObject $resultMock */
$resultMock = $this->getMockBuilder(Result::class)
->onlyMethods(get_class_methods(Result::class))
->getMock();
$resultMock->method('fetchAllAssociative')->willReturn($dbResult);
/** @var Database|MockObject $connectionMock */
$connectionMock = $this->getMockBuilder(Connection::class)
->disableOriginalConstructor()
->onlyMethods(['executeQuery'])
->getMock();
$connectionMock->expects($this->exactly((int) !$throwsException))->method('executeQuery')->willReturn($resultMock);
/** @var d3TestExport|MockObject $modelMock */
$modelMock = $this->getMockBuilder(d3TestExport::class)
->onlyMethods([
'getConnection',
])
->getMock();
$modelMock->expects($this->exactly((int) !$throwsException))->method('getConnection')->willReturn($connectionMock);
$this->_oModel = $modelMock;
try {
$result = $this->callMethod(
$this->_oModel,
'getExportData',
[[$query, ['param1', 'param2']]]
);
$this->assertSame(
[
[
[
'field1' => 'content1',
'field2' => 'content2',
],
],
[
'field1',
'field2',
],
],
$result
);
} catch (TaskException $e) {
if ($throwsException) {
$this->assertStringContainsString('Export kann nicht ausgefĂĽhrt werden', $e->getMessage());
} elseif (!count($dbResult)) {
$this->assertStringContainsString('kein Inhalt', $e->getMessage());
}
}
}
/**
* @return array[]
*/
public function canGetExportDataDataProvider(): array
{
return [
'not SELECT throws exception' => [' UPDATE 1', true, []],
'empty SELECT' => [' SELECT 1', false, []],
'fulfilled SELECT' => [' SELECT 1', false, [['field1' => 'content1', 'field2' => 'content2']]],
];
}
/**
* @covers \D3\DataWizard\Application\Model\ExportBase::getContent
* @test
* @throws ReflectionException
*/
public function canGetContent()
{
/** @var d3TestExport|MockObject $modelMock */
$modelMock = $this->getMockBuilder(d3TestExport::class)
->onlyMethods([
'getQuery',
'getExportData',
'renderContent',
])
->getMock();
$modelMock->expects($this->atLeastOnce())->method('getQuery')->willReturn(['SELECT 1', ['arg1', 'arg2']]);
$modelMock->expects($this->atLeastOnce())->method('getExportData')->willReturn([[1, 2], ['field1', 'field2']]);
$modelMock->expects($this->atLeastOnce())->method('renderContent')->willReturn('some content');
$this->_oModel = $modelMock;
$this->assertSame(
'some content',
$this->callMethod(
$this->_oModel,
'getContent',
['CSV']
)
);
}
}

View File

@ -0,0 +1,203 @@
<?php
/**
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* https://www.d3data.de
*
* @copyright (C) D3 Data Development (Inh. Thomas Dartsch)
* @author D3 Data Development - Daniel Seifert <info@shopmodule.com>
* @link https://www.oxidmodule.com
*/
declare(strict_types=1);
namespace D3\DataWizard\tests\unit\Application\Model\ExportRenderer;
use D3\DataWizard\Application\Model\Exceptions\RenderException;
use D3\DataWizard\Application\Model\ExportRenderer\Csv;
use Generator;
use League\Csv\Exception;
use League\Csv\Writer;
use OxidEsales\Eshop\Core\Config;
use OxidEsales\Eshop\Core\Registry;
use PHPUnit\Framework\MockObject\MockObject;
use ReflectionException;
class CsvTest extends ExportRendererTest
{
/** @var Csv */
protected $_oModel;
public function setUp(): void
{
parent::setUp();
$this->_oModel = oxNew(Csv::class);
}
/**
* @test
*
* @param bool $force
*
* @return void
* @throws ReflectionException
* @covers \D3\DataWizard\Application\Model\ExportRenderer\Csv::__construct
* @dataProvider canForceEncloseDataProvider
*/
public function canForceEnclose(bool $force): void
{
$noForce = oxNew(Csv::class, $force);
$this->assertSame(
$force,
$this->getValue(
$noForce,
'forceEnclose'
)
);
}
public function canForceEncloseDataProvider(): Generator
{
yield 'noForce' => [true];
yield 'force' => [false];
}
/**
* @covers \D3\DataWizard\Application\Model\ExportRenderer\Csv::getContent
* @test
* @throws ReflectionException
* @dataProvider canGetContentDataProvider
*/
public function canGetContent($blThrowException)
{
$expected = 'expectedReturn';
$fieldList = ['field1', 'field2'];
$valueList = ['value1', 'value2'];
/** @var Writer|MockObject $csvMock */
$csvMockBuilder = $this->getMockBuilder(Writer::class);
$csvMockBuilder->disableOriginalConstructor();
$onlyMethods = ['__toString', 'insertOne', 'insertAll'];
$csvMockBuilder->onlyMethods($onlyMethods);
$csvMock = $csvMockBuilder->getMock();
$csvMock->method('insertOne')->willReturn(1);
$csvMock->method('insertAll')->willReturn(1);
if ($blThrowException) {
$csvMock->expects($this->atLeastOnce())->method('__toString')->willThrowException(oxNew(Exception::class));
$this->expectException(RenderException::class);
} else {
$csvMock->expects($this->atLeastOnce())->method('__toString')->willReturn($expected);
}
/** @var Csv|MockObject $modelMock */
$modelMock = $this->getMockBuilder(Csv::class)
->onlyMethods(['getCsv'])
->getMock();
$modelMock->expects($this->atLeastOnce())->method('getCsv')->willReturn($csvMock);
$this->_oModel = $modelMock;
$this->assertSame(
$expected,
$this->callMethod(
$this->_oModel,
'getContent',
[$valueList, $fieldList]
)
);
}
/**
* @return array
*/
public function canGetContentDataProvider(): array
{
return [
'exception' => [true],
'no exception' => [false],
];
}
/**
* @covers \D3\DataWizard\Application\Model\ExportRenderer\Csv::getCsv
* @test
* @throws ReflectionException
*/
public function canGetCsv()
{
$this->assertInstanceOf(
Writer::class,
$this->callMethod(
$this->_oModel,
'getCsv'
)
);
}
/**
* @covers \D3\DataWizard\Application\Model\ExportRenderer\Csv::getCsv
* @test
* @throws ReflectionException
*/
public function canGetCsvNoSettings()
{
/** @var Config|MockObject $configMock */
$configMock = $this->getMockBuilder(Config::class)
->onlyMethods(['getConfigParam'])
->getMock();
$configMock->expects($this->atLeastOnce())->method('getConfigParam')->willReturnCallback(
function ($argName) {
return match ( $argName ) {
'sGiCsvFieldEncloser', 'sCSVSign' => null,
default => Registry::getConfig()->getConfigParam( $argName ),
};
}
);
$modelMock = $this->getMockBuilder(Csv::class)
->onlyMethods(['d3GetConfig'])
->getMock();
$modelMock->method('d3GetConfig')->willReturn($configMock);
$this->_oModel = $modelMock;
$csv = $this->callMethod(
$this->_oModel,
'getCsv'
);
$this->assertInstanceOf(
Writer::class,
$csv
);
$this->assertSame(
'"',
$csv->getEnclosure()
);
$this->assertSame(
';',
$csv->getDelimiter()
);
}
/**
* @covers \D3\DataWizard\Application\Model\ExportRenderer\Csv::d3GetConfig
* @test
* @throws ReflectionException
*/
public function canGetConfig()
{
$this->assertInstanceOf(
Config::class,
$this->callMethod(
$this->_oModel,
'd3GetConfig'
)
);
}
}

View File

@ -0,0 +1,66 @@
<?php
/**
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* https://www.d3data.de
*
* @copyright (C) D3 Data Development (Inh. Thomas Dartsch)
* @author D3 Data Development - Daniel Seifert <info@shopmodule.com>
* @link https://www.oxidmodule.com
*/
namespace D3\DataWizard\tests\unit\Application\Model\ExportRenderer;
use D3\DataWizard\Application\Model\ExportRenderer\RendererInterface;
use D3\ModCfg\Tests\unit\d3ModCfgUnitTestCase;
use ReflectionException;
abstract class ExportRendererTest extends d3ModCfgUnitTestCase
{
/** @var RendererInterface */
protected $_oModel;
public function tearDown(): void
{
parent::tearDown();
unset($this->_oModel);
}
/**
* @covers \D3\DataWizard\Application\Model\ExportRenderer\Csv::getFileExtension
* @covers \D3\DataWizard\Application\Model\ExportRenderer\Json::getFileExtension
* @covers \D3\DataWizard\Application\Model\ExportRenderer\Pretty::getFileExtension
* @test
* @throws ReflectionException
*/
public function canGetFileExtension()
{
$this->assertMatchesRegularExpression(
"/^[a-z0-9._-]*$/i",
$this->callMethod(
$this->_oModel,
'getFileExtension'
)
);
}
/**
* @covers \D3\DataWizard\Application\Model\ExportRenderer\Csv::getTitleTranslationId
* @covers \D3\DataWizard\Application\Model\ExportRenderer\Json::getTitleTranslationId
* @covers \D3\DataWizard\Application\Model\ExportRenderer\Pretty::getTitleTranslationId
* @test
* @throws ReflectionException
*/
public function canGetTitleTranslationId()
{
$this->assertIsString(
$this->callMethod(
$this->_oModel,
'getTitleTranslationId'
)
);
}
}

View File

@ -0,0 +1,67 @@
<?php
/**
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* https://www.d3data.de
*
* @copyright (C) D3 Data Development (Inh. Thomas Dartsch)
* @author D3 Data Development - Daniel Seifert <info@shopmodule.com>
* @link https://www.oxidmodule.com
*/
declare(strict_types=1);
namespace D3\DataWizard\tests\unit\Application\Model\ExportRenderer;
use D3\DataWizard\Application\Model\Exceptions\RenderException;
use D3\DataWizard\Application\Model\ExportRenderer\Json;
use ReflectionException;
class JsonTest extends ExportRendererTest
{
/** @var Json */
protected $_oModel;
public function setUp(): void
{
parent::setUp();
$this->_oModel = oxNew(Json::class);
}
/**
* @covers \D3\DataWizard\Application\Model\ExportRenderer\Json::getContent
* @test
* @throws ReflectionException
* @dataProvider canGetContentDataProvider
*/
public function canGetContent($valueList, $expectException)
{
$fieldList = ['field1', 'field2'];
if ($expectException) {
$this->expectException(RenderException::class);
}
$this->assertJson(
$this->callMethod(
$this->_oModel,
'getContent',
[$valueList, $fieldList]
)
);
}
/**
* @return string[][]
*/
public function canGetContentDataProvider(): array
{
return [
'valid' => [['value1', "value2"], false],
'invalid' => [["text" => "\xB1\x31"], true], // malformed UTF8 chars
];
}
}

View File

@ -0,0 +1,86 @@
<?php
/**
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* https://www.d3data.de
*
* @copyright (C) D3 Data Development (Inh. Thomas Dartsch)
* @author D3 Data Development - Daniel Seifert <info@shopmodule.com>
* @link https://www.oxidmodule.com
*/
declare(strict_types=1);
namespace D3\DataWizard\tests\unit\Application\Model\ExportRenderer;
use D3\DataWizard\Application\Model\ExportRenderer\Pretty;
use MathieuViossat\Util\ArrayToTextTable;
use PHPUnit\Framework\MockObject\MockObject;
use ReflectionException;
class PrettyTest extends ExportRendererTest
{
/** @var Pretty */
protected $_oModel;
public function setUp(): void
{
parent::setUp();
$this->_oModel = oxNew(Pretty::class);
}
/**
* @covers \D3\DataWizard\Application\Model\ExportRenderer\Pretty::getContent
* @test
* @throws ReflectionException
*/
public function canGetContent()
{
$expected = 'expectedReturn';
$fieldList = ['field1', 'field2'];
$valueList = ['value1', 'value2'];
/** @var ArrayToTextTable|MockObject $csvMock */
$arrayToTextTableMock = $this->getMockBuilder(ArrayToTextTable::class)
->disableOriginalConstructor()
->onlyMethods(['getTable'])
->getMock();
$arrayToTextTableMock->expects($this->atLeastOnce())->method('getTable')->willReturn($expected);
/** @var Pretty|MockObject $modelMock */
$modelMock = $this->getMockBuilder(Pretty::class)
->onlyMethods(['getArrayToTextTableInstance'])
->getMock();
$modelMock->expects($this->atLeastOnce())->method('getArrayToTextTableInstance')->willReturn($arrayToTextTableMock);
$this->_oModel = $modelMock;
$this->assertSame(
$expected,
$this->callMethod(
$this->_oModel,
'getContent',
[$valueList, $fieldList]
)
);
}
/**
* @covers \D3\DataWizard\Application\Model\ExportRenderer\Pretty::getArrayToTextTableInstance
* @test
* @throws ReflectionException
*/
public function canGetArrayToTextTableInstance()
{
$this->assertInstanceOf(
ArrayToTextTable::class,
$this->callMethod(
$this->_oModel,
'getArrayToTextTableInstance',
[['field1', 'field2']]
)
);
}
}

View File

@ -0,0 +1,152 @@
<?php
/**
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* https://www.d3data.de
*
* @copyright (C) D3 Data Development (Inh. Thomas Dartsch)
* @author D3 Data Development - Daniel Seifert <info@shopmodule.com>
* @link https://www.oxidmodule.com
*/
declare(strict_types=1);
namespace D3\DataWizard\tests\unit\Application\Model\ExportRenderer;
use D3\DataWizard\Application\Model\Exceptions\NoSuitableRendererException;
use D3\DataWizard\Application\Model\ExportRenderer\Csv;
use D3\DataWizard\Application\Model\ExportRenderer\Json;
use D3\DataWizard\Application\Model\ExportRenderer\Pretty;
use D3\DataWizard\Application\Model\ExportRenderer\RendererBridge;
use D3\DataWizard\Application\Model\ExportRenderer\RendererInterface;
use D3\ModCfg\Tests\unit\d3ModCfgUnitTestCase;
use PHPUnit\Framework\MockObject\MockObject;
use ReflectionException;
class RendererBridgeTest extends d3ModCfgUnitTestCase
{
/** @var RendererBridge */
protected $_oModel;
public function setUp(): void
{
parent::setUp();
$this->_oModel = oxNew(RendererBridge::class);
}
public function tearDown(): void
{
parent::tearDown();
unset($this->_oModel);
}
/**
* @covers \D3\DataWizard\Application\Model\ExportRenderer\RendererBridge::getRendererList
* @test
* @throws ReflectionException
*/
public function canGetRendererList()
{
$list = $this->callMethod(
$this->_oModel,
'getRendererList'
);
$this->assertIsArray($list);
$this->assertTrue((bool) count($list));
}
/**
* @covers \D3\DataWizard\Application\Model\ExportRenderer\RendererBridge::getTranslatedRendererIdList
* @test
* @throws ReflectionException
*/
public function canGetTranslatedRendererIdList()
{
$utlist = $this->callMethod(
$this->_oModel,
'getRendererList'
);
$list = $this->callMethod(
$this->_oModel,
'getTranslatedRendererIdList'
);
$this->assertIsArray($list);
$this->assertTrue((bool) count($list));
$this->assertSame(count($utlist), count($list));
}
/**
* @covers \D3\DataWizard\Application\Model\ExportRenderer\RendererBridge::translateRendererId
* @test
* @throws ReflectionException
*/
public function canTranslateRendererId()
{
$expected = "expectedTranslation";
/** @var RendererInterface|MockObject $renderMock */
$renderMock = $this->getMockBuilder(Pretty::class)
->onlyMethods(['getTitleTranslationId'])
->getMock();
$renderMock->expects($this->atLeastOnce())->method('getTitleTranslationId')->willReturn($expected);
$this->callMethod(
$this->_oModel,
'translateRendererId',
[$renderMock]
);
}
/**
* @covers \D3\DataWizard\Application\Model\ExportRenderer\RendererBridge::getRenderer
* @test
* @param $format
* @param $blThrowException
* @throws ReflectionException
* @dataProvider canGetRendererDataProvider
*/
public function canGetRenderer($format, $blThrowException)
{
/** @var RendererBridge|MockObject $modelMock */
$modelMock = $this->getMockBuilder(RendererBridge::class)
->onlyMethods(['getRendererList'])
->getMock();
$modelMock->expects($this->atLeastOnce())->method('getRendererList')->willReturn(
[
'CSV' => $this->getMockBuilder(Csv::class)->getMock(),
'Pretty' => $this->getMockBuilder(Pretty::class)->getMock(),
'JSON' => $this->getMockBuilder(Json::class)->getMock(),
]
);
$this->_oModel = $modelMock;
if ($blThrowException) {
$this->expectException(NoSuitableRendererException::class);
}
$this->callMethod(
$this->_oModel,
'getRenderer',
[$format]
);
}
/**
* @return array
*/
public function canGetRendererDataProvider(): array
{
return [
'existing renderer'=> [RendererBridge::FORMAT_JSON, false],
'unknown renderer'=> ['unknownRenderer', true],
];
}
}

View File

@ -1,4 +1,4 @@
[{capture assign="d3dw_backgroundimage"}]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)[{/capture}]
[{capture assign="d3dw_noitemmessageid"}]D3_DATAWIZARD_ERR_NOACTION_INSTALLED[{/capture}]
[{include file="d3Wizards.tpl" submit="d3ActionSubmit.tpl"}]
[{include file="@d3datawizard/admin/inc/d3Wizards.tpl" submit="@d3datawizard/admin/inc/d3ActionSubmit.tpl"}]

View File

@ -1,4 +1,4 @@
[{capture assign="d3dw_backgroundimage"}]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))[{/capture}]
[{capture assign="d3dw_noitemmessageid"}]D3_DATAWIZARD_ERR_NOEXPORT_INSTALLED[{/capture}]
[{include file="d3Wizards.tpl" submit="d3ExportSubmit.tpl"}]
[{include file="@d3datawizard/admin/inc/d3Wizards.tpl" submit="@d3datawizard/admin/inc/d3ExportSubmit.tpl"}]

View File

@ -6,6 +6,12 @@
[{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"}]
[{if $readonly}]
[{assign var="readonly" value="readonly disabled"}]
[{else}]
[{assign var="readonly" value=""}]
[{/if}]
<style>
button {
margin: 1em 1em 1em 5em;
@ -41,43 +47,45 @@
}, 3000);
document.getElementById('mask').className='on';
document.getElementById('popup2').className='d3loader-2 on';
document.getElementById('taskid').value = id;
document.getElementById('format').value = format;
document.getElementById('myedit').submit();
form = document.getElementById('form_' + id);
form.format.value = format;
form.submit();
}
[{/strip}][{/capture}]
[{oxscript add=$smarty.capture.d3script}]
<form name="myedit" id="myedit" action="[{$oViewConf->getSelfLink()}]" method="post" style="padding: 0;margin: 0;height:0;">
[{$oViewConf->getHiddenSid()}]
<input type="hidden" name="cl" value="[{$oViewConf->getActiveClassName()}]">
<input type="hidden" name="fnc" value="runTask">
<input type="hidden" name="taskid" id="taskid" value="">
<input type="hidden" name="format" id="format" value="CSV">
[{assign var="groups" value=$oView->getGroups()}]
[{if $groups|@count}]
<div id="accordion">
[{foreach from=$oView->getGroups() item="group"}]
<div class="card mb-2">
<div class="card-header p-1" id="heading[{$group}]">
<h4 class="mb-0">
<span class="btn p-1" data-toggle="collapse" data-target="#collapse[{$group}]" aria-expanded="false" aria-controls="collapse[{$group}]">
[{oxmultilang ident=$group}]
</span>
</h4>
</div>
<div id="collapse[{$group}]" class="collapse" aria-labelledby="heading[{$group}]" data-parent="#accordion">
<div class="card-body pb-0">
<div class="row">
[{foreach from=$oView->getGroupTasks($group) key="id" item="item"}]
<div class="col-sm-6 col-md-4 col-lg-3 pb-4">
<div class="card">
<h5 class="card-header">
[{$item->getTitle()}]
</h5>
<div class="card-body">
<form name="myedit" id="form_[{$id}]" action="[{$oViewConf->getSelfLink()}]" method="post">
[{$oViewConf->getHiddenSid()}]
<input type="hidden" name="cl" value="[{$oViewConf->getActiveClassName()}]">
<input type="hidden" name="fnc" value="runTask">
<input type="hidden" name="taskid" value="[{$id}]">
<input type="hidden" name="format" value="CSV">
[{assign var="groups" value=$oView->getGroups()}]
[{if $groups|@count}]
<div id="accordion">
[{foreach from=$oView->getGroups() item="group"}]
<div class="card mb-2">
<div class="card-header p-1" id="heading[{$group}]">
<h4 class="mb-0">
<span class="btn p-1" data-toggle="collapse" data-target="#collapse[{$group}]" aria-expanded="false" aria-controls="collapse[{$group}]">
[{oxmultilang ident=$group}]
</span>
</h4>
</div>
<div id="collapse[{$group}]" class="collapse" aria-labelledby="heading[{$group}]" data-parent="#accordion">
<div class="card-body pb-0">
<div class="row">
[{foreach from=$oView->getGroupTasks($group) key="id" item="item"}]
<div class="col-sm-6 col-md-4 col-lg-3 pb-4">
<div class="card">
<h5 class="card-header">
[{$item->getTitle()}]
</h5>
<div class="card-body">
[{if $item->getDescription()}]
[{assign var="description" value=$item->getDescription()}]
[{assign var="sectionlength" value="100"}]
@ -89,7 +97,7 @@
<p class="card-text" data-toggle="collapse" data-target="#collapseExample" aria-expanded="false" aria-controls="collapseExample" style="cursor: pointer">
[{$shorttext}]...
</p>
<p class="card-text collapse" id="collapseExample">
<p class="card-text collapse" id="collapseExample_[{$id}]">
...[{$description|replace:$shorttext:''}]
</p>
[{/if}]
@ -104,25 +112,27 @@
[{block name="exportSubmit"}]
[{include file=$submit}]
[{/block}]
</div>
</form>
</div>
</div>
[{/foreach}]
</div>
<div class="clear"></div>
</div>
[{/foreach}]
</div>
<div class="clear"></div>
</div>
</div>
</div>
[{/foreach}]
</div>
[{else}]
<div class="alert alert-primary" role="alert">
[{oxmultilang ident=$d3dw_noitemmessageid}]
</div>
[{/if}]
</form>
[{/foreach}]
</div>
[{else}]
<div class="alert alert-primary" role="alert">
[{oxmultilang ident=$d3dw_noitemmessageid}]
</div>
[{/if}]
<div id="mask" class=""></div>
<div id="popup2" class="d3loader-2">
@ -133,4 +143,4 @@
</div>
</div>
[{include file="d3_cfg_mod_inc.tpl"}]
[{include file="@d3modcfg_lib/admin/inc/inc.tpl"}]

View File

@ -0,0 +1,8 @@
[{block name="submitElements"}]
<div class="btn-group" [{$readonly}]>
<button type="button" class="btn btn-primary" onclick="if (confirm('[{oxmultilang ident="D3_DATAWIZARD_ACTION_SUBMIT_CONFIRM"}]') === true) {startTask('[{$id}]')}" [{$readonly}]>
<i class="fas fa-fw fa-magic"></i>
[{oxmultilang ident=$item->getButtonText()}]
</button>
</div>
[{/block}]

View File

@ -1,10 +1,10 @@
[{block name="submitElements"}]
<div class="btn-group">
<button type="button" class="btn btn-primary" onclick="startTask('[{$id}]', 'CSV')">
<div class="btn-group" [{$readonly}]>
<button type="button" class="btn btn-primary" onclick="startTask('[{$id}]', 'CSV')" [{$readonly}]>
<i class="fas fa-fw fa-magic"></i>
[{oxmultilang ident=$item->getButtonText()}]
</button>
<button type="button" class="btn btn-primary dropdown-toggle dropdown-toggle-split" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<button type="button" class="btn btn-primary dropdown-toggle dropdown-toggle-split" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false" [{$readonly}]>
<span class="sr-only">
<i class="fas fa-fw fa-magic"></i>
[{oxmultilang ident=$item->getButtonText()}]
@ -14,7 +14,7 @@
[{block name="dataWizardFormat"}]
[{assign var="rendererBridge" value=$item->getRendererBridge()}]
[{foreach from=$rendererBridge->getTranslatedRendererIdList() key="key" item="translationId"}]
<button class="dropdown-item" onclick="startTask('[{$id}]', '[{$key}]')">
<button class="dropdown-item" onclick="startTask('[{$id}]', '[{$key}]')" [{$readonly}]>
[{oxmultilang ident=$translationId}]
</button>
[{/foreach}]

View File

@ -0,0 +1,4 @@
{% set d3dw_backgroundimage %}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){% endset %}
{% set d3dw_noitemmessageid %}D3_DATAWIZARD_ERR_NOACTION_INSTALLED{% endset %}
{% include "@d3datawizard/admin/inc/Wizards.html.twig" with {submit: "@d3datawizard/admin/inc/actionSubmit.html.twig"} %}

View File

@ -0,0 +1,4 @@
{% set d3dw_backgroundimage %}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)){% endset %}
{% set d3dw_noitemmessageid %}D3_DATAWIZARD_ERR_NOEXPORT_INSTALLED{% endset %}
{% include "@d3datawizard/admin/inc/Wizards.html.twig" with {submit: "@d3datawizard/admin/inc/exportSubmit.html.twig"} %}

View File

@ -0,0 +1,137 @@
{% include "headitem.html.twig" with {title: "GENERAL_ADMIN_TITLE"|translate} %}
{{ style({ include: "https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" }) }}
{{ script({ include: "https://code.jquery.com/jquery-3.2.1.slim.min.js", dynamic: __oxid_include_dynamic }) }}
{{ script({ include: "https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js", dynamic: __oxid_include_dynamic }) }}
{{ script({ include: "https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js", dynamic: __oxid_include_dynamic }) }}
{{ style({ include: "https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.3/css/solid.min.css" }) }}
<style>
button {
margin: 1em 1em 1em 5em;
}
html {
font-size: 0.8em;
}
/* Image courtesy of gradientmagic.com */
body {
background-image: {{ d3dw_backgroundimage }};
}
h4 .btn {
font-size: 1.3rem;
}
h5.card-header {
font-size: 1.1rem;
}
.formElements label {
display: inline-block;
margin: .5rem 0;
}
</style>
{% capture assign = "d3script" %}{% apply spaceless %}
function startTask(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('taskid').value = id;
document.getElementById('format').value = format;
document.getElementById('myedit').submit();
}
{% endapply %}{% endcapture %}
{{ script({ add: d3script, dynamic: __oxid_include_dynamic }) }}
<form name="myedit" id="myedit" action="{{ oViewConf.getSelfLink() }}" method="post" style="padding: 0;margin: 0;height:0;">
{{ oViewConf.getHiddenSid()|raw }}
<input type="hidden" name="cl" value="{{ oViewConf.getActiveClassName() }}">
<input type="hidden" name="fnc" value="runTask">
<input type="hidden" name="taskid" id="taskid" value="">
<input type="hidden" name="format" id="format" value="CSV">
{% set groups = oView.getGroups() %}
{% if groups|length %}
<div id="accordion">
{% for group in oView.getGroups() %}
<div class="card mb-2">
<div class="card-header p-1" id="heading{{ group }}">
<h4 class="mb-0">
<span class="btn p-1" data-toggle="collapse" data-target="#collapse{{ group }}" aria-expanded="false" aria-controls="collapse{{ group }}">
{{ translate({ ident: group }) }}
</span>
</h4>
</div>
<div id="collapse{{ group }}" class="collapse" aria-labelledby="heading{{ group }}" data-parent="#accordion">
<div class="card-body pb-0">
<div class="row">
{% for id, item in oView.getGroupTasks(group) %}
<div class="col-sm-6 col-md-4 col-lg-3 pb-4">
<div class="card">
<h5 class="card-header">
{{ item.getTitle() }}
</h5>
<div class="card-body">
{% if item.getDescription() %}
{% set description = item.getDescription() %}
{% set sectionlength = "100" %}
{% if description|length <= sectionlength %}
<p class="card-text">{{ description }}</p>
{% else %}
{% set shorttext = description|truncate(sectionlength, '') %}
<p class="card-text" data-toggle="collapse" data-target="#collapseExample" aria-expanded="false" aria-controls="collapseExample" style="cursor: pointer">
{{ shorttext }}...
</p>
<p class="card-text collapse" id="collapseExample">
...{{ description|replace({shorttext:''}) }}
</p>
{% endif %}
{% endif %}
{% if item.hasFormElements() %}
{% for formElement in item.getFormElements() %}
{{ formElement|raw }}
{% endfor %}
{% endif %}
{% block exportSubmit %}
{% include submit %}
{% endblock %}
</div>
</div>
</div>
{% endfor %}
</div>
<div class="clear"></div>
</div>
</div>
</div>
{% endfor %}
</div>
{% else %}
<div class="alert alert-primary" role="alert">
{{ translate({ ident: d3dw_noitemmessageid }) }}
</div>
{% endif %}
</form>
<div id="mask" class=""></div>
<div id="popup2" class="d3loader-2">
<div class="d3loader-spinner">
<div class="d3loader-circle-1"></div>
<div class="d3loader-circle-2"></div>
<div class="d3loader-circle-3"></div>
</div>
</div>
{% include "@d3modcfg_lib/admin/inc/inc.html.twig" %}

View File

@ -0,0 +1,8 @@
{% block submitElements %}
<div class="btn-group">
<button type="button" class="btn btn-primary" onclick="if (confirm('{{ translate({ ident: "D3_DATAWIZARD_ACTION_SUBMIT_CONFIRM" }) }}') === true) {startTask('{{ id }}')}">
<i class="fas fa-fw fa-magic"></i>
{{ translate({ ident: item.getButtonText() }) }}
</button>
</div>
{% endblock %}

View File

@ -0,0 +1,24 @@
{% block submitElements %}
<div class="btn-group">
<button type="button" class="btn btn-primary" onclick="startTask('{{ id }}', 'CSV')">
<i class="fas fa-fw fa-magic"></i>
{{ translate({ ident: item.getButtonText() }) }}
</button>
<button type="button" class="btn btn-primary dropdown-toggle dropdown-toggle-split" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<span class="sr-only">
<i class="fas fa-fw fa-magic"></i>
{{ translate({ ident: item.getButtonText() }) }}
</span>
</button>
<div class="dropdown-menu">
{% block dataWizardFormat %}
{% set rendererBridge = item.getRendererBridge() %}
{% for key, translationId in rendererBridge.getTranslatedRendererIdList() %}
<button class="dropdown-item" onclick="startTask('{{ id }}', '{{ key }}')">
{{ translate({ ident: translationId }) }}
</button>
{% endfor %}
{% endblock %}
</div>
</div>
{% endblock %}