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

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