-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathSetonoSyliusLoyaltyExtension.php
More file actions
177 lines (163 loc) · 7.84 KB
/
Copy pathSetonoSyliusLoyaltyExtension.php
File metadata and controls
177 lines (163 loc) · 7.84 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
<?php
declare(strict_types=1);
namespace Setono\SyliusLoyaltyPlugin\DependencyInjection;
use Setono\SyliusLoyaltyPlugin\Earning\Trigger\AwardOrderPointsStateMachineListener;
use Setono\SyliusLoyaltyPlugin\Earning\Trigger\ClawbackOrderPointsStateMachineListener;
use Setono\SyliusLoyaltyPlugin\Earning\Trigger\ReviewApprovedStateMachineListener;
use Setono\SyliusLoyaltyPlugin\Redemption\RedemptionStateMachineListener;
use Setono\SyliusLoyaltyPlugin\Rule\Amount\EarningAmountInterface;
use Setono\SyliusLoyaltyPlugin\Rule\Condition\EarningConditionInterface;
use Sylius\Bundle\ResourceBundle\DependencyInjection\Extension\AbstractResourceExtension;
use Sylius\Bundle\ResourceBundle\SyliusResourceBundle;
use Sylius\Component\Core\OrderCheckoutTransitions;
use Sylius\Component\Core\OrderPaymentTransitions;
use Sylius\Component\Core\ProductReviewTransitions;
use Sylius\Component\Order\OrderTransitions;
use Symfony\Component\Config\FileLocator;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Extension\PrependExtensionInterface;
use Symfony\Component\DependencyInjection\Loader\XmlFileLoader;
final class SetonoSyliusLoyaltyExtension extends AbstractResourceExtension implements PrependExtensionInterface
{
public function load(array $configs, ContainerBuilder $container): void
{
/** @var array{resources: array<string, mixed>} $config */
$config = $this->processConfiguration($this->getConfiguration([], $container), $configs);
$this->registerResources(
'setono_sylius_loyalty',
SyliusResourceBundle::DRIVER_DOCTRINE_ORM,
$config['resources'],
$container,
);
// A project can add its own earning condition or amount just by implementing the interface —
// the tag is applied automatically when the project has autoconfiguration enabled.
$container->registerForAutoconfiguration(EarningConditionInterface::class)
->addTag('setono_sylius_loyalty.earning_condition');
$container->registerForAutoconfiguration(EarningAmountInterface::class)
->addTag('setono_sylius_loyalty.earning_amount');
$loader = new XmlFileLoader($container, new FileLocator(__DIR__ . '/../Resources/config'));
$loader->load('services.xml');
}
public function prepend(ContainerBuilder $container): void
{
$this->registerCommandBus($container);
$this->registerWinzouCallbacks($container);
$this->registerShopUi($container);
}
/**
* Injects the cart redemption widget into the shop's cart summary.
*/
private function registerShopUi(ContainerBuilder $container): void
{
if (!$container->hasExtension('sylius_ui')) {
return;
}
// Injected into the in-form cart event (which exposes `form`) so the field binds to the cart
// form via form.vars.id and is submitted with the cart-save flow.
$container->prependExtensionConfig('sylius_ui', [
'events' => [
'sylius.shop.cart.summary.items' => [
'blocks' => [
'setono_sylius_loyalty_redemption' => [
'template' => '@SetonoSyliusLoyaltyPlugin/shop/cart/_redemption.html.twig',
],
],
],
],
]);
}
/**
* The plugin owns a dedicated command bus rather than reusing sylius.command_bus. The ledger manages
* its own transaction boundaries (pessimistic locks inside wrapInTransaction), so it must not run
* inside Sylius' command-bus doctrine_transaction middleware, which would wrap the whole handler in a
* single transaction and hold row locks far longer than intended. A dedicated bus (default
* middleware, no doctrine_transaction) also lets an application route the plugin's commands to an
* async transport independently of Sylius' bus.
*/
private function registerCommandBus(ContainerBuilder $container): void
{
$container->prependExtensionConfig('framework', [
'messenger' => [
'buses' => [
'setono_sylius_loyalty.command_bus' => [],
],
],
]);
}
/**
* Registers the winzou callbacks that fire the award and clawback triggers. The symfony/workflow
* counterparts are tagged in services.xml; both are always registered, and each only fires under the
* adapter the application applies transitions through (the ledger's idempotency covers any overlap).
*/
private function registerWinzouCallbacks(ContainerBuilder $container): void
{
if (!$container->hasExtension('winzou_state_machine')) {
return;
}
$award = '@' . AwardOrderPointsStateMachineListener::class;
$clawback = '@' . ClawbackOrderPointsStateMachineListener::class;
$redemption = '@' . RedemptionStateMachineListener::class;
$reviewAward = '@' . ReviewApprovedStateMachineListener::class;
$container->prependExtensionConfig('winzou_state_machine', [
OrderPaymentTransitions::GRAPH => [
'callbacks' => [
'after' => [
'setono_sylius_loyalty_award_order_points' => [
'on' => [OrderPaymentTransitions::TRANSITION_PAY],
'do' => [$award, 'onWinzouPaymentPaid'],
'args' => ['object'],
],
'setono_sylius_loyalty_clawback_order_points' => [
'on' => [OrderPaymentTransitions::TRANSITION_REFUND],
'do' => [$clawback, 'onWinzouPaymentRefunded'],
'args' => ['object'],
],
],
],
],
OrderCheckoutTransitions::GRAPH => [
'callbacks' => [
'after' => [
'setono_sylius_loyalty_redeem_order_points' => [
'on' => [OrderCheckoutTransitions::TRANSITION_COMPLETE],
'do' => [$redemption, 'onWinzouCheckoutCompleted'],
'args' => ['object'],
],
],
],
],
OrderTransitions::GRAPH => [
'callbacks' => [
'after' => [
'setono_sylius_loyalty_award_order_points' => [
'on' => [OrderTransitions::TRANSITION_FULFILL],
'do' => [$award, 'onWinzouOrderFulfilled'],
'args' => ['object'],
],
'setono_sylius_loyalty_clawback_order_points' => [
'on' => [OrderTransitions::TRANSITION_CANCEL],
'do' => [$clawback, 'onWinzouOrderCancelled'],
'args' => ['object'],
],
'setono_sylius_loyalty_rollback_redemption' => [
'on' => [OrderTransitions::TRANSITION_CANCEL],
'do' => [$redemption, 'onWinzouOrderCancelled'],
'args' => ['object'],
],
],
],
],
ProductReviewTransitions::GRAPH => [
'callbacks' => [
'after' => [
'setono_sylius_loyalty_award_review_points' => [
'on' => [ProductReviewTransitions::TRANSITION_ACCEPT],
'do' => [$reviewAward, 'onWinzouReviewAccepted'],
'args' => ['object'],
],
],
],
],
]);
}
}