Completed
Push — master ( c40585...4f6fb4 )
by Kamil
27s
created

OrderPromotionIntegrityChecker::check()   B

Complexity

Conditions 6
Paths 9

Size

Total Lines 39

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 39
rs 8.6737
c 0
b 0
f 0
cc 6
nc 9
nop 1
1
<?php
2
3
/*
4
 * This file is part of the Sylius package.
5
 *
6
 * (c) Paweł Jędrzejewski
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
declare(strict_types=1);
13
14
namespace Sylius\Bundle\ShopBundle\EventListener;
15
16
use Sylius\Bundle\ResourceBundle\Event\ResourceControllerEvent;
17
use Sylius\Component\Core\Model\OrderInterface;
18
use Sylius\Component\Order\SyliusCartEvents;
19
use Sylius\Component\Promotion\Action\PromotionApplicatorInterface;
20
use Sylius\Component\Promotion\Checker\Eligibility\PromotionEligibilityCheckerInterface;
21
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
22
use Symfony\Component\EventDispatcher\GenericEvent;
23
use Symfony\Component\HttpFoundation\RedirectResponse;
24
use Symfony\Component\Routing\RouterInterface;
25
use Webmozart\Assert\Assert;
26
27
final class OrderPromotionIntegrityChecker
28
{
29
    /**
30
     * @var PromotionEligibilityCheckerInterface
31
     */
32
    private $promotionEligibilityChecker;
33
34
    /**
35
     * @var PromotionApplicatorInterface
36
     */
37
    private $promotionApplicator;
38
39
    /**
40
     * @var EventDispatcherInterface
41
     */
42
    private $eventDispatcher;
43
44
    /**
45
     * @var RouterInterface
46
     */
47
    private $router;
48
49
    /**
50
     * @param PromotionEligibilityCheckerInterface $promotionEligibilityChecker
51
     * @param EventDispatcherInterface $eventDispatcher
52
     * @param RouterInterface $router
53
     * @param PromotionApplicatorInterface $promotionApplicator
54
     */
55
    public function __construct(
56
        PromotionEligibilityCheckerInterface $promotionEligibilityChecker,
57
        EventDispatcherInterface $eventDispatcher,
58
        RouterInterface $router,
59
        ?PromotionApplicatorInterface $promotionApplicator = null
60
    ) {
61
        if($promotionApplicator == null){
62
            @trigger_error("You need to supply an promotion applicator in order to work properly. In case you don't provide it, there will be valid cases that will fail due an incorrect recalculation.", \E_USER_DEPRECATED);
63
        }
64
65
        $this->promotionEligibilityChecker = $promotionEligibilityChecker;
66
        $this->eventDispatcher = $eventDispatcher;
67
        $this->router = $router;
68
        $this->promotionApplicator = $promotionApplicator;
69
    }
70
71
    /**
72
     * @param ResourceControllerEvent $event
73
     */
74
    public function check(ResourceControllerEvent $event): void
75
    {
76
        /** @var OrderInterface $order */
77
        $order = $event->getSubject();
78
79
        Assert::isInstanceOf($order, OrderInterface::class);
80
81
        // we create a new promotion collection and remove them from cart
82
        // so we can verify with original conditions (without the price being applied before check)
83
84
        $promotions = $order->getPromotions()->toArray();
85
86
        if($this->promotionApplicator !== null){
87
            foreach($promotions as $promotion){
88
                $this->promotionApplicator->revert($order, $promotion);
89
                $order->removePromotion($promotion);
90
            }
91
        }
92
93
        foreach ($promotions as $promotion) {
94
            if (!$this->promotionEligibilityChecker->isEligible($order, $promotion)) {
95
                $event->stop(
96
                    'sylius.order.promotion_integrity',
97
                    ResourceControllerEvent::TYPE_ERROR,
98
                    ['%promotionName%' => $promotion->getName()]
99
                );
100
101
                $event->setResponse(new RedirectResponse($this->router->generate('sylius_shop_checkout_complete')));
102
103
                $this->eventDispatcher->dispatch(SyliusCartEvents::CART_CHANGE, new GenericEvent($order));
104
105
                break;
106
            }
107
108
            if($this->promotionApplicator !== null){
109
                $this->promotionApplicator->apply($order, $promotion);
110
            }
111
        }
112
    }
113
}
114