vendor/shopware/core/Content/Rule/DataAbstractionLayer/RuleIndexer.php line 168

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\Checkout\Cart\CartRuleLoader;
  5. use Shopware\Core\Content\Rule\Event\RuleIndexerEvent;
  6. use Shopware\Core\Content\Rule\RuleDefinition;
  7. use Shopware\Core\Content\Rule\RuleEvents;
  8. use Shopware\Core\Framework\DataAbstractionLayer\Dbal\Common\IteratorFactory;
  9. use Shopware\Core\Framework\DataAbstractionLayer\Doctrine\RetryableQuery;
  10. use Shopware\Core\Framework\DataAbstractionLayer\EntityRepositoryInterface;
  11. use Shopware\Core\Framework\DataAbstractionLayer\Event\EntityWrittenContainerEvent;
  12. use Shopware\Core\Framework\DataAbstractionLayer\Event\EntityWrittenEvent;
  13. use Shopware\Core\Framework\DataAbstractionLayer\Indexing\EntityIndexer;
  14. use Shopware\Core\Framework\DataAbstractionLayer\Indexing\EntityIndexingMessage;
  15. use Shopware\Core\Framework\Feature;
  16. use Shopware\Core\Framework\Log\Package;
  17. use Shopware\Core\Framework\Plugin\Event\PluginPostActivateEvent;
  18. use Shopware\Core\Framework\Plugin\Event\PluginPostDeactivateEvent;
  19. use Shopware\Core\Framework\Plugin\Event\PluginPostInstallEvent;
  20. use Shopware\Core\Framework\Plugin\Event\PluginPostUninstallEvent;
  21. use Shopware\Core\Framework\Plugin\Event\PluginPostUpdateEvent;
  22. use Shopware\Core\Framework\Plugin\Exception\DecorationPatternException;
  23. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  24. use Symfony\Contracts\EventDispatcher\EventDispatcherInterface;
  25. /**
  26. * @deprecated tag:v6.5.0 - reason:becomes-internal - EventSubscribers will become internal in v6.5.0
  27. */
  28. #[Package('business-ops')]
  29. class RuleIndexer extends EntityIndexer implements EventSubscriberInterface
  30. {
  31. public const PAYLOAD_UPDATER = 'rule.payload';
  32. public const AREA_UPDATER = 'rule.area';
  33. private IteratorFactory $iteratorFactory;
  34. private Connection $connection;
  35. private EntityRepositoryInterface $repository;
  36. private RulePayloadUpdater $payloadUpdater;
  37. private EventDispatcherInterface $eventDispatcher;
  38. private CartRuleLoader $cartRuleLoader;
  39. private RuleAreaUpdater $areaUpdater;
  40. /**
  41. * @internal
  42. */
  43. public function __construct(
  44. Connection $connection,
  45. IteratorFactory $iteratorFactory,
  46. EntityRepositoryInterface $repository,
  47. RulePayloadUpdater $payloadUpdater,
  48. RuleAreaUpdater $areaUpdater,
  49. CartRuleLoader $cartRuleLoader,
  50. EventDispatcherInterface $eventDispatcher
  51. ) {
  52. $this->iteratorFactory = $iteratorFactory;
  53. $this->repository = $repository;
  54. $this->connection = $connection;
  55. $this->payloadUpdater = $payloadUpdater;
  56. $this->areaUpdater = $areaUpdater;
  57. $this->eventDispatcher = $eventDispatcher;
  58. $this->cartRuleLoader = $cartRuleLoader;
  59. }
  60. public function getName(): string
  61. {
  62. return 'rule.indexer';
  63. }
  64. public static function getSubscribedEvents(): array
  65. {
  66. return [
  67. PluginPostInstallEvent::class => 'refreshPlugin',
  68. PluginPostActivateEvent::class => 'refreshPlugin',
  69. PluginPostUpdateEvent::class => 'refreshPlugin',
  70. PluginPostDeactivateEvent::class => 'refreshPlugin',
  71. PluginPostUninstallEvent::class => 'refreshPlugin',
  72. RuleEvents::RULE_WRITTEN_EVENT => 'onRuleWritten',
  73. ];
  74. }
  75. public function refreshPlugin(): void
  76. {
  77. // Delete the payload and invalid flag of all rules
  78. $update = new RetryableQuery(
  79. $this->connection,
  80. $this->connection->prepare('UPDATE `rule` SET `payload` = null, `invalid` = 0')
  81. );
  82. $update->execute();
  83. }
  84. /**
  85. * @param array{offset: string}|null $offset
  86. *
  87. * @deprecated tag:v6.5.0 The parameter $offset will be native typed
  88. */
  89. public function iterate(/*?array */$offset): ?EntityIndexingMessage
  90. {
  91. if ($offset !== null && !\is_array($offset)) {
  92. Feature::triggerDeprecationOrThrow(
  93. 'v6.5.0.0',
  94. 'Parameter `$offset` of method "iterate()" in class "RuleIndexer" will be natively typed to `?array` in v6.5.0.0.'
  95. );
  96. }
  97. $iterator = $this->iteratorFactory->createIterator($this->repository->getDefinition(), $offset);
  98. $ids = $iterator->fetch();
  99. if (empty($ids)) {
  100. return null;
  101. }
  102. return new RuleIndexingMessage(array_values($ids), $iterator->getOffset());
  103. }
  104. public function update(EntityWrittenContainerEvent $event): ?EntityIndexingMessage
  105. {
  106. $updates = $event->getPrimaryKeys(RuleDefinition::ENTITY_NAME);
  107. if (empty($updates)) {
  108. return null;
  109. }
  110. $this->handle(new RuleIndexingMessage(array_values($updates), null, $event->getContext()));
  111. return null;
  112. }
  113. public function handle(EntityIndexingMessage $message): void
  114. {
  115. $ids = $message->getData();
  116. $ids = array_unique(array_filter($ids));
  117. if (empty($ids)) {
  118. return;
  119. }
  120. if ($message->allow(self::PAYLOAD_UPDATER)) {
  121. $this->payloadUpdater->update($ids);
  122. }
  123. if ($message->allow(self::AREA_UPDATER)) {
  124. $this->areaUpdater->update($ids);
  125. }
  126. $this->eventDispatcher->dispatch(new RuleIndexerEvent($ids, $message->getContext(), $message->getSkip()));
  127. }
  128. public function getTotal(): int
  129. {
  130. return $this->iteratorFactory->createIterator($this->repository->getDefinition())->fetchCount();
  131. }
  132. public function getDecorated(): EntityIndexer
  133. {
  134. throw new DecorationPatternException(static::class);
  135. }
  136. public function onRuleWritten(EntityWrittenEvent $event): void
  137. {
  138. $this->cartRuleLoader->invalidate();
  139. }
  140. }