diff --git a/.gitignore b/.gitignore index 62c8935..9a5be19 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,19 @@ -.idea/ \ No newline at end of file +# IDE directories +.idea/ +.vscode/ +.DS_Store + +# Composer +/vendor/ +/composer.lock + +# Temporary files +*.cache +*.log +*.tmp + +# Node modules (if you use any JS build tools) +/node_modules/ + +# Generated files +/config.xml \ No newline at end of file diff --git a/composer.json b/composer.json new file mode 100644 index 0000000..bbe2910 --- /dev/null +++ b/composer.json @@ -0,0 +1,27 @@ +{ + "name": "walzen665/gdprcookieconsent", + "description": "Adds a GDPR compliant cookie consent modal to your shop", + "license": "AFL-3.0", + "authors": [ + { + "name": "Walzen665" + } + ], + "autoload": { + "psr-4": { + "PrestaShop\\Module\\GdprCookieConsent\\": "src/" + } + }, + "require": { + "php": ">=7.1.0", + "ext-json": "*" + }, + "config": { + "preferred-install": "dist", + "prepend-autoloader": false, + "platform": { + "php": "7.1.0" + } + }, + "type": "prestashop-module" +} \ No newline at end of file diff --git a/composer.phar b/composer.phar new file mode 100644 index 0000000..7a3bef9 Binary files /dev/null and b/composer.phar differ diff --git a/config/routes.yml b/config/routes.yml new file mode 100644 index 0000000..35c2f87 --- /dev/null +++ b/config/routes.yml @@ -0,0 +1,7 @@ +gdpr_cookie_consent_configuration: + path: /gdprcookieconsent/configuration + methods: [GET, POST] + defaults: + _controller: 'PrestaShop\Module\GdprCookieConsent\Controller\GdprConfigurationController::indexAction' + _legacy_controller: AdminGdprCookieConsent + _legacy_link: AdminGdprCookieConsent \ No newline at end of file diff --git a/config/services.yml b/config/services.yml new file mode 100644 index 0000000..12a594f --- /dev/null +++ b/config/services.yml @@ -0,0 +1,34 @@ +services: + _defaults: + public: true + autowire: true + autoconfigure: true + + # Form Type + prestashop.module.gdprcookieconsent.form.type.gdpr_configuration: + class: 'PrestaShop\Module\GdprCookieConsent\Form\GdprConfigurationFormType' + parent: 'form.type.translatable.aware' + public: true + tags: + - { name: form.type } + + # Data Configuration + prestashop.module.gdprcookieconsent.form.gdpr_configuration_data_configuration: + class: PrestaShop\Module\GdprCookieConsent\Form\GdprConfigurationDataConfiguration + arguments: ['@prestashop.adapter.legacy.configuration'] + + # Form Data Provider + prestashop.module.gdprcookieconsent.form.gdpr_configuration_form_data_provider: + class: 'PrestaShop\Module\GdprCookieConsent\Form\GdprConfigurationFormDataProvider' + arguments: + - '@prestashop.module.gdprcookieconsent.form.gdpr_configuration_data_configuration' + + # Form Handler + prestashop.module.gdprcookieconsent.form.gdpr_configuration_form_data_handler: + class: 'PrestaShop\PrestaShop\Core\Form\Handler' + arguments: + - '@form.factory' + - '@prestashop.core.hook.dispatcher' + - '@prestashop.module.gdprcookieconsent.form.gdpr_configuration_form_data_provider' + - 'PrestaShop\Module\GdprCookieConsent\Form\GdprConfigurationFormType' + - 'Configuration' \ No newline at end of file diff --git a/gdprcookieconsent.php b/gdprcookieconsent.php index c14ed38..8f5f74f 100644 --- a/gdprcookieconsent.php +++ b/gdprcookieconsent.php @@ -82,44 +82,13 @@ class GdprCookieConsent extends Module */ public function getContent() { - $output = ''; - - // If form submitted - if (Tools::isSubmit('submitGdprCookieModule')) { - // Get configuration values from form - $enabled = (int)Tools::getValue('GDPR_COOKIE_ENABLED'); - $message = Tools::getValue('GDPR_COOKIE_MESSAGE'); - $accept = Tools::getValue('GDPR_COOKIE_ACCEPT'); - $decline = Tools::getValue('GDPR_COOKIE_DECLINE'); - $settings = Tools::getValue('GDPR_COOKIE_SETTINGS'); - $moreInfo = Tools::getValue('GDPR_COOKIE_MORE_INFO'); - $moreInfoUrl = Tools::getValue('GDPR_COOKIE_MORE_INFO_URL'); - $dataController = Tools::getValue('GDPR_COOKIE_DATA_CONTROLLER'); - $retentionPeriod = Tools::getValue('GDPR_COOKIE_RETENTION_PERIOD'); - $thirdParties = Tools::getValue('GDPR_COOKIE_THIRD_PARTIES'); - $manageText = Tools::getValue('GDPR_COOKIE_MANAGE_TEXT'); - $onlyRequired = Tools::getValue('GDPR_COOKIE_ONLY_REQUIRED'); - - // Update configuration values - Configuration::updateValue('GDPR_COOKIE_ENABLED', $enabled); - Configuration::updateValue('GDPR_COOKIE_MESSAGE', $message); - Configuration::updateValue('GDPR_COOKIE_ACCEPT', $accept); - Configuration::updateValue('GDPR_COOKIE_DECLINE', $decline); - Configuration::updateValue('GDPR_COOKIE_SETTINGS', $settings); - Configuration::updateValue('GDPR_COOKIE_MORE_INFO', $moreInfo); - Configuration::updateValue('GDPR_COOKIE_MORE_INFO_URL', $moreInfoUrl); - Configuration::updateValue('GDPR_COOKIE_DATA_CONTROLLER', $dataController); - Configuration::updateValue('GDPR_COOKIE_RETENTION_PERIOD', $retentionPeriod); - Configuration::updateValue('GDPR_COOKIE_THIRD_PARTIES', $thirdParties); - Configuration::updateValue('GDPR_COOKIE_MANAGE_TEXT', $manageText); - Configuration::updateValue('GDPR_COOKIE_ONLY_REQUIRED', $onlyRequired); - - // Display confirmation - $output .= $this->displayConfirmation($this->l('Settings updated')); + try { + // Redirect to the Symfony controller + Tools::redirectAdmin($this->get('router')->generate('gdpr_cookie_consent_configuration')); + } catch (\Exception $e) { + // Fallback in case of error + return $this->displayError($this->l('An error occurred while trying to redirect to the configuration page.')); } - - // Display the configuration form - return $output . $this->displayForm(); } /** @@ -347,4 +316,19 @@ class GdprCookieConsent extends Module return $this->display(__FILE__, 'views/templates/hook/footer.tpl'); } + + /** + * Load the dependency injection container + * + * @param array $params + */ + public function hookActionFrontControllerSetMedia(array $params) + { + // Do not load the container if it's already loaded + if ($this->container !== null) { + return; + } + + $this->container = \PrestaShop\PrestaShop\Adapter\SymfonyContainer::getInstance(); + } } diff --git a/src/Form/GdprConfigurationController.php b/src/Form/GdprConfigurationController.php new file mode 100644 index 0000000..d46ef4a --- /dev/null +++ b/src/Form/GdprConfigurationController.php @@ -0,0 +1,40 @@ +get('prestashop.module.gdprcookieconsent.form.gdpr_configuration_form_data_handler'); + + $form = $formDataHandler->getForm(); + $form->handleRequest($request); + + if ($form->isSubmitted() && $form->isValid()) { + $errors = $formDataHandler->save($form->getData()); + + if (empty($errors)) { + $this->addFlash('success', $this->trans('Successful update.', 'Admin.Notifications.Success')); + + return $this->redirectToRoute('gdpr_cookie_consent_configuration'); + } + + $this->flashErrors($errors); + } + + return $this->render('@Modules/gdprcookieconsent/views/templates/admin/configuration.html.twig', [ + 'gdprConfigurationForm' => $form->createView(), + ]); + } +} \ No newline at end of file diff --git a/src/Form/GdprConfigurationDataConfiguration.php b/src/Form/GdprConfigurationDataConfiguration.php new file mode 100644 index 0000000..ca84a13 --- /dev/null +++ b/src/Form/GdprConfigurationDataConfiguration.php @@ -0,0 +1,92 @@ +configuration = $configuration; + } + + /** + * @return array + */ + public function getConfiguration(): array + { + $config = []; + foreach ($this->configurationKeys as $key) { + $config[$key] = $this->configuration->get($key); + } + + return $config; + } + + /** + * @param array $configuration + * @return array + */ + public function updateConfiguration(array $configuration): array + { + $errors = []; + + if ($this->validateConfiguration($configuration)) { + foreach ($this->configurationKeys as $key) { + if (isset($configuration[$key])) { + $this->configuration->set($key, $configuration[$key]); + } + } + } + + return $errors; + } + + /** + * @param array $configuration + * @return bool + */ + public function validateConfiguration(array $configuration): bool + { + return isset($configuration['GDPR_COOKIE_MESSAGE']) && + isset($configuration['GDPR_COOKIE_ACCEPT']) && + isset($configuration['GDPR_COOKIE_DECLINE']) && + isset($configuration['GDPR_COOKIE_SETTINGS']) && + isset($configuration['GDPR_COOKIE_MORE_INFO']) && + isset($configuration['GDPR_COOKIE_MORE_INFO_URL']) && + isset($configuration['GDPR_COOKIE_DATA_CONTROLLER']) && + isset($configuration['GDPR_COOKIE_RETENTION_PERIOD']) && + isset($configuration['GDPR_COOKIE_THIRD_PARTIES']) && + isset($configuration['GDPR_COOKIE_MANAGE_TEXT']); + } +} \ No newline at end of file diff --git a/src/Form/GdprConfigurationFormDataProvider.php b/src/Form/GdprConfigurationFormDataProvider.php new file mode 100644 index 0000000..958ec9c --- /dev/null +++ b/src/Form/GdprConfigurationFormDataProvider.php @@ -0,0 +1,41 @@ +gdprConfigurationDataConfiguration = $gdprConfigurationDataConfiguration; + } + + /** + * @return array + */ + public function getData(): array + { + return $this->gdprConfigurationDataConfiguration->getConfiguration(); + } + + /** + * @param array $data + * @return array + */ + public function setData(array $data): array + { + return $this->gdprConfigurationDataConfiguration->updateConfiguration($data); + } +} \ No newline at end of file diff --git a/src/Form/GdprConfigurationFormType.php b/src/Form/GdprConfigurationFormType.php new file mode 100644 index 0000000..288baba --- /dev/null +++ b/src/Form/GdprConfigurationFormType.php @@ -0,0 +1,87 @@ +add('GDPR_COOKIE_ENABLED', SwitchType::class, [ + 'label' => $this->trans('Enable Cookie Consent', 'Modules.Gdprcookieconsent.Admin'), + 'help' => $this->trans('Enable or disable the cookie consent banner', 'Modules.Gdprcookieconsent.Admin'), + ]) + ->add('GDPR_COOKIE_MESSAGE', TranslatableType::class, [ + 'label' => $this->trans('Cookie Consent Message', 'Modules.Gdprcookieconsent.Admin'), + 'type' => TextareaType::class, + 'required' => true, + ]) + ->add('GDPR_COOKIE_DATA_CONTROLLER', TranslatableType::class, [ + 'label' => $this->trans('Data Controller', 'Modules.Gdprcookieconsent.Admin'), + 'help' => $this->trans('Your company/organization name', 'Modules.Gdprcookieconsent.Admin'), + 'type' => TextType::class, + 'required' => true, + ]) + ->add('GDPR_COOKIE_RETENTION_PERIOD', TranslatableType::class, [ + 'label' => $this->trans('Cookie Retention Period', 'Modules.Gdprcookieconsent.Admin'), + 'help' => $this->trans('How long cookies will be stored (e.g., 365 days)', 'Modules.Gdprcookieconsent.Admin'), + 'type' => TextType::class, + 'required' => true, + ]) + ->add('GDPR_COOKIE_THIRD_PARTIES', TranslatableType::class, [ + 'label' => $this->trans('Third-Party Recipients', 'Modules.Gdprcookieconsent.Admin'), + 'help' => $this->trans('List third parties that receive cookie data', 'Modules.Gdprcookieconsent.Admin'), + 'type' => TextareaType::class, + 'required' => true, + ]) + ->add('GDPR_COOKIE_ACCEPT', TranslatableType::class, [ + 'label' => $this->trans('Accept Button Text', 'Modules.Gdprcookieconsent.Admin'), + 'type' => TextType::class, + 'required' => true, + ]) + ->add('GDPR_COOKIE_DECLINE', TranslatableType::class, [ + 'label' => $this->trans('Decline Button Text', 'Modules.Gdprcookieconsent.Admin'), + 'type' => TextType::class, + 'required' => true, + ]) + ->add('GDPR_COOKIE_SETTINGS', TranslatableType::class, [ + 'label' => $this->trans('Settings Button Text', 'Modules.Gdprcookieconsent.Admin'), + 'type' => TextType::class, + 'required' => true, + ]) + ->add('GDPR_COOKIE_MANAGE_TEXT', TranslatableType::class, [ + 'label' => $this->trans('Manage Preferences Text', 'Modules.Gdprcookieconsent.Admin'), + 'help' => $this->trans('Text for the manage preferences button (displayed after consent is given)', 'Modules.Gdprcookieconsent.Admin'), + 'type' => TextType::class, + 'required' => true, + ]) + ->add('GDPR_COOKIE_MORE_INFO', TranslatableType::class, [ + 'label' => $this->trans('More Info Button Text', 'Modules.Gdprcookieconsent.Admin'), + 'type' => TextType::class, + 'required' => true, + ]) + ->add('GDPR_COOKIE_MORE_INFO_URL', UrlType::class, [ + 'label' => $this->trans('More Info URL', 'Modules.Gdprcookieconsent.Admin'), + 'help' => $this->trans('URL to your Privacy Policy page', 'Modules.Gdprcookieconsent.Admin'), + 'required' => true, + ]) + ->add('GDPR_COOKIE_ONLY_REQUIRED', SwitchType::class, [ + 'label' => $this->trans('This cookie types are used', 'Modules.Gdprcookieconsent.Admin'), + 'help' => $this->trans('If this option is enabled, no config modal will be rendered and there will only be a single button to hide the cookie notice.', 'Modules.Gdprcookieconsent.Admin'), + 'choices' => [ + $this->trans('Nessessary only', 'Modules.Gdprcookieconsent.Admin') => true, + $this->trans('All cookies', 'Modules.Gdprcookieconsent.Admin') => false, + ], + ]); + } +} \ No newline at end of file diff --git a/views/js/admin.js b/views/js/admin.js new file mode 100644 index 0000000..5d4e6e3 --- /dev/null +++ b/views/js/admin.js @@ -0,0 +1,9 @@ +$(document).ready(function () { + // Initialize PrestaShop UI components + window.prestashop.component.initComponents( + [ + 'TranslatableField', + 'TranslatableInput', + ], + ); +}); \ No newline at end of file diff --git a/views/templates/admin/configuration.html.twig b/views/templates/admin/configuration.html.twig new file mode 100644 index 0000000..d1e6a75 --- /dev/null +++ b/views/templates/admin/configuration.html.twig @@ -0,0 +1,28 @@ +{% extends '@PrestaShop/Admin/layout.html.twig' %} + +{% block content %} + {{ form_start(gdprConfigurationForm) }} +
+

+ settings {{ 'GDPR Cookie Consent Configuration'|trans({}, 'Modules.Gdprcookieconsent.Admin') }} +

+
+
+ {{ form_widget(gdprConfigurationForm) }} +
+
+ +
+ {{ form_end(gdprConfigurationForm) }} +{% endblock %} + +{% block javascripts %} + {{ parent() }} + +{% endblock %} \ No newline at end of file