Updated all the contrib modules to their latest versions.
[yaffs-website] / web / modules / contrib / eu_cookie_compliance / eu_cookie_compliance.module
index e2421377b79cbfaee6b2596310583519a5fe06a2..b7e2aa7191002738418e03cbea5603506c1dda17 100644 (file)
@@ -16,6 +16,8 @@ use Drupal\Component\Utility\Html;
 use Drupal\Core\Routing\RouteMatchInterface;
 use Drupal\smart_ip\SmartIp;
 use Drupal\Core\Database\Database;
+use Drupal\Core\Asset\AttachedAssetsInterface;
+use Drupal\Component\Serialization\Json;
 
 /**
  * Implements hook_help().
@@ -25,15 +27,9 @@ function eu_cookie_compliance_help($route_name, RouteMatchInterface $route_match
     case 'help.page.eu_cookie_compliance':
       $output = '';
       $output .= '<h3>' . t('About') . '</h3>';
-      $output .= '<p>' . t('This module intends to deal with the EU Directive on Privacy and Electronic Communications that comes into effect on 26th May 2012.
-        From that date, if you are not compliant or visibly working towards compliance,
-        you run the risk of enforcement action, which can include a fine of up to
-        half a million pounds for a serious breach.') . '</p>';
+      $output .= '<p>' . t('This module intends to deal with the EU Directive on Privacy and Electronic Communications that comes into effect on 26th May 2012. From that date, if you are not compliant or visibly working towards compliance, you run the risk of enforcement action, which can include a fine of up to half a million pounds for a serious breach.') . '</p>';
       $output .= '<h3>' . t('How it works') . '</h3>';
-      $output .= '<p>' . t('The module displays a banner at the bottom or the top of website to make users aware of the fact that cookies are being set. The user may then give
-        his/her consent or move to a page that provides more details. Consent is given
-        by user pressing the agree buttons or by continuing browsing the website. Once
-        consent is given another banner appears with a “Thank you” message.') . '</p>';
+      $output .= '<p>' . t('The module displays a banner at the bottom or the top of website to make users aware of the fact that cookies are being set. The user may then give his/her consent or move to a page that provides more details. Consent is given by user pressing the agree buttons or by continuing browsing the website. Once consent is given another banner appears with a "Thank you" message.') . '</p>';
       $output .= '<p>' . t('The module provides a settings page where the banner can be customized. There are also template files for the banners that can be overridden by your theme.') . '</p>';
       $output .= '<h3>' . t('Installation') . '</h3>';
       $output .= '<ol><p><li>' . t('Unzip the files to the "sites/all/modules" OR "modules" directory and enable the module.') . '</li></p>';
@@ -67,7 +63,7 @@ function eu_cookie_compliance_page_attachments(&$attachments) {
   if (!empty($config->get('domains_list'))) {
     global $base_url;
 
-    $domains_list = str_replace(array("\r\n", "\r"), "\n", $config->get('domains_list'));
+    $domains_list = str_replace(["\r\n", "\r"], "\n", $config->get('domains_list'));
     $domains_list = explode("\n", $domains_list);
     $domains_list = preg_replace('{/$}', '', $domains_list);
     $domain_match = in_array($base_url, $domains_list);
@@ -85,8 +81,12 @@ function eu_cookie_compliance_page_attachments(&$attachments) {
   $path_match = FALSE;
 
   if (!empty($config->get('exclude_paths'))) {
+    // Check both the URL path and the URL alias against the list to exclude.
     $path = Drupal::service('path.current')->getPath();
+    $url_alias_path = \Drupal::service('path.alias_manager')->getAliasByPath($path);
     $path_match = Drupal::service('path.matcher')->matchPath($path, $config->get('exclude_paths'));
+    $path_match_url_alias = Drupal::service('path.matcher')->matchPath($url_alias_path, $config->get('exclude_paths'));
+    $path_match = $path_match || $path_match_url_alias;
     $exclude_paths = $config->get('exclude_paths');
     Drupal::moduleHandler()->alter('eu_cookie_compliance_path_match', $path_match, $path, $exclude_paths);
   }
@@ -102,7 +102,7 @@ function eu_cookie_compliance_page_attachments(&$attachments) {
     }
   }
 
-  $geoip_match = TRUE;
+  $geoip_match = ['in_eu' => TRUE];
   if (!empty($config->get('eu_only')) && $config->get('eu_only')) {
     $geoip_match = eu_cookie_compliance_user_in_eu();
   }
@@ -119,39 +119,93 @@ function eu_cookie_compliance_page_attachments(&$attachments) {
   $modules_allow_popup = TRUE;
   Drupal::moduleHandler()->alter('eu_cookie_compliance_show_popup', $modules_allow_popup);
 
-  if ($config->get('popup_enabled') && Drupal::currentUser()->hasPermission('display eu cookie compliance popup') && $geoip_match && $domain_allow && !$path_match && !$admin_theme_match && $uid1_match && $modules_allow_popup) {
+  if ($config->get('popup_enabled') && Drupal::currentUser()->hasPermission('display eu cookie compliance popup') && $geoip_match['in_eu'] && $domain_allow && !$path_match && !$admin_theme_match && $uid1_match && $modules_allow_popup) {
     $language = Drupal::languageManager()->getCurrentLanguage();
 
     $data['css'] = '';
     // Color overrides.
     if ($config->get('popup_bg_hex') !== '' && $config->get('popup_text_hex') !== '') {
-      $data['css'] = 'div#sliding-popup {background:#' . Html::escape($config->get('popup_bg_hex')) . '} #sliding-popup h1, #sliding-popup h2, #sliding-popup h3, #sliding-popup p { color:#' . Html::escape($config->get('popup_text_hex')) . ';}';
+      $data['css'] = 'div#sliding-popup, div#sliding-popup .eu-cookie-withdraw-banner, .eu-cookie-withdraw-tab {background: #' . Html::escape($config->get('popup_bg_hex')) . '} div#sliding-popup.eu-cookie-withdraw-wrapper { background: transparent; } #sliding-popup h1, #sliding-popup h2, #sliding-popup h3, #sliding-popup p, .eu-cookie-compliance-more-button, .eu-cookie-compliance-secondary-button, .eu-cookie-withdraw-tab { color: #' . Html::escape($config->get('popup_text_hex')) . ';} .eu-cookie-withdraw-tab { border-color: #' . Html::escape($config->get('popup_text_hex')) . ';}';
     }
     if (!empty($config->get('popup_position')) && $config->get('popup_position') && !empty($config->get('fixed_top_position')) && $config->get('fixed_top_position')) {
       $data['css'] .= '#sliding-popup.sliding-popup-top { position: fixed; }';
     }
 
-    $popup_text_info = str_replace(array("\r", "\n"), '', $config->get('popup_info.value'));
-    $popup_text_agreed = str_replace(array("\r", "\n"), '', $config->get('popup_agreed.value'));
-    $html_info = array(
+    $method = $config->get('method');
+
+    if ($method == 'auto') {
+      $dnt = isset($_SERVER['HTTP_DNT']) ? $_SERVER['HTTP_DNT'] : NULL;
+      if ((int) $dnt === 0 && $dnt !== NULL) {
+        $method = 'default';
+      }
+      else {
+        $method = 'opt_in';
+      }
+    }
+
+    switch ($method) {
+      case 'default':
+        $click_confirmation = $config->get('popup_clicking_confirmation');
+        $scroll_confirmation = $config->get('popup_scrolling_confirmation');
+        $primary_button_label = $config->get('popup_agree_button_message');
+        $primary_button_class = 'agree-button eu-cookie-compliance-default-button';
+        $secondary_button_label = '';
+        $secondary_button_class = '';
+        break;
+
+      case 'opt_in':
+        $click_confirmation = FALSE;
+        $scroll_confirmation = FALSE;
+        $primary_button_label = $config->get('popup_agree_button_message');
+        $primary_button_class = 'agree-button eu-cookie-compliance-secondary-button';
+        $secondary_button_label = $config->get('disagree_button_label');
+        $secondary_button_class = 'decline-button eu-cookie-compliance-default-button';
+        break;
+
+      case 'opt_out':
+        $click_confirmation = FALSE;
+        $scroll_confirmation = FALSE;
+        $primary_button_label = $config->get('disagree_button_label');
+        $primary_button_class = 'decline-button eu-cookie-compliance-secondary-button';
+        $secondary_button_label = $config->get('popup_agree_button_message');
+        $secondary_button_class = 'agree-button eu-cookie-compliance-default-button';
+        break;
+    }
+
+    $popup_text_info = str_replace(["\r", "\n"], '', $config->get('popup_info.value'));
+    $popup_text_agreed = str_replace(["\r", "\n"], '', $config->get('popup_agreed.value'));
+    $withdraw_markup = str_replace(["\r", "\n"], '', $config->get('withdraw_message.value'));
+    $html_info = [
       '#theme' => 'eu_cookie_compliance_popup_info',
       '#message' => check_markup($popup_text_info, $config->get('popup_info.format'), FALSE),
-      '#agree_button' => $config->get('popup_agree_button_message'),
+      '#agree_button' => $primary_button_label,
       '#disagree_button' => ($config->get('show_disagree_button') == TRUE) ? $config->get('popup_disagree_button_message') : FALSE,
-    );
-    $mobile_popup_text_info = str_replace(array("\r", "\n"), '', $config->get('mobile_popup_info.value'));
-    $mobile_html_info = array(
+      '#secondary_button_label' => $secondary_button_label,
+      '#primary_button_class' => $primary_button_class,
+      '#secondary_button_class' => $secondary_button_class,
+    ];
+    $mobile_popup_text_info = str_replace(["\r", "\n"], '', $config->get('mobile_popup_info.value'));
+    $mobile_html_info = [
       '#theme' => 'eu_cookie_compliance_popup_info',
       '#message' => check_markup($mobile_popup_text_info, $config->get('popup_info.format'), FALSE),
-      '#agree_button' => $config->get('popup_agree_button_message'),
+      '#agree_button' => $primary_button_label,
       '#disagree_button' => ($config->get('show_disagree_button') == TRUE) ? $config->get('popup_disagree_button_message') : FALSE,
-    );
-    $html_agreed = array(
+      '#secondary_button_label' => $secondary_button_label,
+      '#primary_button_class' => $primary_button_class,
+      '#secondary_button_class' => $secondary_button_class,
+    ];
+    $html_agreed = [
       '#theme' => 'eu_cookie_compliance_popup_agreed',
       '#message' => check_markup($popup_text_agreed, $config->get('popup_agreed.format'), FALSE),
       '#hide_button' => $config->get('popup_hide_button_message'),
       '#find_more_button' => ($config->get('show_disagree_button') == TRUE) ? $config->get('popup_find_more_button_message') : FALSE,
-    );
+    ];
+    $withdraw_markup = [
+      '#theme' => 'eu_cookie_compliance_withdraw',
+      '#message' => check_markup($withdraw_markup, $config->get('withdraw_message.format'), FALSE),
+      '#withdraw_tab_button_label' => $config->get('withdraw_tab_button_label'),
+      '#withdraw_action_button_label' => $config->get('withdraw_action_button_label'),
+    ];
 
     $was_debugging = FALSE;
 
@@ -168,6 +222,7 @@ function eu_cookie_compliance_page_attachments(&$attachments) {
     $html_info = trim(Drupal::service('renderer')->renderRoot($html_info)->__toString());
     $mobile_html_info = trim(Drupal::service('renderer')->renderRoot($mobile_html_info)->__toString());
     $html_agreed = trim(Drupal::service('renderer')->renderRoot($html_agreed)->__toString());
+    $withdraw_markup = trim(Drupal::service('renderer')->renderRoot($withdraw_markup)->__toString());
 
     if ($was_debugging) {
       $twig_service->enableDebug();
@@ -178,17 +233,21 @@ function eu_cookie_compliance_page_attachments(&$attachments) {
       $popup_link = Url::fromUri($popup_link);
     }
     else {
+      // Guard against translations being entered without leading slash.
+      if (substr( $popup_link, 0, 1) != '/' && substr( $popup_link, 0, 1) != '?' && substr( $popup_link, 0, 1) != '#') {
+        $popup_link = '/' . $popup_link;
+      }
       $popup_link = $popup_link === '<front>' ? '/' : $popup_link;
       $popup_link = Url::fromUserInput($popup_link);
     }
     $popup_link = $popup_link->toString();
 
-    $data['variables'] = array(
+    $data['variables'] = [
       'popup_enabled'        => $config->get('popup_enabled'),
       'popup_agreed_enabled' => $config->get('popup_agreed_enabled'),
       'popup_hide_agreed'    => $config->get('popup_hide_agreed'),
-      'popup_clicking_confirmation' => $config->get('popup_clicking_confirmation'),
-      'popup_scrolling_confirmation' => $config->get('popup_scrolling_confirmation'),
+      'popup_clicking_confirmation' => $click_confirmation,
+      'popup_scrolling_confirmation' => $scroll_confirmation,
       'popup_html_info'      => $config->get('popup_enabled') ? $html_info : FALSE,
       'use_mobile_message'   => !empty($config->get('use_mobile_message')) ? $config->get('use_mobile_message') : FALSE,
       'mobile_popup_html_info' => $config->get('popup_enabled') ? $mobile_html_info : FALSE,
@@ -202,14 +261,20 @@ function eu_cookie_compliance_page_attachments(&$attachments) {
       'popup_link_new_window' => $config->get('popup_link_new_window'),
       'popup_position'       => $config->get('popup_position'),
       'popup_language'       => $language->getId(),
+      'store_consent'        => $config->get('consent_storage_method') != 'do_not_store',
       'better_support_for_screen_readers'         => !empty($config->get('better_support_for_screen_readers')) ? $config->get('better_support_for_screen_readers') : FALSE,
-      'cookie_name'         => !empty($config->get('cookie_name')) ? $config->get('cookie_name') : '',
-      'reload_page'         => !empty($config->get('reload_page')) ? $config->get('reload_page') : FALSE,
+      'cookie_name'          => !empty($config->get('cookie_name')) ? $config->get('cookie_name') : '',
+      'reload_page'          => !empty($config->get('reload_page')) ? $config->get('reload_page') : FALSE,
       'domain'               => $config->get('domain'),
       'popup_eu_only_js'     => !empty($config->get('eu_only_js')) ? $config->get('eu_only_js') : FALSE,
       'cookie_lifetime'      => $config->get('cookie_lifetime'),
-      'disagree_do_not_show_popup'         => !empty($config->get('disagree_do_not_show_popup')) ? $config->get('disagree_do_not_show_popup') : FALSE,
-    );
+      'cookie_session'       => $config->get('cookie_session'),
+      'disagree_do_not_show_popup' => !empty($config->get('disagree_do_not_show_popup')) ? $config->get('disagree_do_not_show_popup') : FALSE,
+      'method'               => $method,
+      'whitelisted_cookies'  => !empty($config->get('whitelisted_cookies')) ? $config->get('whitelisted_cookies') : '',
+      'withdraw_markup'      => $withdraw_markup,
+      'withdraw_enabled'     => $config->get('withdraw_enabled'),
+    ];
 
     $attachments['#attached']['drupalSettings']['eu_cookie_compliance'] = $data['variables'];
     if ($config->get('use_bare_css')) {
@@ -218,6 +283,31 @@ function eu_cookie_compliance_page_attachments(&$attachments) {
     else {
       $attachments['#attached']['library'][] = 'eu_cookie_compliance/eu_cookie_compliance';
     }
+    // Add inline javascript.
+    $disabled_javascripts = $config->get('disabled_javascripts');
+    $load_disabled_scripts = '';
+    if ($disabled_javascripts != '') {
+      $load_disabled_scripts = '';
+      $disabled_javascripts = _eu_cookie_compliance_explode_multiple_lines($disabled_javascripts);
+      foreach ($disabled_javascripts as $script) {
+        if (substr($script, 0, 4) !== 'http' && substr($script, 0, 2) !== '//') {
+          $script = '/' . $script;
+        }
+        $load_disabled_scripts .= 'var scriptTag = document.createElement("script");';
+        $load_disabled_scripts .= 'scriptTag.src = ' . Json::encode($script) . ';';
+        $load_disabled_scripts .= 'document.body.appendChild(scriptTag);';
+      }
+    }
+
+    $attachments['#attached']['html_head'][] = [
+      [
+        '#type' => 'html_tag',
+        '#tag' => 'script',
+        '#value' => 'function euCookieComplianceLoadScripts() {' . $load_disabled_scripts . '}',
+      ],
+      'eu-cookie-compliance-js',
+    ];
+
     // Add inline css.
     $attachments['#attached']['html_head'][] = [
       [
@@ -228,6 +318,27 @@ function eu_cookie_compliance_page_attachments(&$attachments) {
     ];
     $cache_tags = isset($attachments['#cache']['tags']) ? $attachments['#cache']['tags'] : [];
     $attachments['#cache']['tags'] = Cache::mergeTags($cache_tags, $config->getCacheTags());
+
+    // Check if disabled scripts are in page html_head.
+    $disabled_javascripts = $config->get('disabled_javascripts');
+    $disabled_javascripts = _eu_cookie_compliance_explode_multiple_lines($disabled_javascripts);
+    $disabled_javascripts = array_filter($disabled_javascripts);
+
+    if (!empty($disabled_javascripts)) {
+      foreach ($attachments['#attached']['html_head'] as $index => $asset) {
+        $is_script = !empty($asset[0]['#type']) && $asset[0]['#type'] == 'html_tag' && $asset[0]['#tag'] == 'script';
+        $is_src = !empty($asset[0]['#attributes']['src']);
+        if (!$is_script || !$is_src) {
+          continue;
+        }
+        $src = $asset[0]['#attributes']['src'];
+        $src = preg_replace('/\.js\?[^"]+/', '.js', $src);
+        $src = preg_replace('/^\//', '', $src);
+        if (in_array($src, $disabled_javascripts)) {
+          $attachments['#attached']['html_head'][$index][0]['#access'] = FALSE;
+        }
+      }
+    }
   }
 }
 
@@ -235,24 +346,35 @@ function eu_cookie_compliance_page_attachments(&$attachments) {
  * Implements hook_theme().
  */
 function eu_cookie_compliance_theme($existing, $type, $theme, $path) {
-  return array(
-    'eu_cookie_compliance_popup_info' => array(
+  return [
+    'eu_cookie_compliance_popup_info' => [
       'template' => 'eu_cookie_compliance_popup_info',
-      'variables' => array(
+      'variables' => [
         'message' => NULL,
         'agree_button' => NULL,
         'disagree_button' => NULL,
-      ),
-    ),
-    'eu_cookie_compliance_popup_agreed' => array(
+        'secondary_button_label' => NULL,
+        'primary_button_class' => NULL,
+        'secondary_button_class' => NULL,
+      ],
+    ],
+    'eu_cookie_compliance_popup_agreed' => [
       'template' => 'eu_cookie_compliance_popup_agreed',
-      'variables' => array(
+      'variables' => [
         'message' => NULL,
         'hide_button' => NULL,
         'find_more_button' => NULL,
-      ),
-    ),
-  );
+      ],
+    ],
+    'eu_cookie_compliance_withdraw' => [
+      'template' => 'eu_cookie_compliance_withdraw',
+      'variables' => [
+        'withdraw_tab_button_label' => NULL,
+        'message' => NULL,
+        'withdraw_action_button_label' => NULL,
+      ],
+    ],
+  ];
 }
 
 /**
@@ -263,9 +385,9 @@ function eu_cookie_compliance_theme($existing, $type, $theme, $path) {
  * @param \Drupal\Core\Form\FormStateInterface $form_state
  *   Form State Interface.
  */
