Compare commits
1 Commits
extend/thi
...
config/sym
Author | SHA1 | Date | |
---|---|---|---|
1b27d03c4d |
20
.gitignore
vendored
20
.gitignore
vendored
@ -1 +1,19 @@
|
|||||||
.idea/
|
# 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
|
@ -1,214 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* GDPR Cookie Consent Module for PrestaShop
|
|
||||||
*
|
|
||||||
* @author Walzen665
|
|
||||||
* @copyright Copyright (c) 2025
|
|
||||||
* @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0)
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (!defined('_PS_VERSION_')) {
|
|
||||||
exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Helper class for detecting third-party scripts and assigning them to cookie categories
|
|
||||||
*/
|
|
||||||
class GdprScriptDetector
|
|
||||||
{
|
|
||||||
// Common script signatures and their cookie categories
|
|
||||||
private static $scriptPatterns = [
|
|
||||||
'analytics' => [
|
|
||||||
'/google-analytics\.com/i',
|
|
||||||
'/googletagmanager\.com/i',
|
|
||||||
'/gtag/i',
|
|
||||||
'/analytics/i',
|
|
||||||
'/matomo/i',
|
|
||||||
'/piwik/i',
|
|
||||||
'/statcounter/i',
|
|
||||||
'/hotjar/i',
|
|
||||||
'/clarity\.ms/i',
|
|
||||||
'/stats/i'
|
|
||||||
],
|
|
||||||
'marketing' => [
|
|
||||||
'/facebook\.net/i',
|
|
||||||
'/connect\.facebook\.com/i',
|
|
||||||
'/fbevents\.js/i',
|
|
||||||
'/doubleclick\.net/i',
|
|
||||||
'/googlesyndication\.com/i',
|
|
||||||
'/google.*ads/i',
|
|
||||||
'/twitter\.com\/widgets/i',
|
|
||||||
'/platform\.twitter\.com/i',
|
|
||||||
'/pixel/i',
|
|
||||||
'/ads/i',
|
|
||||||
'/adservice/i',
|
|
||||||
'/criteo/i',
|
|
||||||
'/pinterest/i',
|
|
||||||
'/taboola/i',
|
|
||||||
'/outbrain/i'
|
|
||||||
],
|
|
||||||
'functional' => [
|
|
||||||
'/recaptcha/i',
|
|
||||||
'/hcaptcha/i',
|
|
||||||
'/fonts\.googleapis\.com/i',
|
|
||||||
'/cloudflare/i',
|
|
||||||
'/unpkg\.com/i',
|
|
||||||
'/cdn/i',
|
|
||||||
'/chat/i',
|
|
||||||
'/live.*/i',
|
|
||||||
'/support/i',
|
|
||||||
'/feedback/i',
|
|
||||||
'/maps\.google/i',
|
|
||||||
'/disqus/i',
|
|
||||||
'/zendesk/i',
|
|
||||||
'/intercom/i'
|
|
||||||
]
|
|
||||||
];
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if a script URL or content matches any pattern
|
|
||||||
*
|
|
||||||
* @param string $scriptText The script URL or content to check
|
|
||||||
* @return string The cookie category ('necessary', 'functional', 'analytics', 'marketing')
|
|
||||||
*/
|
|
||||||
public static function detectCategory($scriptText)
|
|
||||||
{
|
|
||||||
foreach (self::$scriptPatterns as $category => $patterns) {
|
|
||||||
foreach ($patterns as $pattern) {
|
|
||||||
if (preg_match($pattern, $scriptText)) {
|
|
||||||
return $category;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return 'necessary'; // Default category if no match found
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get common third-party domains and their categories
|
|
||||||
*
|
|
||||||
* @return array Associative array of domains and their categories
|
|
||||||
*/
|
|
||||||
public static function getCommonThirdPartyDomains()
|
|
||||||
{
|
|
||||||
return [
|
|
||||||
// Analytics
|
|
||||||
'google-analytics.com' => 'analytics',
|
|
||||||
'googletagmanager.com' => 'analytics',
|
|
||||||
'analytics.google.com' => 'analytics',
|
|
||||||
'matomo.org' => 'analytics',
|
|
||||||
'matomo.cloud' => 'analytics',
|
|
||||||
'piwik.pro' => 'analytics',
|
|
||||||
'statcounter.com' => 'analytics',
|
|
||||||
'hotjar.com' => 'analytics',
|
|
||||||
'clarity.ms' => 'analytics',
|
|
||||||
'mixpanel.com' => 'analytics',
|
|
||||||
|
|
||||||
// Marketing
|
|
||||||
'facebook.com' => 'marketing',
|
|
||||||
'facebook.net' => 'marketing',
|
|
||||||
'fbcdn.net' => 'marketing',
|
|
||||||
'doubleclick.net' => 'marketing',
|
|
||||||
'googlesyndication.com' => 'marketing',
|
|
||||||
'adservice.google.com' => 'marketing',
|
|
||||||
'twitter.com' => 'marketing',
|
|
||||||
'linkedin.com' => 'marketing',
|
|
||||||
'pinterest.com' => 'marketing',
|
|
||||||
'ads-twitter.com' => 'marketing',
|
|
||||||
'criteo.com' => 'marketing',
|
|
||||||
'criteo.net' => 'marketing',
|
|
||||||
'taboola.com' => 'marketing',
|
|
||||||
'outbrain.com' => 'marketing',
|
|
||||||
|
|
||||||
// Functional
|
|
||||||
'google.com/recaptcha' => 'functional',
|
|
||||||
'gstatic.com/recaptcha' => 'functional',
|
|
||||||
'hcaptcha.com' => 'functional',
|
|
||||||
'fonts.googleapis.com' => 'functional',
|
|
||||||
'cloudflare.com' => 'functional',
|
|
||||||
'cdn.jsdelivr.net' => 'functional',
|
|
||||||
'unpkg.com' => 'functional',
|
|
||||||
'cdnjs.cloudflare.com' => 'functional',
|
|
||||||
'maps.google.com' => 'functional',
|
|
||||||
'maps.googleapis.com' => 'functional',
|
|
||||||
'disqus.com' => 'functional',
|
|
||||||
'zendesk.com' => 'functional',
|
|
||||||
'intercom.io' => 'functional'
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if a domain matches any known third-party domain
|
|
||||||
*
|
|
||||||
* @param string $domain The domain to check
|
|
||||||
* @return string|false The cookie category or false if no match
|
|
||||||
*/
|
|
||||||
public static function matchDomain($domain)
|
|
||||||
{
|
|
||||||
$thirdPartyDomains = self::getCommonThirdPartyDomains();
|
|
||||||
|
|
||||||
foreach ($thirdPartyDomains as $thirdPartyDomain => $category) {
|
|
||||||
if (strpos($domain, $thirdPartyDomain) !== false) {
|
|
||||||
return $category;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Detect inline script content category
|
|
||||||
*
|
|
||||||
* @param string $content The script content to analyze
|
|
||||||
* @return string The cookie category
|
|
||||||
*/
|
|
||||||
public static function detectInlineScriptCategory($content)
|
|
||||||
{
|
|
||||||
// Common script signatures in inline scripts
|
|
||||||
$inlinePatterns = [
|
|
||||||
'analytics' => [
|
|
||||||
'/googleAnalytics/i',
|
|
||||||
'/gtag\s*\(/i',
|
|
||||||
'/_gaq\s*\./i',
|
|
||||||
'/ga\s*\(\s*[\'"]create/i',
|
|
||||||
'/analytics/i',
|
|
||||||
'/matomo/i',
|
|
||||||
'/piwik/i',
|
|
||||||
'/hotjar/i',
|
|
||||||
'/clarity/i'
|
|
||||||
],
|
|
||||||
'marketing' => [
|
|
||||||
'/fbq\s*\(/i',
|
|
||||||
'/FB\.init/i',
|
|
||||||
'/facebook-jssdk/i',
|
|
||||||
'/twttr\s*\./i',
|
|
||||||
'/twitter-widgets/i',
|
|
||||||
'/pintrk/i',
|
|
||||||
'/adsbygoogle/i',
|
|
||||||
'/googletag/i',
|
|
||||||
'/pixel/i',
|
|
||||||
'/track/i'
|
|
||||||
],
|
|
||||||
'functional' => [
|
|
||||||
'/grecaptcha/i',
|
|
||||||
'/hcaptcha/i',
|
|
||||||
'/maps\.googleapis/i',
|
|
||||||
'/gapi\.load/i',
|
|
||||||
'/disqus/i',
|
|
||||||
'/LiveChat/i',
|
|
||||||
'/intercom/i',
|
|
||||||
'/zendesk/i'
|
|
||||||
]
|
|
||||||
];
|
|
||||||
|
|
||||||
foreach ($inlinePatterns as $category => $patterns) {
|
|
||||||
foreach ($patterns as $pattern) {
|
|
||||||
if (preg_match($pattern, $content)) {
|
|
||||||
return $category;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return 'necessary';
|
|
||||||
}
|
|
||||||
}
|
|
27
composer.json
Normal file
27
composer.json
Normal file
@ -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"
|
||||||
|
}
|
BIN
composer.phar
Normal file
BIN
composer.phar
Normal file
Binary file not shown.
7
config/routes.yml
Normal file
7
config/routes.yml
Normal file
@ -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
|
34
config/services.yml
Normal file
34
config/services.yml
Normal file
@ -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'
|
@ -18,7 +18,7 @@ class GdprCookieConsent extends Module
|
|||||||
{
|
{
|
||||||
$this->name = 'gdprcookieconsent';
|
$this->name = 'gdprcookieconsent';
|
||||||
$this->tab = 'front_office_features';
|
$this->tab = 'front_office_features';
|
||||||
$this->version = '1.0.1';
|
$this->version = '1.0.0';
|
||||||
$this->author = 'Walzen665';
|
$this->author = 'Walzen665';
|
||||||
$this->need_instance = 0;
|
$this->need_instance = 0;
|
||||||
$this->ps_versions_compliancy = [
|
$this->ps_versions_compliancy = [
|
||||||
@ -53,11 +53,7 @@ class GdprCookieConsent extends Module
|
|||||||
Configuration::updateValue('GDPR_COOKIE_RETENTION_PERIOD', '365 days') &&
|
Configuration::updateValue('GDPR_COOKIE_RETENTION_PERIOD', '365 days') &&
|
||||||
Configuration::updateValue('GDPR_COOKIE_THIRD_PARTIES', 'Google Analytics, Facebook, etc.') &&
|
Configuration::updateValue('GDPR_COOKIE_THIRD_PARTIES', 'Google Analytics, Facebook, etc.') &&
|
||||||
Configuration::updateValue('GDPR_COOKIE_MANAGE_TEXT', 'Manage Cookie Preferences') &&
|
Configuration::updateValue('GDPR_COOKIE_MANAGE_TEXT', 'Manage Cookie Preferences') &&
|
||||||
Configuration::updateValue('GDPR_COOKIE_ONLY_REQUIRED', 1) &&
|
Configuration::updateValue('GDPR_COOKIE_ONLY_REQUIRED', 1);
|
||||||
Configuration::updateValue('GDPR_COOKIE_NECESSARY_DESC', 'Necessary cookies help make a website usable by enabling basic functions like page navigation and access to secure areas. The website cannot function properly without these cookies.') &&
|
|
||||||
Configuration::updateValue('GDPR_COOKIE_FUNCTIONAL_DESC', 'Functional cookies enable a website to remember information that changes the way the website behaves or looks, like your preferred language or the region you are in.') &&
|
|
||||||
Configuration::updateValue('GDPR_COOKIE_ANALYTICS_DESC', 'Analytics cookies help website owners understand how visitors interact with websites by collecting and reporting information anonymously.') &&
|
|
||||||
Configuration::updateValue('GDPR_COOKIE_MARKETING_DESC', 'Marketing cookies are used to track visitors across websites. The intention is to display ads that are relevant and engaging for the individual user.');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -78,11 +74,7 @@ class GdprCookieConsent extends Module
|
|||||||
Configuration::deleteByName('GDPR_COOKIE_RETENTION_PERIOD') &&
|
Configuration::deleteByName('GDPR_COOKIE_RETENTION_PERIOD') &&
|
||||||
Configuration::deleteByName('GDPR_COOKIE_THIRD_PARTIES') &&
|
Configuration::deleteByName('GDPR_COOKIE_THIRD_PARTIES') &&
|
||||||
Configuration::deleteByName('GDPR_COOKIE_MANAGE_TEXT') &&
|
Configuration::deleteByName('GDPR_COOKIE_MANAGE_TEXT') &&
|
||||||
Configuration::deleteByName('GDPR_COOKIE_ONLY_REQUIRED') &&
|
Configuration::deleteByName('GDPR_COOKIE_ONLY_REQUIRED');
|
||||||
Configuration::deleteByName('GDPR_COOKIE_NECESSARY_DESC') &&
|
|
||||||
Configuration::deleteByName('GDPR_COOKIE_FUNCTIONAL_DESC') &&
|
|
||||||
Configuration::deleteByName('GDPR_COOKIE_ANALYTICS_DESC') &&
|
|
||||||
Configuration::deleteByName('GDPR_COOKIE_MARKETING_DESC');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -90,52 +82,13 @@ class GdprCookieConsent extends Module
|
|||||||
*/
|
*/
|
||||||
public function getContent()
|
public function getContent()
|
||||||
{
|
{
|
||||||
$output = '';
|
try {
|
||||||
|
// Redirect to the Symfony controller
|
||||||
// If form submitted
|
Tools::redirectAdmin($this->get('router')->generate('gdpr_cookie_consent_configuration'));
|
||||||
if (Tools::isSubmit('submitGdprCookieModule')) {
|
} catch (\Exception $e) {
|
||||||
// Get configuration values from form
|
// Fallback in case of error
|
||||||
$enabled = (int)Tools::getValue('GDPR_COOKIE_ENABLED');
|
return $this->displayError($this->l('An error occurred while trying to redirect to the configuration page.'));
|
||||||
$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');
|
|
||||||
$necessaryDesc = Tools::getValue('GDPR_COOKIE_NECESSARY_DESC');
|
|
||||||
$functionalDesc = Tools::getValue('GDPR_COOKIE_FUNCTIONAL_DESC');
|
|
||||||
$analyticsDesc = Tools::getValue('GDPR_COOKIE_ANALYTICS_DESC');
|
|
||||||
$marketingDesc = Tools::getValue('GDPR_COOKIE_MARKETING_DESC');
|
|
||||||
|
|
||||||
// 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);
|
|
||||||
Configuration::updateValue('GDPR_COOKIE_NECESSARY_DESC', $necessaryDesc);
|
|
||||||
Configuration::updateValue('GDPR_COOKIE_FUNCTIONAL_DESC', $functionalDesc);
|
|
||||||
Configuration::updateValue('GDPR_COOKIE_ANALYTICS_DESC', $analyticsDesc);
|
|
||||||
Configuration::updateValue('GDPR_COOKIE_MARKETING_DESC', $marketingDesc);
|
|
||||||
|
|
||||||
// Display confirmation
|
|
||||||
$output .= $this->displayConfirmation($this->l('Settings updated'));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Display the configuration form
|
|
||||||
return $output . $this->displayForm();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -254,34 +207,6 @@ class GdprCookieConsent extends Module
|
|||||||
]
|
]
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
[
|
|
||||||
'type' => 'textarea',
|
|
||||||
'label' => $this->l('Necessary Cookies Description'),
|
|
||||||
'name' => 'GDPR_COOKIE_NECESSARY_DESC',
|
|
||||||
'desc' => $this->l('Description for necessary cookies shown in the modal'),
|
|
||||||
'required' => true,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
'type' => 'textarea',
|
|
||||||
'label' => $this->l('Functional Cookies Description'),
|
|
||||||
'name' => 'GDPR_COOKIE_FUNCTIONAL_DESC',
|
|
||||||
'desc' => $this->l('Description for functional cookies shown in the modal'),
|
|
||||||
'required' => true,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
'type' => 'textarea',
|
|
||||||
'label' => $this->l('Analytics Cookies Description'),
|
|
||||||
'name' => 'GDPR_COOKIE_ANALYTICS_DESC',
|
|
||||||
'desc' => $this->l('Description for analytics cookies shown in the modal'),
|
|
||||||
'required' => true,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
'type' => 'textarea',
|
|
||||||
'label' => $this->l('Marketing Cookies Description'),
|
|
||||||
'name' => 'GDPR_COOKIE_MARKETING_DESC',
|
|
||||||
'desc' => $this->l('Description for marketing cookies shown in the modal'),
|
|
||||||
'required' => true,
|
|
||||||
],
|
|
||||||
],
|
],
|
||||||
'submit' => [
|
'submit' => [
|
||||||
'title' => $this->l('Save'),
|
'title' => $this->l('Save'),
|
||||||
@ -321,10 +246,6 @@ class GdprCookieConsent extends Module
|
|||||||
$helper->fields_value['GDPR_COOKIE_THIRD_PARTIES'] = Configuration::get('GDPR_COOKIE_THIRD_PARTIES');
|
$helper->fields_value['GDPR_COOKIE_THIRD_PARTIES'] = Configuration::get('GDPR_COOKIE_THIRD_PARTIES');
|
||||||
$helper->fields_value['GDPR_COOKIE_MANAGE_TEXT'] = Configuration::get('GDPR_COOKIE_MANAGE_TEXT');
|
$helper->fields_value['GDPR_COOKIE_MANAGE_TEXT'] = Configuration::get('GDPR_COOKIE_MANAGE_TEXT');
|
||||||
$helper->fields_value['GDPR_COOKIE_ONLY_REQUIRED'] = Configuration::get('GDPR_COOKIE_ONLY_REQUIRED');
|
$helper->fields_value['GDPR_COOKIE_ONLY_REQUIRED'] = Configuration::get('GDPR_COOKIE_ONLY_REQUIRED');
|
||||||
$helper->fields_value['GDPR_COOKIE_NECESSARY_DESC'] = Configuration::get('GDPR_COOKIE_NECESSARY_DESC');
|
|
||||||
$helper->fields_value['GDPR_COOKIE_FUNCTIONAL_DESC'] = Configuration::get('GDPR_COOKIE_FUNCTIONAL_DESC');
|
|
||||||
$helper->fields_value['GDPR_COOKIE_ANALYTICS_DESC'] = Configuration::get('GDPR_COOKIE_ANALYTICS_DESC');
|
|
||||||
$helper->fields_value['GDPR_COOKIE_MARKETING_DESC'] = Configuration::get('GDPR_COOKIE_MARKETING_DESC');
|
|
||||||
|
|
||||||
return $helper->generateForm([$form]);
|
return $helper->generateForm([$form]);
|
||||||
}
|
}
|
||||||
@ -363,12 +284,7 @@ class GdprCookieConsent extends Module
|
|||||||
$this->context->smarty->assign([
|
$this->context->smarty->assign([
|
||||||
'gdprCookieManageText' => Configuration::get('GDPR_COOKIE_MANAGE_TEXT', 'Manage Cookies'),
|
'gdprCookieManageText' => Configuration::get('GDPR_COOKIE_MANAGE_TEXT', 'Manage Cookies'),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
// If not in required-only mode, add script for tagging known third-party scripts
|
|
||||||
if (!Configuration::get('GDPR_COOKIE_ONLY_REQUIRED')) {
|
|
||||||
$this->tagThirdPartyScripts();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Return the template content - but don't throw an error if it doesn't exist yet
|
// Return the template content - but don't throw an error if it doesn't exist yet
|
||||||
if (file_exists(_PS_MODULE_DIR_ . $this->name . '/views/templates/hook/manage_button.tpl')) {
|
if (file_exists(_PS_MODULE_DIR_ . $this->name . '/views/templates/hook/manage_button.tpl')) {
|
||||||
return $this->display(__FILE__, 'views/templates/hook/manage_button.tpl');
|
return $this->display(__FILE__, 'views/templates/hook/manage_button.tpl');
|
||||||
@ -396,80 +312,23 @@ class GdprCookieConsent extends Module
|
|||||||
'gdprCookieThirdParties' => Configuration::get('GDPR_COOKIE_THIRD_PARTIES'),
|
'gdprCookieThirdParties' => Configuration::get('GDPR_COOKIE_THIRD_PARTIES'),
|
||||||
'gdprCookieManageText' => Configuration::get('GDPR_COOKIE_MANAGE_TEXT'),
|
'gdprCookieManageText' => Configuration::get('GDPR_COOKIE_MANAGE_TEXT'),
|
||||||
'gdprCookieOnlyRequired' => Configuration::get('GDPR_COOKIE_ONLY_REQUIRED'),
|
'gdprCookieOnlyRequired' => Configuration::get('GDPR_COOKIE_ONLY_REQUIRED'),
|
||||||
'gdprCookieNecessaryDesc' => Configuration::get('GDPR_COOKIE_NECESSARY_DESC'),
|
|
||||||
'gdprCookieFunctionalDesc' => Configuration::get('GDPR_COOKIE_FUNCTIONAL_DESC'),
|
|
||||||
'gdprCookieAnalyticsDesc' => Configuration::get('GDPR_COOKIE_ANALYTICS_DESC'),
|
|
||||||
'gdprCookieMarketingDesc' => Configuration::get('GDPR_COOKIE_MARKETING_DESC'),
|
|
||||||
]);
|
]);
|
||||||
|
|
||||||
return $this->display(__FILE__, 'views/templates/hook/footer.tpl');
|
return $this->display(__FILE__, 'views/templates/hook/footer.tpl');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Helper function to tag third-party scripts with appropriate consent categories
|
* Load the dependency injection container
|
||||||
|
*
|
||||||
|
* @param array $params
|
||||||
*/
|
*/
|
||||||
protected function tagThirdPartyScripts()
|
public function hookActionFrontControllerSetMedia(array $params)
|
||||||
{
|
{
|
||||||
// Require the script detector class
|
// Do not load the container if it's already loaded
|
||||||
require_once(dirname(__FILE__).'/classes/GdprScriptDetector.php');
|
if ($this->container !== null) {
|
||||||
|
|
||||||
// Get PrestaShop's currently registered JS files
|
|
||||||
$jsFiles = $this->context->controller->js_files;
|
|
||||||
|
|
||||||
// Loop through JS files and add consent attributes based on patterns
|
|
||||||
foreach ($jsFiles as $key => $jsFile) {
|
|
||||||
// Use the detector class
|
|
||||||
$category = GdprScriptDetector::detectCategory($jsFile);
|
|
||||||
|
|
||||||
// Add attribute to the script
|
|
||||||
$this->context->smarty->assign([
|
|
||||||
'js_' . md5($jsFile) . '_attributes' => 'data-cookieconsent="' . $category . '"'
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Inject a helper script to tag inline scripts as well
|
|
||||||
$this->context->controller->registerJavascript(
|
|
||||||
'gdpr-cookie-helper',
|
|
||||||
$this->_path . 'views/js/gdpr_cookie_helper.js',
|
|
||||||
['position' => 'head', 'priority' => 1]
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Modifies scripts in the HTML head
|
|
||||||
*/
|
|
||||||
public function hookActionHtmlHeadFooter($params)
|
|
||||||
{
|
|
||||||
if (!Configuration::get('GDPR_COOKIE_ENABLED') || Configuration::get('GDPR_COOKIE_ONLY_REQUIRED')) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the current HTML content
|
$this->container = \PrestaShop\PrestaShop\Adapter\SymfonyContainer::getInstance();
|
||||||
$html = $params['html_content'];
|
|
||||||
|
|
||||||
// Modify script tags to add data-cookieconsent attribute
|
|
||||||
$patterns = [
|
|
||||||
// Google Analytics pattern
|
|
||||||
'/<script([^>]*)(gtag|googletagmanager|google-analytics)([^>]*)>/' => '<script$1$2$3 data-cookieconsent="analytics">',
|
|
||||||
|
|
||||||
// Facebook Pixel pattern
|
|
||||||
'/<script([^>]*)(connect\.facebook\.net|fbevents\.js)([^>]*)>/' => '<script$1$2$3 data-cookieconsent="marketing">',
|
|
||||||
|
|
||||||
// Generic analytics patterns
|
|
||||||
'/<script([^>]*)(analytics|piwik|matomo|stats)([^>]*)>/' => '<script$1$2$3 data-cookieconsent="analytics">',
|
|
||||||
|
|
||||||
// Marketing patterns
|
|
||||||
'/<script([^>]*)(ads|adsbygoogle|doubleclick|googlesyndication)([^>]*)>/' => '<script$1$2$3 data-cookieconsent="marketing">',
|
|
||||||
|
|
||||||
// Functional patterns (more conservative, as these might be necessary)
|
|
||||||
'/<script([^>]*)(recaptcha|chat)([^>]*)>/' => '<script$1$2$3 data-cookieconsent="functional">',
|
|
||||||
];
|
|
||||||
|
|
||||||
foreach ($patterns as $pattern => $replacement) {
|
|
||||||
$html = preg_replace($pattern, $replacement, $html);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update the HTML content
|
|
||||||
$params['html_content'] = $html;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
40
src/Form/GdprConfigurationController.php
Normal file
40
src/Form/GdprConfigurationController.php
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace PrestaShop\Module\GdprCookieConsent\Controller;
|
||||||
|
|
||||||
|
use PrestaShopBundle\Controller\Admin\FrameworkBundleAdminController;
|
||||||
|
use Symfony\Component\HttpFoundation\Request;
|
||||||
|
use Symfony\Component\HttpFoundation\Response;
|
||||||
|
|
||||||
|
class GdprConfigurationController extends FrameworkBundleAdminController
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @param Request $request
|
||||||
|
* @return Response
|
||||||
|
*/
|
||||||
|
public function indexAction(Request $request): Response
|
||||||
|
{
|
||||||
|
$formDataHandler = $this->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(),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
92
src/Form/GdprConfigurationDataConfiguration.php
Normal file
92
src/Form/GdprConfigurationDataConfiguration.php
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace PrestaShop\Module\GdprCookieConsent\Form;
|
||||||
|
|
||||||
|
use PrestaShop\PrestaShop\Core\Configuration\DataConfigurationInterface;
|
||||||
|
use PrestaShop\PrestaShop\Core\ConfigurationInterface;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Configuration is used to save data to configuration table and retrieve from it.
|
||||||
|
*/
|
||||||
|
final class GdprConfigurationDataConfiguration implements DataConfigurationInterface
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var ConfigurationInterface
|
||||||
|
*/
|
||||||
|
private $configuration;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var array Configuration keys
|
||||||
|
*/
|
||||||
|
private $configurationKeys = [
|
||||||
|
'GDPR_COOKIE_ENABLED',
|
||||||
|
'GDPR_COOKIE_MESSAGE',
|
||||||
|
'GDPR_COOKIE_ACCEPT',
|
||||||
|
'GDPR_COOKIE_DECLINE',
|
||||||
|
'GDPR_COOKIE_SETTINGS',
|
||||||
|
'GDPR_COOKIE_MORE_INFO',
|
||||||
|
'GDPR_COOKIE_MORE_INFO_URL',
|
||||||
|
'GDPR_COOKIE_DATA_CONTROLLER',
|
||||||
|
'GDPR_COOKIE_RETENTION_PERIOD',
|
||||||
|
'GDPR_COOKIE_THIRD_PARTIES',
|
||||||
|
'GDPR_COOKIE_MANAGE_TEXT',
|
||||||
|
'GDPR_COOKIE_ONLY_REQUIRED',
|
||||||
|
];
|
||||||
|
|
||||||
|
public function __construct(ConfigurationInterface $configuration)
|
||||||
|
{
|
||||||
|
$this->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']);
|
||||||
|
}
|
||||||
|
}
|
41
src/Form/GdprConfigurationFormDataProvider.php
Normal file
41
src/Form/GdprConfigurationFormDataProvider.php
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace PrestaShop\Module\GdprCookieConsent\Form;
|
||||||
|
|
||||||
|
use PrestaShop\PrestaShop\Core\Configuration\DataConfigurationInterface;
|
||||||
|
use PrestaShop\PrestaShop\Core\Form\FormDataProviderInterface;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provider is responsible for providing form data
|
||||||
|
*/
|
||||||
|
class GdprConfigurationFormDataProvider implements FormDataProviderInterface
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var DataConfigurationInterface
|
||||||
|
*/
|
||||||
|
private $gdprConfigurationDataConfiguration;
|
||||||
|
|
||||||
|
public function __construct(DataConfigurationInterface $gdprConfigurationDataConfiguration)
|
||||||
|
{
|
||||||
|
$this->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);
|
||||||
|
}
|
||||||
|
}
|
87
src/Form/GdprConfigurationFormType.php
Normal file
87
src/Form/GdprConfigurationFormType.php
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace PrestaShop\Module\GdprCookieConsent\Form;
|
||||||
|
|
||||||
|
use PrestaShopBundle\Form\Admin\Type\SwitchType;
|
||||||
|
use PrestaShopBundle\Form\Admin\Type\TranslatableType;
|
||||||
|
use PrestaShopBundle\Form\Admin\Type\TranslatorAwareType;
|
||||||
|
use Symfony\Component\Form\Extension\Core\Type\TextareaType;
|
||||||
|
use Symfony\Component\Form\Extension\Core\Type\TextType;
|
||||||
|
use Symfony\Component\Form\Extension\Core\Type\UrlType;
|
||||||
|
use Symfony\Component\Form\FormBuilderInterface;
|
||||||
|
|
||||||
|
class GdprConfigurationFormType extends TranslatorAwareType
|
||||||
|
{
|
||||||
|
public function buildForm(FormBuilderInterface $builder, array $options): void
|
||||||
|
{
|
||||||
|
$builder
|
||||||
|
->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,
|
||||||
|
],
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
9
views/js/admin.js
Normal file
9
views/js/admin.js
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
$(document).ready(function () {
|
||||||
|
// Initialize PrestaShop UI components
|
||||||
|
window.prestashop.component.initComponents(
|
||||||
|
[
|
||||||
|
'TranslatableField',
|
||||||
|
'TranslatableInput',
|
||||||
|
],
|
||||||
|
);
|
||||||
|
});
|
@ -7,13 +7,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
document.addEventListener('DOMContentLoaded', function() {
|
document.addEventListener('DOMContentLoaded', function() {
|
||||||
// Store for blocked scripts
|
|
||||||
const scriptStore = {
|
|
||||||
functional: [],
|
|
||||||
analytics: [],
|
|
||||||
marketing: []
|
|
||||||
};
|
|
||||||
|
|
||||||
// Cookie functions
|
// Cookie functions
|
||||||
function setCookie(name, value, days) {
|
function setCookie(name, value, days) {
|
||||||
var expires = '';
|
var expires = '';
|
||||||
@ -46,166 +39,14 @@ document.addEventListener('DOMContentLoaded', function() {
|
|||||||
// Hide banner and modal
|
// Hide banner and modal
|
||||||
hideModal();
|
hideModal();
|
||||||
document.getElementById('gdpr-cookie-banner').style.display = 'none';
|
document.getElementById('gdpr-cookie-banner').style.display = 'none';
|
||||||
|
|
||||||
// Show manage button
|
// Show manage button
|
||||||
showManageButton();
|
showManageButton();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Block scripts based on type
|
|
||||||
function blockScripts() {
|
|
||||||
// Find and process script tags with data-cookieconsent attribute
|
|
||||||
const scripts = document.querySelectorAll('script[data-cookieconsent]');
|
|
||||||
|
|
||||||
scripts.forEach(script => {
|
|
||||||
const consentType = script.getAttribute('data-cookieconsent');
|
|
||||||
|
|
||||||
if (!consentType || consentType === 'necessary') {
|
|
||||||
// Necessary scripts always run
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Store script information
|
|
||||||
const scriptData = {
|
|
||||||
src: script.getAttribute('src'),
|
|
||||||
content: script.innerHTML,
|
|
||||||
type: script.getAttribute('type') || 'text/javascript',
|
|
||||||
async: script.async,
|
|
||||||
defer: script.defer
|
|
||||||
};
|
|
||||||
|
|
||||||
// Add to appropriate store
|
|
||||||
if (scriptStore[consentType]) {
|
|
||||||
scriptStore[consentType].push(scriptData);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Remove the script from DOM
|
|
||||||
script.parentNode.removeChild(script);
|
|
||||||
});
|
|
||||||
|
|
||||||
// Also block iframe embeds with data-cookieconsent attribute
|
|
||||||
const iframes = document.querySelectorAll('iframe[data-cookieconsent]');
|
|
||||||
|
|
||||||
iframes.forEach(iframe => {
|
|
||||||
const consentType = iframe.getAttribute('data-cookieconsent');
|
|
||||||
|
|
||||||
if (!consentType || consentType === 'necessary') {
|
|
||||||
// Necessary iframes always load
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create placeholder
|
|
||||||
const placeholder = document.createElement('div');
|
|
||||||
placeholder.className = 'gdpr-blocked-content-placeholder';
|
|
||||||
placeholder.setAttribute('data-cookieconsent', consentType);
|
|
||||||
placeholder.setAttribute('data-src', iframe.getAttribute('src'));
|
|
||||||
placeholder.style.width = iframe.width + 'px' || '100%';
|
|
||||||
placeholder.style.height = iframe.height + 'px' || '150px';
|
|
||||||
placeholder.style.border = '1px dashed #ccc';
|
|
||||||
placeholder.style.display = 'flex';
|
|
||||||
placeholder.style.alignItems = 'center';
|
|
||||||
placeholder.style.justifyContent = 'center';
|
|
||||||
placeholder.style.backgroundColor = '#f9f9f9';
|
|
||||||
placeholder.style.color = '#666';
|
|
||||||
placeholder.innerHTML = `<div>
|
|
||||||
<p>Content blocked due to ${consentType} cookies preferences</p>
|
|
||||||
<button class="gdpr-load-blocked-content" data-type="${consentType}">Load content</button>
|
|
||||||
</div>`;
|
|
||||||
|
|
||||||
// Replace iframe with placeholder
|
|
||||||
iframe.parentNode.replaceChild(placeholder, iframe);
|
|
||||||
});
|
|
||||||
|
|
||||||
// Add event listeners to load content buttons
|
|
||||||
document.querySelectorAll('.gdpr-load-blocked-content').forEach(button => {
|
|
||||||
button.addEventListener('click', function(e) {
|
|
||||||
const type = this.getAttribute('data-type');
|
|
||||||
const placeholder = this.closest('.gdpr-blocked-content-placeholder');
|
|
||||||
|
|
||||||
if (placeholder) {
|
|
||||||
// Get iframe src
|
|
||||||
const src = placeholder.getAttribute('data-src');
|
|
||||||
|
|
||||||
// Create iframe
|
|
||||||
const iframe = document.createElement('iframe');
|
|
||||||
iframe.src = src;
|
|
||||||
iframe.width = placeholder.style.width;
|
|
||||||
iframe.height = placeholder.style.height;
|
|
||||||
iframe.frameBorder = '0';
|
|
||||||
|
|
||||||
// Replace placeholder with iframe
|
|
||||||
placeholder.parentNode.replaceChild(iframe, placeholder);
|
|
||||||
|
|
||||||
// Update consent for this content type
|
|
||||||
const preferences = JSON.parse(getCookie('gdpr_cookie_consent') || '{"necessary":true}');
|
|
||||||
preferences[type] = true;
|
|
||||||
setCookie('gdpr_cookie_consent', JSON.stringify(preferences), 365);
|
|
||||||
|
|
||||||
// Update checkboxes in modal if it exists
|
|
||||||
const checkbox = document.querySelector(`#gdpr-cookie-${type}`);
|
|
||||||
if (checkbox) {
|
|
||||||
checkbox.checked = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Load scripts based on consent
|
|
||||||
function loadConsentedScripts(preferences) {
|
|
||||||
// For each script type
|
|
||||||
Object.keys(scriptStore).forEach(type => {
|
|
||||||
if (preferences[type]) {
|
|
||||||
// Load all scripts of this type
|
|
||||||
scriptStore[type].forEach(scriptData => {
|
|
||||||
const script = document.createElement('script');
|
|
||||||
|
|
||||||
if (scriptData.src) {
|
|
||||||
script.src = scriptData.src;
|
|
||||||
}
|
|
||||||
|
|
||||||
script.type = scriptData.type;
|
|
||||||
script.async = scriptData.async;
|
|
||||||
script.defer = scriptData.defer;
|
|
||||||
|
|
||||||
if (scriptData.content) {
|
|
||||||
script.innerHTML = scriptData.content;
|
|
||||||
}
|
|
||||||
|
|
||||||
document.head.appendChild(script);
|
|
||||||
});
|
|
||||||
|
|
||||||
// Clear the store for this type
|
|
||||||
scriptStore[type] = [];
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Also load blocked iframes
|
|
||||||
document.querySelectorAll('.gdpr-blocked-content-placeholder').forEach(placeholder => {
|
|
||||||
const type = placeholder.getAttribute('data-cookieconsent');
|
|
||||||
|
|
||||||
if (preferences[type]) {
|
|
||||||
// Get iframe src
|
|
||||||
const src = placeholder.getAttribute('data-src');
|
|
||||||
|
|
||||||
// Create iframe
|
|
||||||
const iframe = document.createElement('iframe');
|
|
||||||
iframe.src = src;
|
|
||||||
iframe.width = placeholder.style.width;
|
|
||||||
iframe.height = placeholder.style.height;
|
|
||||||
iframe.frameBorder = '0';
|
|
||||||
|
|
||||||
// Replace placeholder with iframe
|
|
||||||
placeholder.parentNode.replaceChild(iframe, placeholder);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if cookie consent is already set
|
// Check if cookie consent is already set
|
||||||
var cookieConsent = getCookie('gdpr_cookie_consent');
|
var cookieConsent = getCookie('gdpr_cookie_consent');
|
||||||
|
|
||||||
// Always block non-necessary scripts first
|
|
||||||
blockScripts();
|
|
||||||
|
|
||||||
if (!cookieConsent) {
|
if (!cookieConsent) {
|
||||||
// Show the cookie banner if consent is not set
|
// Show the cookie banner if consent is not set
|
||||||
document.getElementById('gdpr-cookie-banner').style.display = 'block';
|
document.getElementById('gdpr-cookie-banner').style.display = 'block';
|
||||||
@ -213,7 +54,7 @@ document.addEventListener('DOMContentLoaded', function() {
|
|||||||
// Apply cookie preferences
|
// Apply cookie preferences
|
||||||
var consentPreferences = JSON.parse(cookieConsent);
|
var consentPreferences = JSON.parse(cookieConsent);
|
||||||
applyConsentPreferences(consentPreferences);
|
applyConsentPreferences(consentPreferences);
|
||||||
|
|
||||||
// Show the manage button since consent was already given
|
// Show the manage button since consent was already given
|
||||||
showManageButton();
|
showManageButton();
|
||||||
}
|
}
|
||||||
@ -257,12 +98,12 @@ document.addEventListener('DOMContentLoaded', function() {
|
|||||||
function showModal() {
|
function showModal() {
|
||||||
document.getElementById('gdpr-cookie-banner').style.display = 'none';
|
document.getElementById('gdpr-cookie-banner').style.display = 'none';
|
||||||
document.getElementById('gdpr-cookie-modal').style.display = 'block';
|
document.getElementById('gdpr-cookie-modal').style.display = 'block';
|
||||||
|
|
||||||
// Load saved preferences if they exist
|
// Load saved preferences if they exist
|
||||||
var cookieConsent = getCookie('gdpr_cookie_consent');
|
var cookieConsent = getCookie('gdpr_cookie_consent');
|
||||||
if (cookieConsent) {
|
if (cookieConsent) {
|
||||||
var preferences = JSON.parse(cookieConsent);
|
var preferences = JSON.parse(cookieConsent);
|
||||||
|
|
||||||
// Set checkboxes based on saved preferences
|
// Set checkboxes based on saved preferences
|
||||||
document.querySelectorAll('.gdpr-cookie-checkbox').forEach(function(checkbox) {
|
document.querySelectorAll('.gdpr-cookie-checkbox').forEach(function(checkbox) {
|
||||||
var category = checkbox.getAttribute('data-cookie-category');
|
var category = checkbox.getAttribute('data-cookie-category');
|
||||||
@ -286,7 +127,7 @@ document.addEventListener('DOMContentLoaded', function() {
|
|||||||
analytics: true,
|
analytics: true,
|
||||||
marketing: true
|
marketing: true
|
||||||
};
|
};
|
||||||
|
|
||||||
setCookie('gdpr_cookie_consent', JSON.stringify(preferences), 365);
|
setCookie('gdpr_cookie_consent', JSON.stringify(preferences), 365);
|
||||||
applyConsentPreferences(preferences);
|
applyConsentPreferences(preferences);
|
||||||
afterConsent(); // Use the new function for consistent post-consent behavior
|
afterConsent(); // Use the new function for consistent post-consent behavior
|
||||||
@ -299,7 +140,7 @@ document.addEventListener('DOMContentLoaded', function() {
|
|||||||
analytics: false,
|
analytics: false,
|
||||||
marketing: false
|
marketing: false
|
||||||
};
|
};
|
||||||
|
|
||||||
setCookie('gdpr_cookie_consent', JSON.stringify(preferences), 365);
|
setCookie('gdpr_cookie_consent', JSON.stringify(preferences), 365);
|
||||||
applyConsentPreferences(preferences);
|
applyConsentPreferences(preferences);
|
||||||
afterConsent(); // Use the new function for consistent post-consent behavior
|
afterConsent(); // Use the new function for consistent post-consent behavior
|
||||||
@ -309,28 +150,28 @@ document.addEventListener('DOMContentLoaded', function() {
|
|||||||
var preferences = {
|
var preferences = {
|
||||||
necessary: true // Necessary cookies are always accepted
|
necessary: true // Necessary cookies are always accepted
|
||||||
};
|
};
|
||||||
|
|
||||||
// Get selected preferences
|
// Get selected preferences
|
||||||
document.querySelectorAll('.gdpr-cookie-checkbox').forEach(function(checkbox) {
|
document.querySelectorAll('.gdpr-cookie-checkbox').forEach(function(checkbox) {
|
||||||
var category = checkbox.getAttribute('data-cookie-category');
|
var category = checkbox.getAttribute('data-cookie-category');
|
||||||
preferences[category] = checkbox.checked;
|
preferences[category] = checkbox.checked;
|
||||||
});
|
});
|
||||||
|
|
||||||
setCookie('gdpr_cookie_consent', JSON.stringify(preferences), 365);
|
setCookie('gdpr_cookie_consent', JSON.stringify(preferences), 365);
|
||||||
applyConsentPreferences(preferences);
|
applyConsentPreferences(preferences);
|
||||||
afterConsent(); // Use the new function for consistent post-consent behavior
|
afterConsent(); // Use the new function for consistent post-consent behavior
|
||||||
}
|
}
|
||||||
|
|
||||||
function applyConsentPreferences(preferences) {
|
function applyConsentPreferences(preferences) {
|
||||||
// Load consented scripts
|
// Example implementation
|
||||||
loadConsentedScripts(preferences);
|
// You would need to adapt this based on your specific cookie usage
|
||||||
|
|
||||||
// Functional cookies
|
// Functional cookies
|
||||||
if (!preferences.functional) {
|
if (!preferences.functional) {
|
||||||
// Disable functional cookies
|
// Disable functional cookies
|
||||||
removeFunctionalCookies();
|
removeFunctionalCookies();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Analytics cookies
|
// Analytics cookies
|
||||||
if (!preferences.analytics) {
|
if (!preferences.analytics) {
|
||||||
// Disable analytics cookies (like Google Analytics)
|
// Disable analytics cookies (like Google Analytics)
|
||||||
@ -339,7 +180,7 @@ document.addEventListener('DOMContentLoaded', function() {
|
|||||||
// Enable analytics
|
// Enable analytics
|
||||||
enableAnalytics();
|
enableAnalytics();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Marketing cookies
|
// Marketing cookies
|
||||||
if (!preferences.marketing) {
|
if (!preferences.marketing) {
|
||||||
// Disable marketing cookies
|
// Disable marketing cookies
|
||||||
@ -353,43 +194,32 @@ document.addEventListener('DOMContentLoaded', function() {
|
|||||||
// Helper functions to implement consent preferences
|
// Helper functions to implement consent preferences
|
||||||
function removeFunctionalCookies() {
|
function removeFunctionalCookies() {
|
||||||
// This is just an example - implement based on your specific needs
|
// This is just an example - implement based on your specific needs
|
||||||
var functionalCookies = ['prefs', 'language', 'theme', 'user_preferences'];
|
var functionalCookies = ['prefs', 'language', 'theme'];
|
||||||
var domains = [window.location.hostname, '.' + window.location.hostname];
|
|
||||||
|
|
||||||
functionalCookies.forEach(function(cookie) {
|
functionalCookies.forEach(function(cookie) {
|
||||||
domains.forEach(function(domain) {
|
document.cookie = cookie + '=; Path=/; Expires=Thu, 01 Jan 1970 00:00:01 GMT;';
|
||||||
document.cookie = cookie + '=; Path=/; Expires=Thu, 01 Jan 1970 00:00:01 GMT; Domain=' + domain;
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function disableAnalytics() {
|
function disableAnalytics() {
|
||||||
// Google Analytics
|
// Example: Disable Google Analytics
|
||||||
window['ga-disable-UA-XXXXXXXX-X'] = true;
|
window['ga-disable-UA-XXXXXXXX-X'] = true;
|
||||||
window['ga-disable-G-XXXXXXXX'] = true;
|
|
||||||
|
|
||||||
// Remove existing GA cookies
|
// Remove existing GA cookies
|
||||||
var analyticsCookies = ['_ga', '_gid', '_gat', '__utma', '__utmb', '__utmc', '__utmt', '__utmz', '_hjid', '_hjAbsoluteSessionInProgress'];
|
document.cookie = '_ga=; Path=/; Expires=Thu, 01 Jan 1970 00:00:01 GMT; Domain=.' + window.location.hostname;
|
||||||
var domains = [window.location.hostname, '.' + window.location.hostname];
|
document.cookie = '_gid=; Path=/; Expires=Thu, 01 Jan 1970 00:00:01 GMT; Domain=.' + window.location.hostname;
|
||||||
|
document.cookie = '_gat=; Path=/; Expires=Thu, 01 Jan 1970 00:00:01 GMT; Domain=.' + window.location.hostname;
|
||||||
analyticsCookies.forEach(function(cookie) {
|
|
||||||
domains.forEach(function(domain) {
|
|
||||||
document.cookie = cookie + '=; Path=/; Expires=Thu, 01 Jan 1970 00:00:01 GMT; Domain=' + domain;
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function enableAnalytics() {
|
function enableAnalytics() {
|
||||||
// Google Analytics
|
// Example: Enable Google Analytics
|
||||||
window['ga-disable-UA-XXXXXXXX-X'] = false;
|
window['ga-disable-UA-XXXXXXXX-X'] = false;
|
||||||
window['ga-disable-G-XXXXXXXX'] = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function disableMarketing() {
|
function disableMarketing() {
|
||||||
// Common marketing cookies
|
// Example implementation for common marketing cookies
|
||||||
var marketingCookies = ['_fbp', 'fr', 'IDE', 'MUID', 'personalization_id', 'VISITOR_INFO1_LIVE', 'YSC', 'NID'];
|
var marketingCookies = ['_fbp', 'fr', 'IDE', 'MUID', 'personalization_id'];
|
||||||
var domains = [window.location.hostname, '.' + window.location.hostname, '.google.com', '.facebook.com', '.youtube.com'];
|
var domains = [window.location.hostname, '.' + window.location.hostname];
|
||||||
|
|
||||||
marketingCookies.forEach(function(cookie) {
|
marketingCookies.forEach(function(cookie) {
|
||||||
domains.forEach(function(domain) {
|
domains.forEach(function(domain) {
|
||||||
document.cookie = cookie + '=; Path=/; Expires=Thu, 01 Jan 1970 00:00:01 GMT; Domain=' + domain;
|
document.cookie = cookie + '=; Path=/; Expires=Thu, 01 Jan 1970 00:00:01 GMT; Domain=' + domain;
|
||||||
@ -398,60 +228,8 @@ document.addEventListener('DOMContentLoaded', function() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function enableMarketing() {
|
function enableMarketing() {
|
||||||
// For enabling marketing, we load the scripts that were blocked
|
// For enabling marketing, we typically don't need to do anything special
|
||||||
// This happens in the loadConsentedScripts function
|
// The marketing scripts will set their cookies when they load
|
||||||
|
// Just ensure the marketing scripts are loaded after checking consent
|
||||||
}
|
}
|
||||||
|
|
||||||
// Function to detect which script is associated with each cookie category
|
|
||||||
function detectThirdPartyScripts() {
|
|
||||||
// This function would scan the page for known third-party scripts
|
|
||||||
// and auto-assign data-cookieconsent attributes
|
|
||||||
const knownScriptPatterns = {
|
|
||||||
analytics: [
|
|
||||||
/google-analytics\.com\/analytics\.js/i,
|
|
||||||
/googletagmanager\.com\/gtag/i,
|
|
||||||
/google-analytics\.com\/ga\.js/i,
|
|
||||||
/hotjar\.com/i,
|
|
||||||
/analytics/i,
|
|
||||||
/matomo/i,
|
|
||||||
/stats/i
|
|
||||||
],
|
|
||||||
marketing: [
|
|
||||||
/facebook\.net/i,
|
|
||||||
/doubleclick\.net/i,
|
|
||||||
/googlesyndication\.com/i,
|
|
||||||
/ads/i,
|
|
||||||
/adservices/i,
|
|
||||||
/pixel/i,
|
|
||||||
/track/i
|
|
||||||
],
|
|
||||||
functional: [
|
|
||||||
/recaptcha/i,
|
|
||||||
/fonts\.googleapis\.com/i,
|
|
||||||
/cloudflare/i,
|
|
||||||
/cdn/i,
|
|
||||||
/livechat/i,
|
|
||||||
/chat/i,
|
|
||||||
/support/i
|
|
||||||
]
|
|
||||||
};
|
|
||||||
|
|
||||||
const scripts = document.querySelectorAll('script:not([data-cookieconsent])');
|
|
||||||
|
|
||||||
scripts.forEach(script => {
|
|
||||||
if (!script.src) return; // Skip inline scripts
|
|
||||||
|
|
||||||
for (const [category, patterns] of Object.entries(knownScriptPatterns)) {
|
|
||||||
for (const pattern of patterns) {
|
|
||||||
if (pattern.test(script.src)) {
|
|
||||||
script.setAttribute('data-cookieconsent', category);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Run script detection
|
|
||||||
detectThirdPartyScripts();
|
|
||||||
});
|
});
|
@ -1,211 +0,0 @@
|
|||||||
/**
|
|
||||||
* GDPR Cookie Consent Helper for PrestaShop
|
|
||||||
*
|
|
||||||
* @author Walzen665
|
|
||||||
* @copyright Copyright (c) 2025
|
|
||||||
* @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0)
|
|
||||||
*/
|
|
||||||
|
|
||||||
// This script runs early in the page load to tag inline scripts with appropriate consent categories
|
|
||||||
(function() {
|
|
||||||
// Known script patterns to identify analytics, marketing and functional scripts
|
|
||||||
const scriptPatterns = {
|
|
||||||
analytics: [
|
|
||||||
/google[\s\-_]?analytics/i,
|
|
||||||
/ga\s*\(\s*['"]create/i,
|
|
||||||
/googletagmanager/i,
|
|
||||||
/gtag/i,
|
|
||||||
/\_gaq/i,
|
|
||||||
/matomo/i,
|
|
||||||
/piwik/i,
|
|
||||||
/mixpanel/i,
|
|
||||||
/hotjar/i,
|
|
||||||
/clarity/i
|
|
||||||
],
|
|
||||||
marketing: [
|
|
||||||
/facebook[\s\-_]?pixel/i,
|
|
||||||
/fbq\s*\(\s*['"]init/i,
|
|
||||||
/doubleclick/i,
|
|
||||||
/adwords/i,
|
|
||||||
/google[\s\-_]?ad[\s\-_]?services/i,
|
|
||||||
/google[\s\-_]?tag[\s\-_]?manager/i,
|
|
||||||
/gtm/i,
|
|
||||||
/twitter[\s\-_]?pixel/i,
|
|
||||||
/pinterest[\s\-_]?tag/i
|
|
||||||
],
|
|
||||||
functional: [
|
|
||||||
/recaptcha/i,
|
|
||||||
/chat/i,
|
|
||||||
/livechat/i,
|
|
||||||
/support/i,
|
|
||||||
/feedback/i,
|
|
||||||
/preference/i,
|
|
||||||
/usercentrics/i
|
|
||||||
]
|
|
||||||
};
|
|
||||||
|
|
||||||
// Function to process and tag a script element
|
|
||||||
function processScript(script) {
|
|
||||||
// Skip if it already has a consent attribute
|
|
||||||
if (script.hasAttribute('data-cookieconsent')) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Skip our own scripts
|
|
||||||
if (script.src && script.src.indexOf('gdpr_cookie') !== -1) {
|
|
||||||
script.setAttribute('data-cookieconsent', 'necessary');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check content for patterns
|
|
||||||
const content = script.innerHTML || '';
|
|
||||||
const src = script.src || '';
|
|
||||||
|
|
||||||
// Determine script category
|
|
||||||
let category = 'necessary'; // Default category
|
|
||||||
|
|
||||||
for (const [cat, patterns] of Object.entries(scriptPatterns)) {
|
|
||||||
for (const pattern of patterns) {
|
|
||||||
if (pattern.test(content) || pattern.test(src)) {
|
|
||||||
category = cat;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (category !== 'necessary') {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Tag the script
|
|
||||||
script.setAttribute('data-cookieconsent', category);
|
|
||||||
|
|
||||||
// For non-necessary scripts, we'll create a duplicate with the correct attribute
|
|
||||||
// but disabled until consent is given
|
|
||||||
if (category !== 'necessary') {
|
|
||||||
const originalScript = script;
|
|
||||||
const newScript = document.createElement('script');
|
|
||||||
|
|
||||||
// Copy attributes
|
|
||||||
Array.from(originalScript.attributes).forEach(attr => {
|
|
||||||
if (attr.name !== 'data-cookieconsent') {
|
|
||||||
newScript.setAttribute(attr.name, attr.value);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Set consent attribute
|
|
||||||
newScript.setAttribute('data-cookieconsent', category);
|
|
||||||
|
|
||||||
// Copy content if it's an inline script
|
|
||||||
if (!originalScript.src && originalScript.innerHTML) {
|
|
||||||
newScript.innerHTML = originalScript.innerHTML;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Replace the original script
|
|
||||||
originalScript.parentNode.replaceChild(newScript, originalScript);
|
|
||||||
|
|
||||||
// Prevent execution by removing src and content
|
|
||||||
newScript.removeAttribute('src');
|
|
||||||
newScript.innerHTML = '';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Process existing scripts
|
|
||||||
document.querySelectorAll('script').forEach(processScript);
|
|
||||||
|
|
||||||
// Use a MutationObserver to catch dynamically added scripts
|
|
||||||
const observer = new MutationObserver(mutations => {
|
|
||||||
mutations.forEach(mutation => {
|
|
||||||
mutation.addedNodes.forEach(node => {
|
|
||||||
if (node.tagName === 'SCRIPT') {
|
|
||||||
processScript(node);
|
|
||||||
} else if (node.querySelectorAll) {
|
|
||||||
node.querySelectorAll('script').forEach(processScript);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
// Start observing the document
|
|
||||||
observer.observe(document.documentElement, {
|
|
||||||
childList: true,
|
|
||||||
subtree: true
|
|
||||||
});
|
|
||||||
|
|
||||||
// Also process iframes
|
|
||||||
function processIframe(iframe) {
|
|
||||||
// Skip if it already has a consent attribute
|
|
||||||
if (iframe.hasAttribute('data-cookieconsent')) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const src = iframe.src || '';
|
|
||||||
|
|
||||||
// Common third-party iframe sources
|
|
||||||
const iframePatterns = {
|
|
||||||
marketing: [
|
|
||||||
/youtube/i,
|
|
||||||
/vimeo/i,
|
|
||||||
/facebook\.com\/plugins/i,
|
|
||||||
/twitter\.com\/widgets/i,
|
|
||||||
/instagram\.com/i,
|
|
||||||
/pinterest\.com/i,
|
|
||||||
/doubleclick/i,
|
|
||||||
/ads/i
|
|
||||||
],
|
|
||||||
analytics: [
|
|
||||||
/googletagmanager/i,
|
|
||||||
/analytics/i
|
|
||||||
],
|
|
||||||
functional: [
|
|
||||||
/recaptcha/i,
|
|
||||||
/maps\.google/i,
|
|
||||||
/google\.com\/maps/i,
|
|
||||||
/disqus/i,
|
|
||||||
/livechat/i,
|
|
||||||
/chat/i
|
|
||||||
]
|
|
||||||
};
|
|
||||||
|
|
||||||
// Determine iframe category
|
|
||||||
let category = 'necessary'; // Default category
|
|
||||||
|
|
||||||
for (const [cat, patterns] of Object.entries(iframePatterns)) {
|
|
||||||
for (const pattern of patterns) {
|
|
||||||
if (pattern.test(src)) {
|
|
||||||
category = cat;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (category !== 'necessary') {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Tag the iframe
|
|
||||||
iframe.setAttribute('data-cookieconsent', category);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Process existing iframes
|
|
||||||
document.querySelectorAll('iframe').forEach(processIframe);
|
|
||||||
|
|
||||||
// Use the observer to catch dynamically added iframes
|
|
||||||
const iframeObserver = new MutationObserver(mutations => {
|
|
||||||
mutations.forEach(mutation => {
|
|
||||||
mutation.addedNodes.forEach(node => {
|
|
||||||
if (node.tagName === 'IFRAME') {
|
|
||||||
processIframe(node);
|
|
||||||
} else if (node.querySelectorAll) {
|
|
||||||
node.querySelectorAll('iframe').forEach(processIframe);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
// Start observing for iframes
|
|
||||||
iframeObserver.observe(document.documentElement, {
|
|
||||||
childList: true,
|
|
||||||
subtree: true
|
|
||||||
});
|
|
||||||
})();
|
|
28
views/templates/admin/configuration.html.twig
Normal file
28
views/templates/admin/configuration.html.twig
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
{% extends '@PrestaShop/Admin/layout.html.twig' %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
{{ form_start(gdprConfigurationForm) }}
|
||||||
|
<div class="card">
|
||||||
|
<h3 class="card-header">
|
||||||
|
<i class="material-icons">settings</i> {{ 'GDPR Cookie Consent Configuration'|trans({}, 'Modules.Gdprcookieconsent.Admin') }}
|
||||||
|
</h3>
|
||||||
|
<div class="card-body">
|
||||||
|
<div class="form-wrapper">
|
||||||
|
{{ form_widget(gdprConfigurationForm) }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="card-footer">
|
||||||
|
<div class="d-flex justify-content-end">
|
||||||
|
<button class="btn btn-primary float-right" id="save-button">
|
||||||
|
{{ 'Save'|trans({}, 'Admin.Actions') }}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{{ form_end(gdprConfigurationForm) }}
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block javascripts %}
|
||||||
|
{{ parent() }}
|
||||||
|
<script src="{{ asset('../modules/gdprcookieconsent/views/js/admin.js') }}"></script>
|
||||||
|
{% endblock %}
|
@ -13,35 +13,35 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="gdpr-cookie-modal-body">
|
<div class="gdpr-cookie-modal-body">
|
||||||
<p>{$gdprCookieMessage}</p>
|
<p>{$gdprCookieMessage}</p>
|
||||||
|
|
||||||
<div class="gdpr-cookie-info-block">
|
<div class="gdpr-cookie-info-block">
|
||||||
<p><strong>{l s='Data Controller:' mod='gdprcookieconsent'}</strong> {$gdprCookieDataController}</p>
|
<p><strong>{l s='Data Controller:' mod='gdprcookieconsent'}</strong> {$gdprCookieDataController}</p>
|
||||||
<p><strong>{l s='Cookie Retention Period:' mod='gdprcookieconsent'}</strong> {$gdprCookieRetentionPeriod}</p>
|
<p><strong>{l s='Cookie Retention Period:' mod='gdprcookieconsent'}</strong> {$gdprCookieRetentionPeriod}</p>
|
||||||
<p><strong>{l s='Third-Party Recipients:' mod='gdprcookieconsent'}</strong> {$gdprCookieThirdParties}</p>
|
<p><strong>{l s='Third-Party Recipients:' mod='gdprcookieconsent'}</strong> {$gdprCookieThirdParties}</p>
|
||||||
<p><strong>{l s='Your Rights:' mod='gdprcookieconsent'}</strong> {l s='You can withdraw your consent at any time by clicking the "Manage Cookie Preferences" button or by deleting cookies in your browser settings.' mod='gdprcookieconsent'}</p>
|
<p><strong>{l s='Your Rights:' mod='gdprcookieconsent'}</strong> {l s='You can withdraw your consent at any time by clicking the "Manage Cookie Preferences" button or by deleting cookies in your browser settings.' mod='gdprcookieconsent'}</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="gdpr-cookie-categories">
|
<div class="gdpr-cookie-categories">
|
||||||
<div class="gdpr-cookie-category">
|
<div class="gdpr-cookie-category">
|
||||||
<input type="checkbox" id="gdpr-cookie-necessary" checked disabled>
|
<input type="checkbox" id="gdpr-cookie-necessary" checked disabled>
|
||||||
<label for="gdpr-cookie-necessary">{l s='Necessary' mod='gdprcookieconsent'}</label>
|
<label for="gdpr-cookie-necessary">{l s='Necessary' mod='gdprcookieconsent'}</label>
|
||||||
<p>{$gdprCookieNecessaryDesc}</p>
|
<p>{l s='Necessary cookies help make a website usable by enabling basic functions like page navigation. The website cannot function properly without these cookies.' mod='gdprcookieconsent'}</p>
|
||||||
</div>
|
</div>
|
||||||
{if !$gdprCookieOnlyRequired}
|
{if !$gdprCookieOnlyRequired}
|
||||||
<div class="gdpr-cookie-category">
|
<div class="gdpr-cookie-category">
|
||||||
<input type="checkbox" id="gdpr-cookie-functional" class="gdpr-cookie-checkbox" data-cookie-category="functional">
|
<input type="checkbox" id="gdpr-cookie-functional" class="gdpr-cookie-checkbox" data-cookie-category="functional">
|
||||||
<label for="gdpr-cookie-functional">{l s='Functional' mod='gdprcookieconsent'}</label>
|
<label for="gdpr-cookie-functional">{l s='Functional' mod='gdprcookieconsent'}</label>
|
||||||
<p>{$gdprCookieFunctionalDesc}</p>
|
<p>{l s='Functional cookies enable a website to remember information that changes the way the website behaves or looks, like your preferred language or the region you are in.' mod='gdprcookieconsent'}</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="gdpr-cookie-category">
|
<div class="gdpr-cookie-category">
|
||||||
<input type="checkbox" id="gdpr-cookie-analytics" class="gdpr-cookie-checkbox" data-cookie-category="analytics">
|
<input type="checkbox" id="gdpr-cookie-analytics" class="gdpr-cookie-checkbox" data-cookie-category="analytics">
|
||||||
<label for="gdpr-cookie-analytics">{l s='Analytics' mod='gdprcookieconsent'}</label>
|
<label for="gdpr-cookie-analytics">{l s='Analytics' mod='gdprcookieconsent'}</label>
|
||||||
<p>{$gdprCookieAnalyticsDesc}</p>
|
<p>{l s='Analytics cookies help website owners understand how visitors interact with websites by collecting and reporting information anonymously.' mod='gdprcookieconsent'}</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="gdpr-cookie-category">
|
<div class="gdpr-cookie-category">
|
||||||
<input type="checkbox" id="gdpr-cookie-marketing" class="gdpr-cookie-checkbox" data-cookie-category="marketing">
|
<input type="checkbox" id="gdpr-cookie-marketing" class="gdpr-cookie-checkbox" data-cookie-category="marketing">
|
||||||
<label for="gdpr-cookie-marketing">{l s='Marketing' mod='gdprcookieconsent'}</label>
|
<label for="gdpr-cookie-marketing">{l s='Marketing' mod='gdprcookieconsent'}</label>
|
||||||
<p>{$gdprCookieMarketingDesc}</p>
|
<p>{l s='Marketing cookies are used to track visitors across websites. The intention is to display ads that are relevant and engaging for the individual user.' mod='gdprcookieconsent'}</p>
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
|
Reference in New Issue
Block a user