diff --git a/src/Sylius/Bundle/ApiBundle/Checker/AppliedCouponEligibilityChecker.php b/src/Sylius/Bundle/ApiBundle/Checker/AppliedCouponEligibilityChecker.php
new file mode 100644
index 000000000000..affaaf3bb62d
--- /dev/null
+++ b/src/Sylius/Bundle/ApiBundle/Checker/AppliedCouponEligibilityChecker.php
@@ -0,0 +1,57 @@
+promotionChecker = $promotionChecker;
+ $this->promotionCouponChecker = $promotionCouponChecker;
+ }
+
+ public function isEligible(PromotionCouponInterface $promotionCoupon, OrderInterface $cart): bool
+ {
+ /** @var PromotionInterface $promotion */
+ $promotion = $promotionCoupon->getPromotion();
+
+ if (!$promotion->getChannels()->contains($cart->getChannel())) {
+ return false;
+ }
+
+ if (!$this->promotionCouponChecker->isEligible($cart, $promotionCoupon)) {
+ return false;
+ }
+
+ if (!$this->promotionChecker->isEligible($cart, $promotionCoupon->getPromotion())) {
+ return false;
+ }
+
+ return true;
+ }
+}
diff --git a/src/Sylius/Bundle/ApiBundle/Checker/AppliedCouponEligibilityCheckerInterface.php b/src/Sylius/Bundle/ApiBundle/Checker/AppliedCouponEligibilityCheckerInterface.php
new file mode 100644
index 000000000000..df98e7d33841
--- /dev/null
+++ b/src/Sylius/Bundle/ApiBundle/Checker/AppliedCouponEligibilityCheckerInterface.php
@@ -0,0 +1,13 @@
+
+
+
+
+
+
-
diff --git a/src/Sylius/Bundle/ApiBundle/Validator/Constraints/PromotionCouponEligibilityValidator.php b/src/Sylius/Bundle/ApiBundle/Validator/Constraints/PromotionCouponEligibilityValidator.php
index 187d1a4aaed7..7a77f47969e5 100644
--- a/src/Sylius/Bundle/ApiBundle/Validator/Constraints/PromotionCouponEligibilityValidator.php
+++ b/src/Sylius/Bundle/ApiBundle/Validator/Constraints/PromotionCouponEligibilityValidator.php
@@ -13,13 +13,11 @@
namespace Sylius\Bundle\ApiBundle\Validator\Constraints;
+use Sylius\Bundle\ApiBundle\Checker\AppliedCouponEligibilityCheckerInterface;
use Sylius\Bundle\ApiBundle\Command\Cart\ApplyCouponToCart;
use Sylius\Component\Core\Model\OrderInterface;
-use Sylius\Component\Core\Model\PromotionInterface;
+use Sylius\Component\Core\Model\PromotionCouponInterface;
use Sylius\Component\Core\Repository\OrderRepositoryInterface;
-use Sylius\Component\Promotion\Checker\Eligibility\PromotionCouponEligibilityCheckerInterface;
-use Sylius\Component\Promotion\Checker\Eligibility\PromotionEligibilityCheckerInterface;
-use Sylius\Component\Promotion\Model\PromotionCouponInterface;
use Sylius\Component\Promotion\Repository\PromotionCouponRepositoryInterface;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
@@ -34,22 +32,17 @@ final class PromotionCouponEligibilityValidator extends ConstraintValidator
/** @var OrderRepositoryInterface */
private $orderRepository;
- /** @var PromotionEligibilityCheckerInterface */
- private $promotionChecker;
-
- /** @var PromotionCouponEligibilityCheckerInterface */
- private $promotionCouponChecker;
+ /** @var AppliedCouponEligibilityCheckerInterface */
+ private $appliedCouponEligibilityChecker;
public function __construct(
PromotionCouponRepositoryInterface $promotionCouponRepository,
OrderRepositoryInterface $orderRepository,
- PromotionEligibilityCheckerInterface $promotionChecker,
- PromotionCouponEligibilityCheckerInterface $promotionCouponChecker
+ AppliedCouponEligibilityCheckerInterface $appliedCouponEligibilityChecker
) {
$this->promotionCouponRepository = $promotionCouponRepository;
$this->orderRepository = $orderRepository;
- $this->promotionChecker = $promotionChecker;
- $this->promotionCouponChecker = $promotionCouponChecker;
+ $this->appliedCouponEligibilityChecker = $appliedCouponEligibilityChecker;
}
public function validate($value, Constraint $constraint): void
@@ -62,9 +55,6 @@ public function validate($value, Constraint $constraint): void
/** @var PromotionCouponInterface|null $promotionCoupon */
$promotionCoupon = $this->promotionCouponRepository->findOneBy(['code' => $value->couponCode]);
- /** @var PromotionInterface $promotion */
- $promotion = $promotionCoupon->getPromotion();
-
/** @var OrderInterface $cart */
$cart = $this->orderRepository->findCartByTokenValue($value->getOrderTokenValue());
@@ -72,16 +62,13 @@ public function validate($value, Constraint $constraint): void
if (
$promotionCoupon === null ||
- !$this->promotionCouponChecker->isEligible($cart, $promotionCoupon) ||
- !$this->promotionChecker->isEligible($cart, $promotionCoupon->getPromotion()) ||
- !$promotion->getChannels()->contains($cart->getChannel())
+ !$this->appliedCouponEligibilityChecker->isEligible($promotionCoupon, $cart)
) {
- $this->addViolation('sylius.promotion_coupon.is_invalid', 'couponCode');
+ $this->context
+ ->buildViolation('sylius.promotion_coupon.is_invalid')
+ ->atPath('couponCode')
+ ->addViolation()
+ ;
}
}
-
- private function addViolation(string $message, string $path): void
- {
- $this->context->buildViolation($message)->atPath($path)->addViolation();
- }
}
diff --git a/src/Sylius/Bundle/ApiBundle/spec/Checker/AppliedCouponEligibilityCheckerSpec.php b/src/Sylius/Bundle/ApiBundle/spec/Checker/AppliedCouponEligibilityCheckerSpec.php
new file mode 100644
index 000000000000..b0399ff06492
--- /dev/null
+++ b/src/Sylius/Bundle/ApiBundle/spec/Checker/AppliedCouponEligibilityCheckerSpec.php
@@ -0,0 +1,133 @@
+beConstructedWith($promotionChecker, $promotionCouponChecker);
+ }
+
+ function it_implements_promotion_coupon_eligibility_checker_interface(): void
+ {
+ $this->shouldImplement(AppliedCouponEligibilityCheckerInterface::class);
+ }
+
+ function it_returns_false_if_cart_channel_is_not_one_of_promotion_channels(
+ PromotionEligibilityCheckerInterface $promotionChecker,
+ PromotionCouponEligibilityCheckerInterface $promotionCouponChecker,
+ PromotionCouponInterface $promotionCoupon,
+ PromotionInterface $promotion,
+ OrderInterface $cart,
+ ChannelInterface $firstChannel,
+ ChannelInterface $secondChannel,
+ ChannelInterface $thirdChannel
+ ): void {
+ $promotionCoupon->getPromotion()->willReturn($promotion);
+
+ $promotion->getChannels()->willReturn(new ArrayCollection([
+ $secondChannel->getWrappedObject(),
+ $thirdChannel->getWrappedObject()
+ ]));
+ $cart->getChannel()->willReturn($firstChannel);
+
+ $promotionChecker->isEligible(Argument::any())->shouldNotBeCalled();
+ $promotionCouponChecker->isEligible(Argument::any())->shouldNotBeCalled();
+
+ $this->isEligible($promotionCoupon, $cart)->shouldReturn(false);
+ }
+
+ function it_returns_false_if_coupon_is_not_eligible(
+ PromotionEligibilityCheckerInterface $promotionChecker,
+ PromotionCouponEligibilityCheckerInterface $promotionCouponChecker,
+ PromotionCouponInterface $promotionCoupon,
+ PromotionInterface $promotion,
+ OrderInterface $cart,
+ ChannelInterface $firstChannel,
+ ChannelInterface $secondChannel
+ ): void {
+ $promotionCoupon->getPromotion()->willReturn($promotion);
+
+ $promotion->getChannels()->willReturn(new ArrayCollection([
+ $firstChannel->getWrappedObject(),
+ $secondChannel->getWrappedObject()
+ ]));
+ $cart->getChannel()->willReturn($firstChannel);
+
+ $promotionCouponChecker->isEligible($cart, $promotionCoupon)->willReturn(false);
+ $promotionChecker->isEligible(Argument::any())->shouldNotBeCalled();
+
+ $this->isEligible($promotionCoupon, $cart)->shouldReturn(false);
+ }
+
+ function it_returns_false_if_promotion_is_not_eligible(
+ PromotionEligibilityCheckerInterface $promotionChecker,
+ PromotionCouponEligibilityCheckerInterface $promotionCouponChecker,
+ PromotionCouponInterface $promotionCoupon,
+ PromotionInterface $promotion,
+ OrderInterface $cart,
+ ChannelInterface $firstChannel,
+ ChannelInterface $secondChannel
+ ): void {
+ $promotionCoupon->getPromotion()->willReturn($promotion);
+
+ $promotion->getChannels()->willReturn(new ArrayCollection([
+ $firstChannel->getWrappedObject(),
+ $secondChannel->getWrappedObject()
+ ]));
+ $cart->getChannel()->willReturn($firstChannel);
+
+ $promotionCouponChecker->isEligible($cart, $promotionCoupon)->willReturn(true);
+ $promotionChecker->isEligible($cart, $promotion)->willReturn(false);
+
+ $this->isEligible($promotionCoupon, $cart)->shouldReturn(false);
+ }
+
+ function it_returns_true_if_promotion_and_coupon_are_eligible(
+ PromotionEligibilityCheckerInterface $promotionChecker,
+ PromotionCouponEligibilityCheckerInterface $promotionCouponChecker,
+ PromotionCouponInterface $promotionCoupon,
+ PromotionInterface $promotion,
+ OrderInterface $cart,
+ ChannelInterface $firstChannel,
+ ChannelInterface $secondChannel
+ ): void {
+ $promotionCoupon->getPromotion()->willReturn($promotion);
+
+ $promotion->getChannels()->willReturn(new ArrayCollection([
+ $firstChannel->getWrappedObject(),
+ $secondChannel->getWrappedObject()
+ ]));
+ $cart->getChannel()->willReturn($firstChannel);
+
+ $promotionCouponChecker->isEligible($cart, $promotionCoupon)->willReturn(true);
+ $promotionChecker->isEligible($cart, $promotion)->willReturn(true);
+
+ $this->isEligible($promotionCoupon, $cart)->shouldReturn(true);
+ }
+}
diff --git a/src/Sylius/Bundle/ApiBundle/spec/Validator/Constraints/PromotionCouponEligibilityValidatorSpec.php b/src/Sylius/Bundle/ApiBundle/spec/Validator/Constraints/PromotionCouponEligibilityValidatorSpec.php
index 83bcfb04a4ad..ea3e8487c1b6 100644
--- a/src/Sylius/Bundle/ApiBundle/spec/Validator/Constraints/PromotionCouponEligibilityValidatorSpec.php
+++ b/src/Sylius/Bundle/ApiBundle/spec/Validator/Constraints/PromotionCouponEligibilityValidatorSpec.php
@@ -13,17 +13,13 @@
namespace spec\Sylius\Bundle\ApiBundle\Validator\Constraints;
-use Doctrine\Common\Collections\ArrayCollection;
use PhpSpec\ObjectBehavior;
+use Sylius\Bundle\ApiBundle\Checker\AppliedCouponEligibilityCheckerInterface;
use Sylius\Bundle\ApiBundle\Command\Cart\ApplyCouponToCart;
use Sylius\Bundle\ApiBundle\Validator\Constraints\PromotionCouponEligibility;
-use Sylius\Component\Core\Model\ChannelInterface;
use Sylius\Component\Core\Model\OrderInterface;
use Sylius\Component\Core\Model\PromotionCouponInterface;
-use Sylius\Component\Core\Model\PromotionInterface;
use Sylius\Component\Core\Repository\OrderRepositoryInterface;
-use Sylius\Component\Promotion\Checker\Eligibility\PromotionCouponEligibilityCheckerInterface;
-use Sylius\Component\Promotion\Checker\Eligibility\PromotionEligibilityCheckerInterface;
use Sylius\Component\Promotion\Repository\PromotionCouponRepositoryInterface;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidatorInterface;
@@ -35,14 +31,12 @@ final class PromotionCouponEligibilityValidatorSpec extends ObjectBehavior
function let(
PromotionCouponRepositoryInterface $promotionCouponRepository,
OrderRepositoryInterface $orderRepository,
- PromotionEligibilityCheckerInterface $promotionChecker,
- PromotionCouponEligibilityCheckerInterface $promotionCouponChecker
+ AppliedCouponEligibilityCheckerInterface $appliedCouponEligibilityChecker
): void {
$this->beConstructedWith(
$promotionCouponRepository,
$orderRepository,
- $promotionChecker,
- $promotionCouponChecker
+ $appliedCouponEligibilityChecker
);
}
@@ -61,15 +55,11 @@ function it_throws_an_exception_if_constraint_is_not_of_expected_type(): void
function it_does_not_add_violation_if_promotion_coupon_is_eligible(
PromotionCouponRepositoryInterface $promotionCouponRepository,
- PromotionCouponEligibilityCheckerInterface $promotionCouponChecker,
- PromotionEligibilityCheckerInterface $promotionChecker,
+ AppliedCouponEligibilityCheckerInterface $appliedCouponEligibilityChecker,
PromotionCouponInterface $promotionCoupon,
- PromotionInterface $promotion,
OrderRepositoryInterface $orderRepository,
OrderInterface $cart,
- ExecutionContextInterface $executionContext,
- ChannelInterface $firstChannel,
- ChannelInterface $secondChannel
+ ExecutionContextInterface $executionContext
): void {
$this->initialize($executionContext);
$constraint = new PromotionCouponEligibility();
@@ -78,18 +68,11 @@ function it_does_not_add_violation_if_promotion_coupon_is_eligible(
$value->setOrderTokenValue('token');
$promotionCouponRepository->findOneBy(['code' => 'couponCode'])->willReturn($promotionCoupon);
-
$orderRepository->findCartByTokenValue('token')->willReturn($cart);
- $cart->getChannel()->willReturn($firstChannel);
$cart->setPromotionCoupon($promotionCoupon)->shouldBeCalled();
- $promotionCouponChecker->isEligible($cart, $promotionCoupon)->willReturn(true);
-
- $promotionCoupon->getPromotion()->willReturn($promotion);
- $promotion->getChannels()->willReturn(new ArrayCollection([$firstChannel->getWrappedObject(), $secondChannel->getWrappedObject()]));
-
- $promotionChecker->isEligible($cart, $promotion)->willReturn(true);
+ $appliedCouponEligibilityChecker->isEligible($promotionCoupon, $cart)->willReturn(true);
$executionContext->buildViolation('sylius.promotion_coupon.is_invalid')->shouldNotBeCalled();
@@ -98,80 +81,8 @@ function it_does_not_add_violation_if_promotion_coupon_is_eligible(
function it_adds_violation_if_promotion_coupon_is_not_eligible(
PromotionCouponRepositoryInterface $promotionCouponRepository,
- PromotionCouponEligibilityCheckerInterface $promotionCouponChecker,
- PromotionCouponInterface $promotionCoupon,
- OrderRepositoryInterface $orderRepository,
- OrderInterface $cart,
- ExecutionContextInterface $executionContext,
- ConstraintViolationBuilderInterface $constraintViolationBuilder
- ): void {
- $this->initialize($executionContext);
- $constraint = new PromotionCouponEligibility();
-
- $value = new ApplyCouponToCart('couponCode');
- $value->setOrderTokenValue('token');
-
- $promotionCouponRepository->findOneBy(['code' => 'couponCode'])->willReturn($promotionCoupon);
-
- $orderRepository->findCartByTokenValue('token')->willReturn($cart);
-
- $cart->setPromotionCoupon($promotionCoupon)->shouldBeCalled();
-
- $promotionCouponChecker->isEligible($cart, $promotionCoupon)->willReturn(false);
-
- $executionContext->buildViolation('sylius.promotion_coupon.is_invalid')->willReturn($constraintViolationBuilder);
- $constraintViolationBuilder->atPath('couponCode')->willReturn($constraintViolationBuilder);
- $constraintViolationBuilder->addViolation()->shouldBeCalled();
-
- $this->validate($value, $constraint);
- }
-
- function it_adds_violation_if_promotion_is_not_available_in_cart_channel(
- PromotionCouponRepositoryInterface $promotionCouponRepository,
- PromotionCouponEligibilityCheckerInterface $promotionCouponChecker,
- PromotionEligibilityCheckerInterface $promotionChecker,
- PromotionCouponInterface $promotionCoupon,
- PromotionInterface $promotion,
- OrderRepositoryInterface $orderRepository,
- OrderInterface $cart,
- ExecutionContextInterface $executionContext,
- ConstraintViolationBuilderInterface $constraintViolationBuilder,
- ChannelInterface $firstChannel,
- ChannelInterface $secondChannel,
- ChannelInterface $thirdChannel
- ): void {
- $this->initialize($executionContext);
- $constraint = new PromotionCouponEligibility();
-
- $value = new ApplyCouponToCart('couponCode');
- $value->setOrderTokenValue('token');
-
- $promotionCouponRepository->findOneBy(['code' => 'couponCode'])->willReturn($promotionCoupon);
- $promotionCoupon->getPromotion()->willReturn($promotion);
- $promotion->getChannels()->willReturn(new ArrayCollection([$firstChannel->getWrappedObject(), $secondChannel->getWrappedObject()]));
-
- $orderRepository->findCartByTokenValue('token')->willReturn($cart);
- $cart->getChannel()->willReturn($thirdChannel);
-
- $cart->setPromotionCoupon($promotionCoupon)->shouldBeCalled();
-
- $promotionCouponChecker->isEligible($cart, $promotionCoupon)->willReturn(true);
-
- $promotionChecker->isEligible($cart, $promotion)->willReturn(false);
-
- $executionContext->buildViolation('sylius.promotion_coupon.is_invalid')->willReturn($constraintViolationBuilder);
- $constraintViolationBuilder->atPath('couponCode')->willReturn($constraintViolationBuilder);
- $constraintViolationBuilder->addViolation()->shouldBeCalled();
-
- $this->validate($value, $constraint);
- }
-
- function it_adds_violation_if_promotion_is_not_eligible(
- PromotionCouponRepositoryInterface $promotionCouponRepository,
- PromotionCouponEligibilityCheckerInterface $promotionCouponChecker,
- PromotionEligibilityCheckerInterface $promotionChecker,
+ AppliedCouponEligibilityCheckerInterface $appliedCouponEligibilityChecker,
PromotionCouponInterface $promotionCoupon,
- PromotionInterface $promotion,
OrderRepositoryInterface $orderRepository,
OrderInterface $cart,
ExecutionContextInterface $executionContext,
@@ -184,15 +95,11 @@ function it_adds_violation_if_promotion_is_not_eligible(
$value->setOrderTokenValue('token');
$promotionCouponRepository->findOneBy(['code' => 'couponCode'])->willReturn($promotionCoupon);
-
$orderRepository->findCartByTokenValue('token')->willReturn($cart);
$cart->setPromotionCoupon($promotionCoupon)->shouldBeCalled();
- $promotionCouponChecker->isEligible($cart, $promotionCoupon)->willReturn(true);
-
- $promotionCoupon->getPromotion()->willReturn($promotion);
- $promotionChecker->isEligible($cart, $promotion)->willReturn(false);
+ $appliedCouponEligibilityChecker->isEligible($promotionCoupon, $cart)->willReturn(false);
$executionContext->buildViolation('sylius.promotion_coupon.is_invalid')->willReturn($constraintViolationBuilder);
$constraintViolationBuilder->atPath('couponCode')->willReturn($constraintViolationBuilder);