iframe_consent-1.0.x-dev/src/Service/IframeConsentHelper.php

src/Service/IframeConsentHelper.php
<?php

namespace Drupal\iframe_consent\Service;

use Drupal\Component\Utility\UrlHelper;
use Drupal\Core\Cache\CacheTagsInvalidatorInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Template\Attribute;
use Drupal\iframe_consent\IframeConsentDomainInterface;

/**
 * Class to handle iframe consent logic.
 *
 * @package Drupal\iframe_consent\Service
 */
class IframeConsentHelper implements IframeConsentHelperInterface {

  /**
   * The iframe consent settings.
   *
   * @var \Drupal\iframe_consent\Service\IframeConsentSettingsInterface
   */
  public $settings;

  /**
   * The entity type manager service.
   *
   * @var \Drupal\Core\Entity\EntityTypeManagerInterface
   */
  public $entityTypeManager;

  /**
   * The cache tags invalidator service.
   *
   * @var \Drupal\Core\Cache\CacheTagsInvalidatorInterface
   */
  protected $cacheTagsInvalidator;

  /**
   * Constructor.
   *
   * @param \Drupal\iframe_consent\Service\IframeConsentSettingsInterface $settings
   *   The iframe consent settings service.
   * @param \Drupal\Core\Cache\CacheTagsInvalidatorInterface $cacheTagsInvalidator
   *   The cache tags invalidator service.
   * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entityTypeManager
   *   The entity type manager service.
   */
  public function __construct(IframeConsentSettingsInterface $settings, CacheTagsInvalidatorInterface $cacheTagsInvalidator, EntityTypeManagerInterface $entityTypeManager) {
    $this->settings = $settings;
    $this->cacheTagsInvalidator = $cacheTagsInvalidator;
    $this->entityTypeManager = $entityTypeManager->getStorage('iframe_consent_domains');
  }

  /**
   * Add consent categories to iframe attributes.
   *
   * @param array $iframe_attributes
   *   The iframe attributes.
   *
   * @return void
   *   The modified iframe attributes.
   */
  private function addConsentCategories(array &$iframe_attributes): void {
    $domain = $this->cleanUri($iframe_attributes['src']) ?? '';
    $consent_groups = $this->getConsentGroupsByUri($domain);

    if (!empty($consent_groups)) {
      $consent_groups_keys = array_keys($consent_groups);
      $iframe_attributes['data-required-consents'] = implode(',', $consent_groups_keys);
    }
  }

  /**
   * Add the facade template type to iframe attributes.
   *
   * @param array $iframe_attributes
   *   The iframe attributes.
   *
   * @return void
   *   The modified iframe attributes.
   */
  private function addFacadeTemplate(array &$iframe_attributes): void {
    $src = $iframe_attributes['src'] ?? '';
    $domain = $this->cleanUri($src);
    $iframe_attributes['data-placeholder-template'] = $this->getTemplateIdByDomain($domain);
    $iframe_attributes['data-hash'] = md5($src);
  }

  /**
   * {@inheritdoc}
   */
  public function alterIframeAttributes(Attribute|array $iframe_attributes): Attribute|array {
    $is_array = TRUE;
    $attributes_array = $iframe_attributes;

    if ($attributes_array instanceof Attribute) {
      $attributes_array = $attributes_array->toArray();
      $is_array = FALSE;
    }

    $this->addConsentCategories($attributes_array);
    $this->addFacadeTemplate($attributes_array);
    $this->obfuscateSrc($attributes_array);
    $attributes_array['class'][] = 'iframe-consent';

    if (!$is_array) {
      $iframe_attributes = new Attribute($attributes_array);
    }

    return $iframe_attributes;
  }

  /**
   * {@inheritdoc}
   */
  public function attachLibraries(array &$build): void {
    $provider = $this->settings->getProvider();

    if (!$provider) {
      return;
    }

    $build['#attached']['library'][] = sprintf('iframe_consent/%s', $provider);
    $build['#attached']['drupalSettings']['iframeConsent']['consentGroups'] = $this->settings->getConsentGroupsList();
  }

  /**
   * {@inheritdoc}
   */
  public function cleanUri(string $uri): string {
    $domain = UrlHelper::filterBadProtocol($uri);
    $domain_parts = parse_url($domain);
    if (empty($domain_parts['host'])) {
      return '';
    }

    $scheme = $domain_parts['scheme'] ?? 'https';
    $sanitized_domain = $scheme . '://' . $domain_parts['host'];

    if (UrlHelper::isValid($sanitized_domain, TRUE)) {
      return $sanitized_domain;
    }

    return '';
  }

