From 6ca5c4fd13081fc3bedb1d7c4cc158d42d50b070 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joachim=20L=C3=B8vgaard?= Date: Wed, 11 Dec 2024 13:09:13 +0100 Subject: [PATCH] Added data provider --- composer.json | 2 + src/DataProvider/ProductDataProvider.php | 44 +++++++++++++++++++ .../DataProviderQueryBuilderCreatedEvent.php | 14 ++++++ .../ProcessCatalogPromotionsHandler.php | 30 ++++++++++++- src/Model/ProductInterface.php | 2 +- src/Model/ProductTrait.php | 4 +- src/Repository/PromotionRepository.php | 13 +++++- .../PromotionRepositoryInterface.php | 4 +- src/Resources/config/services.xml | 1 + .../config/services/data_provider.xml | 16 +++++++ src/Resources/config/services/message.xml | 16 +++++++ 11 files changed, 139 insertions(+), 7 deletions(-) create mode 100644 src/DataProvider/ProductDataProvider.php create mode 100644 src/Event/DataProviderQueryBuilderCreatedEvent.php create mode 100644 src/Resources/config/services/data_provider.xml create mode 100644 src/Resources/config/services/message.xml diff --git a/composer.json b/composer.json index ab09580..0e0c384 100644 --- a/composer.json +++ b/composer.json @@ -16,9 +16,11 @@ "doctrine/dbal": "^3.0", "doctrine/orm": "^2.10", "knplabs/knp-menu": "^3.0", + "ocramius/doctrine-batch-utils": "^2.6", "psr/clock": "^1.0", "psr/clock-implementation": "*", "setono/composite-compiler-pass": "^1.2", + "setono/doctrine-orm-trait": "^1.1", "sylius/channel": "^1.0", "sylius/channel-bundle": "^1.0", "sylius/core": "^1.0", diff --git a/src/DataProvider/ProductDataProvider.php b/src/DataProvider/ProductDataProvider.php new file mode 100644 index 0000000..35e248c --- /dev/null +++ b/src/DataProvider/ProductDataProvider.php @@ -0,0 +1,44 @@ + $productClass */ + private readonly string $productClass, + ) { + $this->managerRegistry = $managerRegistry; + } + + public function getProducts(): \Generator + { + $qb = $this + ->getManager($this->productClass) + ->createQueryBuilder() + ->select('product') + ->from($this->productClass, 'product') + ; + + $this->eventDispatcher->dispatch(new DataProviderQueryBuilderCreatedEvent($qb)); + + /** @var SimpleBatchIteratorAggregate $iterator */ + $iterator = SimpleBatchIteratorAggregate::fromQuery($qb->getQuery(), 100); + + yield from $iterator; + } +} diff --git a/src/Event/DataProviderQueryBuilderCreatedEvent.php b/src/Event/DataProviderQueryBuilderCreatedEvent.php new file mode 100644 index 0000000..f1506f8 --- /dev/null +++ b/src/Event/DataProviderQueryBuilderCreatedEvent.php @@ -0,0 +1,14 @@ +managerRegistry = $managerRegistry; } public function __invoke(ProcessCatalogPromotions $message): void { - $catalogPromotions = $this->promotionRepository->findForProcessing(); + $catalogPromotions = $this->promotionRepository->findForProcessing($message->catalogPromotions); + + $manager = null; + $i = 0; foreach ($this->productDataProvider->getProducts() as $product) { + ++$i; + + // If we check all catalog promotions, we need to reset the pre-qualified catalog promotions on the product. + // Otherwise, we only need to reset the pre-qualified catalog promotions for the catalog promotions we are processing $preQualifiedCatalogPromotions = []; + if ([] !== $message->catalogPromotions) { + $preQualifiedCatalogPromotions = array_filter( + $product->getPreQualifiedCatalogPromotions(), + static fn (string $code) => !in_array($code, $message->catalogPromotions, true), + ); + } foreach ($catalogPromotions as $catalogPromotion) { if ($this->preQualificationChecker->isPreQualified($product, $catalogPromotion)) { @@ -32,6 +52,14 @@ public function __invoke(ProcessCatalogPromotions $message): void } $product->setPreQualifiedCatalogPromotions($preQualifiedCatalogPromotions); + + if ($i % 100 === 0) { + $manager = $this->getManager($product); + $manager->flush(); + $manager->clear(); + } } + + $manager?->flush(); } } diff --git a/src/Model/ProductInterface.php b/src/Model/ProductInterface.php index 67fc48b..cc71d33 100644 --- a/src/Model/ProductInterface.php +++ b/src/Model/ProductInterface.php @@ -17,7 +17,7 @@ interface ProductInterface extends BaseProductInterface public function getPreQualifiedCatalogPromotions(): array; /** - * @param list|null $preQualifiedCatalogPromotions + * @param array|null $preQualifiedCatalogPromotions */ public function setPreQualifiedCatalogPromotions(?array $preQualifiedCatalogPromotions): void; diff --git a/src/Model/ProductTrait.php b/src/Model/ProductTrait.php index 3d98032..b20e911 100644 --- a/src/Model/ProductTrait.php +++ b/src/Model/ProductTrait.php @@ -25,7 +25,7 @@ public function getPreQualifiedCatalogPromotions(): array } /** - * @param list|null $preQualifiedCatalogPromotions + * @param list|null $preQualifiedCatalogPromotions */ public function setPreQualifiedCatalogPromotions(?array $preQualifiedCatalogPromotions): void { @@ -44,7 +44,7 @@ public function hasPreQualifiedCatalogPromotions(): bool } /** - * @param list $codes + * @param array $codes * * @return list */ diff --git a/src/Repository/PromotionRepository.php b/src/Repository/PromotionRepository.php index e15805e..b3f2dd0 100644 --- a/src/Repository/PromotionRepository.php +++ b/src/Repository/PromotionRepository.php @@ -10,10 +10,19 @@ class PromotionRepository extends EntityRepository implements PromotionRepositoryInterface { - public function findForProcessing(): array + public function findForProcessing(array $catalogPromotions = []): array { - $objs = $this->findAll(); + $qb = $this->createQueryBuilder('o'); + if ([] !== $catalogPromotions) { + $qb->andWhere('o.code IN (:catalogPromotions)') + ->setParameter('catalogPromotions', $catalogPromotions) + ; + } + + $objs = $qb->getQuery()->getResult(); + Assert::isArray($objs); Assert::allIsInstanceOf($objs, PromotionInterface::class); + Assert::isList($objs); return $objs; } diff --git a/src/Repository/PromotionRepositoryInterface.php b/src/Repository/PromotionRepositoryInterface.php index 5098fd2..0990f5e 100644 --- a/src/Repository/PromotionRepositoryInterface.php +++ b/src/Repository/PromotionRepositoryInterface.php @@ -10,9 +10,11 @@ interface PromotionRepositoryInterface extends RepositoryInterface { /** + * @param list $catalogPromotions a list of catalog promotion codes to filter by + * * @return list */ - public function findForProcessing(): array; + public function findForProcessing(array $catalogPromotions = []): array; public function findOneByCode(string $code): ?PromotionInterface; } diff --git a/src/Resources/config/services.xml b/src/Resources/config/services.xml index 3ea1511..5fa50fb 100644 --- a/src/Resources/config/services.xml +++ b/src/Resources/config/services.xml @@ -6,6 +6,7 @@ + diff --git a/src/Resources/config/services/data_provider.xml b/src/Resources/config/services/data_provider.xml new file mode 100644 index 0000000..c5e6782 --- /dev/null +++ b/src/Resources/config/services/data_provider.xml @@ -0,0 +1,16 @@ + + + + + + + + + + %sylius.model.product.class% + + + diff --git a/src/Resources/config/services/message.xml b/src/Resources/config/services/message.xml new file mode 100644 index 0000000..738a69d --- /dev/null +++ b/src/Resources/config/services/message.xml @@ -0,0 +1,16 @@ + + + + + + + + + + + + + +