Passed
Push — master ( 843515...db168e )
by Diego
04:15
created

PromotionReward::generateCouponCode()   A

Complexity

Conditions 2
Paths 1

Size

Total Lines 8
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 2
eloc 5
c 1
b 0
f 0
nc 1
nop 0
dl 0
loc 8
rs 10
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
    private PromotionRepositoryInterface $promotionRepository;
24
    private PromotionCouponFactoryInterface $promotionCouponFactory;
25
    private PromotionCouponRepositoryInterface $promotionCouponRepository;
26
    private RewardEmailManagerInterface $rewardEmailManager;
27
    private string $promotionCode;
28
29
    public function __construct(
30
        PromotionRepositoryInterface $promotionRepository,
31
        PromotionCouponFactoryInterface $promotionCouponFactory,
32
        PromotionCouponRepositoryInterface $promotionCouponRepository,
33
        RewardEmailManagerInterface $rewardEmailManager,
34
        string $promotionCode
35
    ) {
36
        $this->promotionRepository = $promotionRepository;
37
        $this->promotionCouponFactory = $promotionCouponFactory;
38
        $this->promotionCouponRepository = $promotionCouponRepository;
39
        $this->rewardEmailManager = $rewardEmailManager;
40
        $this->promotionCode = $promotionCode;
41
    }
42
43
    public function apply(OrderInterface $order): void
44
    {
45
        if (!$order instanceof AffiliateReferralAwareInterface) {
46
            return;
47
        }
48
49
        if (null === $affiliateReferral = $order->getAffiliateReferral()) {
50
            return;
51
        }
52
53
        /** @var AffiliateInterface $affiliate */
54
        $affiliate = $affiliateReferral->getAffiliate();
55
        if (!$affiliate instanceof CustomerInterface) {
56
            return;
57
        }
58
59
        /** @var PromotionInterface|null $promotion */
60
        $promotion = $this->promotionRepository->findOneBy([
61
            'code' => $this->promotionCode
62
        ]);
63
64
        if (null === $promotion) {
65
            throw new NotFoundHttpException();
66
        }
67
68
        if (!$promotion->isCouponBased()) {
69
            return;
70
        }
71
72
        $code = $this->generateCouponCode();
73
74
        /** @var PromotionCouponInterface $coupon */
75
        $coupon = $this->promotionCouponFactory->createForPromotion($promotion);
76
        $coupon->setCode($code);
77
        $coupon->setUsageLimit(1);
78
        $coupon->setPerCustomerUsageLimit(1);
79
80
        $this->promotionCouponRepository->add($coupon);
81
82
        /** @var ChannelInterface $channel */
83
        $channel = $order->getChannel();
84
        /** @var string $localeCode */
85
        $localeCode = $order->getLocaleCode();
86
87
        $this->rewardEmailManager->sendPromotionEmail(
88
            $affiliate,
89
            $coupon,
90
            $channel,
91
            $localeCode
92
        );
93
    }
94
95
    private function generateCouponCode(): string
96
    {
97
        do {
98
            $hash = bin2hex(random_bytes(20));
99
            $code = strtoupper(substr($hash, 0, 8));
100
        } while (null !== $this->promotionCouponRepository->findOneBy(['code' => $code]));
101
102
        return $code;
103
    }
104
}
105