diff --git a/composer.json b/composer.json
index b70e4501..90c1c80b 100644
--- a/composer.json
+++ b/composer.json
@@ -73,7 +73,8 @@
"allow-plugins": {
"dealerdirect/phpcodesniffer-composer-installer": false,
"ergebnis/composer-normalize": true,
- "symfony/thanks": true
+ "symfony/thanks": true,
+ "composer/package-versions-deprecated": true
},
"sort-packages": true
},
diff --git a/src/Applicator/GiftCardApplicator.php b/src/Applicator/GiftCardApplicator.php
index 7a81e444..09441c30 100644
--- a/src/Applicator/GiftCardApplicator.php
+++ b/src/Applicator/GiftCardApplicator.php
@@ -32,17 +32,12 @@ public function __construct(
}
/**
- * @param string|GiftCardInterface|mixed $giftCard
+ * @throws GiftCardNotFoundException if gift card is not found
+ * @throws ChannelMismatchException if the orders channel does not match the gift cards channel
*/
- public function apply(OrderInterface $order, $giftCard): void
+ public function apply(OrderInterface $order, string $giftCardOrPromotionCode): void
{
- if (is_string($giftCard)) {
- $giftCard = $this->getGiftCard($giftCard);
- }
-
- if (!$giftCard instanceof GiftCardInterface) {
- throw new GiftCardNotFoundException($giftCard);
- }
+ $giftCard = $this->getGiftCard($giftCardOrPromotionCode);
$orderChannel = $order->getChannel();
if (null === $orderChannel) {
@@ -59,10 +54,6 @@ public function apply(OrderInterface $order, $giftCard): void
}
$order->addGiftCard($giftCard);
-
- $this->orderProcessor->process($order);
-
- $this->orderManager->flush();
}
/**
diff --git a/src/Applicator/GiftCardApplicatorInterface.php b/src/Applicator/GiftCardApplicatorInterface.php
index 58c0c9ce..f064c498 100644
--- a/src/Applicator/GiftCardApplicatorInterface.php
+++ b/src/Applicator/GiftCardApplicatorInterface.php
@@ -4,23 +4,11 @@
namespace Setono\SyliusGiftCardPlugin\Applicator;
-use Setono\SyliusGiftCardPlugin\Exception\ChannelMismatchException;
-use Setono\SyliusGiftCardPlugin\Exception\GiftCardNotFoundException;
use Setono\SyliusGiftCardPlugin\Model\GiftCardInterface;
use Setono\SyliusGiftCardPlugin\Model\OrderInterface;
-interface GiftCardApplicatorInterface
+interface GiftCardApplicatorInterface extends GiftCardOrPromotionApplicatorInterface
{
- /**
- * Applies $giftCard to $order
- *
- * @param string|GiftCardInterface $giftCard
- *
- * @throws GiftCardNotFoundException if gift card is not found
- * @throws ChannelMismatchException if the orders channel does not match the gift cards channel
- */
- public function apply(OrderInterface $order, $giftCard): void;
-
/**
* @param string|GiftCardInterface|mixed $giftCard
*/
diff --git a/src/Applicator/GiftCardOrPromotionApplicator.php b/src/Applicator/GiftCardOrPromotionApplicator.php
new file mode 100644
index 00000000..74c9f290
--- /dev/null
+++ b/src/Applicator/GiftCardOrPromotionApplicator.php
@@ -0,0 +1,49 @@
+applicators = new PriorityQueue();
+
+ $this->orderProcessor = $orderProcessor;
+ $this->orderManager = $orderManager;
+ }
+
+ public function addApplicator(GiftCardOrPromotionApplicatorInterface $applicator, int $priority = 0): void
+ {
+ $this->applicators->insert($applicator, $priority);
+ }
+
+ public function apply(OrderInterface $order, string $giftCardOrPromotionCode): void
+ {
+ foreach ($this->applicators->toArray() as $applicator) {
+ try {
+ $applicator->apply($order, $giftCardOrPromotionCode);
+
+ break;
+ } catch (ExceptionInterface $e) {
+ }
+ }
+
+ $this->orderProcessor->process($order);
+
+ $this->orderManager->flush();
+ }
+}
diff --git a/src/Applicator/GiftCardOrPromotionApplicatorInterface.php b/src/Applicator/GiftCardOrPromotionApplicatorInterface.php
new file mode 100644
index 00000000..15e1262a
--- /dev/null
+++ b/src/Applicator/GiftCardOrPromotionApplicatorInterface.php
@@ -0,0 +1,12 @@
+promotionCouponRepository = $promotionCouponRepository;
+ }
+
+ public function apply(OrderInterface $order, string $giftCardOrPromotionCode): void
+ {
+ $promotionCoupon = $this->promotionCouponRepository->findOneBy(['code' => $giftCardOrPromotionCode]);
+ if (null === $promotionCoupon) {
+ throw new PromotionCouponNotFoundException($giftCardOrPromotionCode);
+ }
+
+ $order->setPromotionCoupon($promotionCoupon);
+ }
+}
diff --git a/src/Controller/Action/AddGiftCardToOrderAction.php b/src/Controller/Action/AddGiftCardOrPromotionToOrderAction.php
similarity index 70%
rename from src/Controller/Action/AddGiftCardToOrderAction.php
rename to src/Controller/Action/AddGiftCardOrPromotionToOrderAction.php
index 301be4a0..a9a9cb92 100644
--- a/src/Controller/Action/AddGiftCardToOrderAction.php
+++ b/src/Controller/Action/AddGiftCardOrPromotionToOrderAction.php
@@ -4,8 +4,8 @@
namespace Setono\SyliusGiftCardPlugin\Controller\Action;
-use Setono\SyliusGiftCardPlugin\Applicator\GiftCardApplicatorInterface;
-use Setono\SyliusGiftCardPlugin\Form\Type\AddGiftCardToOrderType;
+use Setono\SyliusGiftCardPlugin\Applicator\GiftCardOrPromotionApplicatorInterface;
+use Setono\SyliusGiftCardPlugin\Form\Type\AddGiftCardOrPromotionToOrderType;
use Setono\SyliusGiftCardPlugin\Model\OrderInterface;
use Setono\SyliusGiftCardPlugin\Resolver\RedirectUrlResolverInterface;
use Sylius\Component\Order\Context\CartContextInterface;
@@ -16,9 +16,8 @@
use Symfony\Component\HttpFoundation\Session\Flash\FlashBagInterface;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Twig\Environment;
-use Webmozart\Assert\Assert;
-final class AddGiftCardToOrderAction
+final class AddGiftCardOrPromotionToOrderAction
{
private FormFactoryInterface $formFactory;
@@ -26,7 +25,7 @@ final class AddGiftCardToOrderAction
private FlashBagInterface $flashBag;
- private GiftCardApplicatorInterface $giftCardApplicator;
+ private GiftCardOrPromotionApplicatorInterface $giftCardOrPromotionApplicator;
private RedirectUrlResolverInterface $redirectRouteResolver;
@@ -36,14 +35,14 @@ public function __construct(
FormFactoryInterface $formFactory,
CartContextInterface $cartContext,
FlashBagInterface $flashBag,
- GiftCardApplicatorInterface $giftCardApplicator,
+ GiftCardOrPromotionApplicatorInterface $giftCardOrPromotionApplicator,
RedirectUrlResolverInterface $redirectRouteResolver,
Environment $twig
) {
$this->formFactory = $formFactory;
$this->cartContext = $cartContext;
$this->flashBag = $flashBag;
- $this->giftCardApplicator = $giftCardApplicator;
+ $this->giftCardOrPromotionApplicator = $giftCardOrPromotionApplicator;
$this->redirectRouteResolver = $redirectRouteResolver;
$this->twig = $twig;
}
@@ -57,14 +56,16 @@ public function __invoke(Request $request): Response
throw new NotFoundHttpException();
}
- $addGiftCardToOrderCommand = new AddGiftCardToOrderCommand();
- $form = $this->formFactory->create(AddGiftCardToOrderType::class, $addGiftCardToOrderCommand);
+ $addGiftCardOrPromotionToOrderCommand = new AddGiftCardOrPromotionToOrderCommand();
+ $form = $this->formFactory->create(
+ AddGiftCardOrPromotionToOrderType::class,
+ $addGiftCardOrPromotionToOrderCommand
+ );
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
- $giftCard = $addGiftCardToOrderCommand->getGiftCard();
- Assert::notNull($giftCard);
- $this->giftCardApplicator->apply($order, $giftCard);
+ $giftCardOrPromotionCode = $addGiftCardOrPromotionToOrderCommand->getCode();
+ $this->giftCardOrPromotionApplicator->apply($order, $giftCardOrPromotionCode);
$this->flashBag->add('success', 'setono_sylius_gift_card.gift_card_added');
diff --git a/src/Controller/Action/AddGiftCardOrPromotionToOrderCommand.php b/src/Controller/Action/AddGiftCardOrPromotionToOrderCommand.php
new file mode 100644
index 00000000..338c84ab
--- /dev/null
+++ b/src/Controller/Action/AddGiftCardOrPromotionToOrderCommand.php
@@ -0,0 +1,20 @@
+code;
+ }
+
+ public function setCode(?string $code): void
+ {
+ $this->code = $code;
+ }
+}
diff --git a/src/Controller/Action/AddGiftCardToOrderCommand.php b/src/Controller/Action/AddGiftCardToOrderCommand.php
deleted file mode 100644
index 487d7a45..00000000
--- a/src/Controller/Action/AddGiftCardToOrderCommand.php
+++ /dev/null
@@ -1,22 +0,0 @@
-giftCard;
- }
-
- public function setGiftCard(?GiftCardInterface $giftCard): void
- {
- $this->giftCard = $giftCard;
- }
-}
diff --git a/src/DependencyInjection/Compiler/RegisterGiftCardOrPromotionApplicatorsPass.php b/src/DependencyInjection/Compiler/RegisterGiftCardOrPromotionApplicatorsPass.php
new file mode 100644
index 00000000..04f71421
--- /dev/null
+++ b/src/DependencyInjection/Compiler/RegisterGiftCardOrPromotionApplicatorsPass.php
@@ -0,0 +1,34 @@
+setAlias(
+ GiftCardOrPromotionApplicatorInterface::class,
+ 'setono_sylius_gift_card.gift_card_or_promotion_applicator.applicator'
+ );
+ }
+}
diff --git a/src/DependencyInjection/Compiler/UseSameInputPass.php b/src/DependencyInjection/Compiler/UseSameInputPass.php
new file mode 100644
index 00000000..fe60617e
--- /dev/null
+++ b/src/DependencyInjection/Compiler/UseSameInputPass.php
@@ -0,0 +1,25 @@
+getParameter(
+ 'setono_sylius_gift_card.cart.use_same_input_for_promotion_and_gift_card'
+ );
+
+ if (!$useSameInputForGiftCardAndCoupon) {
+ if ($container->hasDefinition('setono_sylius_gift_card.applicator.promotion')) {
+ $container->removeDefinition('setono_sylius_gift_card.applicator.promotion');
+ }
+ }
+ }
+}
diff --git a/src/DependencyInjection/Configuration.php b/src/DependencyInjection/Configuration.php
index 235023b6..a74541ae 100644
--- a/src/DependencyInjection/Configuration.php
+++ b/src/DependencyInjection/Configuration.php
@@ -44,6 +44,13 @@ public function getConfigTreeBuilder(): TreeBuilder
->min(1)
->max(255)
->example(16)
+ ->end()
+ ->arrayNode('cart')
+ ->addDefaultsIfNotSet()
+ ->children()
+ ->booleanNode('use_same_input_for_promotion_and_gift_card')->defaultFalse()->end()
+ ->end()
+ ->end()
;
$this->addResourcesSection($rootNode);
diff --git a/src/DependencyInjection/SetonoSyliusGiftCardExtension.php b/src/DependencyInjection/SetonoSyliusGiftCardExtension.php
index 00452b31..adfec6e3 100644
--- a/src/DependencyInjection/SetonoSyliusGiftCardExtension.php
+++ b/src/DependencyInjection/SetonoSyliusGiftCardExtension.php
@@ -22,6 +22,16 @@ public function load(array $configs, ContainerBuilder $container): void
$loader = new XmlFileLoader($container, new FileLocator(__DIR__ . '/../Resources/config'));
$container->setParameter('setono_sylius_gift_card.code_length', $config['code_length']);
+ $useSameInputForPromotionAndGiftCard = false;
+ if (array_key_exists('cart', $config)
+ && array_key_exists('use_same_input_for_promotion_and_gift_card', $config['cart'])
+ ) {
+ $useSameInputForPromotionAndGiftCard = $config['cart']['use_same_input_for_promotion_and_gift_card'];
+ }
+ $container->setParameter(
+ 'setono_sylius_gift_card.cart.use_same_input_for_promotion_and_gift_card',
+ $useSameInputForPromotionAndGiftCard
+ );
$this->registerResources('setono_sylius_gift_card', $config['driver'], $config['resources'], $container);
diff --git a/src/Exception/GiftCardNotFoundException.php b/src/Exception/GiftCardNotFoundException.php
index 5faf906d..38cc98c0 100644
--- a/src/Exception/GiftCardNotFoundException.php
+++ b/src/Exception/GiftCardNotFoundException.php
@@ -13,6 +13,7 @@ final class GiftCardNotFoundException extends InvalidArgumentException implement
public function __construct(string $giftCard)
{
+ $this->giftCard = $giftCard;
$message = sprintf('The gift card with code "%s" was not found', $giftCard);
parent::__construct($message);
diff --git a/src/Exception/PromotionCouponNotFoundException.php b/src/Exception/PromotionCouponNotFoundException.php
new file mode 100644
index 00000000..b8272ebd
--- /dev/null
+++ b/src/Exception/PromotionCouponNotFoundException.php
@@ -0,0 +1,26 @@
+couponCode = $couponCode;
+ $message = sprintf('The coupon with code "%s" was not found', $couponCode);
+
+ parent::__construct($message);
+ }
+
+ public function getCouponCode(): string
+ {
+ return $this->couponCode;
+ }
+}
diff --git a/src/Form/Extension/CartTypeExtension.php b/src/Form/Extension/CartTypeExtension.php
new file mode 100644
index 00000000..d2625404
--- /dev/null
+++ b/src/Form/Extension/CartTypeExtension.php
@@ -0,0 +1,31 @@
+useSameInputForGiftCardAndPromotion = $useSameInputForGiftCardAndPromotion;
+ }
+
+ public function buildForm(FormBuilderInterface $builder, array $options)
+ {
+ if ($this->useSameInputForGiftCardAndPromotion) {
+ $builder->remove('promotionCoupon');
+ }
+ }
+
+ public static function getExtendedTypes(): iterable
+ {
+ return [CartType::class];
+ }
+}
diff --git a/src/Form/Type/AddGiftCardToOrderType.php b/src/Form/Type/AddGiftCardOrPromotionToOrderType.php
similarity index 59%
rename from src/Form/Type/AddGiftCardToOrderType.php
rename to src/Form/Type/AddGiftCardOrPromotionToOrderType.php
index 44126ca1..0ca1dcf3 100644
--- a/src/Form/Type/AddGiftCardToOrderType.php
+++ b/src/Form/Type/AddGiftCardOrPromotionToOrderType.php
@@ -4,29 +4,25 @@
namespace Setono\SyliusGiftCardPlugin\Form\Type;
-use Setono\SyliusGiftCardPlugin\Controller\Action\AddGiftCardToOrderCommand;
+use Setono\SyliusGiftCardPlugin\Controller\Action\AddGiftCardOrPromotionToOrderCommand;
use Symfony\Component\Form\AbstractType;
-use Symfony\Component\Form\DataTransformerInterface;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
-final class AddGiftCardToOrderType extends AbstractType
+final class AddGiftCardOrPromotionToOrderType extends AbstractType
{
- private DataTransformerInterface $giftCardToCodeDataTransformer;
-
private array $validationGroups;
- public function __construct(DataTransformerInterface $giftCardToCodeDataTransformer, array $validationGroups)
+ public function __construct(array $validationGroups)
{
- $this->giftCardToCodeDataTransformer = $giftCardToCodeDataTransformer;
$this->validationGroups = $validationGroups;
}
public function buildForm(FormBuilderInterface $builder, array $options): void
{
$builder
- ->add('giftCard', TextType::class, [
+ ->add('code', TextType::class, [
'label' => false,
'attr' => [
'placeholder' => 'setono_sylius_gift_card.ui.enter_gift_card_code',
@@ -34,20 +30,18 @@ public function buildForm(FormBuilderInterface $builder, array $options): void
'invalid_message' => 'setono_sylius_gift_card.add_gift_card_to_order_command.gift_card.does_not_exist',
])
;
-
- $builder->get('giftCard')->addModelTransformer($this->giftCardToCodeDataTransformer);
}
public function configureOptions(OptionsResolver $resolver): void
{
$resolver->setDefaults([
- 'data_class' => AddGiftCardToOrderCommand::class,
+ 'data_class' => AddGiftCardOrPromotionToOrderCommand::class,
'validation_groups' => $this->validationGroups,
]);
}
public function getBlockPrefix(): string
{
- return 'setono_sylius_gift_card_add_gift_card_to_order';
+ return 'setono_sylius_gift_card_add_gift_card_or_promotion_to_order';
}
}
diff --git a/src/Resources/config/services/applicator.xml b/src/Resources/config/services/applicator.xml
index 36ad81a4..d7f21426 100644
--- a/src/Resources/config/services/applicator.xml
+++ b/src/Resources/config/services/applicator.xml
@@ -10,8 +10,20 @@