You are here

function eu_cookie_compliance_page_attachments in EU Cookie Compliance (GDPR Compliance) 8

Same name and namespace in other branches
  1. 2.0.x eu_cookie_compliance.module \eu_cookie_compliance_page_attachments()

Implements hook_page_attachments().

File

./eu_cookie_compliance.module, line 56
The main file for the EU Cookie Compliance module.

Code

function eu_cookie_compliance_page_attachments(&$variables) {

  // Make the module work better with AMP.
  $activeTheme = \Drupal::service('theme.manager')
    ->getActiveTheme();
  $themeName = $activeTheme
    ->getName();
  $parents_theme = $activeTheme
    ->getBaseThemeExtensions();
  if (!empty($parents_theme) && array_key_exists('amptheme', $parents_theme) || $themeName === "amptheme") {
    return;
  }
  $config = \Drupal::config('eu_cookie_compliance.settings');

  // Check Add/Remove domains.
  $domain_allow = TRUE;
  $domain_option = $config
    ->get('domains_option');
  if (!empty($config
    ->get('domains_list'))) {
    global $base_url;
    $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);
    if ($domain_option && $domain_match) {
      $domain_allow = FALSE;
    }
    if (!$domain_option && !$domain_match) {
      $domain_allow = FALSE;
    }
  }

  // Check exclude paths.
  $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);
  }

  // Check hide cookie compliance on admin theme.
  $admin_theme_match = FALSE;
  if ($config
    ->get('exclude_admin_theme')) {

    // Determines whether the active route is an admin one.
    $is_route_admin = \Drupal::service('router.admin_context')
      ->isAdminRoute();
    if ($is_route_admin) {
      $admin_theme_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();
  }

  // Allow other modules to alter the geo IP matching logic.
  \Drupal::moduleHandler()
    ->alter('eu_cookie_compliance_geoip_match', $geoip_match);

  // Get the site-wide admin role.
  $roles = \Drupal::entityTypeManager()
    ->getStorage('user_role')
    ->loadMultiple();
  $admin_role = [];
  foreach ($roles as $role) {
    if ($role
      ->isAdmin()) {
      $admin_role = $role
        ->id();
      break;
    }
  }
  $uid1_match = TRUE;
  if ((\Drupal::currentUser()
    ->id() == 1 || in_array($admin_role, \Drupal::currentUser()
    ->getRoles())) && !empty($config
    ->get('exclude_uid_1')) && $config
    ->get('exclude_uid_1')) {
    $uid1_match = FALSE;
  }

  // Allow other modules to alter if the banner needs to be shown or not.
  $modules_allow_popup = TRUE;
  \Drupal::moduleHandler()
    ->alter('eu_cookie_compliance_show_popup', $modules_allow_popup);
  $open_by_default = FALSE;
  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) {
    $open_by_default = TRUE;
  }
  $language = \Drupal::languageManager()
    ->getCurrentLanguage();

  // Start building out a cache tag.
  $cid = 'eu_cookie_compliance_data:' . $language
    ->getId();

  // Check if the domain should be added to the cache tag.
  $moduleHandler = \Drupal::service('module_handler');
  if ($moduleHandler
    ->moduleExists('domain') && count(\Drupal::entityTypeManager()
    ->getStorage('domain')
    ->getQuery()
    ->range(0, 1)
    ->execute()) > 0) {
    $cid .= ':' . \Drupal::service('domain.negotiator')
      ->getActiveId();
  }

  // Add the current theme to the cache tag.
  $cid .= ':' . \Drupal::service('theme.manager')
    ->getActiveTheme()
    ->getName();

  // Allow other modules to alter the cache id.
  \Drupal::moduleHandler()
    ->alter('eu_cookie_compliance_cid', $cid);
  if ($cache = \Drupal::cache('render')
    ->get($cid)) {
    $data = $cache->data;
  }
  else {
    $data = eu_cookie_compliance_build_data();
    \Drupal::cache('render')
      ->set($cid, $data, Cache::PERMANENT, $config
      ->getCacheTags());
  }
  $variables['#attached']['drupalSettings']['eu_cookie_compliance'] = $data['variables'];
  $variables['#attached']['drupalSettings']['eu_cookie_compliance']['open_by_default'] = $open_by_default;
  $variables['#attached']['library'][] = 'eu_cookie_compliance/eu_cookie_compliance_' . ($config
    ->get('use_bare_css') ? 'bare' : 'default');

  // Add inline javascript.
  $disabled_javascripts = $config
    ->get('disabled_javascripts');
  $load_disabled_scripts = '';

  // Initialize a variable to keep libraries to we wish to disable.
  $libraries_to_disable = [];
  if ($disabled_javascripts != '') {
    $load_disabled_scripts = '';
    $disabled_javascripts = _eu_cookie_compliance_explode_multiple_lines($disabled_javascripts);
    $disabled_javascripts = array_filter($disabled_javascripts, 'strlen');
    foreach ($disabled_javascripts as $key => $script) {
      $parts = explode('%3A', $script);
      $category = NULL;
      if (count($parts) > 1) {
        $category = array_shift($parts);
        $script = implode(':', $parts);
      }

      // Split the string if a | is present.
      // The second parameter (after the |) will be used to trigger a script
      // attach.
      $attach_name = '';
      if (strpos($script, '%7C') !== FALSE) {

        // Swallow a notice in case there are no behavior or library names.
        @(list($script, $attach_name, $library_name) = explode('%7C', $script));

        // Store the library name.
        if ($library_name) {
          $libraries_to_disable[] = $library_name;
        }
      }
      _eu_cookie_compliance_convert_relative_uri($script);
      if (strpos($script, 'http') !== 0 && strpos($script, '//') !== 0) {
        $script = '/' . $script;
      }

      // Store the actual script name, since we will need it later.
      $disabled_javascripts[$key] = $script;
      if ($category) {
        $load_disabled_scripts .= 'if (category === "' . $category . '") {';
      }
      $load_disabled_scripts .= 'var scriptTag = document.createElement("script");';
      $load_disabled_scripts .= 'scriptTag.src = ' . Json::encode($script) . ';';
      $load_disabled_scripts .= 'document.body.appendChild(scriptTag);';

      // The script will not immediately load, so we need to trigger the
      // attach in an interval function.
      if ($attach_name) {
        $load_disabled_scripts .= 'var EUCookieInterval' . $attach_name . '= setInterval(function() { if (Drupal.behaviors.' . $attach_name . ' !== undefined) { Drupal.behaviors.' . $attach_name . '.attach(document, drupalSettings);clearInterval(EUCookieInterval' . $attach_name . ')};}, 100);';
      }
      if ($category) {
        $load_disabled_scripts .= '}';
      }
    }
  }
  if ($load_disabled_scripts) {
    $variables['#attached']['html_head'][] = [
      [
        '#type' => 'html_tag',
        '#tag' => 'script',
        '#value' => 'window.euCookieComplianceLoadScripts = function(category) {' . $load_disabled_scripts . '}',
      ],
      'eu-cookie-compliance-js',
    ];
  }

  // Add inline css.
  if (!empty($data['css'])) {
    $variables['#attached']['html_head'][] = [
      [
        '#tag' => 'style',
        '#value' => $data['css'],
      ],
      'eu-cookie-compliance-css',
    ];
  }
  $cache_tags = isset($variables['#cache']['tags']) ? $variables['#cache']['tags'] : [];
  $variables['#cache']['tags'] = Cache::mergeTags($cache_tags, $config
    ->getCacheTags());
  $category_cache_tags = \Drupal::entityTypeManager()
    ->getStorage('cookie_category')
    ->getEntityType()
    ->getListCacheTags();
  $variables['#cache']['tags'] = Cache::mergeTags($variables['#cache']['tags'], $category_cache_tags);
  if (!empty($disabled_javascripts)) {

    // Check if disabled scripts are in page html_head.
    $disabled_javascripts = array_filter($disabled_javascripts);
    foreach ($variables['#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 (strpos($src, 'http') !== 0 && strpos($src, '//') !== 0) {
        $src = '/' . $src;
      }
      if (in_array($src, $disabled_javascripts)) {
        $variables['#attached']['html_head'][$index][0]['#access'] = FALSE;
      }
    }

    // Remove libraries if they match the ones that we want to exclude.
    foreach ($variables['#attached']['library'] as $index => $library) {
      if (in_array($library, $libraries_to_disable)) {
        unset($variables['#attached']['library'][$index]);
      }
    }
  }
}