  /**
   * {@inheritdoc}
   */
  public function clearCacheTags(): void {
    $this->cacheTagsInvalidator->invalidateTags(['iframe_consent']);
  }

  /**
   * {@inheritdoc}
   */
  public function getDomainByTemplateId(string $template_id): string {
    // Sanitize the template ID to create a valid domain.
    $domain = str_replace('___', '://', $template_id);
    $domain = str_replace('_', '.', $domain);

    return $this->cleanUri($domain);
  }

  /**
   * {@inheritdoc}
   */
  public function getDomainConsentGroups(IframeConsentDomainInterface $entity): array {
    $consent_groups = [];

    $consent_groups_ids = $entity->get('consent_groups')->getValue();
    foreach ($consent_groups_ids as $value) {
      $key = $value['value'];
      $consent_groups[$key] = $this->settings->getConsentGroupLabelById($value['value']);
    }

    return $consent_groups;
  }

  /**
   * {@inheritdoc}
   */
  public function getConsentGroupsByUri(string $uri): array {
    $domain_entity = $this->loadDomainByUri($uri);
    $consent_groups = [];

    if (!$domain_entity) {
      return $consent_groups;
    }

    return $this->getDomainConsentGroups($domain_entity);
  }

  /**
   * {@inheritdoc}
   */
  public function getTemplateIdByDomain(string $domain): string {
    if (!$domain) {
      return 'default';
    }

    // Sanitize the domain to create a valid template ID.
    $template_id = str_replace('://', '___', $domain);
    $template_id = str_replace('.', '_', $template_id);
    return $template_id;
  }

  /**
   * {@inheritdoc}
   */
  public function getTemplatesList() : array {
    $template_ids = [];

    if (!$this->settings->get('templates_by_domain')) {
      return $template_ids;
    }

    $domains = $this->entityTypeManager->getQuery()
      ->accessCheck(TRUE)
      ->range(0, 50)
      ->execute();

    foreach ($domains as $domain) {
      $entity = $this->entityTypeManager->load($domain);
      if (!$entity instanceof IframeConsentDomainInterface) {
        continue;
      }
      $template_id = $this->getTemplateIdByDomain($entity->get('domain')->value);
      if (!in_array($template_id, $template_ids)) {
        $template_ids[] = $template_id;
      }
    }

    return $template_ids;
  }

  /**
   * {@inheritdoc}
   */
  public function isInDomainsList(string $uri): bool {
    $domain = $this->cleanUri($uri);

    if (empty($domain)) {
      return FALSE;
    }

    // Check if the domain is in the list of domains.
    $domains_count = $this->entityTypeManager->getQuery()
      ->accessCheck(TRUE)
      ->condition('domain', $domain)
      ->count()
      ->execute();

    if (empty($domains_count)) {
      return FALSE;
    }

    return TRUE;
  }

  /**
   * {@inheritdoc}
   */
  public function isGroupsInUse(string $id): bool {
    $domains_mapping = $this->entityTypeManager->getQuery()
      ->accessCheck(TRUE)
      ->condition('consent_groups', $id)
      ->count()
      ->execute();

    if ($domains_mapping > 0) {
      return TRUE;
    }

    return FALSE;
  }

  /**
   * {@inheritdoc}
   */
  public function loadDomainByUri(string $uri): IframeConsentDomainInterface|NULL {
    $domain = $this->cleanUri($uri);

    if (empty($domain)) {
      return NULL;
    }

    $result = $this->entityTypeManager->loadByProperties(['domain' => $domain]);
    return !empty($result) ? reset($result) : NULL;
  }

  /**
   * Obfuscate the src attribute of the iframe.
   *
   * @param array $iframe_attributes
   *   The iframe attributes.
   *
   * @return void
   *   The modified iframe attributes.
   */
  private function obfuscateSrc(array &$iframe_attributes): void {
    if (isset($iframe_attributes['src']) && !empty($iframe_attributes['src'])) {
      $iframe_attributes['data-src'] = $iframe_attributes['src'];
      $iframe_attributes['src'] = '';
    }
  }

  /**
   * {@inheritdoc}
   */
  public function setCacheTags(array &$build): void {
    $build['#cache']['tags'][] = 'iframe_consent';
  }

}

Главная | Обратная связь

drupal hosting | друпал хостинг | it patrol .inc