etracker-8.x-3.x-dev/modules/cookies_etracker/cookies_etracker.module
modules/cookies_etracker/cookies_etracker.module
<?php /** * @file * Contains cookies_etracker.module. */ use Drupal\Core\Form\FormStateInterface; use Drupal\Core\Routing\RouteMatchInterface; use Drupal\etracker\Helper\Constants; /** * Implements hook_help(). */ function cookies_etracker_help($route_name, RouteMatchInterface $route_match) { switch ($route_name) { // Main module help for the cookies_etracker module. case 'help.page.cookies_etracker': return t(' <h3>About</h3> <p>Submodule to manage cookies consent provided by COOKiES and eTracker tracking behavior if a user should be tracked or not.</p> <h4>Options explanations</h4> <p>This module introduces the following options for handling tracking and consent behavior.</p> <dl> <dt>Most accuracy</dt> <dd>Tracks user <em>without cookies</em>, before any consent is confirmed. Tracks user <em>with cookies</em>, after consent is confirmed.</dd> <dt>Most privacy</dt> <dd>Does <em>not track user before</em> any consent is confirmed. Tracks <em>without cookies</em>, after consent is confirmed.</dd> <dt>Mixed</dt> <dd>Does <em>not track user before</em> any consent is confirmed. Tracks <em>with cookies</em> after consent is confirmed.</dd> <dt>Ignore consent</dt> <dd>Tracks user without cookies, ignores any consent confirmationSah. Just the same behavior as without <em>cookies_etracker</em> installed.</dd> </dl>'); } } /** * Implements hook_library_info_alter(). */ function cookies_etracker_library_info_alter(array &$libraries, string $extension): void { $eTrackerConfig = \Drupal::config(Constants::ETRACKER_SETTINGS_CONFIG_NAME); $etracker_script_settings = $eTrackerConfig->get('etracker_script_settings'); if (empty($etracker_script_settings['data_block_cookies'])) { // Cookie blocking is completely disabled. // No cookies_etracker action required. Do nothing. return; } // Cookie blocking is enabled! $doKo = \Drupal::service('cookies.knock_out')->doKnockOut(); if ($doKo && isset($libraries[Constants::ETRACKER_LIBRARY_NAME])) { $cookiesEtrackerConfig = \Drupal::config('cookies_etracker.settings'); $knockout_mode = $cookiesEtrackerConfig->get('knockout_mode'); // Cookie blocking is enabled! switch ($knockout_mode) { case 'knockout_without_consent_block_cookies_false': case 'knockout_without_consent_block_cookies_true': // Preprocess libraries for knockout healing: if (!empty($libraries[Constants::ETRACKER_LIBRARY_NAME]['js']['js/etracker.js'])) { // Avoid that the javascript you want to knock-out will be combined. $libraries[Constants::ETRACKER_LIBRARY_NAME]['js']['js/etracker.js']['preprocess'] = FALSE; // Prevent JS execution. src attribute will be ignored this way: $libraries[Constants::ETRACKER_LIBRARY_NAME]['js']['js/etracker.js']['attributes'] = array_merge($libraries[Constants::ETRACKER_LIBRARY_NAME]['js']['js/etracker.js']['attributes'], [ 'id' => 'etracker_script', 'type' => 'application/json', ]); } // Merge some attributes to prepare the script tag. $libraries[Constants::ETRACKER_LIBRARY_NAME]['js'][Constants::ETRACKER_JS_URL]['attributes'] = array_merge($libraries[Constants::ETRACKER_LIBRARY_NAME]['js'][Constants::ETRACKER_JS_URL]['attributes'], [ 'id' => '_etLoader', // Prevent JS execution. src attribute will be ignored this way: 'type' => 'application/json', ]); return; case 'block_cookies_true_without_consent': // No library alteration required. return; case 'block_cookies_true': // Cookie blocking is permanently enabled. // This is already being handled in etracker.module. // No cookies_etracker action required. Do nothing. return; } } } /** * Implements hook_page_attachments(). */ function cookies_etracker_page_attachments(array &$page): void { $eTrackerConfig = \Drupal::config(Constants::ETRACKER_SETTINGS_CONFIG_NAME); if (!_etracker_request_should_be_tracked($eTrackerConfig)) { // eTracker is not tracking, so we also shouldn't do anything here: return; } $etracker_script_settings = $eTrackerConfig->get('etracker_script_settings'); if (empty($etracker_script_settings['data_block_cookies'])) { // Cookie blocking is completely disabled. // No cookies_etracker action required. Do nothing. return; } // Cookie blocking is enabled! $doKo = \Drupal::service('cookies.knock_out')->doKnockOut(); if ($doKo) { $cookiesEtrackerConfig = \Drupal::config('cookies_etracker.settings'); $knockout_mode = $cookiesEtrackerConfig->get('knockout_mode'); // Cookie blocking is enabled! switch ($knockout_mode) { case 'knockout_without_consent_block_cookies_true': case 'knockout_without_consent_block_cookies_false': // Make the settings available in JS: $script_settings = [ 'knockout_mode' => $knockout_mode, ]; $page['#attached']['drupalSettings']['cookies_etracker'] = $script_settings; // Heal the libraries knockout in JavaScript: $page['#attached']['library'][] = 'cookies_etracker/knockout_without_consent'; return; case 'block_cookies_true_without_consent': // Enable cookies in JavaScript after consent was given: $page['#attached']['library'][] = 'cookies_etracker/block_cookies_true_without_consent'; return; case 'block_cookies_true': // Cookie blocking is permanently enabled. // This is already being handled in etracker.module. // No cookies_etracker action required. Do nothing. return; } // We should never reach here, as all cases should have been matched. // If we get here, something must be wrong with the chosen $knockout_mode. // So we better log a warning to recognize this: \Drupal::logger('cookies_etracker')->warning('Unknown cookies_etracker knockout mode: @knockout_mode. This should not happen.', ['@knockout_mode' => $knockout_mode]); } } /** * Implements hook_form_MODULE_admin_settings_alter(). */ function cookies_etracker_form_etracker_admin_settings_alter(array &$form, FormStateInterface $form_state, string $form_id): void { // Show a warning if cookies_etracker module is enabled, // but "Disable cookies" setting is false: $etrackerConfig = \Drupal::config('etracker.settings'); $etracker_script_settings = $etrackerConfig->get('etracker_script_settings'); if (empty($etracker_script_settings['data_block_cookies'])) { \Drupal::messenger()->addWarning(t('You have enabled the COOKiES eTracker (sub)module, but your "Privacy: Disable cookies" setting is not checked. <br /><strong>COOKiES eTracker will not block anything this way!</strong>')); } $config = \Drupal::config('cookies_etracker.settings'); // Add options for eTracker cookie handling: $form['tracking']['privacy']['knockout'] = [ '#type' => 'details', '#open' => TRUE, '#title' => t('Advanced "Disable cookies" handling'), ]; $form['tracking']['privacy']['knockout']['knockout_mode'] = [ '#type' => 'radios', '#title' => t('Blocking mode'), '#description' => t('Additional options provided by the <em>cookies_etracker</em> integration for eTracker cookie handling based on COOKiES cookie consent. eTracker knocked-out means the eTracker tracking snippet is not run and the user is not tracked at all until condition is met.'), '#options' => [ 'block_cookies_true_without_consent' => t('<strong>Most accuracy</strong><br/>eTracker tracking <em>enabled</em> without cookies <code>[data-block-cookies=true]</code> <em>before COOKiES consent</em>. eTracker tracking enabled with cookies <code>[data-block-cookies=false]</code> <em>after COOKiES consent</em>.'), 'knockout_without_consent_block_cookies_true' => t('<strong>Most privacy</strong><br/>eTracker tracking <em>disabled</em> (knocked-out) <em>before COOKiES consent</em>. eTracker tracking enabled without cookies <code>[data-block-cookies=true]</code> <em>after COOKiES consent</em>.'), 'knockout_without_consent_block_cookies_false' => t('<strong>Mixed</strong><br/>eTracker tracking <em>disabled</em> (knocked-out) <em>before COOKiES consent</em>. eTracker tracking enabled with cookies <code>[data-block-cookies=false]</code> <em>after COOKiES consent</em>.'), 'block_cookies_true' => t('<strong>Ignore consent</strong><br/>eTracker tracking <em>always enabled</em>, without cookies <code>[data-block-cookies=true]</code>. <em>Same behavior as without cookies_etracker installed.</em>'), ], '#default_value' => $config->get('knockout_mode'), '#states' => [ 'visible' => [ ':input[name="data_block_cookies"]' => ['checked' => TRUE], ], ], ]; // Show information if "Disable Cookies is checked": $form['tracking']['privacy']['knockout']['knockout_mode_info'] = [ '#type' => 'item', '#title' => t('Blocking mode'), '#markup' => '<div class="messages messages--warning"><p>' . t('You have enabled the COOKiES eTracker submodule, but your "Privacy: Disable cookies" setting is not checked. <br /><strong>COOKiES eTracker will not block anything this way!</strong>') . '</p><p>' . t('With "Disable cookies" unchecked, eTracker uses cookies enabled mode [data-block-cookies="false"]. Uncheck to enable cookie blocking and see COOKiES eTracker advanced options.') . '</p></div>', '#description' => t('Additional options provided by the cookies_etracker submodule for eTracker cookie handling based on COOKiES cookie consent.'), '#states' => [ 'visible' => [ ':input[name="data_block_cookies"]' => ['checked' => FALSE], ], ], ]; $form['#submit'][] = '_cookies_etracker_form_etracker_admin_settings_save'; } /** * Cookies etracker save helper. * * @param array $form * The form array. * @param Drupal\Core\Form\FormStateInterface $form_state * The form state object. */ function _cookies_etracker_form_etracker_admin_settings_save(array &$form, FormStateInterface $form_state): void { $config = \Drupal::service('config.factory')->getEditable('cookies_etracker.settings'); $config->set('knockout_mode', $form_state->getValue('knockout_mode'))->save(); }