Skip to content

Commit

Permalink
Allow a delay when assigning callouts
Browse files Browse the repository at this point in the history
  • Loading branch information
loevgaard committed Jan 26, 2024
1 parent 6c89015 commit 225b23f
Show file tree
Hide file tree
Showing 14 changed files with 80 additions and 84 deletions.
11 changes: 10 additions & 1 deletion src/DependencyInjection/Configuration.php
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
2 changes: 2 additions & 0 deletions src/DependencyInjection/SetonoSyliusCalloutExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ public function load(array $configs, ContainerBuilder $container): void
* @var array{
* elements: list<string>,
* positions: list<string>,
* assignment: array{delay: int},
* resources: array
* } $config
*/
Expand All @@ -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);
}
Expand Down
24 changes: 16 additions & 8 deletions src/EventSubscriber/HandleCalloutUpdateSubscriber.php
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -21,12 +22,14 @@ final class HandleCalloutUpdateSubscriber implements EventSubscriberInterface
/**
* The keys are the callout codes and the values are true
*
* @var array<string, bool>
* @var array<string, CalloutInterface>
*/
private array $calloutsToAssign = [];

public function __construct(private readonly MessageBusInterface $commandBus)
{
public function __construct(

Check failure on line 29 in src/EventSubscriber/HandleCalloutUpdateSubscriber.php

View workflow job for this annotation

GitHub Actions / Backwards Compatibility Check

The number of required arguments for Setono\SyliusCalloutPlugin\EventSubscriber\HandleCalloutUpdateSubscriber#__construct() increased from 1 to 2
private readonly MessageBusInterface $commandBus,
private readonly int $processingDelay,
) {
}

public static function getSubscribedEvents(): array
Expand All @@ -47,7 +50,7 @@ public function prePersist(PrePersistEventArgs $event): void
return;
}

$this->calloutsToAssign[(string) $callout->getCode()] = true;
$this->calloutsToAssign[(string) $callout->getCode()] = $callout;
}

/**
Expand Down Expand Up @@ -91,7 +94,7 @@ private function preUpdateCallout(CalloutInterface $callout, PreUpdateEventArgs
return;
}

$this->calloutsToAssign[(string) $callout->getCode()] = true;
$this->calloutsToAssign[(string) $callout->getCode()] = $callout;
}

/**
Expand All @@ -108,19 +111,24 @@ 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
{
if ([] === $this->calloutsToAssign) {
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);
}
}
31 changes: 0 additions & 31 deletions src/Message/Command/AssignCallout.php

This file was deleted.

8 changes: 6 additions & 2 deletions src/Message/Command/AssignCallouts.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,11 @@
*/
final class AssignCallouts implements CommandInterface
{
/** @var list<string> */
/**
* This is a list of arrays where the first element is the callout code and the second element is the version
*
* @var list<array{string, int|null}>
*/
public array $callouts = [];

/**
Expand All @@ -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];
}
}
}
32 changes: 0 additions & 32 deletions src/Message/Handler/AssignCalloutHandler.php

This file was deleted.

22 changes: 21 additions & 1 deletion src/Message/Handler/AssignCalloutsHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
2 changes: 2 additions & 0 deletions src/Model/ProductTrait.php
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions src/Resources/config/services/event_subscriber.xml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
<service id="setono_sylius_callout.event_subscriber.handle_callout_update"
class="Setono\SyliusCalloutPlugin\EventSubscriber\HandleCalloutUpdateSubscriber">
<argument type="service" id="setono_sylius_callout.command_bus"/>
<argument>%setono_sylius_callout.assignment.delay%</argument>

<tag name="doctrine.event_listener" event="prePersist"/>
<tag name="doctrine.event_listener" event="preUpdate"/>
Expand Down
6 changes: 0 additions & 6 deletions src/Resources/config/services/message.xml
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,6 @@
<argument>%sylius.model.product.class%</argument>
</service>

<service id="setono_sylius_callout.message.handler.assign_callout"
class="Setono\SyliusCalloutPlugin\Message\Handler\AssignCalloutHandler"
parent="setono_sylius_callout.message.handler.abstract_assign_callouts">
<tag name="messenger.message_handler"/>
</service>

<service id="setono_sylius_callout.message.handler.assign_callouts"
class="Setono\SyliusCalloutPlugin\Message\Handler\AssignCalloutsHandler"
parent="setono_sylius_callout.message.handler.abstract_assign_callouts">
Expand Down
1 change: 1 addition & 0 deletions src/Resources/config/services/twig.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
<services>
<service id="setono_sylius_callout.twig.callout_extension"
class="Setono\SyliusCalloutPlugin\Twig\CalloutExtension">
<argument>%setono_sylius_callout.assignment.delay%</argument>
<tag name="twig.extension"/>
</service>

Expand Down
7 changes: 4 additions & 3 deletions src/Resources/translations/messages.en.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -59,13 +62,11 @@ setono_sylius_callout:
on_sale: On sale
position: Position
priority: Priority
rule: Rule
rules: Rules
select_position: Select position...
starts_at: Starts at
text: Text
top_left: Top left
top_right: Top right
type: Type
callout: Callout
rule: Rule
callouts_product_list: Product list
7 changes: 7 additions & 0 deletions src/Resources/views/Admin/Callout/_form.html.twig
Original file line number Diff line number Diff line change
Expand Up @@ -63,3 +63,10 @@
</div>
</div>
</div>

{% if get_callout_assignment_delay() > 0 %}
<div class="ui icon info message" style="max-width: fit-content;">
<i class="info circle icon"></i>
{{ 'setono_sylius_callout.ui.delay_info'|trans( { '%seconds%': get_callout_assignment_delay() }) }}
</div>
{% endif %}
10 changes: 10 additions & 0 deletions src/Twig/CalloutExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
}

0 comments on commit 225b23f

Please sign in to comment.