Failed Conditions
Pull Request — master (#131)
by Łukasz
03:32
created

PromotionCouponCodeValidator::validate()   C

Complexity

Conditions 7
Paths 5

Size

Total Lines 43
Code Lines 22

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 43
rs 6.7272
cc 7
eloc 22
nc 5
nop 2
1
<?php
2
3
namespace Sylius\ShopApiPlugin\Validator;
4
5
use Sylius\Component\Core\Model\OrderInterface;
6
use Sylius\Component\Core\Model\PromotionCouponInterface;
7
use Sylius\Component\Core\Model\PromotionInterface;
8
use Sylius\Component\Core\Repository\OrderRepositoryInterface;
9
use Sylius\Component\Promotion\Checker\Eligibility\PromotionCouponEligibilityCheckerInterface;
10
use Sylius\Component\Promotion\Checker\Eligibility\PromotionEligibilityCheckerInterface;
11
use Sylius\Component\Promotion\Repository\PromotionCouponRepositoryInterface;
12
use Sylius\ShopApiPlugin\Request\AddCouponRequest;
13
use Symfony\Component\Validator\Constraint;
14
use Symfony\Component\Validator\ConstraintValidator;
15
use Webmozart\Assert\Assert;
16
17
final class PromotionCouponCodeValidator extends ConstraintValidator
18
{
19
    /**
20
     * @var OrderRepositoryInterface
21
     */
22
    private $orderRepository;
23
24
    /**
25
     * @var PromotionCouponRepositoryInterface
26
     */
27
    private $promotionCouponRepository;
28
29
    /**
30
     * @var PromotionCouponEligibilityCheckerInterface
31
     */
32
    private $couponEligibilityChecker;
33
34
    /**
35
     * @var PromotionEligibilityCheckerInterface
36
     */
37
    private $promotionEligibilityChecker;
38
39
    /**
40
     * @param OrderRepositoryInterface $orderRepository
41
     * @param PromotionCouponRepositoryInterface $promotionCouponRepository
42
     * @param PromotionCouponEligibilityCheckerInterface $couponEligibilityChecker
43
     * @param PromotionEligibilityCheckerInterface $promotionEligibilityChecker
44
     */
45
    public function __construct(
46
        OrderRepositoryInterface $orderRepository,
47
        PromotionCouponRepositoryInterface $promotionCouponRepository,
48
        PromotionCouponEligibilityCheckerInterface $couponEligibilityChecker,
49
        PromotionEligibilityCheckerInterface $promotionEligibilityChecker
50
    ) {
51
        $this->orderRepository = $orderRepository;
52
        $this->promotionCouponRepository = $promotionCouponRepository;
53
        $this->couponEligibilityChecker = $couponEligibilityChecker;
54
        $this->promotionEligibilityChecker = $promotionEligibilityChecker;
55
    }
56
57
    /**
58
     * {@inheritdoc}
59
     */
60
    public function validate($request, Constraint $constraint)
61
    {
62
        /** @var AddCouponRequest $request */
63
        Assert::isInstanceOf($request, AddCouponRequest::class);
64
65
        try {
66
            $command = $request->getCommand();
67
        } catch (\InvalidArgumentException $exception) {
68
            $this->buildViolation($constraint);
69
70
            return;
71
        }
72
73
        /** @var OrderInterface $cart */
74
        $cart = $this->orderRepository->findOneBy(['tokenValue' => $command->orderToken(), 'state' => OrderInterface::STATE_CART]);
75
76
        if (null === $cart) {
77
            return;
78
        }
79
80
        /** @var PromotionCouponInterface $coupon */
81
        $coupon = $this->promotionCouponRepository->findOneBy(['code' => $command->couponCode()]);
82
83
        if (null === $coupon) {
84
            $this->buildViolation($constraint);
85
86
            return;
87
        }
88
89
        /** @var PromotionInterface $promotion */
90
        $promotion = $coupon->getPromotion();
91
        $cart->setPromotionCoupon($coupon);
92
93
        if (
94
            !$promotion->hasChannel($cart->getChannel())
95
            || !$this->couponEligibilityChecker->isEligible($cart, $coupon)
96
            || !$this->promotionEligibilityChecker->isEligible($cart, $coupon->getPromotion())
97
        ) {
98
            $this->buildViolation($constraint);
99
        }
100
101
        $cart->setPromotionCoupon(null);
102
    }
103
104
    /**
105
     * @param Constraint $constraint
106
     */
107
    private function buildViolation(Constraint $constraint)
108
    {
109
        $this->context
110
            ->buildViolation($constraint->message)
111
            ->atPath('coupon')
112
            ->addViolation()
113
        ;
114
    }
115
}
116