vendor/pimcore/pimcore/lib/Targeting/ConditionMatcher.php line 133

Open in your IDE?
  1. <?php
  2. declare(strict_types=1);
  3. /**
  4.  * Pimcore
  5.  *
  6.  * This source file is available under two different licenses:
  7.  * - GNU General Public License version 3 (GPLv3)
  8.  * - Pimcore Commercial License (PCL)
  9.  * Full copyright and license information is available in
  10.  * LICENSE.md which is distributed with this source code.
  11.  *
  12.  *  @copyright  Copyright (c) Pimcore GmbH (http://www.pimcore.org)
  13.  *  @license    http://www.pimcore.org/license     GPLv3 and PCL
  14.  */
  15. namespace Pimcore\Targeting;
  16. use Pimcore\Targeting\Condition\ConditionInterface;
  17. use Pimcore\Targeting\Condition\EventDispatchingConditionInterface;
  18. use Pimcore\Targeting\Condition\VariableConditionInterface;
  19. use Pimcore\Targeting\ConditionMatcher\ExpressionBuilder;
  20. use Pimcore\Targeting\Model\VisitorInfo;
  21. use Psr\Log\LoggerInterface;
  22. use Symfony\Component\ExpressionLanguage\ExpressionLanguage;
  23. use Symfony\Contracts\EventDispatcher\EventDispatcherInterface;
  24. class ConditionMatcher implements ConditionMatcherInterface
  25. {
  26.     /**
  27.      * @var ConditionFactoryInterface
  28.      */
  29.     private $conditionFactory;
  30.     /**
  31.      * @var DataLoaderInterface
  32.      */
  33.     private $dataLoader;
  34.     /**
  35.      * @var EventDispatcherInterface
  36.      */
  37.     private $eventDispatcher;
  38.     /**
  39.      * @var ExpressionLanguage
  40.      */
  41.     private $expressionLanguage;
  42.     /**
  43.      * @var LoggerInterface
  44.      */
  45.     private $logger;
  46.     /**
  47.      * @var array
  48.      */
  49.     private $collectedVariables = [];
  50.     public function __construct(
  51.         ConditionFactoryInterface $conditionFactory,
  52.         DataLoaderInterface $dataLoader,
  53.         EventDispatcherInterface $eventDispatcher,
  54.         ExpressionLanguage $expressionLanguage,
  55.         LoggerInterface $logger
  56.     ) {
  57.         $this->conditionFactory $conditionFactory;
  58.         $this->dataLoader $dataLoader;
  59.         $this->eventDispatcher $eventDispatcher;
  60.         $this->expressionLanguage $expressionLanguage;
  61.         $this->logger $logger;
  62.     }
  63.     /**
  64.      * {@inheritdoc}
  65.      */
  66.     public function match(VisitorInfo $visitorInfo, array $conditionsbool $collectVariables false): bool
  67.     {
  68.         // reset internal state
  69.         $this->collectedVariables = [];
  70.         $count count($conditions);
  71.         if (=== $count) {
  72.             // no conditions -> rule matches
  73.             return true;
  74.         } elseif (=== $count) {
  75.             // no need to build up expression if there's only one condition
  76.             return $this->matchCondition($visitorInfo$conditions[0], $collectVariables);
  77.         }
  78.         $expressionBuilder = new ExpressionBuilder();
  79.         foreach ($conditions as $conditionConfig) {
  80.             $conditionResult $this->matchCondition($visitorInfo$conditionConfig$collectVariables);
  81.             $expressionBuilder->addCondition($conditionConfig$conditionResult);
  82.         }
  83.         $expression $expressionBuilder->getExpression();
  84.         $values $expressionBuilder->getValues();
  85.         $result $this->expressionLanguage->evaluate($expression$values);
  86.         return (bool)$result;
  87.     }
  88.     /**
  89.      * {@inheritdoc}
  90.      */
  91.     public function getCollectedVariables(): array
  92.     {
  93.         return $this->collectedVariables;
  94.     }
  95.     private function matchCondition(VisitorInfo $visitorInfo, array $configbool $collectVariables false): bool
  96.     {
  97.         try {
  98.             $condition $this->conditionFactory->build($config);
  99.         } catch (\Throwable $e) {
  100.             $this->logger->error($e);
  101.             return false;
  102.         }
  103.         // check prerequisites - e.g. a condition without a value
  104.         // (= all values match) does not need to fetch provider data
  105.         // as location or browser
  106.         if (!$condition->canMatch()) {
  107.             return false;
  108.         }
  109.         if ($condition instanceof DataProviderDependentInterface) {
  110.             $this->dataLoader->loadDataFromProviders($visitorInfo$condition->getDataProviderKeys());
  111.         }
  112.         if ($condition instanceof EventDispatchingConditionInterface) {
  113.             $condition->preMatch($visitorInfo$this->eventDispatcher);
  114.         }
  115.         $result false;
  116.         try {
  117.             $result $condition->match($visitorInfo);
  118.         } catch (\Throwable $e) {
  119.             $this->logger->error($e);
  120.             return false;
  121.         }
  122.         if ($collectVariables) {
  123.             $this->collectConditionVariables($config$condition);
  124.         }
  125.         if ($condition instanceof EventDispatchingConditionInterface) {
  126.             $condition->postMatch($visitorInfo$this->eventDispatcher);
  127.         }
  128.         return $result;
  129.     }
  130.     private function collectConditionVariables(array $configConditionInterface $condition)
  131.     {
  132.         $data = [
  133.             'type' => $config['type'],
  134.         ];
  135.         if ($condition instanceof VariableConditionInterface) {
  136.             $variables $condition->getMatchedVariables();
  137.             if (!empty($variables)) {
  138.                 $data['data'] = $variables;
  139.             }
  140.         }
  141.         $this->collectedVariables[] = $data;
  142.     }
  143. }