google_tag-8.x-1.x-dev/src/TagContainerResolver.php
src/TagContainerResolver.php
<?php declare(strict_types=1); namespace Drupal\google_tag; use Drupal\Component\Plugin\Exception\ContextException; use Drupal\Component\Plugin\Exception\MissingValueContextException; use Drupal\Core\Condition\ConditionAccessResolverTrait; use Drupal\Core\Entity\EntityTypeManagerInterface; use Drupal\Core\Plugin\Context\ContextHandlerInterface; use Drupal\Core\Plugin\Context\ContextRepositoryInterface; use Drupal\Core\Plugin\ContextAwarePluginInterface; use Drupal\google_tag\Entity\TagContainer; use Symfony\Component\HttpFoundation\RequestStack; /** * Resolves google tag config based on requests. */ final class TagContainerResolver { use ConditionAccessResolverTrait; /** * Special object storage to store google tag entity per request. * * @var \SplObjectStorage * * @phpstan-var \SplObjectStorage<\Symfony\Component\HttpFoundation\Request, TagContainer|null> */ private \SplObjectStorage $resolved; /** * The Request Stack Service. * * @var \Symfony\Component\HttpFoundation\RequestStack */ private RequestStack $requestStack; /** * The Entity Type Manager. * * @var \Drupal\Core\Entity\EntityTypeManagerInterface */ private EntityTypeManagerInterface $entityTypeManager; /** * The Context Repository Service. * * @var \Drupal\Core\Plugin\Context\ContextRepositoryInterface */ private ContextRepositoryInterface $contextRepository; /** * The Context Handler. * * @var \Drupal\Core\Plugin\Context\ContextHandlerInterface */ private ContextHandlerInterface $contextHandler; /** * GoogleTagResolver constructor. * * @param \Symfony\Component\HttpFoundation\RequestStack $requestStack * Request stack. * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entityTypeManager * Entity type manager. * @param \Drupal\Core\Plugin\Context\ContextRepositoryInterface $contextRepository * Context repository. * @param \Drupal\Core\Plugin\Context\ContextHandlerInterface $contextHandler * Context handler. */ public function __construct(RequestStack $requestStack, EntityTypeManagerInterface $entityTypeManager, ContextRepositoryInterface $contextRepository, ContextHandlerInterface $contextHandler) { $this->requestStack = $requestStack; $this->entityTypeManager = $entityTypeManager; $this->contextRepository = $contextRepository; $this->contextHandler = $contextHandler; $this->resolved = new \SplObjectStorage(); } /** * Resolves google tag config based on request. * * @return \Drupal\google_tag\Entity\TagContainer|null * Google tag entity if resolved, otherwise null. * * @throws \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException * @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException */ public function resolve(): ?TagContainer { $request = $this->requestStack->getCurrentRequest(); if ($request === NULL) { return NULL; } if (!$this->resolved->contains($request)) { $storage = $this->entityTypeManager->getStorage('google_tag_container'); $config_ids = $storage->getQuery() // @todo remove after https://github.com/mglaman/phpstan-drupal/issues/479 ->accessCheck() ->condition('status', 1) ->sort('weight') ->execute(); /** @var array<string, TagContainer> $configs */ $configs = $storage->loadMultiple($config_ids); foreach ($configs as $config) { if (!$this->passesConditions($config)) { continue; } $this->resolved[$request] = $config; break; } } return $this->resolved[$request] ?? NULL; } /** * Checks if google tag entity passes conditions. * * @param \Drupal\google_tag\Entity\TagContainer $entity * Google tag config object. * * @return bool * True if passes, else false. */ private function passesConditions(TagContainer $entity): bool { $conditions = []; $missing_context = FALSE; $missing_value = FALSE; foreach ($entity->getInsertionConditions() as $condition_id => $condition) { if ($condition instanceof ContextAwarePluginInterface) { try { $contexts = $this->contextRepository->getRuntimeContexts(array_values($condition->getContextMapping())); $this->contextHandler->applyContextMapping($condition, $contexts); } catch (MissingValueContextException $missingValueContextException) { $missing_value = TRUE; } catch (ContextException $contextException) { $missing_context = TRUE; } } $conditions[$condition_id] = $condition; } if ($missing_context || $missing_value) { return FALSE; } return $this->resolveConditions($conditions, 'and'); } }