PromotionReward   A
last analyzed

Complexity

Total Complexity 9

Size/Duplication

Total Lines 71
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 32
dl 0
loc 71
rs 10
c 1
b 0
f 0
wmc 9

3 Methods

Rating   Name   Duplication   Size   Complexity  
A generateCouponCode() 0 8 2
A __construct() 0 7 1
B apply() 0 49 6
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Odiseo\SyliusReferralsPlugin\Reward\Handler;
6
7
use Odiseo\SyliusReferralsPlugin\Entity\AffiliateInterface;
8
use Odiseo\SyliusReferralsPlugin\Entity\AffiliateReferralAwareInterface;
9
use Odiseo\SyliusReferralsPlugin\Mailer\RewardEmailManagerInterface;
10
use Odiseo\SyliusReferralsPlugin\Reward\RewardHandlerInterface;
11
use Sylius\Component\Core\Model\ChannelInterface;
12
use Sylius\Component\Core\Model\CustomerInterface;
13
use Sylius\Component\Core\Model\OrderInterface;
14
use Sylius\Component\Core\Model\PromotionCouponInterface;
15
use Sylius\Component\Core\Model\PromotionInterface;
16
use Sylius\Component\Core\Repository\PromotionRepositoryInterface;
17
use Sylius\Component\Promotion\Factory\PromotionCouponFactoryInterface;
18
use Sylius\Component\Promotion\Repository\PromotionCouponRepositoryInterface;
19
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
20
21
class PromotionReward implements RewardHandlerInterface
22
{
23
    public function __construct(
24
        private PromotionRepositoryInterface $promotionRepository,
25
        private PromotionCouponFactoryInterface $promotionCouponFactory,
26
        private PromotionCouponRepositoryInterface $promotionCouponRepository,
27
        private RewardEmailManagerInterface $rewardEmailManager,
28
        private string $promotionCode,
29
    ) {
30
    }
31
32
    public function apply(OrderInterface $order): void
33
    {
34
        if (!$order instanceof AffiliateReferralAwareInterface) {
35
            return;
36
        }
37
38
        if (null === $affiliateReferral = $order->getAffiliateReferral()) {
39
            return;
40
        }
41
42
        /** @var AffiliateInterface $affiliate */
43
        $affiliate = $affiliateReferral->getAffiliate();
44
        if (!$affiliate instanceof CustomerInterface) {
45
            return;
46
        }
47
48
        /** @var PromotionInterface|null $promotion */
49
        $promotion = $this->promotionRepository->findOneBy([
50
            'code' => $this->promotionCode,
51
        ]);
52
53
        if (null === $promotion) {
54
            throw new NotFoundHttpException();
55
        }
56
57
        if (!$promotion->isCouponBased()) {
58
            return;
59
        }
60
61
        $code = $this->generateCouponCode();
62
63
        /** @var PromotionCouponInterface $coupon */
64
        $coupon = $this->promotionCouponFactory->createForPromotion($promotion);
65
        $coupon->setCode($code);
66
        $coupon->setUsageLimit(1);
67
        $coupon->setPerCustomerUsageLimit(1);
68
69
        $this->promotionCouponRepository->add($coupon);
70
71
        /** @var ChannelInterface $channel */
72
        $channel = $order->getChannel();
73
        /** @var string $localeCode */
74
        $localeCode = $order->getLocaleCode();
75
76
        $this->rewardEmailManager->sendPromotionEmail(
77
            $affiliate,
78
            $coupon,
79
            $channel,
80
            $localeCode,
81
        );
82
    }
83
84
    private function generateCouponCode(): string
85
    {
86
        do {
87
            $hash = bin2hex(random_bytes(20));
88
            $code = strtoupper(substr($hash, 0, 8));
89
        } while (null !== $this->promotionCouponRepository->findOneBy(['code' => $code]));
90
91
        return $code;
92
    }
93
}
94