From 225b23f5f2d5bd67e98f744e1f1b25a6ad2dc23b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joachim=20L=C3=B8vgaard?= Date: Fri, 26 Jan 2024 10:46:42 +0100 Subject: [PATCH] Allow a delay when assigning callouts --- src/DependencyInjection/Configuration.php | 11 ++++++- .../SetonoSyliusCalloutExtension.php | 2 ++ .../HandleCalloutUpdateSubscriber.php | 24 +++++++++----- src/Message/Command/AssignCallout.php | 31 ------------------ src/Message/Command/AssignCallouts.php | 8 +++-- src/Message/Handler/AssignCalloutHandler.php | 32 ------------------- src/Message/Handler/AssignCalloutsHandler.php | 22 ++++++++++++- src/Model/ProductTrait.php | 2 ++ .../config/services/event_subscriber.xml | 1 + src/Resources/config/services/message.xml | 6 ---- src/Resources/config/services/twig.xml | 1 + src/Resources/translations/messages.en.yml | 7 ++-- .../views/Admin/Callout/_form.html.twig | 7 ++++ src/Twig/CalloutExtension.php | 10 ++++++ 14 files changed, 80 insertions(+), 84 deletions(-) delete mode 100644 src/Message/Command/AssignCallout.php delete mode 100644 src/Message/Handler/AssignCalloutHandler.php diff --git a/src/DependencyInjection/Configuration.php b/src/DependencyInjection/Configuration.php index 525dd4e..82bec48 100644 --- a/src/DependencyInjection/Configuration.php +++ b/src/DependencyInjection/Configuration.php @@ -50,7 +50,16 @@ public function getConfigTreeBuilder(): TreeBuilder 'bottom_center', 'bottom_right', ]) - ->scalarPrototype() + ->scalarPrototype()->end() + ->end() + ->arrayNode('assignment') + ->addDefaultsIfNotSet() + ->children() + ->integerNode('delay') + ->info('The delay in seconds when assigning a callout. This is to avoid assigning the same callout multiple times within a short interval') + ->defaultValue(60) + ->min(0) + ; $this->addResourcesSection($rootNode); diff --git a/src/DependencyInjection/SetonoSyliusCalloutExtension.php b/src/DependencyInjection/SetonoSyliusCalloutExtension.php index 0a15136..951e9bc 100644 --- a/src/DependencyInjection/SetonoSyliusCalloutExtension.php +++ b/src/DependencyInjection/SetonoSyliusCalloutExtension.php @@ -21,6 +21,7 @@ public function load(array $configs, ContainerBuilder $container): void * @var array{ * elements: list, * positions: list, + * assignment: array{delay: int}, * resources: array * } $config */ @@ -31,6 +32,7 @@ public function load(array $configs, ContainerBuilder $container): void $container->setParameter('setono_sylius_callout.elements', $config['elements']); $container->setParameter('setono_sylius_callout.positions', $config['positions']); + $container->setParameter('setono_sylius_callout.assignment.delay', $config['assignment']['delay']); $this->registerResources('setono_sylius_callout', SyliusResourceBundle::DRIVER_DOCTRINE_ORM, $config['resources'], $container); } diff --git a/src/EventSubscriber/HandleCalloutUpdateSubscriber.php b/src/EventSubscriber/HandleCalloutUpdateSubscriber.php index 065b1ae..abee099 100644 --- a/src/EventSubscriber/HandleCalloutUpdateSubscriber.php +++ b/src/EventSubscriber/HandleCalloutUpdateSubscriber.php @@ -11,6 +11,7 @@ use Setono\SyliusCalloutPlugin\Model\CalloutRuleInterface; use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Symfony\Component\Messenger\MessageBusInterface; +use Symfony\Component\Messenger\Stamp\DelayStamp; /** * This subscriber listens for changes to callouts and callout rules @@ -21,12 +22,14 @@ final class HandleCalloutUpdateSubscriber implements EventSubscriberInterface /** * The keys are the callout codes and the values are true * - * @var array + * @var array */ private array $calloutsToAssign = []; - public function __construct(private readonly MessageBusInterface $commandBus) - { + public function __construct( + private readonly MessageBusInterface $commandBus, + private readonly int $processingDelay, + ) { } public static function getSubscribedEvents(): array @@ -47,7 +50,7 @@ public function prePersist(PrePersistEventArgs $event): void return; } - $this->calloutsToAssign[(string) $callout->getCode()] = true; + $this->calloutsToAssign[(string) $callout->getCode()] = $callout; } /** @@ -91,7 +94,7 @@ private function preUpdateCallout(CalloutInterface $callout, PreUpdateEventArgs return; } - $this->calloutsToAssign[(string) $callout->getCode()] = true; + $this->calloutsToAssign[(string) $callout->getCode()] = $callout; } /** @@ -108,12 +111,12 @@ private function preUpdateCalloutRule(CalloutRuleInterface $calloutRule, PreUpda return; } - $this->calloutsToAssign[(string) $callout->getCode()] = true; + $this->calloutsToAssign[(string) $callout->getCode()] = $callout; } /** * This is called when a callout is created or updated by Sylius. - * In the lifecycle this is the last method called and therefore we can safely dispatch the message here if needed + * In the lifecycle this is the last method called, and therefore we can safely dispatch the message here if needed */ public function postUpdate(): void { @@ -121,6 +124,11 @@ public function postUpdate(): void return; } - $this->commandBus->dispatch(new AssignCallouts(array_keys($this->calloutsToAssign))); + $stamps = []; + if ($this->processingDelay > 0) { + $stamps[] = new DelayStamp($this->processingDelay * 1000); + } + + $this->commandBus->dispatch(new AssignCallouts(array_values($this->calloutsToAssign)), $stamps); } } diff --git a/src/Message/Command/AssignCallout.php b/src/Message/Command/AssignCallout.php deleted file mode 100644 index 1f32fb1..0000000 --- a/src/Message/Command/AssignCallout.php +++ /dev/null @@ -1,31 +0,0 @@ -version = $callout->getVersion(); - $callout = (string) $callout->getCode(); - } - - $this->callout = $callout; - } -} diff --git a/src/Message/Command/AssignCallouts.php b/src/Message/Command/AssignCallouts.php index 42e8cdb..07e7f16 100644 --- a/src/Message/Command/AssignCallouts.php +++ b/src/Message/Command/AssignCallouts.php @@ -11,7 +11,11 @@ */ final class AssignCallouts implements CommandInterface { - /** @var list */ + /** + * This is a list of arrays where the first element is the callout code and the second element is the version + * + * @var list + */ public array $callouts = []; /** @@ -20,7 +24,7 @@ final class AssignCallouts implements CommandInterface public function __construct(array $callouts = []) { foreach ($callouts as $callout) { - $this->callouts[] = $callout instanceof CalloutInterface ? (string) $callout->getCode() : $callout; + $this->callouts[] = $callout instanceof CalloutInterface ? [(string) $callout->getCode(), $callout->getVersion()] : [$callout, null]; } } } diff --git a/src/Message/Handler/AssignCalloutHandler.php b/src/Message/Handler/AssignCalloutHandler.php deleted file mode 100644 index 2228d13..0000000 --- a/src/Message/Handler/AssignCalloutHandler.php +++ /dev/null @@ -1,32 +0,0 @@ -calloutRepository->findOneByCode($message->callout); - if (null === $callout) { - throw new UnrecoverableMessageHandlingException(sprintf('Callout with code "%s" does not exist', $message->callout)); - } - - if (null !== $message->version && $message->version !== $callout->getVersion()) { - // this means the callout has been updated since the message was sent - throw new UnrecoverableMessageHandlingException(sprintf('Callout with id %s has version %s, but version %s was expected', $message->callout, (string) $callout->getVersion(), $message->version)); - } - - if (!$callout->isEnabled()) { - throw new UnrecoverableMessageHandlingException(sprintf('Callout with id %s is not enabled', $message->callout)); - } - - $callouts = [$callout]; - - $this->assign(callouts: $callouts); - } -} diff --git a/src/Message/Handler/AssignCalloutsHandler.php b/src/Message/Handler/AssignCalloutsHandler.php index c819eb5..0130a11 100644 --- a/src/Message/Handler/AssignCalloutsHandler.php +++ b/src/Message/Handler/AssignCalloutsHandler.php @@ -11,8 +11,28 @@ final class AssignCalloutsHandler extends AbstractAssignCalloutsHandler public function __invoke(AssignCallouts $message): void { $callouts = []; + if ([] !== $message->callouts) { - $callouts = $this->calloutRepository->findEnabled($message->callouts); + foreach ($message->callouts as $calloutShape) { + $callout = $this->calloutRepository->findOneByCode($calloutShape[0]); + if (null === $callout) { + continue; + } + + if (null !== $calloutShape[1] && $calloutShape[1] !== $callout->getVersion()) { + continue; + } + + if (!$callout->isEnabled()) { + continue; + } + + $callouts[] = $callout; + } + + if ([] === $callouts) { + return; + } } $this->assign(callouts: $callouts); diff --git a/src/Model/ProductTrait.php b/src/Model/ProductTrait.php index c7820b8..9b012b1 100644 --- a/src/Model/ProductTrait.php +++ b/src/Model/ProductTrait.php @@ -45,6 +45,8 @@ public function removePreQualifiedCallout(CalloutInterface|string $preQualifiedC if (false !== $key) { unset($this->preQualifiedCallouts[$key]); } + + $this->preQualifiedCallouts = array_values($this->preQualifiedCallouts); } public function resetPreQualifiedCallouts(): void diff --git a/src/Resources/config/services/event_subscriber.xml b/src/Resources/config/services/event_subscriber.xml index ad3f27c..695f8fd 100644 --- a/src/Resources/config/services/event_subscriber.xml +++ b/src/Resources/config/services/event_subscriber.xml @@ -12,6 +12,7 @@ + %setono_sylius_callout.assignment.delay% diff --git a/src/Resources/config/services/message.xml b/src/Resources/config/services/message.xml index 3af1892..bf6239e 100644 --- a/src/Resources/config/services/message.xml +++ b/src/Resources/config/services/message.xml @@ -13,12 +13,6 @@ %sylius.model.product.class% - - - - diff --git a/src/Resources/config/services/twig.xml b/src/Resources/config/services/twig.xml index 25797cf..dba24d0 100644 --- a/src/Resources/config/services/twig.xml +++ b/src/Resources/config/services/twig.xml @@ -6,6 +6,7 @@ + %setono_sylius_callout.assignment.delay% diff --git a/src/Resources/translations/messages.en.yml b/src/Resources/translations/messages.en.yml index 83c1846..42dbaaa 100755 --- a/src/Resources/translations/messages.en.yml +++ b/src/Resources/translations/messages.en.yml @@ -46,8 +46,11 @@ setono_sylius_callout: assign: Assign bottom_left: Bottom left bottom_right: Bottom right + callout: Callout callouts: Callouts + callouts_product_list: Product list code: Code + delay_info: "NOTICE: Callouts are configured to wait %seconds% seconds before the assignment process is started" edit_callout: Edit callout enabled: Enabled ends_at: Ends at @@ -59,6 +62,7 @@ setono_sylius_callout: on_sale: On sale position: Position priority: Priority + rule: Rule rules: Rules select_position: Select position... starts_at: Starts at @@ -66,6 +70,3 @@ setono_sylius_callout: top_left: Top left top_right: Top right type: Type - callout: Callout - rule: Rule - callouts_product_list: Product list diff --git a/src/Resources/views/Admin/Callout/_form.html.twig b/src/Resources/views/Admin/Callout/_form.html.twig index 58ab9e9..e809f80 100755 --- a/src/Resources/views/Admin/Callout/_form.html.twig +++ b/src/Resources/views/Admin/Callout/_form.html.twig @@ -63,3 +63,10 @@ + +{% if get_callout_assignment_delay() > 0 %} +
+ + {{ 'setono_sylius_callout.ui.delay_info'|trans( { '%seconds%': get_callout_assignment_delay() }) }} +
+{% endif %} diff --git a/src/Twig/CalloutExtension.php b/src/Twig/CalloutExtension.php index a815fab..8eae0e3 100644 --- a/src/Twig/CalloutExtension.php +++ b/src/Twig/CalloutExtension.php @@ -9,12 +9,22 @@ final class CalloutExtension extends AbstractExtension { + public function __construct(private readonly int $delay) + { + } + public function getFunctions(): array { return [ new TwigFunction('get_callouts', [CalloutRuntime::class, 'getCallouts']), + new TwigFunction('get_callout_assignment_delay', $this->getDelay(...)), new TwigFunction('render_class_attribute', [CalloutRuntime::class, 'renderClassAttribute']), new TwigFunction('render_callout', [CalloutRuntime::class, 'renderCallout'], ['is_safe' => ['html']]), ]; } + + public function getDelay(): int + { + return $this->delay; + } }