Completed
Push — master ( dbff07...330d66 )
by Kamil
18:51
created

areCouponsEligibleForPromotion()   B

Complexity

Conditions 6
Paths 6

Size

Total Lines 24
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 24
rs 8.5125
cc 6
eloc 13
nc 6
nop 2
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
namespace Sylius\Component\Core\Promotion\Checker;
13
14
use Sylius\Component\Core\Model\CouponInterface;
15
use Sylius\Component\Core\Model\CustomerInterface;
16
use Sylius\Component\Core\Repository\OrderRepositoryInterface;
17
use Sylius\Component\Promotion\Checker\PromotionEligibilityChecker as BasePromotionEligibilityChecker;
18
use Sylius\Component\Promotion\Model\PromotionCouponAwareSubjectInterface;
19
use Sylius\Component\Promotion\Model\PromotionInterface;
20
use Sylius\Component\Promotion\Model\PromotionSubjectInterface;
21
use Sylius\Component\Promotion\SyliusPromotionEvents;
22
use Sylius\Component\Registry\ServiceRegistryInterface;
23
use Sylius\Component\User\Model\CustomerAwareInterface;
24
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
25
use Symfony\Component\EventDispatcher\GenericEvent;
26
27
class PromotionEligibilityChecker extends BasePromotionEligibilityChecker
28
{
29
    /**
30
     * @var OrderRepositoryInterface
31
     */
32
    private $subjectRepository;
33
34
    /**
35
     * @param OrderRepositoryInterface $subjectRepository
36
     * @param ServiceRegistryInterface $registry
37
     * @param EventDispatcherInterface $dispatcher
38
     */
39
    public function __construct(OrderRepositoryInterface $subjectRepository, ServiceRegistryInterface $registry, EventDispatcherInterface $dispatcher)
40
    {
41
        parent::__construct($registry, $dispatcher);
42
43
        $this->subjectRepository = $subjectRepository;
44
    }
45
46
    /**
47
     * {@inheritdoc}
48
     */
49
    protected function areCouponsEligibleForPromotion(PromotionSubjectInterface $subject, PromotionInterface $promotion)
50
    {
51
        if (!$subject instanceof CustomerAwareInterface) {
52
            return false;
53
        }
54
55
        $eligible = false;
56
57
        // Check to see if there is a per customer usage limit on coupon
58
        if ($subject instanceof PromotionCouponAwareSubjectInterface) {
59
            $coupon = $subject->getPromotionCoupon();
60
            if (null !== $coupon && $promotion === $coupon->getPromotion()) {
61
                $eligible = $this->isCouponEligibleToLimit($coupon, $promotion, $subject->getCustomer());
62
            }
63
        } else {
64
            return false;
65
        }
66
67
        if ($eligible) {
68
            $this->dispatcher->dispatch(SyliusPromotionEvents::COUPON_ELIGIBLE, new GenericEvent($promotion));
69
        }
70
71
        return $eligible;
72
    }
73
74
    private function isCouponEligibleToLimit(CouponInterface $coupon, PromotionInterface $promotion, CustomerInterface $customer = null)
75
    {
76
        if (!$coupon instanceof CouponInterface) {
77
            return true;
78
        }
79
80
        if (!$coupon->getPerCustomerUsageLimit()) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $coupon->getPerCustomerUsageLimit() of type null|integer is loosely compared to false; this is ambiguous if the integer can be zero. You might want to explicitly use === null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For integer values, zero is a special case, in particular the following results might be unexpected:

0   == false // true
0   == null  // true
123 == false // false
123 == null  // false

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
81
            return true;
82
        }
83
84
        if (null === $customer && $coupon->getPerCustomerUsageLimit()) {
85
            return false;
86
        }
87
88
        return $this->isCouponEligible($coupon, $promotion, $customer);
89
    }
90
91
    private function isCouponEligible(CouponInterface $coupon, PromotionInterface $promotion, CustomerInterface $customer)
92
    {
93
        $countPlacedOrders = $this->subjectRepository->countByCustomerAndCoupon($customer, $coupon);
94
95
        // <= because we need to include the cart orders as well
96
        if ($countPlacedOrders <= $coupon->getPerCustomerUsageLimit()) {
97
            $this->dispatcher->dispatch(SyliusPromotionEvents::COUPON_ELIGIBLE, new GenericEvent($promotion));
98
99
            return true;
100
        }
101
102
        return false;
103
    }
104
}
105