-function eu_cookie_compliance_validate_hex($element, FormStateInterface &$form_state) {
+function eu_cookie_compliance_validate_hex(array $element, FormStateInterface &$form_state) {
   if (!empty($element['#value']) && !preg_match('/^[0-9a-fA-F]{3,6}$/', $element['#value'])) {
-    $form_state->setError($element, t('%name must be a HEX value (without leading #) or empty.', array('%name' => $element['#title'])));
+    $form_state->setError($element, t('%name must be a HEX value (without leading #) or empty.', ['%name' => $element['#title']]));
   }
 }
 
@@ -274,11 +396,11 @@ function eu_cookie_compliance_validate_hex($element, FormStateInterface &$form_s
  */
 function eu_cookie_compliance_user_in_eu() {
   $geoip_match = FALSE;
-  $eu_countries_default = array(
+  $eu_countries_default = [
     NULL, 'BE', 'BG', 'CZ', 'DK', 'DE', 'EE', 'IE', 'EL', 'ES', 'FR', 'HR',
     'IT', 'CY', 'LV', 'LT', 'LU', 'HU', 'MT', 'NL', 'AT', 'PL', 'PT', 'RO',
     'SI', 'SK', 'FI', 'SE', 'UK', 'GB', 'NO',
-  );
+  ];
   // Allow custom array of countries to be loaded from settings.php, defaulting
   // to the array above.
   $config = Drupal::config('eu_cookie_compliance.settings');
@@ -295,10 +417,43 @@ function eu_cookie_compliance_user_in_eu() {
     $geoip_match = TRUE;
   }
 
-  return array(
+  return [
     'country' => $country_code,
     'in_eu' => $geoip_match,
-  );
+  ];
+}
+
+/**
+ * Implements hook_js_alter().
+ */
+function eu_cookie_compliance_js_alter(&$javascript, AttachedAssetsInterface $assets) {
+  $config = Drupal::config('eu_cookie_compliance.settings');
+  $disabled_javascripts = $config->get('disabled_javascripts');
+  $disabled_javascripts = _eu_cookie_compliance_explode_multiple_lines($disabled_javascripts);
+
+  foreach ($disabled_javascripts as $script) {
+    unset($javascript[$script]);
+  }
+}
+
+/**
+ * Splits a return delimited text string into an array.
+ *
+ * @param string $text
+ *   Text to split.
+ *
+ * @return array
+ *   Text split into an array.
+ */
+function _eu_cookie_compliance_explode_multiple_lines($text) {
+  $text = explode("\r\n", $text);
+  if (count($text) == 1) {
+    $text = explode("\r", $text[0]);
+  }
+  if (count($text) == 1) {
+    $text = explode("\n", $text[0]);
+  }
+  return $text;
 }
 
 /**
@@ -308,6 +463,10 @@ function eu_cookie_compliance_user_in_eu() {
  *   URL to the node if found, otherwise FALSE.
  */
 function _eu_cookie_compliance_find_privacy_policy() {
+  if (!\Drupal::entityTypeManager()->hasDefinition('node')) {
+    return FALSE;
+  }
+
   $pattern = 'privacy|privacy +policy|cookie +policy|terms +of +use|terms +of +service|terms +and +conditions';
 
   $connection = Database::getConnection();
@@ -334,3 +493,22 @@ function _eu_cookie_compliance_find_privacy_policy() {
   }
   return FALSE;
 }
+
+/**
+ * Helper function to set module weight.
+ */
+function eu_cookie_compliance_module_set_weight() {
+  $weight = 1;
+  $exclude_modules = [
+    'eu_cookie_compliance',
+  ];
+
+  $extension_config = \Drupal::configFactory()->get('core.extension');
+  // Loop through all installed modules to find the highest weight.
+  foreach ($extension_config->get('module') as $module_name => $module_weight) {
+    if ($module_weight > $weight && !in_array($module_name, $exclude_modules)) {
+      $weight = $module_weight + 1;
+    }
+  }
+  module_set_weight('eu_cookie_compliance', $weight);
+}