diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..62c8935 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +.idea/ \ No newline at end of file diff --git a/gdprcookieconsent.php b/gdprcookieconsent.php index 1f6d4b5..c14ed38 100644 --- a/gdprcookieconsent.php +++ b/gdprcookieconsent.php @@ -1,4 +1,5 @@ registerHook('displayHeader') && $this->registerHook('displayFooter') && Configuration::updateValue('GDPR_COOKIE_ENABLED', 1) && - Configuration::updateValue('GDPR_COOKIE_MESSAGE', 'This website uses cookies to ensure you get the best experience on our website.') && + Configuration::updateValue('GDPR_COOKIE_MESSAGE', 'This website uses cookies to ensure you get the best experience. We collect and process your data for website functionality, analytics, and personalized advertising.') && Configuration::updateValue('GDPR_COOKIE_ACCEPT', 'Accept All Cookies') && - Configuration::updateValue('GDPR_COOKIE_DECLINE', 'Decline') && + Configuration::updateValue('GDPR_COOKIE_DECLINE', 'Decline Non-Essential') && Configuration::updateValue('GDPR_COOKIE_SETTINGS', 'Cookie Settings') && Configuration::updateValue('GDPR_COOKIE_MORE_INFO', 'More Information') && - Configuration::updateValue('GDPR_COOKIE_MORE_INFO_URL', 'content/2-privacy-policy'); + Configuration::updateValue('GDPR_COOKIE_MORE_INFO_URL', 'https://yourstore.net/content/privacy-policy') && + Configuration::updateValue('GDPR_COOKIE_DATA_CONTROLLER', 'Your Company Name') && + Configuration::updateValue('GDPR_COOKIE_RETENTION_PERIOD', '365 days') && + Configuration::updateValue('GDPR_COOKIE_THIRD_PARTIES', 'Google Analytics, Facebook, etc.') && + Configuration::updateValue('GDPR_COOKIE_MANAGE_TEXT', 'Manage Cookie Preferences') && + Configuration::updateValue('GDPR_COOKIE_ONLY_REQUIRED', 1); } + /** * Uninstall the module */ @@ -62,7 +69,12 @@ class GdprCookieConsent extends Module Configuration::deleteByName('GDPR_COOKIE_DECLINE') && Configuration::deleteByName('GDPR_COOKIE_SETTINGS') && Configuration::deleteByName('GDPR_COOKIE_MORE_INFO') && - Configuration::deleteByName('GDPR_COOKIE_MORE_INFO_URL'); + Configuration::deleteByName('GDPR_COOKIE_MORE_INFO_URL') && + Configuration::deleteByName('GDPR_COOKIE_DATA_CONTROLLER') && + Configuration::deleteByName('GDPR_COOKIE_RETENTION_PERIOD') && + Configuration::deleteByName('GDPR_COOKIE_THIRD_PARTIES') && + Configuration::deleteByName('GDPR_COOKIE_MANAGE_TEXT') && + Configuration::deleteByName('GDPR_COOKIE_ONLY_REQUIRED'); } /** @@ -82,6 +94,11 @@ class GdprCookieConsent extends Module $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); @@ -91,6 +108,11 @@ class GdprCookieConsent extends Module 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')); @@ -137,6 +159,27 @@ class GdprCookieConsent extends Module 'name' => 'GDPR_COOKIE_MESSAGE', 'required' => true, ], + [ + 'type' => 'text', + 'label' => $this->l('Data Controller'), + 'name' => 'GDPR_COOKIE_DATA_CONTROLLER', + 'desc' => $this->l('Your company/organization name'), + 'required' => true, + ], + [ + 'type' => 'text', + 'label' => $this->l('Cookie Retention Period'), + 'name' => 'GDPR_COOKIE_RETENTION_PERIOD', + 'desc' => $this->l('How long cookies will be stored (e.g., 365 days)'), + 'required' => true, + ], + [ + 'type' => 'textarea', + 'label' => $this->l('Third-Party Recipients'), + 'name' => 'GDPR_COOKIE_THIRD_PARTIES', + 'desc' => $this->l('List third parties that receive cookie data'), + 'required' => true, + ], [ 'type' => 'text', 'label' => $this->l('Accept Button Text'), @@ -155,6 +198,13 @@ class GdprCookieConsent extends Module 'name' => 'GDPR_COOKIE_SETTINGS', 'required' => true, ], + [ + 'type' => 'text', + 'label' => $this->l('Manage Preferences Text'), + 'name' => 'GDPR_COOKIE_MANAGE_TEXT', + 'desc' => $this->l('Text for the manage preferences button (displayed after consent is given)'), + 'required' => true, + ], [ 'type' => 'text', 'label' => $this->l('More Info Button Text'), @@ -168,6 +218,26 @@ class GdprCookieConsent extends Module 'name' => 'GDPR_COOKIE_MORE_INFO_URL', 'required' => true, ], + [ + 'type' => 'switch', + 'label' => $this->l('This cookie types are used'), + 'name' => 'GDPR_COOKIE_ONLY_REQUIRED', + 'desc' => $this->l('If this option is enabled, no config modal will be rendered and there will only be a single button to hide the cookie notice. (Only enable this, if you don\'t track any user data)'), + 'is_bool' => true, + 'required' => true, + 'values' => [ + [ + 'id' => 'active_on', + 'value' => 1, + 'label' => $this->l('Nessessary only') + ], + [ + 'id' => 'active_off', + 'value' => 0, + 'label' => $this->l('All cookies') + ] + ], + ], ], 'submit' => [ 'title' => $this->l('Save'), @@ -202,6 +272,11 @@ class GdprCookieConsent extends Module $helper->fields_value['GDPR_COOKIE_SETTINGS'] = Configuration::get('GDPR_COOKIE_SETTINGS'); $helper->fields_value['GDPR_COOKIE_MORE_INFO'] = Configuration::get('GDPR_COOKIE_MORE_INFO'); $helper->fields_value['GDPR_COOKIE_MORE_INFO_URL'] = Configuration::get('GDPR_COOKIE_MORE_INFO_URL'); + $helper->fields_value['GDPR_COOKIE_DATA_CONTROLLER'] = Configuration::get('GDPR_COOKIE_DATA_CONTROLLER'); + $helper->fields_value['GDPR_COOKIE_RETENTION_PERIOD'] = Configuration::get('GDPR_COOKIE_RETENTION_PERIOD'); + $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_ONLY_REQUIRED'] = Configuration::get('GDPR_COOKIE_ONLY_REQUIRED'); return $helper->generateForm([$form]); } @@ -228,10 +303,23 @@ class GdprCookieConsent extends Module 'gdprCookieDecline' => Configuration::get('GDPR_COOKIE_DECLINE'), 'gdprCookieSettings' => Configuration::get('GDPR_COOKIE_SETTINGS'), 'gdprCookieMoreInfo' => Configuration::get('GDPR_COOKIE_MORE_INFO'), - 'gdprCookieMoreInfoUrl' => $this->context->link->getCMSLink( - Configuration::get('GDPR_COOKIE_MORE_INFO_URL') - ), + 'gdprCookieMoreInfoUrl' => Configuration::get('GDPR_COOKIE_MORE_INFO_URL'), + 'gdprCookieDataController' => Configuration::get('GDPR_COOKIE_DATA_CONTROLLER', ''), + 'gdprCookieRetentionPeriod' => Configuration::get('GDPR_COOKIE_RETENTION_PERIOD', '365 days'), + 'gdprCookieThirdParties' => Configuration::get('GDPR_COOKIE_THIRD_PARTIES', ''), + 'gdprCookieManageText' => Configuration::get('GDPR_COOKIE_MANAGE_TEXT', 'Manage Cookies'), + 'gdprCookieOnlyRequired' => Configuration::get('GDPR_COOKIE_ONLY_REQUIRED'), ]); + + // Assign variables to Smarty for the manage button template + $this->context->smarty->assign([ + 'gdprCookieManageText' => Configuration::get('GDPR_COOKIE_MANAGE_TEXT', 'Manage Cookies'), + ]); + + // 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')) { + return $this->display(__FILE__, 'views/templates/hook/manage_button.tpl'); + } } /** @@ -249,11 +337,14 @@ class GdprCookieConsent extends Module 'gdprCookieDecline' => Configuration::get('GDPR_COOKIE_DECLINE'), 'gdprCookieSettings' => Configuration::get('GDPR_COOKIE_SETTINGS'), 'gdprCookieMoreInfo' => Configuration::get('GDPR_COOKIE_MORE_INFO'), - 'gdprCookieMoreInfoUrl' => $this->context->link->getCMSLink( - Configuration::get('GDPR_COOKIE_MORE_INFO_URL') - ), + 'gdprCookieMoreInfoUrl' => Configuration::get('GDPR_COOKIE_MORE_INFO_URL'), + 'gdprCookieDataController' => Configuration::get('GDPR_COOKIE_DATA_CONTROLLER'), + 'gdprCookieRetentionPeriod' => Configuration::get('GDPR_COOKIE_RETENTION_PERIOD'), + 'gdprCookieThirdParties' => Configuration::get('GDPR_COOKIE_THIRD_PARTIES'), + 'gdprCookieManageText' => Configuration::get('GDPR_COOKIE_MANAGE_TEXT'), + 'gdprCookieOnlyRequired' => Configuration::get('GDPR_COOKIE_ONLY_REQUIRED'), ]); return $this->display(__FILE__, 'views/templates/hook/footer.tpl'); } -} \ No newline at end of file +} diff --git a/views/css/gdpr_cookie.css b/views/css/gdpr_cookie.css index 2cb4050..0e79b8a 100644 --- a/views/css/gdpr_cookie.css +++ b/views/css/gdpr_cookie.css @@ -224,4 +224,73 @@ .gdpr-cookie-more-info { margin-bottom: 10px; } +} + +.gdpr-cookie-info-block { + margin: 15px 0; + padding: 15px; + background-color: #f9f9f9; + border: 1px solid #eee; + border-radius: 5px; +} + +.gdpr-cookie-info-block p { + margin: 5px 0; + font-size: 13px; + color: #666; +} + +.gdpr-cookie-banner-info { + margin: 5px 0 10px; +} + +.gdpr-cookie-banner-info p { + font-size: 12px; + opacity: 0.9; + margin: 0; +} + +/* Equal prominence for buttons */ +.gdpr-cookie-banner-decline, +.gdpr-cookie-banner-accept { + font-weight: 400; + padding: 8px 15px; + border-radius: 3px; + /* Make both buttons similar size but distinctive */ + min-width: 120px; +} + +.gdpr-cookie-banner-decline { + background-color: #f1f1f1; + color: #333; + border: 1px solid #ccc; +} + +.gdpr-cookie-banner-accept { + background-color: #4caf50; + color: white; + border: 1px solid #4caf50; +} + +/* Manage button styles */ +.gdpr-cookie-manage-button { + position: fixed; + bottom: 20px; + right: 20px; + z-index: 9990; +} + +.gdpr-cookie-manage { + padding: 8px 12px; + background-color: #f1f1f1; + color: #333; + border: 1px solid #ccc; + border-radius: 3px; + font-size: 12px; + cursor: pointer; + box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1); +} + +.gdpr-cookie-manage:hover { + background-color: #e5e5e5; } \ No newline at end of file diff --git a/views/js/gdpr_cookie.js b/views/js/gdpr_cookie.js index 21131fd..6f6ee41 100644 --- a/views/js/gdpr_cookie.js +++ b/views/js/gdpr_cookie.js @@ -29,6 +29,21 @@ document.addEventListener('DOMContentLoaded', function() { return null; } + // Show manage preferences button when cookies are already set + function showManageButton() { + document.getElementById('gdpr-cookie-manage-button').style.display = 'block'; + } + + // After user consents, hide banner and modal and show the manage button + function afterConsent() { + // Hide banner and modal + hideModal(); + document.getElementById('gdpr-cookie-banner').style.display = 'none'; + + // Show manage button + showManageButton(); + } + // Check if cookie consent is already set var cookieConsent = getCookie('gdpr_cookie_consent'); @@ -39,6 +54,9 @@ document.addEventListener('DOMContentLoaded', function() { // Apply cookie preferences var consentPreferences = JSON.parse(cookieConsent); applyConsentPreferences(consentPreferences); + + // Show the manage button since consent was already given + showManageButton(); } // Banner buttons @@ -46,25 +64,34 @@ document.addEventListener('DOMContentLoaded', function() { acceptAllCookies(); }); - document.getElementById('gdpr-cookie-banner-decline').addEventListener('click', function() { - declineAllCookies(); - }); + if(!gdprCookieOnlyRequired) { + document.getElementById('gdpr-cookie-banner-decline').addEventListener('click', function() { + declineAllCookies(); + }); + } document.getElementById('gdpr-cookie-banner-settings').addEventListener('click', function() { showModal(); }); // Modal buttons + if(!gdprCookieOnlyRequired) { + document.getElementById('gdpr-cookie-decline').addEventListener('click', function() { + declineAllCookies(); + }); + + document.getElementById('gdpr-cookie-accept-selected').addEventListener('click', function() { + acceptSelectedCookies(); + }); + } + document.getElementById('gdpr-cookie-accept-all').addEventListener('click', function() { acceptAllCookies(); }); - document.getElementById('gdpr-cookie-decline').addEventListener('click', function() { - declineAllCookies(); - }); - - document.getElementById('gdpr-cookie-accept-selected').addEventListener('click', function() { - acceptSelectedCookies(); + // Manage button (for after consent is given) + document.getElementById('gdpr-cookie-manage').addEventListener('click', function() { + showModal(); }); // Functions @@ -103,8 +130,7 @@ document.addEventListener('DOMContentLoaded', function() { setCookie('gdpr_cookie_consent', JSON.stringify(preferences), 365); applyConsentPreferences(preferences); - hideModal(); - document.getElementById('gdpr-cookie-banner').style.display = 'none'; + afterConsent(); // Use the new function for consistent post-consent behavior } function declineAllCookies() { @@ -117,8 +143,7 @@ document.addEventListener('DOMContentLoaded', function() { setCookie('gdpr_cookie_consent', JSON.stringify(preferences), 365); applyConsentPreferences(preferences); - hideModal(); - document.getElementById('gdpr-cookie-banner').style.display = 'none'; + afterConsent(); // Use the new function for consistent post-consent behavior } function acceptSelectedCookies() { @@ -134,8 +159,7 @@ document.addEventListener('DOMContentLoaded', function() { setCookie('gdpr_cookie_consent', JSON.stringify(preferences), 365); applyConsentPreferences(preferences); - hideModal(); - document.getElementById('gdpr-cookie-banner').style.display = 'none'; + afterConsent(); // Use the new function for consistent post-consent behavior } function applyConsentPreferences(preferences) { @@ -179,6 +203,11 @@ document.addEventListener('DOMContentLoaded', function() { function disableAnalytics() { // Example: Disable Google Analytics window['ga-disable-UA-XXXXXXXX-X'] = true; + + // Remove existing GA cookies + document.cookie = '_ga=; Path=/; Expires=Thu, 01 Jan 1970 00:00:01 GMT; Domain=.' + 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; } function enableAnalytics() { @@ -187,12 +216,20 @@ document.addEventListener('DOMContentLoaded', function() { } function disableMarketing() { - // Example implementation - // You would implement according to your specific marketing cookies + // Example implementation for common marketing cookies + var marketingCookies = ['_fbp', 'fr', 'IDE', 'MUID', 'personalization_id']; + var domains = [window.location.hostname, '.' + window.location.hostname]; + + marketingCookies.forEach(function(cookie) { + domains.forEach(function(domain) { + document.cookie = cookie + '=; Path=/; Expires=Thu, 01 Jan 1970 00:00:01 GMT; Domain=' + domain; + }); + }); } function enableMarketing() { - // Example implementation - // You would implement according to your specific marketing cookies + // For enabling marketing, we typically don't need to do anything special + // The marketing scripts will set their cookies when they load + // Just ensure the marketing scripts are loaded after checking consent } }); \ No newline at end of file diff --git a/views/templates/hook/footer.tpl b/views/templates/hook/footer.tpl index aac84df..b838617 100644 --- a/views/templates/hook/footer.tpl +++ b/views/templates/hook/footer.tpl @@ -14,34 +14,45 @@
@@ -51,10 +62,20 @@ + + \ No newline at end of file diff --git a/views/templates/hook/manage_button.tpl b/views/templates/hook/manage_button.tpl new file mode 100644 index 0000000..5ddef7a --- /dev/null +++ b/views/templates/hook/manage_button.tpl @@ -0,0 +1,11 @@ +{* +* 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) +*} + + \ No newline at end of file