vendor/shopware/core/Content/Rule/DataAbstractionLayer/RulePayloadUpdater.php line 97

Open in your IDE?
  1. <?php declare(strict_types=1);
  2. namespace Shopware\Core\Content\Rule\DataAbstractionLayer;
  3. use Doctrine\DBAL\Connection;
  4. use Shopware\Core\Content\Rule\DataAbstractionLayer\Indexing\ConditionTypeNotFound;
  5. use Shopware\Core\Framework\App\Event\AppScriptConditionEvents;
  6. use Shopware\Core\Framework\DataAbstractionLayer\Doctrine\FetchModeHelper;
  7. use Shopware\Core\Framework\DataAbstractionLayer\Doctrine\RetryableQuery;
  8. use Shopware\Core\Framework\DataAbstractionLayer\Event\EntityWrittenEvent;
  9. use Shopware\Core\Framework\Rule\Collector\RuleConditionRegistry;
  10. use Shopware\Core\Framework\Rule\Container\AndRule;
  11. use Shopware\Core\Framework\Rule\Container\ContainerInterface;
  12. use Shopware\Core\Framework\Rule\Rule;
  13. use Shopware\Core\Framework\Rule\ScriptRule;
  14. use Shopware\Core\Framework\Uuid\Uuid;
  15. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  16. /**
  17.  * @deprecated tag:v6.5.0 - reason:becomes-internal - EventSubscribers will become internal in v6.5.0
  18.  */
  19. class RulePayloadUpdater implements EventSubscriberInterface
  20. {
  21.     private Connection $connection;
  22.     private RuleConditionRegistry $ruleConditionRegistry;
  23.     /**
  24.      * @internal
  25.      */
  26.     public function __construct(Connection $connectionRuleConditionRegistry $ruleConditionRegistry)
  27.     {
  28.         $this->connection $connection;
  29.         $this->ruleConditionRegistry $ruleConditionRegistry;
  30.     }
  31.     public static function getSubscribedEvents(): array
  32.     {
  33.         return [
  34.             AppScriptConditionEvents::APP_SCRIPT_CONDITION_WRITTEN_EVENT => 'updatePayloads',
  35.         ];
  36.     }
  37.     /**
  38.      * @param list<string> $ids
  39.      *
  40.      * @return array<string, array{payload: string|null, invalid: bool}>
  41.      */
  42.     public function update(array $ids): array
  43.     {
  44.         $conditions $this->connection->fetchAllAssociative(
  45.             'SELECT LOWER(HEX(rc.rule_id)) as array_key, rc.*, rs.script, rs.identifier, rs.updated_at as lastModified
  46.             FROM rule_condition rc
  47.             LEFT JOIN app_script_condition rs ON rc.script_id = rs.id AND rs.active = 1
  48.             WHERE rc.rule_id IN (:ids)
  49.             ORDER BY rc.rule_id',
  50.             ['ids' => Uuid::fromHexToBytesList($ids)],
  51.             ['ids' => Connection::PARAM_STR_ARRAY]
  52.         );
  53.         $rules FetchModeHelper::group($conditions);
  54.         $update = new RetryableQuery(
  55.             $this->connection,
  56.             $this->connection->prepare('UPDATE `rule` SET payload = :payload, invalid = :invalid WHERE id = :id')
  57.         );
  58.         $updated = [];
  59.         /** @var string $id */
  60.         foreach ($rules as $id => $rule) {
  61.             $invalid false;
  62.             $serialized null;
  63.             try {
  64.                 $nested $this->buildNested($rulenull);
  65.                 //ensure the root rule is an AndRule
  66.                 $nested = new AndRule($nested);
  67.                 $serialized serialize($nested);
  68.             } catch (ConditionTypeNotFound $exception) {
  69.                 $invalid true;
  70.             } finally {
  71.                 $update->execute([
  72.                     'id' => Uuid::fromHexToBytes($id),
  73.                     'payload' => $serialized,
  74.                     'invalid' => (int) $invalid,
  75.                 ]);
  76.             }
  77.             $updated[$id] = ['payload' => $serialized'invalid' => $invalid];
  78.         }
  79.         return $updated;
  80.     }
  81.     public function updatePayloads(EntityWrittenEvent $event): void
  82.     {
  83.         $ruleIds $this->connection->fetchFirstColumn(
  84.             'SELECT DISTINCT rc.rule_id
  85.                 FROM rule_condition rc
  86.                 INNER JOIN app_script_condition rs ON rc.script_id = rs.id
  87.                 WHERE rs.id IN (:ids)',
  88.             ['ids' => Uuid::fromHexToBytesList(array_values($event->getIds()))],
  89.             ['ids' => Connection::PARAM_STR_ARRAY]
  90.         );
  91.         if (empty($ruleIds)) {
  92.             return;
  93.         }
  94.         $this->update(Uuid::fromBytesToHexList($ruleIds));
  95.     }
  96.     /**
  97.      * @param array<string, mixed> $rules
  98.      *
  99.      * @return list<Rule>
  100.      */
  101.     private function buildNested(array $rules, ?string $parentId): array
  102.     {
  103.         $nested = [];
  104.         foreach ($rules as $rule) {
  105.             if ($rule['parent_id'] !== $parentId) {
  106.                 continue;
  107.             }
  108.             if (!$this->ruleConditionRegistry->has($rule['type'])) {
  109.                 throw new ConditionTypeNotFound($rule['type']);
  110.             }
  111.             $ruleClass $this->ruleConditionRegistry->getRuleClass($rule['type']);
  112.             $object = new $ruleClass();
  113.             if ($object instanceof ScriptRule) {
  114.                 $object->assign([
  115.                     'script' => $rule['script'] ?? '',
  116.                     'lastModified' => $rule['lastModified'] ? new \DateTimeImmutable($rule['lastModified']) : null,
  117.                     'identifier' => $rule['identifier'] ?? null,
  118.                     'values' => $rule['value'] ? json_decode($rule['value'], true) : [],
  119.                 ]);
  120.                 $nested[] = $object;
  121.                 continue;
  122.             }
  123.             if ($rule['value'] !== null) {
  124.                 $object->assign(json_decode($rule['value'], true));
  125.             }
  126.             if ($object instanceof ContainerInterface) {
  127.                 $children $this->buildNested($rules$rule['id']);
  128.                 foreach ($children as $child) {
  129.                     $object->addRule($child);
  130.                 }
  131.             }
  132.             $nested[] = $object;
  133.         }
  134.         return $nested;
  135.     }
  136. }