From 336b4363b0b0008a25e1ba7aa1425b80b1659c64 Mon Sep 17 00:00:00 2001 From: Dominik Pfaffenbauer Date: Tue, 20 Jun 2023 14:51:33 +0200 Subject: [PATCH 01/22] [Next] prepare Pimcore 11 --- composer.json | 16 +- config/config.yaml | 1 - config/migrations.yaml | 19 -- config/packages/security.yaml | 49 ++--- config/routes.yaml | 2 +- config/routes/dev/routes.yaml | 3 +- config/system.yml | 17 -- .../Command/ExportCommand.php | 14 +- .../Command/ImportCommand.php | 13 +- .../AbstractDefinitionController.php | 41 ++++ .../Controller/ExportDefinitionController.php | 16 +- .../Controller/ImportDefinitionController.php | 43 ++-- .../Controller/ImportRuleController.php | 2 +- .../DataDefinitionsBundle.php | 41 ++-- .../DependencyInjection/Configuration.php | 87 ++++++++ .../DataDefinitionsExtension.php | 16 +- .../EventListener/PimcoreSettingsListener.php | 30 +++ .../EventListener/WriteableListener.php | 47 +++++ .../Fetcher/ObjectsFetcher.php | 2 +- .../Importer/Importer.php | 8 + .../Model/AbstractDataDefinition.php | 12 +- .../Model/DataDefinitionInterface.php | 4 - .../Model/ExportDefinition.php | 12 +- .../Model/ExportDefinition/Dao.php | 166 +++++++-------- .../Model/ExportDefinition/Listing.php | 15 +- .../Model/ExportDefinition/Listing/Dao.php | 51 ++--- .../Model/ImportDefinition.php | 12 +- .../Model/ImportDefinition/Dao.php | 190 ++++++++---------- .../Model/ImportDefinition/Listing.php | 12 +- .../Model/ImportDefinition/Listing/Dao.php | 50 ++--- .../Provider/CsvProvider.php | 2 +- .../Resources/config/pimcore/config.yml | 4 + .../config/serializer/Model.Definition.yml | 2 +- .../Resources/config/services.yml | 10 +- .../Resources/config/services/forms.yml | 7 +- .../public/pimcore/css/datadefinition.css | 4 +- .../pimcore/js/definition/abstractItem.js | 11 +- .../public/pimcore/js/export/item.js | 4 + .../public/pimcore/js/export/panel.js | 14 ++ .../public/pimcore/js/import/item.js | 4 + .../public/pimcore/js/import/panel.js | 13 ++ .../Resources/public/pimcore/js/startup.js | 8 +- src/Kernel.php | 4 +- 43 files changed, 638 insertions(+), 440 deletions(-) delete mode 100644 config/migrations.yaml create mode 100644 src/DataDefinitionsBundle/Controller/AbstractDefinitionController.php create mode 100644 src/DataDefinitionsBundle/EventListener/PimcoreSettingsListener.php create mode 100644 src/DataDefinitionsBundle/EventListener/WriteableListener.php diff --git a/composer.json b/composer.json index f091d699..04541a11 100755 --- a/composer.json +++ b/composer.json @@ -32,15 +32,18 @@ "php": ">=8.0", "ext-json": "*", "box/spout": "^3.0", - "coreshop/pimcore-bundle": "^3.0", - "coreshop/resource-bundle": "^3.0", - "coreshop/rule-bundle": "^3.0", + "coreshop/pimcore-bundle": "^4.0", + "coreshop/resource-bundle": "^4.0", + "coreshop/rule-bundle": "^4.0", "jms/serializer": "^3.17.1", "league/csv": "^9.7", "nyholm/psr7": "^1.5", - "pimcore/pimcore": "^10.5", + "pimcore/admin-ui-classic-bundle": "^1.0", + "pimcore/pimcore": "^11.0", "psr/http-client-implementation": "^1.0", - "psr/http-factory-implementation": "^1.0" + "psr/http-factory-implementation": "^1.0", + "symfony/dotenv": "^6.3", + "symfony/http-client": "^6.3" }, "require-dev": { "roave/security-advisories": "dev-latest", @@ -65,7 +68,8 @@ }, "autoload-dev": { "psr-4": { - "Wvision\\Bundle\\DataDefinitionsBundle\\Behat\\": "tests/DataDefinitionsBundle/Behat" + "Wvision\\Bundle\\DataDefinitionsBundle\\Behat\\": "tests/DataDefinitionsBundle/Behat", + "Pimcore\\Model\\DataObject\\": "var/classes/DataObject" }, "classmap": [ "src/Kernel.php" diff --git a/config/config.yaml b/config/config.yaml index 3df4a70d..d84a1e5f 100644 --- a/config/config.yaml +++ b/config/config.yaml @@ -1,6 +1,5 @@ imports: - { resource: services.yaml } - - { resource: migrations.yaml } - { resource: system.yml } - { resource: 'local/' } diff --git a/config/migrations.yaml b/config/migrations.yaml deleted file mode 100644 index 9617ac97..00000000 --- a/config/migrations.yaml +++ /dev/null @@ -1,19 +0,0 @@ -doctrine_migrations: - connection: default - migrations_paths: - 'Pimcore\Bundle\CoreBundle\Migrations': '@PimcoreCoreBundle/Migrations' - storage: - table_storage: - table_name: 'migration_versions' - version_column_name: 'version' - version_column_length: 1024 - executed_at_column_name: 'executed_at' - execution_time_column_name: 'execution_time' - all_or_nothing: false - check_database_platform: false - factories: - 'Doctrine\Migrations\MigrationsRepository': 'Pimcore\Migrations\FilteredMigrationsRepository' - 'Doctrine\Migrations\Metadata\Storage\MetadataStorage': 'Pimcore\Migrations\FilteredTableMetadataStorage' - - - diff --git a/config/packages/security.yaml b/config/packages/security.yaml index 9675d5a6..df3e2daf 100644 --- a/config/packages/security.yaml +++ b/config/packages/security.yaml @@ -1,7 +1,9 @@ security: + enable_authenticator_manager: true + providers: pimcore_admin: - id: Pimcore\Bundle\AdminBundle\Security\User\UserProvider + id: Pimcore\Security\User\UserProvider firewalls: dev: @@ -9,46 +11,25 @@ security: security: false # Pimcore WebDAV HTTP basic // DO NOT CHANGE! - pimcore_admin_webdav: - pattern: ^/admin/asset/webdav + pimcore_webdav: + pattern: ^/asset/webdav provider: pimcore_admin http_basic: ~ - # Pimcore admin form login // DO NOT CHANGE! - pimcore_admin: - anonymous: ~ - pattern: ^/admin(/.*)?$ - # admin firewall is stateless as we open the admin - # session on demand for non-blocking parallel requests - stateless: true - provider: pimcore_admin - logout: - path: /admin/logout - target: /admin/login - success_handler: Pimcore\Bundle\AdminBundle\Security\LogoutSuccessHandler - guard: - entry_point: Pimcore\Bundle\AdminBundle\Security\Guard\AdminAuthenticator - authenticators: - - Pimcore\Bundle\AdminBundle\Security\Guard\AdminAuthenticator - two_factor: - auth_form_path: /admin/login/2fa # Path or route name of the two-factor form - check_path: /admin/login/2fa-verify # Path or route name of the two-factor code check - default_target_path: /admin # Where to redirect by default after successful authentication - always_use_default_target_path: false # If it should always redirect to default_target_path - auth_code_parameter_name: _auth_code # Name of the parameter for the two-factor authentication code - trusted_parameter_name: _trusted # Name of the parameter for the trusted device option - multi_factor: false # If ALL active two-factor methods need to be fulfilled (multi-factor authentication) - + # Pimcore Admin Bundle firewall + pimcore_admin: '%pimcore_admin_bundle.firewall_settings%' access_control: # Pimcore admin ACl // DO NOT CHANGE! - - { path: ^/admin/settings/display-custom-logo, roles: IS_AUTHENTICATED_ANONYMOUSLY } - - { path: ^/admin/login/2fa-verify, roles: IS_AUTHENTICATED_2FA_IN_PROGRESS} - - { path: ^/admin/login/2fa, roles: IS_AUTHENTICATED_2FA_IN_PROGRESS} - - { path: ^/admin/login$, roles: IS_AUTHENTICATED_ANONYMOUSLY } - - { path: ^/admin/login/(login|lostpassword|deeplink|csrf-token)$, roles: IS_AUTHENTICATED_ANONYMOUSLY } + - { path: ^/admin/settings/display-custom-logo, roles: PUBLIC_ACCESS } + - { path: ^/admin/login/2fa-verify, roles: IS_AUTHENTICATED_2FA_IN_PROGRESS } + - { path: ^/admin/login/2fa-setup, roles: ROLE_PIMCORE_USER } + - { path: ^/admin/login/2fa, roles: IS_AUTHENTICATED_2FA_IN_PROGRESS } + - { path: ^/admin/login$, roles: PUBLIC_ACCESS } + - { path: ^/admin/login/(login|lostpassword|deeplink|csrf-token)$, roles: PUBLIC_ACCESS } - { path: ^/admin, roles: ROLE_PIMCORE_USER } + - { path: ^/asset/webdav, roles: ROLE_PIMCORE_USER } role_hierarchy: # Pimcore admin // DO NOT CHANGE! - ROLE_PIMCORE_ADMIN: [ROLE_PIMCORE_USER] + ROLE_PIMCORE_ADMIN: [ROLE_PIMCORE_USER] \ No newline at end of file diff --git a/config/routes.yaml b/config/routes.yaml index 3c1894dd..b516051b 100644 --- a/config/routes.yaml +++ b/config/routes.yaml @@ -1,2 +1,2 @@ _pimcore: - resource: "@PimcoreCoreBundle/Resources/config/routing.yml" + resource: "@PimcoreCoreBundle/config/routing.yaml" diff --git a/config/routes/dev/routes.yaml b/config/routes/dev/routes.yaml index 8ee148fe..50d25c70 100644 --- a/config/routes/dev/routes.yaml +++ b/config/routes/dev/routes.yaml @@ -1,3 +1,2 @@ _pimcore_dev: - resource: "@PimcoreCoreBundle/Resources/config/routing_dev.yml" - + resource: "@PimcoreCoreBundle/config/routing_dev.yaml" \ No newline at end of file diff --git a/config/system.yml b/config/system.yml index 5995ca1d..b7a4b2b8 100644 --- a/config/system.yml +++ b/config/system.yml @@ -12,7 +12,6 @@ pimcore: default_language: '' disable_usage_statistics: false debug_admin_translations: false - instance_identifier: '' documents: versions: days: null @@ -32,14 +31,6 @@ pimcore: steps: 10 icc_rgb_profile: '' icc_cmyk_profile: '' - hide_edit_image: false - disable_tree_preview: false - services: - google: - client_id: '' - email: '' - simple_api_key: '' - browser_api_key: '' httpclient: adapter: Socket proxy_host: '' @@ -53,14 +44,6 @@ pimcore: return: name: pimcore email: pimcore@example.com - newsletter: - sender: - name: '' - email: '' - return: - name: '' - email: '' - use_specific: true applicationlog: mail_notification: send_log_summary: false diff --git a/src/DataDefinitionsBundle/Command/ExportCommand.php b/src/DataDefinitionsBundle/Command/ExportCommand.php index 5cb1c0d3..255ca8ee 100644 --- a/src/DataDefinitionsBundle/Command/ExportCommand.php +++ b/src/DataDefinitionsBundle/Command/ExportCommand.php @@ -77,21 +77,21 @@ protected function execute(InputInterface $input, OutputInterface $output) $params = json_decode($input->getOption('params'), true); try { - $definition = $this->repository->find($input->getOption('definition')); - } catch (InvalidArgumentException $e) { $definition = $this->repository->findByName($input->getOption('definition')); - } - $progress = null; - $process = null; + } catch (InvalidArgumentException $e) { - if (!is_array($params)) { - $params = []; } if (!$definition instanceof ExportDefinitionInterface) { throw new Exception('Export Definition not found'); } + $progress = null; + + if (!is_array($params)) { + $params = []; + } + $imStatus = function (ExportDefinitionEvent $e) use (&$progress) { if ($progress instanceof ProgressBar) { $progress->setMessage($e->getSubject()); diff --git a/src/DataDefinitionsBundle/Command/ImportCommand.php b/src/DataDefinitionsBundle/Command/ImportCommand.php index c5f1ee3c..b12cd21e 100644 --- a/src/DataDefinitionsBundle/Command/ImportCommand.php +++ b/src/DataDefinitionsBundle/Command/ImportCommand.php @@ -83,20 +83,19 @@ protected function execute(InputInterface $input, OutputInterface $output) } try { - $definition = $this->repository->find($input->getOption('definition')); - } catch (InvalidArgumentException $e) { $definition = $this->repository->findByName($input->getOption('definition')); - } + } catch (InvalidArgumentException $e) { - $progress = null; - $process = null; - $countProgress = 0; - $startTime = time(); + } if (!$definition instanceof ImportDefinitionInterface) { throw new Exception('Import Definition not found'); } + $progress = null; + $countProgress = 0; + $startTime = time(); + $imStatus = function (ImportDefinitionEvent $e) use ($output, &$progress, &$countProgress, $startTime) { if ($progress instanceof ProgressBar) { $progress->setMessage($e->getSubject()); diff --git a/src/DataDefinitionsBundle/Controller/AbstractDefinitionController.php b/src/DataDefinitionsBundle/Controller/AbstractDefinitionController.php new file mode 100644 index 00000000..4f22d0b2 --- /dev/null +++ b/src/DataDefinitionsBundle/Controller/AbstractDefinitionController.php @@ -0,0 +1,41 @@ +isGrantedOr403(); + + $resources = $this->findOr404((string) $this->getParameterFromRequest($request, 'id')); + + return $this->viewHandler->handle(['data' => $resources, 'success' => true], ['group' => 'Detailed']); + } +} diff --git a/src/DataDefinitionsBundle/Controller/ExportDefinitionController.php b/src/DataDefinitionsBundle/Controller/ExportDefinitionController.php index f4c639aa..9dd71c0c 100644 --- a/src/DataDefinitionsBundle/Controller/ExportDefinitionController.php +++ b/src/DataDefinitionsBundle/Controller/ExportDefinitionController.php @@ -27,7 +27,7 @@ use Wvision\Bundle\DataDefinitionsBundle\Model\ExportDefinitionInterface; use Wvision\Bundle\DataDefinitionsBundle\Model\ExportMapping\FromColumn; -class ExportDefinitionController extends ResourceController +class ExportDefinitionController extends AbstractDefinitionController { public function getConfigAction(): JsonResponse { @@ -416,36 +416,36 @@ protected function getFieldConfiguration(DataObject\ClassDefinition\Data $field, protected function getConfigProviders(): array { - return $this->container->getParameter('data_definitions.export_providers'); + return $this->getParameter('data_definitions.export_providers'); } protected function getConfigInterpreters(): array { - return $this->container->getParameter('data_definitions.interpreters'); + return $this->getParameter('data_definitions.interpreters'); } protected function getConfigRunners(): array { - return $this->container->getParameter('data_definitions.export_runners'); + return $this->getParameter('data_definitions.export_runners'); } protected function getConfigGetters(): array { - return $this->container->getParameter('data_definitions.getters'); + return $this->getParameter('data_definitions.getters'); } protected function getConfigFetchers(): array { - return $this->container->getParameter('data_definitions.fetchers'); + return $this->getParameter('data_definitions.fetchers'); } protected function getImportRuleConditions(): array { - return $this->container->getParameter('data_definitions.import_rule.conditions'); + return $this->getParameter('data_definitions.import_rule.conditions'); } protected function getImportRuleActions(): array { - return $this->container->getParameter('data_definitions.import_rule.actions'); + return $this->getParameter('data_definitions.import_rule.actions'); } } diff --git a/src/DataDefinitionsBundle/Controller/ImportDefinitionController.php b/src/DataDefinitionsBundle/Controller/ImportDefinitionController.php index 3cde1817..220e31d1 100644 --- a/src/DataDefinitionsBundle/Controller/ImportDefinitionController.php +++ b/src/DataDefinitionsBundle/Controller/ImportDefinitionController.php @@ -16,21 +16,23 @@ namespace Wvision\Bundle\DataDefinitionsBundle\Controller; -use CoreShop\Bundle\ResourceBundle\Controller\ResourceController; +use CoreShop\Component\Registry\ServiceRegistryInterface; use Exception; use Pimcore\Model\DataObject; +use Symfony\Component\DependencyInjection\Attribute\Autowire; use Symfony\Component\HttpFoundation\File\UploadedFile; use Symfony\Component\HttpFoundation\JsonResponse; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; +use Symfony\Contracts\Service\Attribute\SubscribedService; use Wvision\Bundle\DataDefinitionsBundle\Model\ImportDefinitionInterface; use Wvision\Bundle\DataDefinitionsBundle\Model\ImportMapping; use Wvision\Bundle\DataDefinitionsBundle\Model\ImportMapping\FromColumn; use Wvision\Bundle\DataDefinitionsBundle\Service\FieldSelection; use function is_array; -class ImportDefinitionController extends ResourceController +class ImportDefinitionController extends AbstractDefinitionController { public function getConfigAction(): JsonResponse { @@ -68,7 +70,9 @@ public function testDataAction(Request $request): JsonResponse if ($definition instanceof ImportDefinitionInterface) { try { - if ($this->get('data_definitions.registry.provider')->get($definition->getProvider())->testData( + if ($this->container->get('data_definitions.registry.provider')->get( + $definition->getProvider() + )->testData( $definition->getConfiguration() )) { return $this->viewHandler->handle(['success' => true]); @@ -92,7 +96,7 @@ public function getColumnsAction(Request $request): JsonResponse $customFromColumn->setLabel('Custom'); try { - $fromColumns = $this->get('data_definitions.registry.provider')->get( + $fromColumns = $this->container->get('data_definitions.registry.provider')->get( $definition->getProvider() )->getColumns($definition->getConfiguration()); $fromColumns[] = $customFromColumn; @@ -106,7 +110,7 @@ public function getColumnsAction(Request $request): JsonResponse throw new NotFoundHttpException(); } - $toColumns = $this->get(FieldSelection::class)->getClassDefinition($classDefinition); + $toColumns = $this->container->get(FieldSelection::class)->getClassDefinition($classDefinition); $mappings = $definition->getMapping(); $mappingDefinition = []; $fromColumnsResult = []; @@ -263,53 +267,62 @@ public function duplicateAction(Request $request): JsonResponse return $this->viewHandler->handle(['success' => false]); } + public static function getSubscribedServices(): array + { + return parent::getSubscribedServices() + [ + FieldSelection::class, + new SubscribedService('data_definitions.registry.provider', ServiceRegistryInterface::class, attributes: new Autowire(service: 'data_definitions.registry.provider')) + ]; + } + + protected function getConfigProviders(): array { - return $this->container->getParameter('data_definitions.import_providers'); + return $this->getParameter('data_definitions.import_providers'); } protected function getConfigLoaders(): array { - return $this->container->getParameter('data_definitions.loaders'); + return $this->getParameter('data_definitions.loaders'); } protected function getConfigInterpreters(): array { - return $this->container->getParameter('data_definitions.interpreters'); + return $this->getParameter('data_definitions.interpreters'); } protected function getConfigCleaners(): array { - return $this->container->getParameter('data_definitions.cleaners'); + return $this->getParameter('data_definitions.cleaners'); } protected function getConfigSetters(): array { - return $this->container->getParameter('data_definitions.setters'); + return $this->getParameter('data_definitions.setters'); } protected function getConfigFilters(): array { - return $this->container->getParameter('data_definitions.filters'); + return $this->getParameter('data_definitions.filters'); } protected function getConfigRunners(): array { - return $this->container->getParameter('data_definitions.runners'); + return $this->getParameter('data_definitions.runners'); } protected function getConfigPersisters(): array { - return $this->container->getParameter('data_definitions.persisters'); + return $this->getParameter('data_definitions.persisters'); } protected function getImportRuleConditions(): array { - return $this->container->getParameter('data_definitions.import_rule.conditions'); + return $this->getParameter('data_definitions.import_rule.conditions'); } protected function getImportRuleActions(): array { - return $this->container->getParameter('data_definitions.import_rule.actions'); + return $this->getParameter('data_definitions.import_rule.actions'); } } diff --git a/src/DataDefinitionsBundle/Controller/ImportRuleController.php b/src/DataDefinitionsBundle/Controller/ImportRuleController.php index 4eb20db7..ffa45046 100644 --- a/src/DataDefinitionsBundle/Controller/ImportRuleController.php +++ b/src/DataDefinitionsBundle/Controller/ImportRuleController.php @@ -16,7 +16,7 @@ namespace Wvision\Bundle\DataDefinitionsBundle\Controller; -use Pimcore\Bundle\AdminBundle\Controller\AdminController; +use Pimcore\Bundle\AdminBundle\Controller\GDPR\AdminController; use Symfony\Component\Form\FormFactoryInterface; use Symfony\Component\HttpFoundation\BinaryFileResponse; use Symfony\Component\HttpFoundation\File\UploadedFile; diff --git a/src/DataDefinitionsBundle/DataDefinitionsBundle.php b/src/DataDefinitionsBundle/DataDefinitionsBundle.php index 0cdc04af..fbb00edd 100644 --- a/src/DataDefinitionsBundle/DataDefinitionsBundle.php +++ b/src/DataDefinitionsBundle/DataDefinitionsBundle.php @@ -20,6 +20,8 @@ use CoreShop\Bundle\ResourceBundle\AbstractResourceBundle; use CoreShop\Bundle\ResourceBundle\CoreShopResourceBundle; use CoreShop\Bundle\RuleBundle\CoreShopRuleBundle; +use Pimcore\Bundle\AdminBundle\PimcoreAdminBundle; +use Pimcore\Bundle\SimpleBackendSearchBundle\PimcoreSimpleBackendSearchBundle; use Pimcore\Extension\Bundle\Installer\InstallerInterface; use Pimcore\Extension\Bundle\PimcoreBundleInterface; use Pimcore\HttpKernel\BundleCollection\BundleCollection; @@ -45,6 +47,11 @@ public static function registerDependentBundles(BundleCollection $collection): v { parent::registerDependentBundles($collection); + $collection->addBundles([ + new PimcoreAdminBundle(), + new PimcoreSimpleBackendSearchBundle() + ]); + $collection->addBundles([ new CoreShopRuleBundle(), ], 3500); @@ -57,24 +64,24 @@ public function getSupportedDrivers(): array ]; } - public function build(ContainerBuilder $builder): void + public function build(ContainerBuilder $container): void { - parent::build($builder); - - $builder->addCompilerPass(new CleanerRegistryCompilerPass()); - $builder->addCompilerPass(new FilterRegistryCompilerPass()); - $builder->addCompilerPass(new InterpreterRegistryCompilerPass()); - $builder->addCompilerPass(new ProviderRegistryCompilerPass()); - $builder->addCompilerPass(new RunnerRegistryCompilerPass()); - $builder->addCompilerPass(new SetterRegistryCompilerPass()); - $builder->addCompilerPass(new LoaderRegistryCompilerPass()); - $builder->addCompilerPass(new GetterRegistryCompilerPass()); - $builder->addCompilerPass(new FetcherRegistryCompilerPass()); - $builder->addCompilerPass(new ExportProviderRegistryCompilerPass()); - $builder->addCompilerPass(new ExportRunnerRegistryCompilerPass()); - $builder->addCompilerPass(new ImportRuleConditionPass()); - $builder->addCompilerPass(new ImportRuleActionPass()); - $builder->addCompilerPass(new PersisterRegistryCompilerPass()); + parent::build($container); + + $container->addCompilerPass(new CleanerRegistryCompilerPass()); + $container->addCompilerPass(new FilterRegistryCompilerPass()); + $container->addCompilerPass(new InterpreterRegistryCompilerPass()); + $container->addCompilerPass(new ProviderRegistryCompilerPass()); + $container->addCompilerPass(new RunnerRegistryCompilerPass()); + $container->addCompilerPass(new SetterRegistryCompilerPass()); + $container->addCompilerPass(new LoaderRegistryCompilerPass()); + $container->addCompilerPass(new GetterRegistryCompilerPass()); + $container->addCompilerPass(new FetcherRegistryCompilerPass()); + $container->addCompilerPass(new ExportProviderRegistryCompilerPass()); + $container->addCompilerPass(new ExportRunnerRegistryCompilerPass()); + $container->addCompilerPass(new ImportRuleConditionPass()); + $container->addCompilerPass(new ImportRuleActionPass()); + $container->addCompilerPass(new PersisterRegistryCompilerPass()); } public function getVersion(): string diff --git a/src/DataDefinitionsBundle/DependencyInjection/Configuration.php b/src/DataDefinitionsBundle/DependencyInjection/Configuration.php index 9eeb03d3..45ff383f 100644 --- a/src/DataDefinitionsBundle/DependencyInjection/Configuration.php +++ b/src/DataDefinitionsBundle/DependencyInjection/Configuration.php @@ -18,6 +18,8 @@ use CoreShop\Bundle\ResourceBundle\CoreShopResourceBundle; use CoreShop\Component\Resource\Factory\Factory; +use Pimcore\Bundle\CoreBundle\DependencyInjection\ConfigurationHelper; +use Pimcore\Config\LocationAwareConfigRepository; use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition; use Symfony\Component\Config\Definition\Builder\TreeBuilder; use Symfony\Component\Config\Definition\ConfigurationInterface; @@ -38,11 +40,96 @@ public function getConfigTreeBuilder(): TreeBuilder $treeBuilder = new TreeBuilder('wvision_data_definitions'); $rootNode = $treeBuilder->getRootNode(); + ConfigurationHelper::addConfigLocationWithWriteTargetNodes($rootNode, [ + 'import_definitions' => '/var/config/import-definitions', + 'export_definitions' => '/var/config/export-definitions' + ]); + $rootNode ->children() ->scalarNode('driver')->defaultValue(CoreShopResourceBundle::DRIVER_PIMCORE)->end() ->end(); + $rootNode + ->children() + ->arrayNode('import_definitions') + ->normalizeKeys(false) + ->prototype('array') + ->children() + ->scalarNode('name')->end() + ->scalarNode('provider')->end() + ->scalarNode('class')->end() + ->scalarNode('runner')->end() + ->booleanNode('stopOnException')->end() + ->scalarNode('failureNotificationDocument')->end() + ->scalarNode('successNotificationDocument')->end() + ->scalarNode('loader')->end() + ->scalarNode('objectPath')->end() + ->scalarNode('cleaner')->end() + ->scalarNode('key')->end() + ->scalarNode('filter')->end() + ->booleanNode('renameExistingObjects')->end() + ->booleanNode('relocateExistingObjects')->end() + ->booleanNode('skipNewObjects')->end() + ->booleanNode('skipExistingObjects')->end() + ->booleanNode('createVersion')->end() + ->booleanNode('omitMandatoryCheck')->end() + ->booleanNode('forceLoadObject')->end() + ->variableNode('configuration')->end() + ->arrayNode('mapping') + ->prototype('array') + ->children() + ->scalarNode('primaryIdentifier')->end() + ->scalarNode('setter')->end() + ->variableNode('setterConfig')->end() + ->scalarNode('fromColumn')->end() + ->scalarNode('toColumn')->end() + ->scalarNode('interpreter')->end() + ->variableNode('interpreterConfig')->end() + ->end() + ->end() + ->end() + ->integerNode('creationDate')->end() + ->integerNode('modificationDate')->end() + ->end() + ->end() + ->end() + ->arrayNode('export_definitions') + ->normalizeKeys(false) + ->prototype('array') + ->children() + ->scalarNode('name')->end() + ->scalarNode('fetcher')->end() + ->variableNode('fetcherConfig')->end() + ->booleanNode('fetchUnpublished')->end() + ->scalarNode('provider')->end() + ->scalarNode('class')->end() + ->scalarNode('loader')->end() + ->variableNode('configuration')->end() + ->scalarNode('runner')->end() + ->booleanNode('stopOnException')->end() + ->scalarNode('failureNotificationDocument')->end() + ->scalarNode('successNotificationDocument')->end() + ->arrayNode('mapping') + ->prototype('array') + ->children() + ->scalarNode('primaryIdentifier')->end() + ->scalarNode('getter')->end() + ->variableNode('getterConfig')->end() + ->scalarNode('fromColumn')->end() + ->scalarNode('toColumn')->end() + ->scalarNode('interpreter')->end() + ->variableNode('interpreterConfig')->end() + ->end() + ->end() + ->end() + ->integerNode('creationDate')->end() + ->integerNode('modificationDate')->end() + ->end() + ->end() + ->end() + ->end(); + $this->addPimcoreResourcesSection($rootNode); $this->addModelsSection($rootNode); diff --git a/src/DataDefinitionsBundle/DependencyInjection/DataDefinitionsExtension.php b/src/DataDefinitionsBundle/DependencyInjection/DataDefinitionsExtension.php index 23f5498b..738f7f34 100644 --- a/src/DataDefinitionsBundle/DependencyInjection/DataDefinitionsExtension.php +++ b/src/DataDefinitionsBundle/DependencyInjection/DataDefinitionsExtension.php @@ -17,9 +17,12 @@ namespace Wvision\Bundle\DataDefinitionsBundle\DependencyInjection; use CoreShop\Bundle\ResourceBundle\DependencyInjection\Extension\AbstractModelExtension; +use Pimcore\Config\LocationAwareConfigRepository; use Symfony\Component\Config\FileLocator; use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Extension\PrependExtensionInterface; use Symfony\Component\DependencyInjection\Loader; +use Symfony\Component\DependencyInjection\Loader\YamlFileLoader; use Wvision\Bundle\DataDefinitionsBundle\Cleaner\CleanerInterface; use Wvision\Bundle\DataDefinitionsBundle\DependencyInjection\Compiler\CleanerRegistryCompilerPass; use Wvision\Bundle\DataDefinitionsBundle\DependencyInjection\Compiler\ExportProviderRegistryCompilerPass; @@ -45,7 +48,7 @@ use Wvision\Bundle\DataDefinitionsBundle\Runner\RunnerInterface; use Wvision\Bundle\DataDefinitionsBundle\Setter\SetterInterface; -class DataDefinitionsExtension extends AbstractModelExtension +class DataDefinitionsExtension extends AbstractModelExtension implements PrependExtensionInterface { public function load(array $configs, ContainerBuilder $container) { @@ -121,5 +124,16 @@ public function load(array $configs, ContainerBuilder $container) $container ->registerForAutoconfiguration(PersisterInterface::class) ->addTag(PersisterRegistryCompilerPass::PERSISTER_TAG); + + $container->setParameter('data_definitions.config_location', $config['config_location'] ?? []); + + $container->setParameter('data_definitions.import_definitions', $config['import_definitions']); + $container->setParameter('data_definitions.export_definitions', $config['export_definitions']); + } + + public function prepend(ContainerBuilder $container): void + { + LocationAwareConfigRepository::loadSymfonyConfigFiles($container, 'data_definitions', 'export_definitions'); + LocationAwareConfigRepository::loadSymfonyConfigFiles($container, 'data_definitions', 'import_definitions'); } } diff --git a/src/DataDefinitionsBundle/EventListener/PimcoreSettingsListener.php b/src/DataDefinitionsBundle/EventListener/PimcoreSettingsListener.php new file mode 100644 index 00000000..82e8bab9 --- /dev/null +++ b/src/DataDefinitionsBundle/EventListener/PimcoreSettingsListener.php @@ -0,0 +1,30 @@ +addSetting('data-definitions-import-definition-writeable', (new ImportDefinition())->isWriteable()); + $settingsEvent->addSetting('data-definitions-export-definition-writeable', (new ExportDefinition())->isWriteable()); + } +} diff --git a/src/DataDefinitionsBundle/EventListener/WriteableListener.php b/src/DataDefinitionsBundle/EventListener/WriteableListener.php new file mode 100644 index 00000000..271c10d0 --- /dev/null +++ b/src/DataDefinitionsBundle/EventListener/WriteableListener.php @@ -0,0 +1,47 @@ +getSubject(); + + if ($subject instanceof ImportDefinition && !$subject->isWriteable()) { + throw new ConfigWriteException(); + } + + if ($subject instanceof ExportDefinition && !$subject->isWriteable()) { + throw new ConfigWriteException(); + } + } + + public static function getSubscribedEvents() + { + return [ + 'data_definitions.import_definition.pre_save' => 'definitionIsWritable', + 'data_definitions.export_definition.pre_save' => 'definitionIsWritable', + ]; + } +} diff --git a/src/DataDefinitionsBundle/Fetcher/ObjectsFetcher.php b/src/DataDefinitionsBundle/Fetcher/ObjectsFetcher.php index ebf3564f..6dfb67a8 100644 --- a/src/DataDefinitionsBundle/Fetcher/ObjectsFetcher.php +++ b/src/DataDefinitionsBundle/Fetcher/ObjectsFetcher.php @@ -98,7 +98,7 @@ private function getClassListing(ExportDefinitionInterface $definition, array $p $list->setCondition(implode(' AND ', $conditionFilters)); // ensure a stable sort across pages - $list->setOrderKey('o_id'); + $list->setOrderKey('id'); $list->setOrder('asc'); return $this->list = $list; diff --git a/src/DataDefinitionsBundle/Importer/Importer.php b/src/DataDefinitionsBundle/Importer/Importer.php index 1fa1273d..4b587db2 100644 --- a/src/DataDefinitionsBundle/Importer/Importer.php +++ b/src/DataDefinitionsBundle/Importer/Importer.php @@ -163,6 +163,10 @@ public function doImport(ImportDefinitionInterface $definition, $params): array public function processSuccessfullImport(ImportDefinitionInterface $definition, $params, $objectIds, $exceptions) { + if (!is_int($definition->getSuccessNotificationDocument())) { + return; + } + $this->sendDocument( $definition, Document::getById($definition->getSuccessNotificationDocument()), @@ -174,6 +178,10 @@ public function processSuccessfullImport(ImportDefinitionInterface $definition, public function processFailedImport(ImportDefinitionInterface $definition, $params, $objectIds, $exceptions) { + if (!is_int($definition->getFailureNotificationDocument())) { + return; + } + $this->sendDocument( $definition, Document::getById($definition->getFailureNotificationDocument()), diff --git a/src/DataDefinitionsBundle/Model/AbstractDataDefinition.php b/src/DataDefinitionsBundle/Model/AbstractDataDefinition.php index c55dbb31..b534767d 100644 --- a/src/DataDefinitionsBundle/Model/AbstractDataDefinition.php +++ b/src/DataDefinitionsBundle/Model/AbstractDataDefinition.php @@ -18,10 +18,16 @@ use Pimcore\Model\AbstractModel; +/** + * @method bool isWriteable() + * @method string getWriteTarget() + * @method void save() + * @method void delete() + */ abstract class AbstractDataDefinition extends AbstractModel implements DataDefinitionInterface { /** - * @var int + * @var int|string|null */ public $id; @@ -80,7 +86,7 @@ abstract class AbstractDataDefinition extends AbstractModel implements DataDefin */ public $successNotificationDocument; - public function getId() + public function getId(): int|string|null { return $this->id; } @@ -128,6 +134,8 @@ public function getName() public function setName($name) { $this->name = $name; + + $this->setId($name); } public function getMapping() diff --git a/src/DataDefinitionsBundle/Model/DataDefinitionInterface.php b/src/DataDefinitionsBundle/Model/DataDefinitionInterface.php index addc6fe6..429ba971 100644 --- a/src/DataDefinitionsBundle/Model/DataDefinitionInterface.php +++ b/src/DataDefinitionsBundle/Model/DataDefinitionInterface.php @@ -20,10 +20,6 @@ interface DataDefinitionInterface extends ResourceInterface { - /** - * @return mixed - */ - public function getId(); /** * @param int $id diff --git a/src/DataDefinitionsBundle/Model/ExportDefinition.php b/src/DataDefinitionsBundle/Model/ExportDefinition.php index 052f0199..8edb9ef9 100644 --- a/src/DataDefinitionsBundle/Model/ExportDefinition.php +++ b/src/DataDefinitionsBundle/Model/ExportDefinition.php @@ -16,6 +16,9 @@ namespace Wvision\Bundle\DataDefinitionsBundle\Model; +/** + * @method ExportDefinition\Dao getDao() + */ class ExportDefinition extends AbstractDataDefinition implements ExportDefinitionInterface { /** @@ -33,7 +36,12 @@ class ExportDefinition extends AbstractDataDefinition implements ExportDefinitio */ public $fetchUnpublished = false; - public static function getById($id) + public static function getById(string $name) + { + return static::getByName($name); + } + + public static function getByName($id) { $definitionEntry = new ExportDefinition(); $definitionEntry->setId((int)$id); @@ -41,7 +49,7 @@ public static function getById($id) * @var \Wvision\Bundle\DataDefinitionsBundle\Model\ExportDefinition\Dao|\Wvision\Bundle\DataDefinitionsBundle\Model\ImportDefinition\Dao */ $dao = $definitionEntry->getDao(); - $dao->getById($id); + $dao->getByName($id); return $definitionEntry; } diff --git a/src/DataDefinitionsBundle/Model/ExportDefinition/Dao.php b/src/DataDefinitionsBundle/Model/ExportDefinition/Dao.php index 898ae3d5..f88fa881 100644 --- a/src/DataDefinitionsBundle/Model/ExportDefinition/Dao.php +++ b/src/DataDefinitionsBundle/Model/ExportDefinition/Dao.php @@ -24,49 +24,28 @@ use function in_array; use function is_array; -class Dao extends Model\Dao\PhpArrayTable +class Dao extends Model\Dao\PimcoreLocationAwareConfigDao { - /** - * Configure Configuration File - */ - public function configure() - { - parent::configure(); - $this->setFile('exportdefinitions'); - } + private const CONFIG_KEY = 'export_definitions'; /** - * Get Configuration By Id - * - * @param null $id - * @throws Exception + * Configure Configuration File */ - public function getById($id = null) + public function configure(): void { - if ($id !== null) { - $this->model->setId($id); - } + $config = \Pimcore::getContainer()->getParameter('data_definitions.config_location'); + $definitions = \Pimcore::getContainer()->getParameter('data_definitions.export_definitions'); - $data = $this->db->getById($this->model->getId()); + $storageConfig = $config[self::CONFIG_KEY]; - if (isset($data['id'])) { - $this->assignVariablesToModel($data); - } else { - throw new InvalidArgumentException( - sprintf( - 'Export Definition with id: %s does not exist', - $this->model->getId() - ) - ); - } + parent::configure([ + 'containerConfig' => $definitions, + 'settingsStoreScope' => 'data_definitions', + 'storageConfig' => $storageConfig, + ]); } - /** - * @param array $data - * @return void - * @throws Exception - */ - protected function assignVariablesToModel($data) + protected function assignVariablesToModel($data): void { parent::assignVariablesToModel($data); @@ -94,27 +73,26 @@ protected function assignVariablesToModel($data) * @param null $name * @throws Exception */ - public function getByName($name = null) + public function getByName(string $id = null): void { - if ($name !== null) { - $this->model->setName($name); + if ($id != null) { + $this->model->setName($id); } - $name = $this->model->getName(); + $data = $this->getDataByName($this->model->getName()); - $data = $this->db->fetchAll(function ($row) use ($name) { - return $row['name'] === $name; - }); + if ($data && $id != null) { + $data['id'] = $id; + } - if ($data[0]['id'] && count($data)) { - $this->assignVariablesToModel($data[0]); + if ($data) { + $this->assignVariablesToModel($data); + $this->model->setName($data['id']); } else { - throw new InvalidArgumentException( - sprintf( - 'Definition with name: %s does not exist', - $this->model->getName() - ) - ); + throw new Model\Exception\NotFoundException(sprintf( + 'Thumbnail with ID "%s" does not exist.', + $this->model->getName() + )); } } @@ -131,56 +109,58 @@ public function save() } $this->model->setModificationDate($ts); - try { - $dataRaw = get_object_vars($this->model); - $data = []; - $allowedProperties = [ - 'id', - 'name', - 'provider', - 'class', - 'configuration', - 'creationDate', - 'modificationDate', - 'mapping', - 'runner', - 'stopOnException', - 'fetchUnpublished', - 'failureNotificationDocument', - 'successNotificationDocument', - 'fetcher', - 'fetcherConfig', - ]; - - foreach ($dataRaw as $key => $value) { - if (in_array($key, $allowedProperties, true)) { - if ($key === 'providerConfiguration') { - if ($value) { - $data[$key] = get_object_vars($value); - } - } elseif ($key === 'mapping') { - if ($value) { - $data[$key] = array(); - - if (is_array($value)) { - foreach ($value as $map) { - $data[$key][] = get_object_vars($map); - } + $dataRaw = get_object_vars($this->model); + $data = []; + $allowedProperties = [ + 'name', + 'provider', + 'class', + 'configuration', + 'creationDate', + 'modificationDate', + 'mapping', + 'runner', + 'stopOnException', + 'fetchUnpublished', + 'failureNotificationDocument', + 'successNotificationDocument', + 'fetcher', + 'fetcherConfig', + ]; + + foreach ($dataRaw as $key => $value) { + if (in_array($key, $allowedProperties, true)) { + if ($key === 'providerConfiguration') { + if ($value) { + $data[$key] = get_object_vars($value); + } + } elseif ($key === 'mapping') { + if ($value) { + $data[$key] = array(); + + if (is_array($value)) { + foreach ($value as $map) { + $data[$key][] = get_object_vars($map); } } - } else { - $data[$key] = $value; } + } else { + $data[$key] = $value; } } - $this->db->insertOrUpdate($data, $this->model->getId()); - } catch (Exception $e) { - throw $e; } + $this->saveData($this->model->getName(), $data); + } - if (!$this->model->getId()) { - $this->model->setId($this->db->getLastInsertId()); - } + protected function prepareDataStructureForYaml(string $id, mixed $data): mixed + { + return [ + 'data_definitions' => [ + 'export_definitions' => [ + $id => $data, + ], + ], + ]; } /** @@ -189,6 +169,6 @@ public function save() */ public function delete() { - $this->db->delete($this->model->getId()); + $this->deleteData($this->model->getName()); } } diff --git a/src/DataDefinitionsBundle/Model/ExportDefinition/Listing.php b/src/DataDefinitionsBundle/Model/ExportDefinition/Listing.php index fa97d043..1a77d772 100644 --- a/src/DataDefinitionsBundle/Model/ExportDefinition/Listing.php +++ b/src/DataDefinitionsBundle/Model/ExportDefinition/Listing.php @@ -17,11 +17,18 @@ namespace Wvision\Bundle\DataDefinitionsBundle\Model\ExportDefinition; use Exception; -use Pimcore\Model; +use Pimcore\Model\AbstractModel; +use Pimcore\Model\Listing\CallableFilterListingInterface; +use Pimcore\Model\Listing\CallableOrderListingInterface; +use Pimcore\Model\Listing\Traits\FilterListingTrait; +use Pimcore\Model\Listing\Traits\OrderListingTrait; use Wvision\Bundle\DataDefinitionsBundle\Model\ExportDefinitionInterface; -class Listing extends Model\Listing\JsonListing +class Listing extends AbstractModel implements CallableFilterListingInterface, CallableOrderListingInterface { + use FilterListingTrait; + use OrderListingTrait; + /** * Contains the results of the list. * They are all an instance of Configuration. @@ -34,10 +41,10 @@ class Listing extends Model\Listing\JsonListing * @return ExportDefinitionInterface[] * @throws Exception */ - public function getObjects(): ?array + public function getObjects() { if (null === $this->definitions) { - $this->load(); + $this->loadList(); } return $this->definitions; diff --git a/src/DataDefinitionsBundle/Model/ExportDefinition/Listing/Dao.php b/src/DataDefinitionsBundle/Model/ExportDefinition/Listing/Dao.php index 315bc1a6..71b22167 100644 --- a/src/DataDefinitionsBundle/Model/ExportDefinition/Listing/Dao.php +++ b/src/DataDefinitionsBundle/Model/ExportDefinition/Listing/Dao.php @@ -16,52 +16,31 @@ namespace Wvision\Bundle\DataDefinitionsBundle\Model\ExportDefinition\Listing; -use Exception; -use Pimcore; use Wvision\Bundle\DataDefinitionsBundle\Model\ExportDefinition; use function count; -class Dao extends Pimcore\Model\Dao\PhpArrayTable +class Dao extends ExportDefinition\Dao { - /** - * Configure - */ - public function configure() + public function loadList(): array { - parent::configure(); - $this->setFile('exportdefinitions'); - } - - /** - * Loads a list of Definitions for the specified parameters, returns an array of Definitions elements. - * - * @return array - * @throws Exception - */ - public function load() - { - $routesData = $this->db->fetchAll($this->model->getFilter(), $this->model->getOrder()); - - $routes = array(); - foreach ($routesData as $routeData) { - $routes[] = ExportDefinition::getById($routeData['id']); + $definitions = []; + foreach ($this->loadIdList() as $name) { + $definitions[] = ExportDefinition::getByName($name); } - $this->model->setObjects($routes); + if ($this->model->getFilter()) { + $definitions = array_filter($definitions, $this->model->getFilter()); + } + if ($this->model->getOrder()) { + usort($definitions, $this->model->getOrder()); + } + $this->model->setObjects($definitions); - return $routes; + return $definitions; } - /** - * Get total count - * - * @return int - * @throws Exception - */ - public function getTotalCount() + public function getTotalCount(): int { - $data = $this->db->fetchAll($this->model->getFilter(), $this->model->getOrder()); - - return count($data); + return count($this->loadList()); } } diff --git a/src/DataDefinitionsBundle/Model/ImportDefinition.php b/src/DataDefinitionsBundle/Model/ImportDefinition.php index 438f43ba..86ec2f14 100644 --- a/src/DataDefinitionsBundle/Model/ImportDefinition.php +++ b/src/DataDefinitionsBundle/Model/ImportDefinition.php @@ -16,6 +16,9 @@ namespace Wvision\Bundle\DataDefinitionsBundle\Model; +/** + * @method ImportDefinition\Dao getDao() + */ class ImportDefinition extends AbstractDataDefinition implements ImportDefinitionInterface { /** @@ -83,7 +86,12 @@ class ImportDefinition extends AbstractDataDefinition implements ImportDefinitio */ public $persister; - public static function getById($id) + public static function getById(string $name) + { + return static::getByName($name); + } + + public static function getByName($id) { $definitionEntry = new ImportDefinition(); $definitionEntry->setId((int)$id); @@ -91,7 +99,7 @@ public static function getById($id) * @var \Wvision\Bundle\DataDefinitionsBundle\Model\ExportDefinition\Dao|\Wvision\Bundle\DataDefinitionsBundle\Model\ImportDefinition\Dao */ $dao = $definitionEntry->getDao(); - $dao->getById($id); + $dao->getByName($id); return $definitionEntry; } diff --git a/src/DataDefinitionsBundle/Model/ImportDefinition/Dao.php b/src/DataDefinitionsBundle/Model/ImportDefinition/Dao.php index 23e965dd..69f68096 100644 --- a/src/DataDefinitionsBundle/Model/ImportDefinition/Dao.php +++ b/src/DataDefinitionsBundle/Model/ImportDefinition/Dao.php @@ -17,56 +17,33 @@ namespace Wvision\Bundle\DataDefinitionsBundle\Model\ImportDefinition; use Exception; -use InvalidArgumentException; use Pimcore\Model; use Wvision\Bundle\DataDefinitionsBundle\Model\ImportMapping; -use function count; use function in_array; use function is_array; -class Dao extends Model\Dao\PhpArrayTable +class Dao extends Model\Dao\PimcoreLocationAwareConfigDao { - /** - * Configure Configuration File - */ - public function configure() - { - parent::configure(); - $this->setFile('importdefinitions'); - } + private const CONFIG_KEY = 'import_definitions'; /** - * Get Configuration By Id - * - * @param null $id - * @throws Exception + * Configure Configuration File */ - public function getById($id = null) + public function configure(): void { - if ($id !== null) { - $this->model->setId($id); - } + $config = \Pimcore::getContainer()->getParameter('data_definitions.config_location'); + $definitions = \Pimcore::getContainer()->getParameter('data_definitions.import_definitions'); - $data = $this->db->getById($this->model->getId()); + $storageConfig = $config[self::CONFIG_KEY]; - if (isset($data['id'])) { - $this->assignVariablesToModel($data); - } else { - throw new InvalidArgumentException( - sprintf( - 'Definition with id: %s does not exist', - $this->model->getId() - ) - ); - } + parent::configure([ + 'containerConfig' => $definitions, + 'settingsStoreScope' => 'data_definitions', + 'storageConfig' => $storageConfig, + ]); } - /** - * @param array $data - * @return void - * @throws Exception - */ - protected function assignVariablesToModel($data) + protected function assignVariablesToModel($data): void { parent::assignVariablesToModel($data); @@ -94,27 +71,26 @@ protected function assignVariablesToModel($data) * @param null $name * @throws Exception */ - public function getByName($name = null) + public function getByName(string $id = null): void { - if ($name !== null) { - $this->model->setName($name); + if ($id != null) { + $this->model->setName($id); } - $name = $this->model->getName(); + $data = $this->getDataByName($this->model->getName()); - $data = $this->db->fetchAll(function ($row) use ($name) { - return $row['name'] === $name; - }); + if ($data && $id != null) { + $data['id'] = $id; + } - if (isset($data[0]['id']) && count($data)) { - $this->assignVariablesToModel($data[0]); + if ($data) { + $this->assignVariablesToModel($data); + $this->model->setName($data['id']); } else { - throw new InvalidArgumentException( - sprintf( - 'Definition with name: %s does not exist', - $this->model->getName() - ) - ); + throw new Model\Exception\NotFoundException(sprintf( + 'Thumbnail with ID "%s" does not exist.', + $this->model->getName() + )); } } @@ -131,67 +107,69 @@ public function save() } $this->model->setModificationDate($ts); - try { - $dataRaw = get_object_vars($this->model); - $data = []; - $allowedProperties = [ - 'id', - 'name', - 'provider', - 'class', - 'configuration', - 'creationDate', - 'modificationDate', - 'mapping', - 'objectPath', - 'cleaner', - 'key', - 'renameExistingObjects', - 'relocateExistingObjects', - 'filter', - 'runner', - 'createVersion', - 'stopOnException', - 'omitMandatoryCheck', - 'failureNotificationDocument', - 'successNotificationDocument', - 'skipExistingObjects', - 'skipNewObjects', - 'forceLoadObject', - 'loader', - 'fetcher', - ]; - - foreach ($dataRaw as $key => $value) { - if (in_array($key, $allowedProperties, true)) { - if ($key === 'providerConfiguration') { - if ($value) { - $data[$key] = get_object_vars($value); - } - } elseif ($key === 'mapping') { - if ($value) { - $data[$key] = array(); - - if (is_array($value)) { - foreach ($value as $map) { - $data[$key][] = get_object_vars($map); - } + $dataRaw = get_object_vars($this->model); + $data = []; + $allowedProperties = [ + 'name', + 'provider', + 'class', + 'configuration', + 'creationDate', + 'modificationDate', + 'mapping', + 'objectPath', + 'cleaner', + 'key', + 'renameExistingObjects', + 'relocateExistingObjects', + 'filter', + 'runner', + 'createVersion', + 'stopOnException', + 'omitMandatoryCheck', + 'failureNotificationDocument', + 'successNotificationDocument', + 'skipExistingObjects', + 'skipNewObjects', + 'forceLoadObject', + 'loader', + 'fetcher', + ]; + + foreach ($dataRaw as $key => $value) { + if (in_array($key, $allowedProperties, true)) { + if ($key === 'providerConfiguration') { + if ($value) { + $data[$key] = get_object_vars($value); + } + } elseif ($key === 'mapping') { + if ($value) { + $data[$key] = array(); + + if (is_array($value)) { + foreach ($value as $map) { + $data[$key][] = get_object_vars($map); } } - } else { - $data[$key] = $value; } + } else { + $data[$key] = $value; } } - - $this->db->insertOrUpdate($data, $this->model->getId()); - } catch (Exception $e) { - throw $e; } - if (!$this->model->getId()) { - $this->model->setId($this->db->getLastInsertId()); - } + $this->saveData($this->model->getName(), $data); + } + + protected function prepareDataStructureForYaml(string $id, mixed $data): mixed + { + return [ + 'data_definitions' => [ + 'import_definitions' => [ + $id => $data, + ], + ], + ]; } /** @@ -200,6 +178,6 @@ public function save() */ public function delete() { - $this->db->delete($this->model->getId()); + $this->deleteData($this->model->getName()); } } diff --git a/src/DataDefinitionsBundle/Model/ImportDefinition/Listing.php b/src/DataDefinitionsBundle/Model/ImportDefinition/Listing.php index fe5abf2b..580e3556 100644 --- a/src/DataDefinitionsBundle/Model/ImportDefinition/Listing.php +++ b/src/DataDefinitionsBundle/Model/ImportDefinition/Listing.php @@ -18,10 +18,18 @@ use Exception; use Pimcore\Model; +use Pimcore\Model\AbstractModel; +use Pimcore\Model\Listing\CallableFilterListingInterface; +use Pimcore\Model\Listing\CallableOrderListingInterface; +use Pimcore\Model\Listing\Traits\FilterListingTrait; +use Pimcore\Model\Listing\Traits\OrderListingTrait; use Wvision\Bundle\DataDefinitionsBundle\Model\ImportDefinitionInterface; -class Listing extends Model\Listing\JsonListing +class Listing extends AbstractModel implements CallableFilterListingInterface, CallableOrderListingInterface { + use FilterListingTrait; + use OrderListingTrait; + /** * Contains the results of the list. * They are all an instance of Configuration. @@ -37,7 +45,7 @@ class Listing extends Model\Listing\JsonListing public function getObjects() { if (null === $this->definitions) { - $this->load(); + $this->loadList(); } return $this->definitions; diff --git a/src/DataDefinitionsBundle/Model/ImportDefinition/Listing/Dao.php b/src/DataDefinitionsBundle/Model/ImportDefinition/Listing/Dao.php index c587dd33..02e5b73b 100644 --- a/src/DataDefinitionsBundle/Model/ImportDefinition/Listing/Dao.php +++ b/src/DataDefinitionsBundle/Model/ImportDefinition/Listing/Dao.php @@ -18,50 +18,32 @@ use Exception; use Pimcore; +use Pimcore\Bundle\StaticRoutesBundle\Model\Staticroute; use Wvision\Bundle\DataDefinitionsBundle\Model\ImportDefinition; use function count; -class Dao extends Pimcore\Model\Dao\PhpArrayTable +class Dao extends ImportDefinition\Dao { - /** - * Configure - */ - public function configure() + public function loadList(): array { - parent::configure(); - $this->setFile('importdefinitions'); - } - - /** - * Loads a list of Definitions for the specified parameters, returns an array of Definitions elements. - * - * @return array - * @throws Exception - */ - public function load() - { - $routesData = $this->db->fetchAll($this->model->getFilter(), $this->model->getOrder()); - - $routes = array(); - foreach ($routesData as $routeData) { - $routes[] = ImportDefinition::getById($routeData['id']); + $definitions = []; + foreach ($this->loadIdList() as $name) { + $definitions[] = ImportDefinition::getByName($name); } - $this->model->setObjects($routes); + if ($this->model->getFilter()) { + $definitions = array_filter($definitions, $this->model->getFilter()); + } + if ($this->model->getOrder()) { + usort($definitions, $this->model->getOrder()); + } + $this->model->setObjects($definitions); - return $routes; + return $definitions; } - /** - * Get total count - * - * @return int - * @throws Exception - */ - public function getTotalCount() + public function getTotalCount(): int { - $data = $this->db->fetchAll($this->model->getFilter(), $this->model->getOrder()); - - return count($data); + return count($this->loadList()); } } diff --git a/src/DataDefinitionsBundle/Provider/CsvProvider.php b/src/DataDefinitionsBundle/Provider/CsvProvider.php index 57b38d68..e0c67f82 100644 --- a/src/DataDefinitionsBundle/Provider/CsvProvider.php +++ b/src/DataDefinitionsBundle/Provider/CsvProvider.php @@ -52,7 +52,7 @@ public function getColumns(array $configuration): array if (count($rows) > 0) { $headerRow = $rows[0]; - $headers = str_getcsv($headerRow, $delimiter, $enclosure ?: chr(8)); + $headers = str_getcsv($headerRow, $delimiter ?? ',', $enclosure ?: chr(8)); if (count($headers) > 0) { //First line are the headers diff --git a/src/DataDefinitionsBundle/Resources/config/pimcore/config.yml b/src/DataDefinitionsBundle/Resources/config/pimcore/config.yml index 16f5c299..aabbb4be 100644 --- a/src/DataDefinitionsBundle/Resources/config/pimcore/config.yml +++ b/src/DataDefinitionsBundle/Resources/config/pimcore/config.yml @@ -75,3 +75,7 @@ data_definitions: import_rules_action_object: '/bundles/datadefinitions/pimcore/js/import_rule/actions/object.js' css: data_definition: '/bundles/datadefinitions/pimcore/css/datadefinition.css' + +framework: + http_client: + enabled: true \ No newline at end of file diff --git a/src/DataDefinitionsBundle/Resources/config/serializer/Model.Definition.yml b/src/DataDefinitionsBundle/Resources/config/serializer/Model.Definition.yml index c7391ba6..f87cd6bb 100755 --- a/src/DataDefinitionsBundle/Resources/config/serializer/Model.Definition.yml +++ b/src/DataDefinitionsBundle/Resources/config/serializer/Model.Definition.yml @@ -4,7 +4,7 @@ Wvision\Bundle\DataDefinitionsBundle\Model\Definition: properties: id: expose: true - type: integer + type: string xml_attribute: true groups: [ List, Detailed ] name: diff --git a/src/DataDefinitionsBundle/Resources/config/services.yml b/src/DataDefinitionsBundle/Resources/config/services.yml index 95a9cc03..990a0075 100644 --- a/src/DataDefinitionsBundle/Resources/config/services.yml +++ b/src/DataDefinitionsBundle/Resources/config/services.yml @@ -381,4 +381,12 @@ services: Wvision\Bundle\DataDefinitionsBundle\Service\StorageLocator: arguments: - $locator: !tagged_locator { tag: flysystem.storage } \ No newline at end of file + $locator: !tagged_locator { tag: flysystem.storage } + + Wvision\Bundle\DataDefinitionsBundle\EventListener\PimcoreSettingsListener: + tags: + - { name: kernel.event_listener, event: pimcore.admin.indexAction.settings, method: indexSettings } + + Wvision\Bundle\DataDefinitionsBundle\EventListener\WriteableListener: + tags: + - { name: kernel.event_subscriber } \ No newline at end of file diff --git a/src/DataDefinitionsBundle/Resources/config/services/forms.yml b/src/DataDefinitionsBundle/Resources/config/services/forms.yml index fb9935eb..dfd4632f 100644 --- a/src/DataDefinitionsBundle/Resources/config/services/forms.yml +++ b/src/DataDefinitionsBundle/Resources/config/services/forms.yml @@ -5,12 +5,7 @@ parameters: data_definitions.form.type.export_mapping.validation_groups: [ data_definitions ] services: - Wvision\Bundle\DataDefinitionsBundle\Form\DataMapper\DefinitionMappingDataMapper: - arguments: - - !service - class: Symfony\Component\Form\Extension\Core\DataMapper\PropertyPathMapper - arguments: - - '@property_accessor' + Wvision\Bundle\DataDefinitionsBundle\Form\DataMapper\DefinitionMappingDataMapper: ~ Wvision\Bundle\DataDefinitionsBundle\Form\Type\ClassChoiceType: tags: diff --git a/src/DataDefinitionsBundle/Resources/public/pimcore/css/datadefinition.css b/src/DataDefinitionsBundle/Resources/public/pimcore/css/datadefinition.css index bb84fe85..da4ec80e 100644 --- a/src/DataDefinitionsBundle/Resources/public/pimcore/css/datadefinition.css +++ b/src/DataDefinitionsBundle/Resources/public/pimcore/css/datadefinition.css @@ -6,7 +6,7 @@ background: url(../img/import_definition.svg) center center no-repeat !important; } -body.pimcore_version_10 .data_definitions_nav_icon_import_definition { +body.pimcore_version_11 .data_definitions_nav_icon_import_definition { background: url(../img/import_definition_white.svg) center center no-repeat !important; } @@ -18,7 +18,7 @@ body.pimcore_version_10 .data_definitions_nav_icon_import_definition { background: url(../img/export_definition.svg) center center no-repeat !important; } -body.pimcore_version_10 .data_definitions_nav_icon_export_definition { +body.pimcore_version_11 .data_definitions_nav_icon_export_definition { background: url(../img/export_definition_white.svg) center center no-repeat !important; } diff --git a/src/DataDefinitionsBundle/Resources/public/pimcore/js/definition/abstractItem.js b/src/DataDefinitionsBundle/Resources/public/pimcore/js/definition/abstractItem.js index 1a2fca67..6b64cf29 100644 --- a/src/DataDefinitionsBundle/Resources/public/pimcore/js/definition/abstractItem.js +++ b/src/DataDefinitionsBundle/Resources/public/pimcore/js/definition/abstractItem.js @@ -14,6 +14,10 @@ pimcore.registerNS('pimcore.plugin.datadefinitions.definition.abstractItem'); pimcore.plugin.datadefinitions.definition.abstractItem = Class.create(coreshop.resource.item, { + saveDisabled: function() { + return false; + }, + getPanel: function () { var me = this, panel = new Ext.TabPanel({ @@ -45,7 +49,8 @@ pimcore.plugin.datadefinitions.definition.abstractItem = Class.create(coreshop.r { text: t('data_definitions_import_definition'), iconCls: 'pimcore_icon_import', - handler: this.upload.bind(this) + handler: this.upload.bind(this), + disabled: this.saveDisabled() }, { text: t('data_definitions_export_definition'), @@ -58,6 +63,7 @@ pimcore.plugin.datadefinitions.definition.abstractItem = Class.create(coreshop.r { text: t('data_definitions_duplicate_definition'), iconCls: 'pimcore_icon_copy', + disabled: this.saveDisabled(), handler: function () { var id = me.data.id; @@ -88,7 +94,8 @@ pimcore.plugin.datadefinitions.definition.abstractItem = Class.create(coreshop.r { text: t('save'), iconCls: 'pimcore_icon_apply', - handler: this.save.bind(this) + handler: this.save.bind(this), + disabled: this.saveDisabled() }], items: this.getItems() }); diff --git a/src/DataDefinitionsBundle/Resources/public/pimcore/js/export/item.js b/src/DataDefinitionsBundle/Resources/public/pimcore/js/export/item.js index 40cb601e..890ba4aa 100644 --- a/src/DataDefinitionsBundle/Resources/public/pimcore/js/export/item.js +++ b/src/DataDefinitionsBundle/Resources/public/pimcore/js/export/item.js @@ -24,6 +24,10 @@ pimcore.plugin.datadefinitions.export.item = Class.create(pimcore.plugin.datadef providers: [], + saveDisabled: function () { + return !pimcore.settings['data-definitions-export-definition-writeable']; + }, + getSettings: function () { var classesStore = new Ext.data.JsonStore({ autoDestroy: true, diff --git a/src/DataDefinitionsBundle/Resources/public/pimcore/js/export/panel.js b/src/DataDefinitionsBundle/Resources/public/pimcore/js/export/panel.js index 0ea8a6c9..d7a2c66b 100755 --- a/src/DataDefinitionsBundle/Resources/public/pimcore/js/export/panel.js +++ b/src/DataDefinitionsBundle/Resources/public/pimcore/js/export/panel.js @@ -38,6 +38,20 @@ pimcore.plugin.datadefinitions.export.panel = Class.create(coreshop.resource.pan filters: [], runners: [], + + getTopBar: function () { + return [ + { + // add button + text: t('add'), + iconCls: 'pimcore_icon_add', + itemId: 'add-button', + handler: this.addItem.bind(this), + disabled: !pimcore.settings['data-definitions-import-definition-writeable'] + } + ]; + }, + getDefaultGridConfiguration: function () { return { region: 'west', diff --git a/src/DataDefinitionsBundle/Resources/public/pimcore/js/import/item.js b/src/DataDefinitionsBundle/Resources/public/pimcore/js/import/item.js index f5aad625..2bbf0843 100644 --- a/src/DataDefinitionsBundle/Resources/public/pimcore/js/import/item.js +++ b/src/DataDefinitionsBundle/Resources/public/pimcore/js/import/item.js @@ -25,6 +25,10 @@ pimcore.plugin.datadefinitions.import.item = Class.create(pimcore.plugin.datadef providers: [], + saveDisabled: function () { + return !pimcore.settings['data-definitions-import-definition-writeable']; + }, + getSettings: function () { var classesStore = new Ext.data.JsonStore({ autoDestroy: true, diff --git a/src/DataDefinitionsBundle/Resources/public/pimcore/js/import/panel.js b/src/DataDefinitionsBundle/Resources/public/pimcore/js/import/panel.js index 0943b337..de5d7ff5 100755 --- a/src/DataDefinitionsBundle/Resources/public/pimcore/js/import/panel.js +++ b/src/DataDefinitionsBundle/Resources/public/pimcore/js/import/panel.js @@ -39,6 +39,19 @@ pimcore.plugin.datadefinitions.import.panel = Class.create(coreshop.resource.pan runners: [], persisters: [], + getTopBar: function () { + return [ + { + // add button + text: t('add'), + iconCls: 'pimcore_icon_add', + itemId: 'add-button', + handler: this.addItem.bind(this), + disabled: !pimcore.settings['data-definitions-import-definition-writeable'] + } + ]; + }, + getDefaultGridConfiguration: function () { return { region: 'west', diff --git a/src/DataDefinitionsBundle/Resources/public/pimcore/js/startup.js b/src/DataDefinitionsBundle/Resources/public/pimcore/js/startup.js index 8246ce92..9208129e 100755 --- a/src/DataDefinitionsBundle/Resources/public/pimcore/js/startup.js +++ b/src/DataDefinitionsBundle/Resources/public/pimcore/js/startup.js @@ -13,16 +13,18 @@ pimcore.registerNS('pimcore.plugin.data_definitions'); -pimcore.plugin.data_definitions = Class.create(pimcore.plugin.admin, { +pimcore.plugin.data_definitions = Class.create({ getClassName: function () { return 'pimcore.plugin.data_definitions'; }, initialize: function () { - pimcore.plugin.broker.registerPlugin(this); + document.addEventListener(pimcore.events.pimcoreReady, (e) => { + this.pimcoreReady(); + }); }, - pimcoreReady: function (params, broker) { + pimcoreReady: function () { var user = pimcore.globalmanager.get('user'); diff --git a/src/Kernel.php b/src/Kernel.php index 2e2ba14d..e5d88e27 100644 --- a/src/Kernel.php +++ b/src/Kernel.php @@ -17,13 +17,13 @@ class Kernel extends PimcoreKernel { - public function registerBundlesToCollection(BundleCollection $collection) + public function registerBundlesToCollection(BundleCollection $collection): void { $collection->addBundle(new \Wvision\Bundle\DataDefinitionsBundle\DataDefinitionsBundle()); $collection->addBundle(new \FriendsOfBehat\SymfonyExtension\Bundle\FriendsOfBehatSymfonyExtensionBundle()); } - public function boot() + public function boot(): void { \Pimcore::setKernel($this); From 297a2b621aafe583e753763c9063000d65ce93fc Mon Sep 17 00:00:00 2001 From: Dominik Pfaffenbauer Date: Tue, 20 Jun 2023 14:53:22 +0200 Subject: [PATCH 02/22] run tests on next --- .github/workflows/behat.yml | 4 ++-- .github/workflows/static.yml | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/behat.yml b/.github/workflows/behat.yml index e2c18e7f..9a984fb4 100644 --- a/.github/workflows/behat.yml +++ b/.github/workflows/behat.yml @@ -1,9 +1,9 @@ name: Behat on: push: - branches: [ master ] + branches: [ next ] pull_request: - branches: [ master ] + branches: [ next ] jobs: behat: diff --git a/.github/workflows/static.yml b/.github/workflows/static.yml index 54d4d198..a2b4607a 100644 --- a/.github/workflows/static.yml +++ b/.github/workflows/static.yml @@ -1,9 +1,9 @@ name: Static Tests (Lint, Stan) on: push: - branches: [ master ] + branches: [ next ] pull_request: - branches: [ master ] + branches: [ next ] jobs: lint: From ec962445a1be237e7c6f156d9a461387257f9ee3 Mon Sep 17 00:00:00 2001 From: Dominik Pfaffenbauer Date: Tue, 20 Jun 2023 15:36:01 +0200 Subject: [PATCH 03/22] tests --- .github/workflows/behat.yml | 50 +++++++++++++++++++----------------- .github/workflows/static.yml | 25 +++++++++--------- 2 files changed, 39 insertions(+), 36 deletions(-) diff --git a/.github/workflows/behat.yml b/.github/workflows/behat.yml index 9a984fb4..94adacbc 100644 --- a/.github/workflows/behat.yml +++ b/.github/workflows/behat.yml @@ -11,41 +11,45 @@ jobs: env: APP_ENV: "test" IM_SKIP_DB_SETUP: "1" + PIMCORE_TEST_DB_DSN: "mysql://root:root@127.0.0.1:3306/coreshop_test" PIMCORE_INSTALL_ADMIN_USERNAME: "admin" PIMCORE_INSTALL_ADMIN_PASSWORD: "admin" PIMCORE_INSTALL_MYSQL_HOST_SOCKET: "127.0.0.1" PIMCORE_INSTALL_MYSQL_USERNAME: "root" PIMCORE_INSTALL_MYSQL_PASSWORD: "root" - PIMCORE_INSTALL_MYSQL_DATABASE: "data_defs_test" + PIMCORE_INSTALL_MYSQL_DATABASE: "coreshop_test" PIMCORE_INSTALL_MYSQL_PORT: "3306" PIMCORE_KERNEL_CLASS: 'Kernel' PIMCORE_CLASS_DIRECTORY: 'var/tmp/behat/var/classes' - PIMCORE_WRITE_TARGET_STATICROUTES: 'settings-store' - PIMCORE_TEST_DB_DSN: "mysql://root:root@127.0.0.1:3306/data_defs_test" + + strategy: + matrix: + php: [ 8.1, 8.2 ] + pimcore: [ ^11.0 ] + dependencies: [ highest ] + exclude: + - php: 8.1 + dependencies: lowest services: database: - image: "mariadb:10.5" + image: "mysql:8" env: MYSQL_ROOT_PASSWORD: root - MYSQL_DATABASE: data_defs_test ports: - 3306:3306 options: --health-cmd="mysqladmin ping" --health-interval=10s --health-timeout=5s --health-retries=3 - name: "${{ matrix.pimcore }}, PHP ${{ matrix.php }}" - strategy: - matrix: - php: [ 8.0, 8.1 ] - pimcore: [ ^10.5 ] + name: "${{ matrix.pimcore }}, PHP ${{ matrix.php }}, Deps ${{ matrix.dependencies }}" steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Install PHP uses: shivammathur/setup-php@v2 with: php-version: ${{ matrix.php }} + ini-values: display_errors=On, display_startup_errors=On, error_reporting=32767 extensions: intl, gd, simpleXML, dom, exif, fileinfo, iconv, mbstring, mysqli, pdo_mysql, zip, zlib - name: Check PHP Version @@ -57,27 +61,27 @@ jobs: - name: Get composer cache directory id: composer-cache - run: echo "::set-output name=dir::$(composer config cache-files-dir)" + run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT - name: Cache composer dependencies - uses: actions/cache@v1 + uses: actions/cache@v3 with: path: ${{ steps.composer-cache.outputs.dir }} key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.json') }} restore-keys: ${{ runner.os }}-composer- - - name: Cache composer dependencies - uses: actions/cache@v1 - with: - path: ${{ steps.composer-cache.outputs.dir }} - key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.json') }} - restore-keys: ${{ runner.os }}-composer- - - - name: Install dependencies highest + - if: matrix.dependencies == 'highest' + name: Install dependencies highest run: | - composer req guzzlehttp/psr7 pimcore/pimcore:${{ matrix.pimcore }} --no-interaction --no-scripts --no-update + composer req pimcore/pimcore:${{ matrix.pimcore }} --no-interaction --no-scripts --no-update composer update --no-progress --prefer-dist --optimize-autoloader + - if: matrix.dependencies == 'lowest' + name: Install dependencies lowest + run: | + composer req pimcore/pimcore:${{ matrix.pimcore }} --no-interaction --no-scripts --no-update + composer update --no-progress --prefer-dist --optimize-autoloader --prefer-lowest + - name: Cache clear run: bin/console cache:clear @@ -85,7 +89,7 @@ jobs: run: bin/console assets:install --symlink - name: Install Pimcore - run: PIMCORE_KERNEL_CLASS=Kernel vendor/bin/pimcore-install --ignore-existing-config --env=test --skip-database-config + run: PIMCORE_KERNEL_CLASS=Kernel vendor/bin/pimcore-install --env=test --skip-database-config - name: Install DataDefinitions run: bin/console pimcore:bundle:install DataDefinitionsBundle diff --git a/.github/workflows/static.yml b/.github/workflows/static.yml index a2b4607a..efd524cf 100644 --- a/.github/workflows/static.yml +++ b/.github/workflows/static.yml @@ -10,32 +10,31 @@ jobs: runs-on: ubuntu-latest env: APP_ENV: "test" - PIMCORE_TEST_DB_DSN: "mysql://root:root@127.0.0.1:3306/data_defs_test" + PIMCORE_TEST_DB_DSN: "mysql://root:root@127.0.0.1:3306/coreshop_test" strategy: matrix: - php: [ 8.0, 8.1 ] - pimcore: [ ^10.5 ] - database: [ 'mysql:8.0' ] - dependencies: [ highest, lowest ] + php: [ 8.1, 8.2 ] + pimcore: [ ^11.0 ] + dependencies: [ highest ] exclude: - php: 8.1 dependencies: lowest services: database: - image: "${{ matrix.database }}" + image: "mysql:8" env: MYSQL_ROOT_PASSWORD: root - MYSQL_DATABASE: data_defs_test + MYSQL_DATABASE: coreshop_test ports: - 3306:3306 options: --health-cmd="mysqladmin ping" --health-interval=10s --health-timeout=5s --health-retries=3 - name: "${{ matrix.pimcore }}, PHP ${{ matrix.php }}, DB ${{ matrix.database }}, Deps ${{ matrix.dependencies }}" + name: "${{ matrix.pimcore }}, PHP ${{ matrix.php }}, Deps ${{ matrix.dependencies }}" steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Install PHP uses: shivammathur/setup-php@v2 @@ -49,10 +48,10 @@ jobs: - name: Get composer cache directory id: composer-cache - run: echo "::set-output name=dir::$(composer config cache-files-dir)" + run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT - name: Cache composer dependencies - uses: actions/cache@v1 + uses: actions/cache@v3 with: path: ${{ steps.composer-cache.outputs.dir }} key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.json') }} @@ -61,13 +60,13 @@ jobs: - if: matrix.dependencies == 'highest' name: Install dependencies highest run: | - composer req guzzlehttp/psr7 pimcore/pimcore:${{ matrix.pimcore }} --no-interaction --no-scripts --no-update + composer req pimcore/pimcore:${{ matrix.pimcore }} --no-interaction --no-scripts --no-update composer update --no-progress --prefer-dist --optimize-autoloader - if: matrix.dependencies == 'lowest' name: Install dependencies lowest run: | - composer req guzzlehttp/psr7 pimcore/pimcore:${{ matrix.pimcore }} --no-interaction --no-scripts --no-update + composer req pimcore/pimcore:${{ matrix.pimcore }} --no-interaction --no-scripts --no-update composer update --no-progress --prefer-dist --optimize-autoloader --prefer-lowest - name: Validate YAML From 16dd8a72737eefe17a47df4ae6cae2cb8deaa00e Mon Sep 17 00:00:00 2001 From: Dominik Pfaffenbauer Date: Mon, 26 Jun 2023 16:04:43 +0200 Subject: [PATCH 04/22] [Messenger] introduce async imports --- .../Command/ImportAsyncCommand.php | 95 +++++++++++++++++++ .../Importer/AsyncImporterInterface.php | 26 +++++ .../Importer/Importer.php | 67 ++++++++++++- .../Messenger/ImportRowMessage.php | 46 +++++++++ .../Messenger/ImportRowMessageHandler.php | 44 +++++++++ .../Resources/config/pimcore/config.yml | 3 + .../Resources/config/pimcore/messenger.yml | 18 ++++ .../Resources/config/services.yml | 8 +- .../Resources/config/services/commands.yml | 8 ++ 9 files changed, 312 insertions(+), 3 deletions(-) create mode 100644 src/DataDefinitionsBundle/Command/ImportAsyncCommand.php create mode 100644 src/DataDefinitionsBundle/Importer/AsyncImporterInterface.php create mode 100644 src/DataDefinitionsBundle/Messenger/ImportRowMessage.php create mode 100644 src/DataDefinitionsBundle/Messenger/ImportRowMessageHandler.php create mode 100755 src/DataDefinitionsBundle/Resources/config/pimcore/messenger.yml diff --git a/src/DataDefinitionsBundle/Command/ImportAsyncCommand.php b/src/DataDefinitionsBundle/Command/ImportAsyncCommand.php new file mode 100644 index 00000000..0f470de5 --- /dev/null +++ b/src/DataDefinitionsBundle/Command/ImportAsyncCommand.php @@ -0,0 +1,95 @@ +eventDispatcher = $eventDispatcher; + $this->repository = $repository; + $this->importer = $importer; + + parent::__construct(); + } + + protected function configure(): void + { + $this + ->setName('data-definitions:async-import') + ->setDescription('Run a Data Definition Import Async.') + ->addOption( + 'definition', + 'd', + InputOption::VALUE_REQUIRED, + 'Import Definition ID or Name' + ) + ->addOption( + 'params', + 'p', + InputOption::VALUE_REQUIRED, + 'JSON Encoded Params' + ); + } + + protected function execute(InputInterface $input, OutputInterface $output) + { + $eventDispatcher = $this->eventDispatcher; + + $params = json_decode($input->getOption('params'), true); + + if (!isset($params['userId'])) { + $params['userId'] = 0; + } + + try { + $definition = $this->repository->find($input->getOption('definition')); + } catch (InvalidArgumentException $e) { + $definition = $this->repository->findByName($input->getOption('definition')); + } + + if (!$definition instanceof ImportDefinitionInterface) { + throw new Exception('Import Definition not found'); + } + + $this->importer->doImportAsync($definition, $params); + + return 0; + } +} diff --git a/src/DataDefinitionsBundle/Importer/AsyncImporterInterface.php b/src/DataDefinitionsBundle/Importer/AsyncImporterInterface.php new file mode 100644 index 00000000..8a1cca58 --- /dev/null +++ b/src/DataDefinitionsBundle/Importer/AsyncImporterInterface.php @@ -0,0 +1,26 @@ +getCreateVersion()) { + Version::enable(); + } else { + Version::disable(); + } + + $dataSet = new ArrayImportDataSet($row); + $runner = null; + $runnerContext = $this->contextFactory->createRunnerContext($definition, $params, $row, $dataSet, null); + + if ($definition->getRunner()) { + /** + * @var RunnerInterface $runner + */ + $runner = $this->runnerRegistry->get($definition->getRunner()); + } + + if ($runner instanceof ImportStartFinishRunnerInterface) { + $runner->startImport($runnerContext); + } + + $filter = null; + $filterType = $definition->getFilter(); + if ($filterType) { + /** + * @var FilterInterface $filter + */ + $filter = $this->filterRegistry->get($filterType); + } + + + $object = $this->importRow( + $definition, + $row, + $dataSet, + $params, + $filter, + $runner + ); + } + + public function doImportAsync(ImportDefinitionInterface $definition, array $params): void + { + /** @var ImportDataSetInterface|array $data */ + $data = $this->getData($definition, $params); + + foreach ($data as $row) { + $this->bus->dispatch( + new ImportRowMessage( + $definition->getId(), + $row, + $params, + ) + ); + } + } + public function doImport(ImportDefinitionInterface $definition, $params): array { $filter = null; diff --git a/src/DataDefinitionsBundle/Messenger/ImportRowMessage.php b/src/DataDefinitionsBundle/Messenger/ImportRowMessage.php new file mode 100644 index 00000000..e821d42a --- /dev/null +++ b/src/DataDefinitionsBundle/Messenger/ImportRowMessage.php @@ -0,0 +1,46 @@ +definitionId = $definitionId; + $this->data = $data; + $this->params = $params; + } + + public function getDefinitionId(): int + { + return $this->definitionId; + } + + public function getData(): array + { + return $this->data; + } + + public function getParams(): array + { + return $this->params; + } +} diff --git a/src/DataDefinitionsBundle/Messenger/ImportRowMessageHandler.php b/src/DataDefinitionsBundle/Messenger/ImportRowMessageHandler.php new file mode 100644 index 00000000..12d8baeb --- /dev/null +++ b/src/DataDefinitionsBundle/Messenger/ImportRowMessageHandler.php @@ -0,0 +1,44 @@ +getDefinitionId()); + + if (!$definition) { + throw new \InvalidArgumentException('Invalid definition id'); + } + + $this->importer->doImportRowAsync( + $definition, + $message->getData(), + $message->getParams(), + ); + } +} diff --git a/src/DataDefinitionsBundle/Resources/config/pimcore/config.yml b/src/DataDefinitionsBundle/Resources/config/pimcore/config.yml index 16f5c299..0aa0fcb6 100644 --- a/src/DataDefinitionsBundle/Resources/config/pimcore/config.yml +++ b/src/DataDefinitionsBundle/Resources/config/pimcore/config.yml @@ -1,3 +1,6 @@ +imports: + - { resource: messenger.yml } + jms_serializer: metadata: directories: diff --git a/src/DataDefinitionsBundle/Resources/config/pimcore/messenger.yml b/src/DataDefinitionsBundle/Resources/config/pimcore/messenger.yml new file mode 100755 index 00000000..fe0ff6cd --- /dev/null +++ b/src/DataDefinitionsBundle/Resources/config/pimcore/messenger.yml @@ -0,0 +1,18 @@ +framework: + messenger: + transports: + data_definitions_import: + dsn: "doctrine://default?queue_name=data_definitions_import" + failure_transport: data_definitions_import_failed + retry_strategy: + max_retries: 5 + delay: 300000 + multiplier: 2 + # we store failed messages here for admins to manually review them later + data_definitions_import_failed: + dsn: "doctrine://default?queue_name=data_definitions_import_failed" + retry_strategy: + max_retries: 0 + + routing: + 'Wvision\Bundle\DataDefinitionsBundle\Messenger\ImportRowMessage': data_definitions_import \ No newline at end of file diff --git a/src/DataDefinitionsBundle/Resources/config/services.yml b/src/DataDefinitionsBundle/Resources/config/services.yml index 95a9cc03..7ca2a596 100644 --- a/src/DataDefinitionsBundle/Resources/config/services.yml +++ b/src/DataDefinitionsBundle/Resources/config/services.yml @@ -381,4 +381,10 @@ services: Wvision\Bundle\DataDefinitionsBundle\Service\StorageLocator: arguments: - $locator: !tagged_locator { tag: flysystem.storage } \ No newline at end of file + $locator: !tagged_locator { tag: flysystem.storage } + + Wvision\Bundle\DataDefinitionsBundle\Messenger\ImportRowMessageHandler: + arguments: + - '@Wvision\Bundle\DataDefinitionsBundle\Importer\ImporterInterface' + tags: + - { name: messenger.message_handler } diff --git a/src/DataDefinitionsBundle/Resources/config/services/commands.yml b/src/DataDefinitionsBundle/Resources/config/services/commands.yml index d8a32392..ea5aa5ef 100644 --- a/src/DataDefinitionsBundle/Resources/config/services/commands.yml +++ b/src/DataDefinitionsBundle/Resources/config/services/commands.yml @@ -19,6 +19,14 @@ services: tags: - { name: 'console.command', command: 'data-definitions:import' } + Wvision\Bundle\DataDefinitionsBundle\Command\ImportAsyncCommand: + arguments: + - '@event_dispatcher' + - '@data_definitions.repository.import_definition' + - '@Wvision\Bundle\DataDefinitionsBundle\Importer\ImporterInterface' + tags: + - { name: 'console.command', command: 'data-definitions:async-import' } + Wvision\Bundle\DataDefinitionsBundle\Command\ExportCommand: arguments: - '@event_dispatcher' From 9957d797e605a84535a227c4b4679b1f8de09e30 Mon Sep 17 00:00:00 2001 From: Dominik Pfaffenbauer Date: Mon, 26 Jun 2023 16:08:12 +0200 Subject: [PATCH 05/22] run tests on 4.0 --- .github/workflows/behat.yml | 4 ++-- .github/workflows/static.yml | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/behat.yml b/.github/workflows/behat.yml index e2c18e7f..d45dc077 100644 --- a/.github/workflows/behat.yml +++ b/.github/workflows/behat.yml @@ -1,9 +1,9 @@ name: Behat on: push: - branches: [ master ] + branches: [ '4.0' ] pull_request: - branches: [ master ] + branches: [ '4.0' ] jobs: behat: diff --git a/.github/workflows/static.yml b/.github/workflows/static.yml index 54d4d198..f7bcc927 100644 --- a/.github/workflows/static.yml +++ b/.github/workflows/static.yml @@ -1,9 +1,9 @@ name: Static Tests (Lint, Stan) on: push: - branches: [ master ] + branches: [ '4.0' ] pull_request: - branches: [ master ] + branches: [ '4.0' ] jobs: lint: From 4018846085489d89b4e59a45eef89bd63d6b31dc Mon Sep 17 00:00:00 2001 From: Dominik Pfaffenbauer Date: Mon, 26 Jun 2023 16:08:38 +0200 Subject: [PATCH 06/22] [Messenger] introduce async imports --- .../Command/ImportAsyncCommand.php | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/src/DataDefinitionsBundle/Command/ImportAsyncCommand.php b/src/DataDefinitionsBundle/Command/ImportAsyncCommand.php index 0f470de5..ac964c23 100644 --- a/src/DataDefinitionsBundle/Command/ImportAsyncCommand.php +++ b/src/DataDefinitionsBundle/Command/ImportAsyncCommand.php @@ -33,19 +33,11 @@ final class ImportAsyncCommand extends AbstractCommand { - protected EventDispatcherInterface $eventDispatcher; - protected DefinitionRepository $repository; - protected ImporterInterface $importer; - public function __construct( - EventDispatcherInterface $eventDispatcher, - DefinitionRepository $repository, - AsyncImporterInterface $importer + protected EventDispatcherInterface $eventDispatcher, + protected DefinitionRepository $repository, + protected AsyncImporterInterface $importer ) { - $this->eventDispatcher = $eventDispatcher; - $this->repository = $repository; - $this->importer = $importer; - parent::__construct(); } From e6619f56781f1d3201a4aa1ec731e9ebc01c83a2 Mon Sep 17 00:00:00 2001 From: Dominik Pfaffenbauer Date: Mon, 26 Jun 2023 16:13:28 +0200 Subject: [PATCH 07/22] [Messenger] introduce async imports --- src/DataDefinitionsBundle/Resources/config/services.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/src/DataDefinitionsBundle/Resources/config/services.yml b/src/DataDefinitionsBundle/Resources/config/services.yml index 7ca2a596..c5e22e0d 100644 --- a/src/DataDefinitionsBundle/Resources/config/services.yml +++ b/src/DataDefinitionsBundle/Resources/config/services.yml @@ -31,6 +31,7 @@ services: - '@logger' - '@pimcore.model.factory' - '@coreshop.expression_language' + - '@messenger.bus.default' tags: - { name: monolog.logger, channel: import_definition } - { name: 'kernel.event_listener', event: 'data_definitions.stop', method: 'stop' } From e2491d79ce4e5a82607a9365dc6885c7eef369d2 Mon Sep 17 00:00:00 2001 From: Dominik Pfaffenbauer Date: Mon, 26 Jun 2023 16:16:14 +0200 Subject: [PATCH 08/22] [Messenger] introduce async imports --- src/DataDefinitionsBundle/Resources/config/services.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/DataDefinitionsBundle/Resources/config/services.yml b/src/DataDefinitionsBundle/Resources/config/services.yml index c5e22e0d..ca0aef39 100644 --- a/src/DataDefinitionsBundle/Resources/config/services.yml +++ b/src/DataDefinitionsBundle/Resources/config/services.yml @@ -31,7 +31,7 @@ services: - '@logger' - '@pimcore.model.factory' - '@coreshop.expression_language' - - '@messenger.bus.default' + - '@messenger.default_bus' tags: - { name: monolog.logger, channel: import_definition } - { name: 'kernel.event_listener', event: 'data_definitions.stop', method: 'stop' } From 5222843ae6b4a7b8a3b4a8a59f6a6d701abe6000 Mon Sep 17 00:00:00 2001 From: Dominik Pfaffenbauer Date: Mon, 26 Jun 2023 16:28:33 +0200 Subject: [PATCH 09/22] [Messenger] introduce async imports --- src/Kernel.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Kernel.php b/src/Kernel.php index 2e2ba14d..19a89cb8 100644 --- a/src/Kernel.php +++ b/src/Kernel.php @@ -25,8 +25,8 @@ public function registerBundlesToCollection(BundleCollection $collection) public function boot() { - \Pimcore::setKernel($this); - parent::boot(); + + \Pimcore::setKernel($this); } } From dfe971c24149b5cf7dfa8a7f1e55c018c64b942c Mon Sep 17 00:00:00 2001 From: Dominik Pfaffenbauer Date: Thu, 6 Jul 2023 12:39:07 +0200 Subject: [PATCH 10/22] Next --- behat-bootstrap.php | 18 +++++++--- composer.json | 5 ++- config/packages/test/config.yaml | 9 +++++ features/cleaner/deleter.feature | 2 +- features/cleaner/none.feature | 2 +- features/cleaner/unpublisher.feature | 2 +- src/BehatKernel.php | 32 +++++++++++++++++ .../Command/ExportCommand.php | 1 + .../Command/ImportCommand.php | 2 ++ .../Importer/Importer.php | 2 +- .../Model/ExportDefinition/Listing.php | 3 ++ .../Model/ImportDefinition/Listing.php | 3 ++ src/DataDefinitionsBundle/Model/Log/Dao.php | 2 +- .../Model/Log/Listing.php | 17 ++++------ .../Model/Log/Listing/Dao.php | 8 ++--- .../Provider/AbstractFileProvider.php | 4 +-- .../Provider/XmlProvider.php | 2 +- .../Rules/Model/ImportRule.php | 2 +- .../Behat/Context/Domain/PimcoreContext.php | 4 +-- .../Behat/Context/Hook/IMSetupContext.php | 34 +++++++++++++------ .../Behat/Context/Hook/PimcoreDaoContext.php | 28 ++++++++++----- .../Context/Setup/PimcoreClassContext.php | 22 ++++++------ .../Context/Transform/PimcoreClassContext.php | 6 ++-- .../Resources/config/profiles/default.yml | 4 +-- .../config/services/contexts/hook.yml | 1 + 25 files changed, 149 insertions(+), 66 deletions(-) create mode 100644 src/BehatKernel.php diff --git a/behat-bootstrap.php b/behat-bootstrap.php index 5a946700..db37a032 100755 --- a/behat-bootstrap.php +++ b/behat-bootstrap.php @@ -1,10 +1,20 @@ addBundle(new \Wvision\Bundle\DataDefinitionsBundle\DataDefinitionsBundle()); + $collection->addBundle(new \FriendsOfBehat\SymfonyExtension\Bundle\FriendsOfBehatSymfonyExtensionBundle()); + } + + public function boot(): void + { + parent::boot(); + + \Pimcore::setKernel($this); + } +} diff --git a/src/DataDefinitionsBundle/Command/ExportCommand.php b/src/DataDefinitionsBundle/Command/ExportCommand.php index 255ca8ee..dbe1d666 100644 --- a/src/DataDefinitionsBundle/Command/ExportCommand.php +++ b/src/DataDefinitionsBundle/Command/ExportCommand.php @@ -76,6 +76,7 @@ protected function execute(InputInterface $input, OutputInterface $output) $eventDispatcher = $this->eventDispatcher; $params = json_decode($input->getOption('params'), true); + $definition = null; try { $definition = $this->repository->findByName($input->getOption('definition')); } catch (InvalidArgumentException $e) { diff --git a/src/DataDefinitionsBundle/Command/ImportCommand.php b/src/DataDefinitionsBundle/Command/ImportCommand.php index b12cd21e..2278bf3f 100644 --- a/src/DataDefinitionsBundle/Command/ImportCommand.php +++ b/src/DataDefinitionsBundle/Command/ImportCommand.php @@ -82,6 +82,8 @@ protected function execute(InputInterface $input, OutputInterface $output) $params['userId'] = 0; } + $definition = null; + try { $definition = $this->repository->findByName($input->getOption('definition')); } catch (InvalidArgumentException $e) { diff --git a/src/DataDefinitionsBundle/Importer/Importer.php b/src/DataDefinitionsBundle/Importer/Importer.php index 4b587db2..40e5ebec 100644 --- a/src/DataDefinitionsBundle/Importer/Importer.php +++ b/src/DataDefinitionsBundle/Importer/Importer.php @@ -412,7 +412,7 @@ private function importRow( $params['versionNote'] = sprintf('%s - %s', $definition->getId(), $definition->getName()); $object->setUserModification($params['userId'] ?? 0); - $object->setOmitMandatoryCheck($definition->getOmitMandatoryCheck()); + $object->setOmitMandatoryCheck($definition->getOmitMandatoryCheck() ?: false); $this->saveObject($object, $definition, $params); diff --git a/src/DataDefinitionsBundle/Model/ExportDefinition/Listing.php b/src/DataDefinitionsBundle/Model/ExportDefinition/Listing.php index 1a77d772..19c8b1e0 100644 --- a/src/DataDefinitionsBundle/Model/ExportDefinition/Listing.php +++ b/src/DataDefinitionsBundle/Model/ExportDefinition/Listing.php @@ -24,6 +24,9 @@ use Pimcore\Model\Listing\Traits\OrderListingTrait; use Wvision\Bundle\DataDefinitionsBundle\Model\ExportDefinitionInterface; +/** + * @method loadList() + */ class Listing extends AbstractModel implements CallableFilterListingInterface, CallableOrderListingInterface { use FilterListingTrait; diff --git a/src/DataDefinitionsBundle/Model/ImportDefinition/Listing.php b/src/DataDefinitionsBundle/Model/ImportDefinition/Listing.php index 580e3556..cbec7d43 100644 --- a/src/DataDefinitionsBundle/Model/ImportDefinition/Listing.php +++ b/src/DataDefinitionsBundle/Model/ImportDefinition/Listing.php @@ -25,6 +25,9 @@ use Pimcore\Model\Listing\Traits\OrderListingTrait; use Wvision\Bundle\DataDefinitionsBundle\Model\ImportDefinitionInterface; +/** + * @method loadList() + */ class Listing extends AbstractModel implements CallableFilterListingInterface, CallableOrderListingInterface { use FilterListingTrait; diff --git a/src/DataDefinitionsBundle/Model/Log/Dao.php b/src/DataDefinitionsBundle/Model/Log/Dao.php index e1e35e91..596ec91d 100644 --- a/src/DataDefinitionsBundle/Model/Log/Dao.php +++ b/src/DataDefinitionsBundle/Model/Log/Dao.php @@ -40,7 +40,7 @@ public function getById($id = null) $this->model->setId($id); } - $data = $this->db->fetchRow('SELECT * FROM '.$this->tableName.' WHERE id = ?', $this->model->getId()); + $data = $this->db->fetchAssociative('SELECT * FROM '.$this->tableName.' WHERE id = ?', [$this->model->getId()]); if (!$data['id']) { throw new InvalidArgumentException(sprintf('Object with the ID %s does not exist', $this->model->getId())); diff --git a/src/DataDefinitionsBundle/Model/Log/Listing.php b/src/DataDefinitionsBundle/Model/Log/Listing.php index 52f06ee9..eef5296b 100644 --- a/src/DataDefinitionsBundle/Model/Log/Listing.php +++ b/src/DataDefinitionsBundle/Model/Log/Listing.php @@ -24,12 +24,7 @@ class Listing extends Model\Listing\AbstractListing implements PaginateListingInterface { - /** - * List of Logs. - * - * @var array - */ - public $data; + public ?array $data; /** * @var string @@ -48,7 +43,7 @@ class Listing extends Model\Listing\AbstractListing implements PaginateListingIn * * @return bool */ - public function isValidOrderKey($key) + public function isValidOrderKey($key): bool { return in_array($key, $this->validOrderKeys, true); } @@ -92,10 +87,10 @@ public function count(): int * * @param int $offset * @param int $itemCountPerPage - * @return mixed + * @return array * @throws Exception */ - public function getItems($offset, $itemCountPerPage) + public function getItems($offset, $itemCountPerPage): array { $this->setOffset($offset); $this->setLimit($itemCountPerPage); @@ -164,10 +159,10 @@ public function current(): mixed /** * Key * - * @return mixed + * @return int|string|null * @throws Exception */ - public function key(): mixed + public function key(): int|string|null { $this->getData(); diff --git a/src/DataDefinitionsBundle/Model/Log/Listing/Dao.php b/src/DataDefinitionsBundle/Model/Log/Listing/Dao.php index ff77c639..3d15e660 100644 --- a/src/DataDefinitionsBundle/Model/Log/Listing/Dao.php +++ b/src/DataDefinitionsBundle/Model/Log/Listing/Dao.php @@ -49,7 +49,7 @@ protected function getTableName() * @return Log[] * @throws Exception */ - public function load() + public function load(): array { // load id's $list = $this->loadIdList(); @@ -85,7 +85,7 @@ public function getQueryBuilder(...$columns): DoctrineQueryBuilder public function loadIdList() { $queryBuilder = $this->getQueryBuilder(['id']); - $assetIds = $this->db->fetchCol( + $assetIds = $this->db->fetchFirstColumn( (string)$queryBuilder, $this->model->getConditionVariables(), $this->model->getConditionVariableTypes() @@ -105,7 +105,7 @@ public function getCount(): int { return (int)$this->db->fetchOne( 'SELECT COUNT(*) as amount FROM '.$this->getTableName().$this->getCondition().$this->getOffsetLimit(), - $this->model->getConditionVariables() + [$this->model->getConditionVariables()] ); } @@ -119,7 +119,7 @@ public function getTotalCount(): int { return (int)$this->db->fetchOne( 'SELECT COUNT(*) as amount FROM '.$this->getTableName().$this->getCondition(), - $this->model->getConditionVariables() + [$this->model->getConditionVariables()] ); } } diff --git a/src/DataDefinitionsBundle/Provider/AbstractFileProvider.php b/src/DataDefinitionsBundle/Provider/AbstractFileProvider.php index 4677cb00..4454f059 100644 --- a/src/DataDefinitionsBundle/Provider/AbstractFileProvider.php +++ b/src/DataDefinitionsBundle/Provider/AbstractFileProvider.php @@ -67,11 +67,11 @@ protected function createTemporaryFileFromStream($stream) { if (is_string($stream)) { $src = fopen($stream, 'rb'); - $fileExtension = File::getFileExtension($stream); + $fileExtension = pathinfo($stream, PATHINFO_EXTENSION); } else { $src = $stream; $streamMeta = stream_get_meta_data($src); - $fileExtension = File::getFileExtension($streamMeta['uri']); + $fileExtension = pathinfo($streamMeta['uri'], PATHINFO_EXTENSION); } $tmpFilePath = File::getLocalTempFilePath($fileExtension); diff --git a/src/DataDefinitionsBundle/Provider/XmlProvider.php b/src/DataDefinitionsBundle/Provider/XmlProvider.php index 360903d8..92f679dd 100755 --- a/src/DataDefinitionsBundle/Provider/XmlProvider.php +++ b/src/DataDefinitionsBundle/Provider/XmlProvider.php @@ -135,7 +135,7 @@ public function exportData(array $configuration, ExportDefinitionInterface $defi throw new RuntimeException(sprintf('Passed XSLT file "%1$s" not found', $path)); } - $extension = File::getFileExtension($configuration['xsltPath']); + $extension = pathinfo($configuration['xsltPath'], PATHINFO_EXTENSION); $workingPath = File::getLocalTempFilePath($extension); file_put_contents($workingPath, $storage->read($path)); diff --git a/src/DataDefinitionsBundle/Rules/Model/ImportRule.php b/src/DataDefinitionsBundle/Rules/Model/ImportRule.php index 16bf733f..e8fa3a01 100644 --- a/src/DataDefinitionsBundle/Rules/Model/ImportRule.php +++ b/src/DataDefinitionsBundle/Rules/Model/ImportRule.php @@ -24,7 +24,7 @@ class ImportRule implements ImportRuleInterface protected int $id; - public function getId() + public function getId(): ?int { return $this->id; } diff --git a/tests/DataDefinitionsBundle/Behat/Context/Domain/PimcoreContext.php b/tests/DataDefinitionsBundle/Behat/Context/Domain/PimcoreContext.php index a691ed8e..94a74ed1 100644 --- a/tests/DataDefinitionsBundle/Behat/Context/Domain/PimcoreContext.php +++ b/tests/DataDefinitionsBundle/Behat/Context/Domain/PimcoreContext.php @@ -64,7 +64,7 @@ public function thereAreUnpublishedDataObjects(int $count, ClassDefinition $defi * @var DataObject\Listing $list */ $list = $fqcn::getList(); - $list->setCondition('o_published=0'); + $list->setCondition('published=0'); Assert::eq($count, $list->getTotalCount(), sprintf( @@ -88,7 +88,7 @@ public function thereArePublishedDataObjects(int $count, ClassDefinition $defini * @var DataObject\Listing $list */ $list = $fqcn::getList(); - $list->setCondition('o_published=1'); + $list->setCondition('published=1'); Assert::eq($count, $list->getTotalCount(), sprintf( diff --git a/tests/DataDefinitionsBundle/Behat/Context/Hook/IMSetupContext.php b/tests/DataDefinitionsBundle/Behat/Context/Hook/IMSetupContext.php index fa471a0c..2709f863 100644 --- a/tests/DataDefinitionsBundle/Behat/Context/Hook/IMSetupContext.php +++ b/tests/DataDefinitionsBundle/Behat/Context/Hook/IMSetupContext.php @@ -17,6 +17,8 @@ use Behat\Behat\Context\Context; use Wvision\Bundle\DataDefinitionsBundle\Installer; use Pimcore\Db\PhpArrayFileTable; +use Wvision\Bundle\DataDefinitionsBundle\Model\ExportDefinition; +use Wvision\Bundle\DataDefinitionsBundle\Model\ImportDefinition; final class IMSetupContext implements Context { @@ -46,18 +48,30 @@ public static function setupImportDefinitions() */ public function purgeDefinitions() { - if (file_exists(PIMCORE_CONFIGURATION_DIRECTORY.'/importdefinitions.php')) { - unlink(PIMCORE_CONFIGURATION_DIRECTORY.'/importdefinitions.php'); - } + $importDefinitions = new ImportDefinition\Listing(); - if (file_exists(PIMCORE_CONFIGURATION_DIRECTORY.'/exportdefinitions.php')) { - unlink(PIMCORE_CONFIGURATION_DIRECTORY.'/exportdefinitions.php'); + foreach ($importDefinitions->getObjects() as $definition) { + $definition->delete(); } - $obj = new PhpArrayFileTable(); - $refObject = new \ReflectionObject($obj); - $refProperty = $refObject->getProperty('tables'); - $refProperty->setAccessible(true); - $refProperty->setValue(null, []); + $exportDefinitions = new ExportDefinition\Listing(); + + foreach ($exportDefinitions->getObjects() as $definition) { + $definition->delete(); + } +// +// if (file_exists(PIMCORE_CONFIGURATION_DIRECTORY.'/importdefinitions.php')) { +// unlink(PIMCORE_CONFIGURATION_DIRECTORY.'/importdefinitions.php'); +// } +// +// if (file_exists(PIMCORE_CONFIGURATION_DIRECTORY.'/exportdefinitions.php')) { +// unlink(PIMCORE_CONFIGURATION_DIRECTORY.'/exportdefinitions.php'); +// } +// +// $obj = new PhpArrayFileTable(); +// $refObject = new \ReflectionObject($obj); +// $refProperty = $refObject->getProperty('tables'); +// $refProperty->setAccessible(true); +// $refProperty->setValue(null, []); } } diff --git a/tests/DataDefinitionsBundle/Behat/Context/Hook/PimcoreDaoContext.php b/tests/DataDefinitionsBundle/Behat/Context/Hook/PimcoreDaoContext.php index b6b1c4fc..5dd74b03 100644 --- a/tests/DataDefinitionsBundle/Behat/Context/Hook/PimcoreDaoContext.php +++ b/tests/DataDefinitionsBundle/Behat/Context/Hook/PimcoreDaoContext.php @@ -23,14 +23,24 @@ use Pimcore\Model\DataObject\Fieldcollection; use Pimcore\Model\DataObject\Listing; use Pimcore\Model\DataObject\Objectbrick; +use Symfony\Component\HttpKernel\KernelInterface; final class PimcoreDaoContext implements Context { - private $connection; + public function __construct( + private Connection $connection, + private KernelInterface $kernel, + ) + { + + } - public function __construct(Connection $connection) + /** + * @BeforeScenario + */ + public function setKernel(): void { - $this->connection = $connection; + \Pimcore::setKernel($this->kernel); } /** @@ -39,14 +49,14 @@ public function __construct(Connection $connection) public function purgeObjects() { Cache::clearAll(); - Cache\Runtime::clear(); + Cache\RuntimeCache::clear(); /** * @var Listing $list */ $list = new DataObject\Listing(); $list->setUnpublished(true); - $list->setCondition('o_id <> 1'); + $list->setCondition('id <> 1'); $list->load(); foreach ($list->getObjects() as $obj) { @@ -60,7 +70,7 @@ public function purgeObjects() public function purgeAssets() { Cache::clearAll(); - Cache\Runtime::clear(); + Cache\RuntimeCache::clear(); /** * @var Asset\Listing $list @@ -107,7 +117,7 @@ public function purgeBricks() public function clearRuntimeCacheScenario() { //Clearing it here is totally fine, since each scenario has its own separated context of objects - \Pimcore\Cache\Runtime::clear(); + Cache\RuntimeCache::clear(); } /** @@ -117,7 +127,7 @@ public function clearRuntimeCacheStep() { //We should not clear Pimcore Objects here, otherwise we lose the reference to it //and end up having the same object twice - $copy = \Pimcore\Cache\Runtime::getInstance()->getArrayCopy(); + $copy = \Pimcore\Cache\RuntimeCache::getInstance()->getArrayCopy(); $keepItems = []; foreach ($copy as $key => $value) { @@ -126,7 +136,7 @@ public function clearRuntimeCacheStep() } } - \Pimcore\Cache\Runtime::clear($keepItems); + \Pimcore\Cache\RuntimeCache::clear($keepItems); } /** diff --git a/tests/DataDefinitionsBundle/Behat/Context/Setup/PimcoreClassContext.php b/tests/DataDefinitionsBundle/Behat/Context/Setup/PimcoreClassContext.php index 0385632a..bd92c194 100644 --- a/tests/DataDefinitionsBundle/Behat/Context/Setup/PimcoreClassContext.php +++ b/tests/DataDefinitionsBundle/Behat/Context/Setup/PimcoreClassContext.php @@ -79,7 +79,7 @@ public function createClassNamed($className) "bodyStyle": null, "datatype": "layout", "permissions": null, - "childs": [ + "children": [ { "fieldtype": "panel", "labelWidth": 100, @@ -95,7 +95,7 @@ public function createClassNamed($className) "bodyStyle": null, "datatype": "layout", "permissions": null, - "childs": [], + "children": [], "locked": false } ], @@ -159,7 +159,7 @@ public function createBrickNamed($brickName) "bodyStyle": null, "datatype": "layout", "permissions": null, - "childs": [ + "children": [ { "fieldtype": "panel", "labelWidth": 100, @@ -175,7 +175,7 @@ public function createBrickNamed($brickName) "bodyStyle": null, "datatype": "layout", "permissions": null, - "childs": [], + "children": [], "locked": false } ], @@ -217,7 +217,7 @@ public function createCollectionNamed($collection) "bodyStyle": null, "datatype": "layout", "permissions": null, - "childs": [ + "children": [ { "fieldtype": "panel", "labelWidth": 100, @@ -233,7 +233,7 @@ public function createCollectionNamed($collection) "bodyStyle": null, "datatype": "layout", "permissions": null, - "childs": [], + "children": [], "locked": false } ], @@ -318,9 +318,9 @@ public function definitionHasExternalImageField($definition, $name) $jsonDefinition = sprintf(' { "fieldtype": "externalImage", - "previewWidth": "", - "inputWidth": "", - "previewHeight": "", + "previewWidth": null, + "inputWidth": null, + "previewHeight": null, "name": "%s", "title": "%s", "tooltip": "", @@ -522,7 +522,7 @@ public function definitionHasLocalizedInputField($definition, $name) { "fieldtype": "localizedfields", "phpdocType": "\\Pimcore\\Model\\DataObject\\Localizedfield", - "childs": [ + "children": [ { "fieldtype": "input", "width": null, @@ -587,7 +587,7 @@ public function definitionHasLocalizedTextareaField($definition, $name) { "fieldtype": "localizedfields", "phpdocType": "\\Pimcore\\Model\\DataObject\\Localizedfield", - "childs": [ + "children": [ { "fieldtype": "textarea", "width": "", diff --git a/tests/DataDefinitionsBundle/Behat/Context/Transform/PimcoreClassContext.php b/tests/DataDefinitionsBundle/Behat/Context/Transform/PimcoreClassContext.php index ce2ff728..dce8bc31 100644 --- a/tests/DataDefinitionsBundle/Behat/Context/Transform/PimcoreClassContext.php +++ b/tests/DataDefinitionsBundle/Behat/Context/Transform/PimcoreClassContext.php @@ -17,7 +17,7 @@ use Behat\Behat\Context\Context; use Wvision\Bundle\DataDefinitionsBundle\Behat\Service\ClassStorageInterface; use Wvision\Bundle\DataDefinitionsBundle\Behat\Service\SharedStorageInterface; -use Pimcore\Cache\Runtime; +use Pimcore\Cache\RuntimeCache; use Pimcore\Model\DataObject; use Pimcore\Model\DataObject\ClassDefinition; use Pimcore\Model\DataObject\Concrete; @@ -42,7 +42,7 @@ public function __construct( */ public function class($name) { - Runtime::clear(); + RuntimeCache::clear(); $name = $this->classStorage->get($name); @@ -129,7 +129,7 @@ public function objectOfTheClass($name) */ public function definition() { - Runtime::clear(); + RuntimeCache::clear(); $name = $this->sharedStorage->get('pimcore_definition_name'); $class = $this->sharedStorage->get('pimcore_definition_class'); diff --git a/tests/DataDefinitionsBundle/Behat/Resources/config/profiles/default.yml b/tests/DataDefinitionsBundle/Behat/Resources/config/profiles/default.yml index aee25a91..e88d3ecd 100644 --- a/tests/DataDefinitionsBundle/Behat/Resources/config/profiles/default.yml +++ b/tests/DataDefinitionsBundle/Behat/Resources/config/profiles/default.yml @@ -9,6 +9,6 @@ default: FriendsOfBehat\SymfonyExtension: bootstrap: behat-bootstrap.php kernel: - path: src/Kernel.php - class: Kernel + path: src/BehatKernel.php + class: BehatKernel environment: test diff --git a/tests/DataDefinitionsBundle/Behat/Resources/config/services/contexts/hook.yml b/tests/DataDefinitionsBundle/Behat/Resources/config/services/contexts/hook.yml index 8b689ee8..d11a7946 100644 --- a/tests/DataDefinitionsBundle/Behat/Resources/config/services/contexts/hook.yml +++ b/tests/DataDefinitionsBundle/Behat/Resources/config/services/contexts/hook.yml @@ -6,6 +6,7 @@ services: class: Wvision\Bundle\DataDefinitionsBundle\Behat\Context\Hook\PimcoreDaoContext arguments: - '@doctrine.dbal.default_connection' + - '@kernel' tags: - { name: fob.context_service } From f5b6e64b56b09ea720d85a602d2a5062bc39df85 Mon Sep 17 00:00:00 2001 From: Bram Gerritsen Date: Thu, 20 Jul 2023 07:59:08 +0200 Subject: [PATCH 11/22] Add missing type casting interpreter definition --- src/DataDefinitionsBundle/Resources/config/services.yml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/DataDefinitionsBundle/Resources/config/services.yml b/src/DataDefinitionsBundle/Resources/config/services.yml index 990a0075..05e07d3f 100644 --- a/src/DataDefinitionsBundle/Resources/config/services.yml +++ b/src/DataDefinitionsBundle/Resources/config/services.yml @@ -269,6 +269,10 @@ services: tags: - { name: data_definitions.interpreter, type: donotsetonempty, form-type: Wvision\Bundle\DataDefinitionsBundle\Form\Type\NoConfigurationType } + Wvision\Bundle\DataDefinitionsBundle\Interpreter\TypeCastingInterpreter: + tags: + - { name: data_definitions.interpreter, type: type_casting, form-type: Wvision\Bundle\DataDefinitionsBundle\Form\Type\NoConfigurationType } + Wvision\Bundle\DataDefinitionsBundle\Interpreter\LinkInterpreter: tags: - { name: data_definitions.interpreter, type: link, form-type: Wvision\Bundle\DataDefinitionsBundle\Form\Type\NoConfigurationType } @@ -389,4 +393,4 @@ services: Wvision\Bundle\DataDefinitionsBundle\EventListener\WriteableListener: tags: - - { name: kernel.event_subscriber } \ No newline at end of file + - { name: kernel.event_subscriber } From 238af7e62b775a17e4c3b424bd8748292727bcdd Mon Sep 17 00:00:00 2001 From: Bram Date: Fri, 21 Jul 2023 08:59:29 +0200 Subject: [PATCH 12/22] add float to possible types and add GUI config form --- .../TypeCastingInterpreterType.php | 37 +++++++++++++++++ .../Interpreter/TypeCastingInterpreter.php | 9 ++-- .../Resources/config/pimcore/config.yml | 1 + .../Resources/config/services.yml | 6 +-- .../pimcore/js/interpreters/typecasting.js | 41 +++++++++++++++++++ 5 files changed, 88 insertions(+), 6 deletions(-) create mode 100644 src/DataDefinitionsBundle/Form/Type/Interpreter/TypeCastingInterpreterType.php create mode 100644 src/DataDefinitionsBundle/Resources/public/pimcore/js/interpreters/typecasting.js diff --git a/src/DataDefinitionsBundle/Form/Type/Interpreter/TypeCastingInterpreterType.php b/src/DataDefinitionsBundle/Form/Type/Interpreter/TypeCastingInterpreterType.php new file mode 100644 index 00000000..400c7295 --- /dev/null +++ b/src/DataDefinitionsBundle/Form/Type/Interpreter/TypeCastingInterpreterType.php @@ -0,0 +1,37 @@ +add('toType', ChoiceType::class, [ + 'choices' => [ + TypeCastingInterpreter::TYPE_INT => TypeCastingInterpreter::TYPE_INT, + TypeCastingInterpreter::TYPE_STRING => TypeCastingInterpreter::TYPE_STRING, + TypeCastingInterpreter::TYPE_BOOLEAN => TypeCastingInterpreter::TYPE_BOOLEAN, + ], + ]); + } +} diff --git a/src/DataDefinitionsBundle/Interpreter/TypeCastingInterpreter.php b/src/DataDefinitionsBundle/Interpreter/TypeCastingInterpreter.php index c803c365..94840c79 100644 --- a/src/DataDefinitionsBundle/Interpreter/TypeCastingInterpreter.php +++ b/src/DataDefinitionsBundle/Interpreter/TypeCastingInterpreter.php @@ -21,9 +21,10 @@ class TypeCastingInterpreter implements InterpreterInterface { - protected const TYPE_INT = 'int'; - protected const TYPE_STRING = 'string'; - protected const TYPE_BOOLEAN = 'boolean'; + public const TYPE_INT = 'int'; + public const TYPE_FLOAT = 'float'; + public const TYPE_STRING = 'string'; + public const TYPE_BOOLEAN = 'boolean'; public function interpret(InterpreterContextInterface $context): mixed { @@ -32,6 +33,8 @@ public function interpret(InterpreterContextInterface $context): mixed switch ($type) { case static::TYPE_INT: return (int)$context->getValue(); + case static::TYPE_FLOAT: + return (float)$context->getValue(); case static::TYPE_STRING: return (string)$context->getValue(); case static::TYPE_BOOLEAN: diff --git a/src/DataDefinitionsBundle/Resources/config/pimcore/config.yml b/src/DataDefinitionsBundle/Resources/config/pimcore/config.yml index aabbb4be..de1f6b2f 100644 --- a/src/DataDefinitionsBundle/Resources/config/pimcore/config.yml +++ b/src/DataDefinitionsBundle/Resources/config/pimcore/config.yml @@ -53,6 +53,7 @@ data_definitions: interpreter_twig: '/bundles/datadefinitions/pimcore/js/interpreters/twig.js' interpreter_carbon: '/bundles/datadefinitions/pimcore/js/interpreters/carbon.js' interpreter_metadata: '/bundles/datadefinitions/pimcore/js/interpreters/metadata.js' + interpreter_typecasting: '/bundles/datadefinitions/pimcore/js/interpreters/typecasting.js' setter_abstract: '/bundles/datadefinitions/pimcore/js/setters/abstract.js' setter_fieldcollection: '/bundles/datadefinitions/pimcore/js/setters/fieldcollection.js' setter_objectbrick: '/bundles/datadefinitions/pimcore/js/setters/objectbrick.js' diff --git a/src/DataDefinitionsBundle/Resources/config/services.yml b/src/DataDefinitionsBundle/Resources/config/services.yml index 05e07d3f..e1f9bb93 100644 --- a/src/DataDefinitionsBundle/Resources/config/services.yml +++ b/src/DataDefinitionsBundle/Resources/config/services.yml @@ -270,8 +270,8 @@ services: - { name: data_definitions.interpreter, type: donotsetonempty, form-type: Wvision\Bundle\DataDefinitionsBundle\Form\Type\NoConfigurationType } Wvision\Bundle\DataDefinitionsBundle\Interpreter\TypeCastingInterpreter: - tags: - - { name: data_definitions.interpreter, type: type_casting, form-type: Wvision\Bundle\DataDefinitionsBundle\Form\Type\NoConfigurationType } + tags: + - { name: data_definitions.interpreter, type: type_casting, form-type: Wvision\Bundle\DataDefinitionsBundle\Form\Type\Interpreter\TypeCastingInterpreterType } Wvision\Bundle\DataDefinitionsBundle\Interpreter\LinkInterpreter: tags: @@ -393,4 +393,4 @@ services: Wvision\Bundle\DataDefinitionsBundle\EventListener\WriteableListener: tags: - - { name: kernel.event_subscriber } + - { name: kernel.event_subscriber } \ No newline at end of file diff --git a/src/DataDefinitionsBundle/Resources/public/pimcore/js/interpreters/typecasting.js b/src/DataDefinitionsBundle/Resources/public/pimcore/js/interpreters/typecasting.js new file mode 100644 index 00000000..cd846392 --- /dev/null +++ b/src/DataDefinitionsBundle/Resources/public/pimcore/js/interpreters/typecasting.js @@ -0,0 +1,41 @@ +/** + * Data Definitions. + * + * LICENSE + * + * This source file is subject to the GNU General Public License version 3 (GPLv3) + * For the full copyright and license information, please view the LICENSE.md and gpl-3.0.txt + * files that are distributed with this source code. + * + * @copyright Copyright (c) 2016-2019 w-vision AG (https://www.w-vision.ch) + * @license https://github.com/w-vision/DataDefinitions/blob/master/gpl-3.0.txt GNU General Public License version 3 (GPLv3) + */ + +pimcore.registerNS('pimcore.plugin.datadefinitions.interpreters.type_casting'); + +pimcore.plugin.datadefinitions.interpreters.type_casting = Class.create(pimcore.plugin.datadefinitions.interpreters.abstract, { + getLayout: function (fromColumn, toColumn, record, config) { + const typeStore = new Ext.data.ArrayStore({ + fields: ['key', 'value'], + data: [ + ['int', 'integer'], + ['float', 'float'], + ['string', 'string'], + ['boolean', 'boolean'] + ] + }); + + return [ + { + xtype: 'combo', + fieldLabel: t('type'), + name: 'toType', + displayField: 'value', + valueField: 'key', + store: typeStore, + width: 500, + value: config.Totype ? config.Totype : 'int' + }, + ]; + } +}); From 2ebbfb4f1389cf5b302615ec50245ce6b16e5507 Mon Sep 17 00:00:00 2001 From: Bram Date: Fri, 21 Jul 2023 09:00:48 +0200 Subject: [PATCH 13/22] add float --- .../Form/Type/Interpreter/TypeCastingInterpreterType.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/DataDefinitionsBundle/Form/Type/Interpreter/TypeCastingInterpreterType.php b/src/DataDefinitionsBundle/Form/Type/Interpreter/TypeCastingInterpreterType.php index 400c7295..7922be43 100644 --- a/src/DataDefinitionsBundle/Form/Type/Interpreter/TypeCastingInterpreterType.php +++ b/src/DataDefinitionsBundle/Form/Type/Interpreter/TypeCastingInterpreterType.php @@ -29,6 +29,7 @@ public function buildForm(FormBuilderInterface $builder, array $options): void ->add('toType', ChoiceType::class, [ 'choices' => [ TypeCastingInterpreter::TYPE_INT => TypeCastingInterpreter::TYPE_INT, + TypeCastingInterpreter::TYPE_FLOAT => TypeCastingInterpreter::TYPE_FLOAT, TypeCastingInterpreter::TYPE_STRING => TypeCastingInterpreter::TYPE_STRING, TypeCastingInterpreter::TYPE_BOOLEAN => TypeCastingInterpreter::TYPE_BOOLEAN, ], From 79370b5c5f077a509880e4fc3639800c19ada73f Mon Sep 17 00:00:00 2001 From: Dominik Pfaffenbauer Date: Wed, 27 Sep 2023 16:38:20 +0200 Subject: [PATCH 14/22] [Writable] only allow writable definitions to be saved --- .../EventListener/PimcoreSettingsListener.php | 3 +-- .../Resources/config/serializer/Model.ExportDefinition.yml | 5 +++++ .../Resources/config/serializer/Model.ImportDefinition.yml | 5 +++++ .../Resources/public/pimcore/js/export/item.js | 2 +- .../Resources/public/pimcore/js/import/item.js | 2 +- 5 files changed, 13 insertions(+), 4 deletions(-) diff --git a/src/DataDefinitionsBundle/EventListener/PimcoreSettingsListener.php b/src/DataDefinitionsBundle/EventListener/PimcoreSettingsListener.php index 82e8bab9..9b48546d 100644 --- a/src/DataDefinitionsBundle/EventListener/PimcoreSettingsListener.php +++ b/src/DataDefinitionsBundle/EventListener/PimcoreSettingsListener.php @@ -24,7 +24,6 @@ class PimcoreSettingsListener { public function indexSettings(IndexActionSettingsEvent $settingsEvent): void { - $settingsEvent->addSetting('data-definitions-import-definition-writeable', (new ImportDefinition())->isWriteable()); - $settingsEvent->addSetting('data-definitions-export-definition-writeable', (new ExportDefinition())->isWriteable()); + } } diff --git a/src/DataDefinitionsBundle/Resources/config/serializer/Model.ExportDefinition.yml b/src/DataDefinitionsBundle/Resources/config/serializer/Model.ExportDefinition.yml index fb48406b..30e861c6 100755 --- a/src/DataDefinitionsBundle/Resources/config/serializer/Model.ExportDefinition.yml +++ b/src/DataDefinitionsBundle/Resources/config/serializer/Model.ExportDefinition.yml @@ -14,3 +14,8 @@ Wvision\Bundle\DataDefinitionsBundle\Model\ExportDefinition: expose: true type: boolean groups: [ Detailed ] + virtual_properties: + isWriteable: + exp: object.isWriteable() + type: boolean + serialized_name: isWriteable \ No newline at end of file diff --git a/src/DataDefinitionsBundle/Resources/config/serializer/Model.ImportDefinition.yml b/src/DataDefinitionsBundle/Resources/config/serializer/Model.ImportDefinition.yml index 1ec31c51..df9641c6 100755 --- a/src/DataDefinitionsBundle/Resources/config/serializer/Model.ImportDefinition.yml +++ b/src/DataDefinitionsBundle/Resources/config/serializer/Model.ImportDefinition.yml @@ -50,3 +50,8 @@ Wvision\Bundle\DataDefinitionsBundle\Model\ImportDefinition: expose: true type: boolean groups: [ Detailed ] + virtual_properties: + isWriteable: + exp: object.isWriteable() + type: boolean + serialized_name: isWriteable \ No newline at end of file diff --git a/src/DataDefinitionsBundle/Resources/public/pimcore/js/export/item.js b/src/DataDefinitionsBundle/Resources/public/pimcore/js/export/item.js index 890ba4aa..1e1b2799 100644 --- a/src/DataDefinitionsBundle/Resources/public/pimcore/js/export/item.js +++ b/src/DataDefinitionsBundle/Resources/public/pimcore/js/export/item.js @@ -25,7 +25,7 @@ pimcore.plugin.datadefinitions.export.item = Class.create(pimcore.plugin.datadef providers: [], saveDisabled: function () { - return !pimcore.settings['data-definitions-export-definition-writeable']; + return !this.data.isWriteable; }, getSettings: function () { diff --git a/src/DataDefinitionsBundle/Resources/public/pimcore/js/import/item.js b/src/DataDefinitionsBundle/Resources/public/pimcore/js/import/item.js index 2bbf0843..b10f623a 100644 --- a/src/DataDefinitionsBundle/Resources/public/pimcore/js/import/item.js +++ b/src/DataDefinitionsBundle/Resources/public/pimcore/js/import/item.js @@ -26,7 +26,7 @@ pimcore.plugin.datadefinitions.import.item = Class.create(pimcore.plugin.datadef providers: [], saveDisabled: function () { - return !pimcore.settings['data-definitions-import-definition-writeable']; + return !this.data.isWriteable; }, getSettings: function () { From 32933d60e3750b5b26558ffd894e0848f9133d3b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dalibor=20Karlovi=C4=87?= Date: Thu, 28 Sep 2023 17:06:00 +0200 Subject: [PATCH 15/22] Update export_contextmenu.js for Pimcore 11 --- .../js/process_manager/export_contextmenu.js | 153 ++++++++---------- 1 file changed, 69 insertions(+), 84 deletions(-) diff --git a/src/DataDefinitionsBundle/Resources/public/pimcore/js/process_manager/export_contextmenu.js b/src/DataDefinitionsBundle/Resources/public/pimcore/js/process_manager/export_contextmenu.js index 8f62748f..71f7242c 100644 --- a/src/DataDefinitionsBundle/Resources/public/pimcore/js/process_manager/export_contextmenu.js +++ b/src/DataDefinitionsBundle/Resources/public/pimcore/js/process_manager/export_contextmenu.js @@ -1,92 +1,77 @@ -pimcore.registerNS("pimcore.plugin.datadefinitions.export.context_menu"); - -pimcore.plugin.datadefinitions.export.context_menu = Class.create(pimcore.plugin.admin, { - getClassName: function () { - return "pimcore.plugin.datadefinitions.export.context_menu"; - }, - - initialize: function () { - pimcore.plugin.broker.registerPlugin(this); - }, +document.addEventListener(pimcore.events.prepareObjectTreeContextMenu, function (event) { + if (!Ext.ClassManager.get('Executable')) { + Ext.define('Executable', { + extend: 'Ext.data.Model', + fields: [ + {name: 'name', type: 'string'}, + ] + }); + } - prepareObjectTreeContextMenu: function (tree, treeClass, menuItem) { - if (!Ext.ClassManager.get('Executable')) { - Ext.define('Executable', { - extend: 'Ext.data.Model', - fields: [ - {name: 'name', type: 'string'}, - ] - }); - } + const tree = event.detail.menu; - var $this = this; - Ext.create('Ext.data.Store', { - model: 'Executable', - proxy: { - type: 'ajax', - url: '/admin/process_manager/executables/list-by-type', - extraParams: { - type: 'exportdefinition' - }, - reader: { - type: 'json', - rootProperty: 'data' - } + Ext.create('Ext.data.Store', { + model: 'Executable', + proxy: { + type: 'ajax', + url: '/admin/process_manager/executables/list-by-type', + extraParams: { + type: 'exportdefinition' }, - sorters: [{ - property: 'name', - direction: 'ASC' - }], - sortRoot: 'data', - autoLoad: true, - listeners: { - refresh: function (store) { - var exportMenu = []; - store.each(function (executable) { - exportMenu.push({ - text: executable.get('name'), - iconCls: "pimcore_icon_object pimcore_icon_overlay_add", - handler: $this.exportObjects.bind($this, executable, menuItem) - }); - }); - - if (exportMenu) { - tree.add([ - {xtype: 'menuseparator'}, - { - text: t("data_definitions_processmanager_export_from_here"), - iconCls: "pimcore_icon_object pimcore_icon_overlay_download", - menu: exportMenu - } - ]); - } - } + reader: { + type: 'json', + rootProperty: 'data' } - }); - }, + }, + sorters: [{ + property: 'name', + direction: 'ASC' + }], + sortRoot: 'data', + autoLoad: true, + listeners: { + refresh: function (store) { + var exportMenu = []; + store.each(function (executable) { + exportMenu.push({ + text: executable.get('name'), + iconCls: "pimcore_icon_object pimcore_icon_overlay_add", + handler: function (menuItem) { + Ext.Ajax.request({ + url: '/admin/process_manager/executables/run', + params: { + id: executable.id, + startupConfig: Ext.encode({ + root: menuItem.$iid, + }), + csrfToken: pimcore.settings['csrfToken'] + }, + method: 'POST', + success: function (result) { + result = Ext.decode(result.responseText); - exportObjects: function (executable, menuItem) { - Ext.Ajax.request({ - url: '/admin/process_manager/executables/run', - params: { - id: executable.id, - startupConfig: Ext.encode({ - root: menuItem.get('id'), - }), - csrfToken: pimcore.settings['csrfToken'] - }, - method: 'POST', - success: function (result) { - result = Ext.decode(result.responseText); + if (result.success) { + Ext.Msg.alert(t('success'), t('processmanager_executable_started')); + } else { + Ext.Msg.alert(t('error'), result.message); + } + }.bind(this) + }); + } + }); + }); - if (result.success) { - Ext.Msg.alert(t('success'), t('processmanager_executable_started')); - } else { - Ext.Msg.alert(t('error'), result.message); + if (exportMenu) { + tree.add([ + {xtype: 'menuseparator'}, + { + text: t("data_definitions_processmanager_export_from_here"), + iconCls: "pimcore_icon_object pimcore_icon_overlay_download", + menu: exportMenu + } + ]); } - }.bind(this) - }); - } + } + } + }); }); - -new pimcore.plugin.datadefinitions.export.context_menu(); From 2774cbef4f0cbd1f42319c7023626294f7dd4a63 Mon Sep 17 00:00:00 2001 From: Paul Verdu Date: Mon, 2 Oct 2023 15:24:52 +0200 Subject: [PATCH 16/22] Fix problem where persister is not saved or retrieved from config file --- src/DataDefinitionsBundle/Model/ImportDefinition/Dao.php | 1 + .../Resources/config/serializer/Model.ImportDefinition.yml | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/src/DataDefinitionsBundle/Model/ImportDefinition/Dao.php b/src/DataDefinitionsBundle/Model/ImportDefinition/Dao.php index 6755c430..15bdcfa9 100644 --- a/src/DataDefinitionsBundle/Model/ImportDefinition/Dao.php +++ b/src/DataDefinitionsBundle/Model/ImportDefinition/Dao.php @@ -152,6 +152,7 @@ public function save() 'forceLoadObject', 'loader', 'fetcher', + 'persister', ]; foreach ($dataRaw as $key => $value) { diff --git a/src/DataDefinitionsBundle/Resources/config/serializer/Model.ImportDefinition.yml b/src/DataDefinitionsBundle/Resources/config/serializer/Model.ImportDefinition.yml index be7b7b33..f2426729 100755 --- a/src/DataDefinitionsBundle/Resources/config/serializer/Model.ImportDefinition.yml +++ b/src/DataDefinitionsBundle/Resources/config/serializer/Model.ImportDefinition.yml @@ -50,3 +50,7 @@ Wvision\Bundle\DataDefinitionsBundle\Model\ImportDefinition: expose: true type: boolean groups: [Detailed] + persister: + expose: true + type: string + groups: [Detailed] From 6ff1a40708d1c51eda222fc7b1b43796990a4fdf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dalibor=20Karlovi=C4=87?= Date: Wed, 4 Oct 2023 15:42:16 +0200 Subject: [PATCH 17/22] Update ObjectsFetcher.php --- src/DataDefinitionsBundle/Fetcher/ObjectsFetcher.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/DataDefinitionsBundle/Fetcher/ObjectsFetcher.php b/src/DataDefinitionsBundle/Fetcher/ObjectsFetcher.php index 6dfb67a8..0c9bf78b 100644 --- a/src/DataDefinitionsBundle/Fetcher/ObjectsFetcher.php +++ b/src/DataDefinitionsBundle/Fetcher/ObjectsFetcher.php @@ -17,8 +17,8 @@ namespace Wvision\Bundle\DataDefinitionsBundle\Fetcher; use InvalidArgumentException; +use Pimcore\Model\DataObject\AbstractObject; use Pimcore\Model\DataObject\ClassDefinition; -use Pimcore\Model\DataObject\Concrete; use Pimcore\Model\DataObject\Listing; use Wvision\Bundle\DataDefinitionsBundle\Context\FetcherContextInterface; use Wvision\Bundle\DataDefinitionsBundle\Model\ExportDefinitionInterface; @@ -60,12 +60,12 @@ private function getClassListing(ExportDefinitionInterface $definition, array $p $rootNode = null; $conditionFilters = []; if (isset($params['root'])) { - $rootNode = Concrete::getById($params['root']); + $rootNode = AbstractObject::getById($params['root']); if (null !== $rootNode) { $quotedPath = $list->quote($rootNode->getRealFullPath()); $quotedWildcardPath = $list->quote(str_replace('//', '/', $rootNode->getRealFullPath().'/').'%'); - $conditionFilters[] = '(o_path = '.$quotedPath.' OR o_path LIKE '.$quotedWildcardPath.')'; + $conditionFilters[] = '(path = '.$quotedPath.' OR path LIKE '.$quotedWildcardPath.')'; } } @@ -79,10 +79,10 @@ private function getClassListing(ExportDefinitionInterface $definition, array $p } if (isset($params['only_direct_children']) && $params['only_direct_children'] == 'true' && null !== $rootNode) { - $conditionFilters[] = 'o_parentId = '.$rootNode->getId(); + $conditionFilters[] = 'parentId = '.$rootNode->getId(); } - if (isset($params['condition'])) { + if (isset($params['condition'])) { $conditionFilters[] = '('.$params['condition'].')'; } if (isset($params['ids'])) { From 3c55759ad3c299fa002d5c99c0027d172bf13068 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dalibor=20Karlovi=C4=87?= Date: Wed, 4 Oct 2023 15:43:32 +0200 Subject: [PATCH 18/22] Update ObjectsFetcher.php --- src/DataDefinitionsBundle/Fetcher/ObjectsFetcher.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/DataDefinitionsBundle/Fetcher/ObjectsFetcher.php b/src/DataDefinitionsBundle/Fetcher/ObjectsFetcher.php index 0c9bf78b..8f2773f5 100644 --- a/src/DataDefinitionsBundle/Fetcher/ObjectsFetcher.php +++ b/src/DataDefinitionsBundle/Fetcher/ObjectsFetcher.php @@ -82,7 +82,7 @@ private function getClassListing(ExportDefinitionInterface $definition, array $p $conditionFilters[] = 'parentId = '.$rootNode->getId(); } - if (isset($params['condition'])) { + if (isset($params['condition'])) { $conditionFilters[] = '('.$params['condition'].')'; } if (isset($params['ids'])) { From 02a91df50bf43a42be5a93681fd447f2a5cf8bdf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dalibor=20Karlovi=C4=87?= Date: Wed, 4 Oct 2023 16:03:53 +0200 Subject: [PATCH 19/22] fix passing the menu item ID --- .../public/pimcore/js/process_manager/export_contextmenu.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/DataDefinitionsBundle/Resources/public/pimcore/js/process_manager/export_contextmenu.js b/src/DataDefinitionsBundle/Resources/public/pimcore/js/process_manager/export_contextmenu.js index 71f7242c..a393c167 100644 --- a/src/DataDefinitionsBundle/Resources/public/pimcore/js/process_manager/export_contextmenu.js +++ b/src/DataDefinitionsBundle/Resources/public/pimcore/js/process_manager/export_contextmenu.js @@ -9,6 +9,7 @@ document.addEventListener(pimcore.events.prepareObjectTreeContextMenu, function } const tree = event.detail.menu; + const item = event.detail.object; Ext.create('Ext.data.Store', { model: 'Executable', @@ -36,13 +37,13 @@ document.addEventListener(pimcore.events.prepareObjectTreeContextMenu, function exportMenu.push({ text: executable.get('name'), iconCls: "pimcore_icon_object pimcore_icon_overlay_add", - handler: function (menuItem) { + handler: function () { Ext.Ajax.request({ url: '/admin/process_manager/executables/run', params: { id: executable.id, startupConfig: Ext.encode({ - root: menuItem.$iid, + root: item.get('id'), }), csrfToken: pimcore.settings['csrfToken'] }, From 7e55cbd1a26e6f244c1a008693688a3fce5608c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dalibor=20Karlovi=C4=87?= Date: Wed, 4 Oct 2023 16:05:18 +0200 Subject: [PATCH 20/22] fix export from here in search, no more SQL editor --- .../Resources/public/pimcore/js/process_manager/export_search.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/DataDefinitionsBundle/Resources/public/pimcore/js/process_manager/export_search.js b/src/DataDefinitionsBundle/Resources/public/pimcore/js/process_manager/export_search.js index 235a0b4f..82bb725e 100644 --- a/src/DataDefinitionsBundle/Resources/public/pimcore/js/process_manager/export_search.js +++ b/src/DataDefinitionsBundle/Resources/public/pimcore/js/process_manager/export_search.js @@ -90,7 +90,6 @@ pimcore.object.search = Class.create(pimcore.object.search, { root: this.object.id, query: this.searchField.getValue(), only_direct_children: this.checkboxOnlyDirectChildren.getValue(), - condition: this.sqlEditor.getValue(), ids: ids, }), csrfToken: pimcore.settings['csrfToken'] From a94d4c880165b4e701fd17bf5bfd5e28df3be461 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tanel=20P=C3=A4=C3=A4ro?= Date: Wed, 15 Nov 2023 10:58:32 +0200 Subject: [PATCH 21/22] allow 'o_id' system field to be mapped --- src/DataDefinitionsBundle/Service/FieldSelection.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/DataDefinitionsBundle/Service/FieldSelection.php b/src/DataDefinitionsBundle/Service/FieldSelection.php index 8ba08ff6..f94e7718 100644 --- a/src/DataDefinitionsBundle/Service/FieldSelection.php +++ b/src/DataDefinitionsBundle/Service/FieldSelection.php @@ -27,6 +27,7 @@ public function getClassDefinition(DataObject\ClassDefinition $class): array $fields = $class->getFieldDefinitions(); $systemColumns = [ + 'o_id', 'o_published', 'o_key', 'o_parentId', From 74d46a844b7384dc21ea74f1849a8f67ca00cabd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tanel=20P=C3=A4=C3=A4ro?= Date: Wed, 7 Feb 2024 14:02:19 +0200 Subject: [PATCH 22/22] ability to enable/disable value inheritance when exporting --- .../Exporter/Exporter.php | 6 ++++++ .../Form/Type/ExportDefinitionType.php | 1 + .../Model/ExportDefinition.php | 21 +++++++++++++++++++ .../Model/ExportDefinition/Dao.php | 1 + .../Model/ExportDefinitionInterface.php | 10 +++++++++ .../serializer/Model.ExportDefinition.yml | 4 ++++ .../public/pimcore/js/export/item.js | 6 ++++++ .../Resources/translations/admin.en.yml | 1 + 8 files changed, 50 insertions(+) diff --git a/src/DataDefinitionsBundle/Exporter/Exporter.php b/src/DataDefinitionsBundle/Exporter/Exporter.php index 736fbc7a..c1f794db 100644 --- a/src/DataDefinitionsBundle/Exporter/Exporter.php +++ b/src/DataDefinitionsBundle/Exporter/Exporter.php @@ -21,6 +21,7 @@ use Exception; use InvalidArgumentException; use Pimcore; +use Pimcore\Model\DataObject; use Pimcore\Model\DataObject\Concrete; use Psr\Log\LoggerInterface; use Symfony\Component\EventDispatcher\EventDispatcherInterface; @@ -116,6 +117,9 @@ private function runExport( FetcherInterface $fetcher, ExportProviderInterface $provider ) { + $getInheritedValues = DataObject::getGetInheritedValues(); + DataObject::setGetInheritedValues($definition->isEnableInheritance()); + UnpublishedHelper::hideUnpublished( function () use ($definition, $params, $total, $fetcher, $provider, $fetcherContext) { $count = 0; @@ -180,6 +184,8 @@ function () use ($definition, $params, $total, $fetcher, $provider, $fetcherCont }, false === $definition->isFetchUnpublished() ); + + DataObject::setGetInheritedValues($getInheritedValues); } private function exportRow( diff --git a/src/DataDefinitionsBundle/Form/Type/ExportDefinitionType.php b/src/DataDefinitionsBundle/Form/Type/ExportDefinitionType.php index 7ffa436f..95764898 100644 --- a/src/DataDefinitionsBundle/Form/Type/ExportDefinitionType.php +++ b/src/DataDefinitionsBundle/Form/Type/ExportDefinitionType.php @@ -52,6 +52,7 @@ public function buildForm(FormBuilderInterface $builder, array $options): void ->add('runner', ExportRunnerChoiceType::class) ->add('name', TextType::class) ->add('stopOnException', CheckboxType::class) + ->add('enableInheritance', CheckboxType::class) ->add('fetchUnpublished', CheckboxType::class) ->add('failureNotificationDocument', IntegerType::class) ->add('successNotificationDocument', IntegerType::class) diff --git a/src/DataDefinitionsBundle/Model/ExportDefinition.php b/src/DataDefinitionsBundle/Model/ExportDefinition.php index 8edb9ef9..bf11ad7f 100644 --- a/src/DataDefinitionsBundle/Model/ExportDefinition.php +++ b/src/DataDefinitionsBundle/Model/ExportDefinition.php @@ -21,6 +21,11 @@ */ class ExportDefinition extends AbstractDataDefinition implements ExportDefinitionInterface { + /** + * @var bool + */ + public $enableInheritance = true; + /** * @var string */ @@ -54,6 +59,22 @@ public static function getByName($id) return $definitionEntry; } + /** + * @param bool $enableInheritance + */ + public function setEnableInheritance(bool $enableInheritance): void + { + $this->enableInheritance = $enableInheritance; + } + + /** + * @return bool + */ + public function isEnableInheritance(): bool + { + return $this->enableInheritance; + } + public function getFetcher() { return $this->fetcher; diff --git a/src/DataDefinitionsBundle/Model/ExportDefinition/Dao.php b/src/DataDefinitionsBundle/Model/ExportDefinition/Dao.php index f88fa881..ef15b1d4 100644 --- a/src/DataDefinitionsBundle/Model/ExportDefinition/Dao.php +++ b/src/DataDefinitionsBundle/Model/ExportDefinition/Dao.php @@ -121,6 +121,7 @@ public function save() 'mapping', 'runner', 'stopOnException', + 'enableInheritance', 'fetchUnpublished', 'failureNotificationDocument', 'successNotificationDocument', diff --git a/src/DataDefinitionsBundle/Model/ExportDefinitionInterface.php b/src/DataDefinitionsBundle/Model/ExportDefinitionInterface.php index 96dc6f28..7239c17e 100644 --- a/src/DataDefinitionsBundle/Model/ExportDefinitionInterface.php +++ b/src/DataDefinitionsBundle/Model/ExportDefinitionInterface.php @@ -18,6 +18,16 @@ interface ExportDefinitionInterface extends DataDefinitionInterface { + /** + * @param bool $enableInheritance + */ + public function setEnableInheritance(bool $enableInheritance): void; + + /** + * @return bool + */ + public function isEnableInheritance(): bool; + /** * @return mixed */ diff --git a/src/DataDefinitionsBundle/Resources/config/serializer/Model.ExportDefinition.yml b/src/DataDefinitionsBundle/Resources/config/serializer/Model.ExportDefinition.yml index 30e861c6..e131cfec 100755 --- a/src/DataDefinitionsBundle/Resources/config/serializer/Model.ExportDefinition.yml +++ b/src/DataDefinitionsBundle/Resources/config/serializer/Model.ExportDefinition.yml @@ -2,6 +2,10 @@ Wvision\Bundle\DataDefinitionsBundle\Model\ExportDefinition: exclusion_policy: ALL xml_root_name: export_definition properties: + enableInheritance: + expose: true + type: boolean + groups: [Detailed] fetcher: expose: true type: string diff --git a/src/DataDefinitionsBundle/Resources/public/pimcore/js/export/item.js b/src/DataDefinitionsBundle/Resources/public/pimcore/js/export/item.js index 1e1b2799..cd0dd0d5 100644 --- a/src/DataDefinitionsBundle/Resources/public/pimcore/js/export/item.js +++ b/src/DataDefinitionsBundle/Resources/public/pimcore/js/export/item.js @@ -124,6 +124,12 @@ pimcore.plugin.datadefinitions.export.item = Class.create(pimcore.plugin.datadef name: 'stopOnException', checked: this.data.stopOnException }, + { + fieldLabel: t('data_definitions_enable_inheritance'), + xtype: 'checkbox', + name: 'enableInheritance', + checked: this.data.enableInheritance + }, { fieldLabel: t('data_definitions_fetcher_objects_unpublished'), xtype: 'checkbox', diff --git a/src/DataDefinitionsBundle/Resources/translations/admin.en.yml b/src/DataDefinitionsBundle/Resources/translations/admin.en.yml index f784385e..3c577562 100644 --- a/src/DataDefinitionsBundle/Resources/translations/admin.en.yml +++ b/src/DataDefinitionsBundle/Resources/translations/admin.en.yml @@ -44,6 +44,7 @@ data_definitions_filter: 'Filter' data_definitions_runner: 'Runner' data_definitions_create_version: 'Create new Version on every Run' data_definitions_stop_on_exception: 'Stop on Exception' +data_definitions_enable_inheritance: 'Enable Inheritance' data_definitions_installed: 'ImportDefinitions has been installed' data_definitions_uninstalled: 'ImportDefinitions has been uninstalled' data_definitions_success_document: 'Success Notification Document'