vendor/pimcore/customer-management-framework-bundle/src/Targeting/Condition/HasSegment.php line 81

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 CustomerManagementFrameworkBundle\Targeting\Condition;
  16. use CustomerManagementFrameworkBundle\Model\CustomerSegmentInterface;
  17. use CustomerManagementFrameworkBundle\Targeting\DataProvider\CustomerSegments;
  18. use CustomerManagementFrameworkBundle\Targeting\SegmentTracker;
  19. use Pimcore\Model\DataObject\CustomerSegment;
  20. use Pimcore\Targeting\Condition\AbstractVariableCondition;
  21. use Pimcore\Targeting\DataProvider\TargetingStorage;
  22. use Pimcore\Targeting\DataProviderDependentInterface;
  23. use Pimcore\Targeting\Model\VisitorInfo;
  24. use Pimcore\Targeting\Storage\TargetingStorageInterface;
  25. use Symfony\Component\OptionsResolver\OptionsResolver;
  26. class HasSegment extends AbstractVariableCondition implements DataProviderDependentInterface
  27. {
  28.     /**
  29.      * @var int|null
  30.      */
  31.     private $segmentId;
  32.     /**
  33.      * @var array
  34.      */
  35.     private $options = [];
  36.     /**
  37.      * @param int|null $segmentId
  38.      * @param array $options
  39.      */
  40.     public function __construct(int $segmentId null, array $options = [])
  41.     {
  42.         $this->segmentId $segmentId;
  43.         $resolver = new OptionsResolver();
  44.         $this->configureOptions($resolver);
  45.         $this->options $resolver->resolve($options);
  46.     }
  47.     private function configureOptions(OptionsResolver $resolver)
  48.     {
  49.         $resolver->setDefaults([
  50.             'operator' => '>=',
  51.             'value' => 1,
  52.             'considerCustomerSegments' => true,
  53.             'considerTrackedSegments' => true
  54.         ]);
  55.         $resolver->setAllowedTypes('operator''string');
  56.         $resolver->setAllowedValues('operator', ['%''=''<''<=''>''>=']);
  57.         $resolver->setAllowedTypes('value''int');
  58.         $resolver->setAllowedValues('value', function ($value) {
  59.             return $value 0;
  60.         });
  61.         $resolver->setAllowedTypes('considerCustomerSegments''bool');
  62.         $resolver->setAllowedTypes('considerTrackedSegments''bool');
  63.     }
  64.     /**
  65.      * @inheritDoc
  66.      */
  67.     public static function fromConfig(array $config)
  68.     {
  69.         $segmentId null;
  70.         if (is_numeric($config['segment'])) {
  71.             $segmentId = (int)$config['segment'];
  72.         } else {
  73.             // TODO load from segment manager?
  74.             $segment CustomerSegment::getByPath($config['segment']);
  75.             if ($segment instanceof CustomerSegmentInterface) {
  76.                 $segmentId $segment->getId();
  77.             }
  78.         }
  79.         return new self(
  80.             $segmentId,
  81.             [
  82.                 'operator' => $config['condition_operator'] ?? '>=',
  83.                 'value' => $config['value'] ?? 1,
  84.                 'considerCustomerSegments' => $config['considerCustomerSegments'] ?? true,
  85.                 'considerTrackedSegments' => $config['considerTrackedSegments'] ?? true
  86.             ]
  87.         );
  88.     }
  89.     /**
  90.      * @inheritDoc
  91.      */
  92.     public function getDataProviderKeys(): array
  93.     {
  94.         $providers = [];
  95.         if ($this->options['considerCustomerSegments']) {
  96.             $providers[] = CustomerSegments::PROVIDER_KEY;
  97.         }
  98.         if ($this->options['considerTrackedSegments']) {
  99.             $providers[] = TargetingStorage::PROVIDER_KEY;
  100.         }
  101.         return $providers;
  102.     }
  103.     /**
  104.      * @inheritDoc
  105.      */
  106.     public function canMatch(): bool
  107.     {
  108.         return null !== $this->segmentId;
  109.     }
  110.     /**
  111.      * @inheritDoc
  112.      */
  113.     public function match(VisitorInfo $visitorInfo): bool
  114.     {
  115.         $segments $this->loadSegments($visitorInfo);
  116.         if (isset($segments[$this->segmentId])) {
  117.             $result $this->matchCondition(
  118.                 $segments[$this->segmentId],
  119.                 $this->options['operator'],
  120.                 $this->options['value']
  121.             );
  122.             if ($result) {
  123.                 $this->setMatchedVariables([$this->segmentId => $segments[$this->segmentId]]);
  124.             }
  125.             return $result;
  126.         }
  127.         return false;
  128.     }
  129.     private function matchCondition(int $segmentCountstring $operatorint $value): bool
  130.     {
  131.         switch ($operator) {
  132.             case '%':
  133.                 return $segmentCount $value === 0;
  134.             case '=':
  135.                 return $segmentCount === $value;
  136.             case '>':
  137.                 return $segmentCount $value;
  138.             case '>=':
  139.                 return $segmentCount >= $value;
  140.             case '<':
  141.                 return $segmentCount $value;
  142.             case '<=':
  143.                 return $segmentCount <= $value;
  144.         }
  145.         throw new \InvalidArgumentException(sprintf('Unsupported operator "%s"'$operator));
  146.     }
  147.     private function loadSegments(VisitorInfo $visitorInfo): array
  148.     {
  149.         $segments = [];
  150.         if ($this->options['considerCustomerSegments']) {
  151.             $segments $this->mergeSegments(
  152.                 $segments,
  153.                 $visitorInfo->get(CustomerSegments::PROVIDER_KEY)
  154.             );
  155.         }
  156.         if ($this->options['considerTrackedSegments']) {
  157.             $segments $this->mergeSegments(
  158.                 $segments,
  159.                 $this->loadTrackedSegments($visitorInfo)
  160.             );
  161.         }
  162.         return $segments;
  163.     }
  164.     private function loadTrackedSegments(VisitorInfo $visitorInfo): array
  165.     {
  166.         /** @var TargetingStorageInterface $storage */
  167.         $storage $visitorInfo->get(TargetingStorage::PROVIDER_KEY);
  168.         $segments $storage->get(
  169.             $visitorInfo,
  170.             TargetingStorageInterface::SCOPE_VISITOR,
  171.             SegmentTracker::KEY_SEGMENTS,
  172.             []
  173.         );
  174.         return $segments;
  175.     }
  176.     private function mergeSegments(array $segments, array $data): array
  177.     {
  178.         foreach ($data as $segmentId => $count) {
  179.             if (!isset($segments[$segmentId])) {
  180.                 $segments[$segmentId] = 0;
  181.             }
  182.             $segments[$segmentId] += $count;
  183.         }
  184.         return $segments;
  185.     }
  186. }