Completed
Push — master ( 23d5f0...daf9a4 )
by Kamil
05:58
created

PromotionContext::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 19

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 19
rs 9.6333
c 0
b 0
f 0
cc 1
nc 1
nop 8

How to fix   Many Parameters   

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

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\Behat\Context\Setup;
15
16
use Behat\Behat\Context\Context;
17
use Doctrine\Common\Persistence\ObjectManager;
18
use Sylius\Behat\Service\SharedStorageInterface;
19
use Sylius\Component\Core\Factory\PromotionActionFactoryInterface;
20
use Sylius\Component\Core\Factory\PromotionRuleFactoryInterface;
21
use Sylius\Component\Core\Model\ChannelInterface;
22
use Sylius\Component\Core\Model\ProductInterface;
23
use Sylius\Component\Core\Model\PromotionCouponInterface;
24
use Sylius\Component\Core\Model\PromotionInterface;
25
use Sylius\Component\Core\Model\TaxonInterface;
26
use Sylius\Component\Core\Promotion\Checker\Rule\CustomerGroupRuleChecker;
27
use Sylius\Component\Core\Test\Factory\TestPromotionFactoryInterface;
28
use Sylius\Component\Customer\Model\CustomerGroupInterface;
29
use Sylius\Component\Promotion\Factory\PromotionCouponFactoryInterface;
30
use Sylius\Component\Promotion\Generator\PromotionCouponGeneratorInstruction;
31
use Sylius\Component\Promotion\Generator\PromotionCouponGeneratorInterface;
32
use Sylius\Component\Promotion\Model\PromotionActionInterface;
33
use Sylius\Component\Promotion\Model\PromotionRuleInterface;
34
use Sylius\Component\Promotion\Repository\PromotionRepositoryInterface;
35
36
final class PromotionContext implements Context
37
{
38
    /** @var SharedStorageInterface */
39
    private $sharedStorage;
40
41
    /** @var PromotionActionFactoryInterface */
42
    private $actionFactory;
43
44
    /** @var PromotionCouponFactoryInterface */
45
    private $couponFactory;
46
47
    /** @var PromotionRuleFactoryInterface */
48
    private $ruleFactory;
49
50
    /** @var TestPromotionFactoryInterface */
51
    private $testPromotionFactory;
52
53
    /** @var PromotionRepositoryInterface */
54
    private $promotionRepository;
55
56
    /** @var PromotionCouponGeneratorInterface */
57
    private $couponGenerator;
58
59
    /** @var ObjectManager */
60
    private $objectManager;
61
62
    public function __construct(
63
        SharedStorageInterface $sharedStorage,
64
        PromotionActionFactoryInterface $actionFactory,
65
        PromotionCouponFactoryInterface $couponFactory,
66
        PromotionRuleFactoryInterface $ruleFactory,
67
        TestPromotionFactoryInterface $testPromotionFactory,
68
        PromotionRepositoryInterface $promotionRepository,
69
        PromotionCouponGeneratorInterface $couponGenerator,
70
        ObjectManager $objectManager
71
    ) {
72
        $this->sharedStorage = $sharedStorage;
73
        $this->actionFactory = $actionFactory;
74
        $this->couponFactory = $couponFactory;
75
        $this->ruleFactory = $ruleFactory;
76
        $this->testPromotionFactory = $testPromotionFactory;
77
        $this->promotionRepository = $promotionRepository;
78
        $this->couponGenerator = $couponGenerator;
79
        $this->objectManager = $objectManager;
80
    }
81
82
    /**
83
     * @Given there is (also) a promotion :name
84
     * @Given there is a promotion :name identified by :code code
85
     */
86
    public function thereIsPromotion(string $name, ?string $code = null): void
87
    {
88
        $this->createPromotion($name, $code);
89
    }
90
91
    /**
92
     * @Given /^there is a promotion "([^"]+)" with "Has at least one from taxons" rule (configured with "[^"]+" and "[^"]+")$/
93
     */
94
    public function thereIsAPromotionWithHasAtLeastOneFromTaxonsRuleConfiguredWith(string $name, array $taxons): void
95
    {
96
        $promotion = $this->createPromotion($name);
97
        $rule = $this->ruleFactory->createHasTaxon([$taxons[0]->getCode(), $taxons[1]->getCode()]);
98
        $promotion->addRule($rule);
99
100
        $this->objectManager->flush();
101
    }
102
103
    /**
104
     * @Given /^there is a promotion "([^"]+)" with "Total price of items from taxon" rule configured with ("[^"]+" taxon) and (?:€|£|\$)([^"]+) amount for ("[^"]+" channel)$/
105
     */
106
    public function thereIsAPromotionWithTotalPriceOfItemsFromTaxonRuleConfiguredWithTaxonAndAmountForChannel(
107
        string $name,
108
        TaxonInterface $taxon,
109
        int $amount,
110
        ChannelInterface $channel
111
    ): void {
112
        $promotion = $this->createPromotion($name);
113
        $rule = $this->ruleFactory->createItemsFromTaxonTotal($channel->getCode(), $taxon->getCode(), $amount);
114
        $promotion->addRule($rule);
115
116
        $this->objectManager->flush();
117
    }
118
119
    /**
120
     * @Given /^there is a promotion "([^"]+)" with priority ([^"]+)$/
121
     */
122
    public function thereIsAPromotionWithPriority($promotionName, $priority)
123
    {
124
        $promotion = $this->testPromotionFactory
125
            ->createForChannel($promotionName, $this->sharedStorage->get('channel'))
126
        ;
127
128
        $promotion->setPriority((int) $priority);
129
130
        $this->promotionRepository->add($promotion);
131
        $this->sharedStorage->set('promotion', $promotion);
132
    }
133
134
    /**
135
     * @Given /^there is an exclusive promotion "([^"]+)"(?:| with priority ([^"]+))$/
136
     */
137
    public function thereIsAnExclusivePromotionWithPriority($promotionName, $priority = 0)
138
    {
139
        $promotion = $this->testPromotionFactory
140
            ->createForChannel($promotionName, $this->sharedStorage->get('channel'))
141
        ;
142
143
        $promotion->setExclusive(true);
144
        $promotion->setPriority((int) $priority);
145
146
        $this->promotionRepository->add($promotion);
147
        $this->sharedStorage->set('promotion', $promotion);
148
    }
149
150
    /**
151
     * @Given there is a promotion :promotionName limited to :usageLimit usages
152
     */
153
    public function thereIsPromotionLimitedToUsages($promotionName, $usageLimit)
154
    {
155
        $promotion = $this->testPromotionFactory->createForChannel($promotionName, $this->sharedStorage->get('channel'));
156
157
        $promotion->setUsageLimit((int) $usageLimit);
158
159
        $this->promotionRepository->add($promotion);
160
        $this->sharedStorage->set('promotion', $promotion);
161
    }
162
163
    /**
164
     * @Given the store has promotion :promotionName with coupon :couponCode
165
     * @Given the store has a promotion :promotionName with a coupon :couponCode that is limited to :usageLimit usages
166
     */
167
    public function thereIsPromotionWithCoupon(string $promotionName, string $couponCode, ?int $usageLimit = null): void
168
    {
169
        $coupon = $this->createCoupon($couponCode, $usageLimit);
170
171
        $promotion = $this->testPromotionFactory
172
            ->createForChannel($promotionName, $this->sharedStorage->get('channel'))
173
        ;
174
        $promotion->addCoupon($coupon);
175
        $promotion->setCouponBased(true);
176
177
        $this->promotionRepository->add($promotion);
178
179
        $this->sharedStorage->set('promotion', $promotion);
180
        $this->sharedStorage->set('coupon', $coupon);
181
    }
182
183
    /**
184
     * @Given /^(this promotion) has "([^"]+)", "([^"]+)" and "([^"]+)" coupons/
185
     */
186
    public function thisPromotionHasCoupons(PromotionInterface $promotion, string ...$couponCodes): void
187
    {
188
        foreach ($couponCodes as $couponCode) {
189
            $coupon = $this->createCoupon($couponCode);
190
            $promotion->addCoupon($coupon);
191
        }
192
193
        $promotion->setCouponBased(true);
194
195
        $this->objectManager->flush();
196
    }
197
198
    /**
199
     * @Given /^(this promotion) has already expired$/
200
     */
201
    public function thisPromotionHasExpired(PromotionInterface $promotion)
202
    {
203
        $promotion->setEndsAt(new \DateTime('1 day ago'));
204
205
        $this->objectManager->flush();
206
    }
207
208
    /**
209
     * @Given /^(this promotion) expires tomorrow$/
210
     */
211
    public function thisPromotionExpiresTomorrow(PromotionInterface $promotion)
212
    {
213
        $promotion->setEndsAt(new \DateTime('tomorrow'));
214
215
        $this->objectManager->flush();
216
    }
217
218
    /**
219
     * @Given /^(this promotion) has started yesterday$/
220
     */
221
    public function thisPromotionHasStartedYesterday(PromotionInterface $promotion)
222
    {
223
        $promotion->setStartsAt(new \DateTime('1 day ago'));
224
225
        $this->objectManager->flush();
226
    }
227
228
    /**
229
     * @Given /^(this promotion) starts tomorrow$/
230
     */
231
    public function thisPromotionStartsTomorrow(PromotionInterface $promotion)
232
    {
233
        $promotion->setStartsAt(new \DateTime('tomorrow'));
234
235
        $this->objectManager->flush();
236
    }
237
238
    /**
239
     * @Given /^(this coupon) has already expired$/
240
     */
241
    public function thisCouponHasExpired(PromotionCouponInterface $coupon)
242
    {
243
        $coupon->setExpiresAt(new \DateTime('1 day ago'));
244
245
        $this->objectManager->flush();
246
    }
247
248
    /**
249
     * @Given /^(this coupon) expires tomorrow$/
250
     */
251
    public function thisCouponExpiresTomorrow(PromotionCouponInterface $coupon)
252
    {
253
        $coupon->setExpiresAt(new \DateTime('tomorrow'));
254
255
        $this->objectManager->flush();
256
    }
257
258
    /**
259
     * @Given /^(this coupon) is set as non reusable after cancelling the order in which it has been used$/
260
     */
261
    public function thisIsSetAsNonReusableAfterCancellingTheOrderInWhichItHasBeenUsed(PromotionCouponInterface $coupon): void
262
    {
263
        $coupon->setReusableFromCancelledOrders(false);
264
265
        $this->objectManager->flush();
266
    }
267
268
    /**
269
     * @Given /^(this coupon) has already reached its usage limit$/
270
     */
271
    public function thisCouponHasReachedItsUsageLimit(PromotionCouponInterface $coupon)
272
    {
273
        $coupon->setUsed(42);
274
        $coupon->setUsageLimit(42);
275
276
        $this->objectManager->flush();
277
    }
278
279
    /**
280
     * @Given /^(this coupon) can be used (\d+) times?$/
281
     * @Given /^(this coupon) can be used once$/
282
     */
283
    public function thisCouponCanBeUsedNTimes(PromotionCouponInterface $coupon, int $usageLimit = 1): void
284
    {
285
        $coupon->setUsageLimit($usageLimit);
286
287
        $this->objectManager->flush();
288
    }
289
290
    /**
291
     * @Given /^(this coupon) can be used once per customer$/
292
     */
293
    public function thisCouponCanBeUsedOncePerCustomer(PromotionCouponInterface $coupon): void
294
    {
295
        $coupon->setPerCustomerUsageLimit(1);
296
297
        $this->objectManager->flush();
298
    }
299
300
    /**
301
     * @Given /^(this coupon) can be used twice per customer$/
302
     */
303
    public function thisCouponCanBeUsedTwicePerCustomer(PromotionCouponInterface $coupon): void
304
    {
305
        $coupon->setPerCustomerUsageLimit(2);
306
307
        $this->objectManager->flush();
308
    }
309
310
    /**
311
     * @Given /^([^"]+) gives ("(?:€|£|\$)[^"]+") discount to every order$/
312
     */
313
    public function itGivesFixedDiscountToEveryOrder(PromotionInterface $promotion, $discount)
314
    {
315
        $this->createFixedPromotion($promotion, $discount);
316
    }
317
318
    /**
319
     * @Given /^([^"]+) gives ("(?:€|£|\$)[^"]+") discount to every order in the ("[^"]+" channel) and ("(?:€|£|\$)[^"]+") discount to every order in the ("[^"]+" channel)$/
320
     */
321
    public function thisPromotionGivesDiscountToEveryOrderInTheChannelAndDiscountToEveryOrderInTheChannel(
322
        PromotionInterface $promotion,
323
        $firstChannelDiscount,
324
        ChannelInterface $firstChannel,
325
        $secondChannelDiscount,
326
        ChannelInterface $secondChannel
327
    ) {
328
        /** @var PromotionActionInterface $action */
329
        $action = $this->actionFactory->createFixedDiscount($firstChannelDiscount, $firstChannel->getCode());
330
        $action->setConfiguration(array_merge($action->getConfiguration(), [$secondChannel->getCode() => ['amount' => $secondChannelDiscount]]));
331
332
        $promotion->addChannel($firstChannel);
333
        $promotion->addChannel($secondChannel);
334
        $promotion->addAction($action);
335
336
        $this->objectManager->flush();
337
    }
338
339
    /**
340
     * @Given /^([^"]+) gives ("[^"]+%") discount to every order$/
341
     */
342
    public function itGivesPercentageDiscountToEveryOrder(PromotionInterface $promotion, $discount)
343
    {
344
        $this->createPercentagePromotion($promotion, $discount);
345
    }
346
347
    /**
348
     * @Given /^([^"]+) gives ("(?:€|£|\$)[^"]+") discount to every order with quantity at least ([^"]+)$/
349
     */
350
    public function itGivesFixedDiscountToEveryOrderWithQuantityAtLeast(
351
        PromotionInterface $promotion,
352
        $discount,
353
        $quantity
354
    ) {
355
        $rule = $this->ruleFactory->createCartQuantity((int) $quantity);
356
357
        $this->createFixedPromotion($promotion, $discount, [], $rule);
358
    }
359
360
    /**
361
     * @Given /^([^"]+) gives ("(?:€|£|\$)[^"]+") discount to every order with items total at least ("[^"]+")$/
362
     */
363
    public function itGivesFixedDiscountToEveryOrderWithItemsTotalAtLeast(
364
        PromotionInterface $promotion,
365
        $discount,
366
        $targetAmount
367
    ) {
368
        $channelCode = $this->sharedStorage->get('channel')->getCode();
369
        $rule = $this->ruleFactory->createItemTotal($channelCode, $targetAmount);
370
371
        $this->createFixedPromotion($promotion, $discount, [], $rule);
372
    }
373
374
    /**
375
     * @Given /^([^"]+) gives ("[^"]+%") discount to every order with items total at least ("[^"]+")$/
376
     */
377
    public function itGivesPercentageDiscountToEveryOrderWithItemsTotalAtLeast(
378
        PromotionInterface $promotion,
379
        $discount,
380
        $targetAmount
381
    ) {
382
        $channelCode = $this->sharedStorage->get('channel')->getCode();
383
        $rule = $this->ruleFactory->createItemTotal($channelCode, $targetAmount);
384
        $this->createPercentagePromotion($promotion, $discount, [], $rule);
385
    }
386
387
    /**
388
     * @Given /^([^"]+) gives ("[^"]+%") off on every product when the item total is at least ("(?:€|£|\$)[^"]+")$/
389
     */
390
    public function itGivesOffOnEveryItemWhenItemTotalExceeds(
391
        PromotionInterface $promotion,
392
        $discount,
393
        $targetAmount
394
    ) {
395
        $channelCode = $this->sharedStorage->get('channel')->getCode();
396
        $rule = $this->ruleFactory->createItemTotal($channelCode, $targetAmount);
397
398
        $this->createUnitPercentagePromotion($promotion, $discount, [], $rule);
399
    }
400
401
    /**
402
     * @Given /^([^"]+) gives ("[^"]+%") discount on shipping to every order$/
403
     */
404
    public function itGivesPercentageDiscountOnShippingToEveryOrder(PromotionInterface $promotion, $discount)
405
    {
406
        $action = $this->actionFactory->createShippingPercentageDiscount($discount);
407
        $promotion->addAction($action);
408
409
        $this->objectManager->flush();
410
    }
411
412
    /**
413
     * @Given /^([^"]+) gives free shipping to every order$/
414
     */
415
    public function thePromotionGivesFreeShippingToEveryOrder(PromotionInterface $promotion)
416
    {
417
        $this->itGivesPercentageDiscountOnShippingToEveryOrder($promotion, 1);
418
    }
419
420
    /**
421
     * @Given /^([^"]+) gives(?:| another) ("[^"]+%") off every product (classified as "[^"]+")$/
422
     */
423
    public function itGivesPercentageOffEveryProductClassifiedAs(
424
        PromotionInterface $promotion,
425
        $discount,
426
        TaxonInterface $taxon
427
    ) {
428
        $this->createUnitPercentagePromotion($promotion, $discount, $this->getTaxonFilterConfiguration([$taxon->getCode()]));
429
    }
430
431
    /**
432
     * @Given /^([^"]+) gives(?:| another) ("(?:€|£|\$)[^"]+") off on every product (classified as "[^"]+")$/
433
     */
434
    public function itGivesFixedOffEveryProductClassifiedAs(
435
        PromotionInterface $promotion,
436
        $discount,
437
        TaxonInterface $taxon
438
    ) {
439
        $this->createUnitFixedPromotion($promotion, $discount, $this->getTaxonFilterConfiguration([$taxon->getCode()]));
440
    }
441
442
    /**
443
     * @Given /^([^"]+) gives ("(?:€|£|\$)[^"]+") off on every product with minimum price at ("(?:€|£|\$)[^"]+")$/
444
     */
445
    public function thisPromotionGivesOffOnEveryProductWithMinimumPriceAt(
446
        PromotionInterface $promotion,
447
        $discount,
448
        $amount
449
    ) {
450
        $this->createUnitFixedPromotion($promotion, $discount, $this->getPriceRangeFilterConfiguration($amount));
451
    }
452
453
    /**
454
     * @Given /^([^"]+) gives ("(?:€|£|\$)[^"]+") off on every product priced between ("(?:€|£|\$)[^"]+") and ("(?:€|£|\$)[^"]+")$/
455
     */
456
    public function thisPromotionGivesOffOnEveryProductPricedBetween(
457
        PromotionInterface $promotion,
458
        $discount,
459
        $minAmount,
460
        $maxAmount
461
    ) {
462
        $this->createUnitFixedPromotion(
463
            $promotion,
464
            $discount,
465
            $this->getPriceRangeFilterConfiguration($minAmount, $maxAmount)
466
        );
467
    }
468
469
    /**
470
     * @Given /^([^"]+) gives ("[^"]+%") off on every product with minimum price at ("(?:€|£|\$)[^"]+")$/
471
     */
472
    public function thisPromotionPercentageGivesOffOnEveryProductWithMinimumPriceAt(
473
        PromotionInterface $promotion,
474
        $discount,
475
        $amount
476
    ) {
477
        $this->createUnitPercentagePromotion($promotion, $discount, $this->getPriceRangeFilterConfiguration($amount));
478
    }
479
480
    /**
481
     * @Given /^([^"]+) gives ("[^"]+%") off on every product priced between ("(?:€|£|\$)[^"]+") and ("(?:€|£|\$)[^"]+")$/
482
     */
483
    public function thisPromotionPercentageGivesOffOnEveryProductPricedBetween(
484
        PromotionInterface $promotion,
485
        $discount,
486
        $minAmount,
487
        $maxAmount
488
    ) {
489
        $this->createUnitPercentagePromotion(
490
            $promotion,
491
            $discount,
492
            $this->getPriceRangeFilterConfiguration($minAmount, $maxAmount)
493
        );
494
    }
495
496
    /**
497
     * @Given /^([^"]+) gives ("(?:€|£|\$)[^"]+") off if order contains products (classified as "[^"]+")$/
498
     */
499
    public function thePromotionGivesOffIfOrderContainsProductsClassifiedAs(
500
        PromotionInterface $promotion,
501
        $discount,
502
        TaxonInterface $taxon
503
    ) {
504
        $rule = $this->ruleFactory->createHasTaxon([$taxon->getCode()]);
505
506
        $this->createFixedPromotion($promotion, $discount, [], $rule);
507
    }
508
509
    /**
510
     * @Given /^([^"]+) gives ("(?:€|£|\$)[^"]+") off if order contains products (classified as "[^"]+" or "[^"]+")$/
511
     */
512
    public function thePromotionGivesOffIfOrderContainsProductsClassifiedAsOr(
513
        PromotionInterface $promotion,
514
        $discount,
515
        array $taxons
516
    ) {
517
        $rule = $this->ruleFactory->createHasTaxon([$taxons[0]->getCode(), $taxons[1]->getCode()]);
518
519
        $this->createFixedPromotion($promotion, $discount, [], $rule);
520
    }
521
522
    /**
523
     * @Given /^([^"]+) gives ("(?:€|£|\$)[^"]+") off if order contains products (classified as "[^"]+") with a minimum value of ("(?:€|£|\$)[^"]+")$/
524
     */
525
    public function thePromotionGivesOffIfOrderContainsProductsClassifiedAsAndPricedAt(
526
        PromotionInterface $promotion,
527
        $discount,
528
        TaxonInterface $taxon,
529
        $amount
530
    ) {
531
        $channelCode = $this->sharedStorage->get('channel')->getCode();
532
        $rule = $this->ruleFactory->createItemsFromTaxonTotal($channelCode, $taxon->getCode(), $amount);
533
534
        $this->createFixedPromotion($promotion, $discount, [], $rule);
535
    }
536
537
    /**
538
     * @Given /^([^"]+) gives ("(?:€|£|\$)[^"]+") off customer's (\d)(?:st|nd|rd|th) order$/
539
     */
540
    public function itGivesFixedOffCustomersNthOrder(PromotionInterface $promotion, $discount, $nth)
541
    {
542
        $rule = $this->ruleFactory->createNthOrder((int) $nth);
543
544
        $this->createFixedPromotion($promotion, $discount, [], $rule);
545
    }
546
547
    /**
548
     * @Given /^([^"]+) gives ("[^"]+%") off on the customer's (\d)(?:st|nd|rd|th) order$/
549
     */
550
    public function itGivesPercentageOffCustomersNthOrder(PromotionInterface $promotion, $discount, $nth)
551
    {
552
        $rule = $this->ruleFactory->createNthOrder((int) $nth);
553
554
        $this->createPercentagePromotion($promotion, $discount, [], $rule);
555
    }
556
557
    /**
558
     * @Given /^([^"]+) gives ("[^"]+%") off on every product (classified as "[^"]+") and ("(?:€|£|\$)[^"]+") discount on every order$/
559
     */
560
    public function itGivesPercentageOffOnEveryProductClassifiedAsAndAmountDiscountOnOrder(
561
        PromotionInterface $promotion,
562
        $productDiscount,
563
        TaxonInterface $discountTaxon,
564
        $orderDiscount
565
    ) {
566
        $this->createUnitPercentagePromotion($promotion, $productDiscount, $this->getTaxonFilterConfiguration([$discountTaxon->getCode()]));
567
        $this->createFixedPromotion($promotion, $orderDiscount);
568
    }
569
570
    /**
571
     * @Given /^([^"]+) gives ("(?:€|£|\$)[^"]+") off on every product (classified as "[^"]+") and a free shipping to every order with items total equal at least ("[^"]+")$/
572
     */
573
    public function itGivesOffOnEveryProductClassifiedAsAndAFreeShippingToEveryOrderWithItemsTotalEqualAtLeast(
574
        PromotionInterface $promotion,
575
        $discount,
576
        TaxonInterface $taxon,
577
        $targetAmount
578
    ) {
579
        $freeShippingAction = $this->actionFactory->createShippingPercentageDiscount(1);
580
        $promotion->addAction($freeShippingAction);
581
582
        $channelCode = $this->sharedStorage->get('channel')->getCode();
583
        $rule = $this->ruleFactory->createItemTotal($channelCode, $targetAmount);
584
585
        $this->createUnitFixedPromotion($promotion, $discount, [], $rule);
586
    }
587
588
    /**
589
     * @Given /^([^"]+) gives ("[^"]+%") off on every product (classified as "[^"]+") and a ("(?:€|£|\$)[^"]+") discount to every order with items total equal at least ("(?:€|£|\$)[^"]+")$/
590
     */
591
    public function itGivesOffOnEveryProductClassifiedAsAndAFixedDiscountToEveryOrderWithItemsTotalEqualAtLeast(
592
        PromotionInterface $promotion,
593
        $taxonDiscount,
594
        TaxonInterface $taxon,
595
        $orderDiscount,
596
        $targetAmount
597
    ) {
598
        $orderDiscountAction = $this->actionFactory->createFixedDiscount($orderDiscount, $this->sharedStorage->get('channel')->getCode());
599
        $promotion->addAction($orderDiscountAction);
600
601
        $channelCode = $this->sharedStorage->get('channel')->getCode();
602
        $rule = $this->ruleFactory->createItemTotal($channelCode, $targetAmount);
603
604
        $this->createUnitPercentagePromotion(
605
            $promotion,
606
            $taxonDiscount,
607
            $this->getTaxonFilterConfiguration([$taxon->getCode()]),
608
            $rule
609
        );
610
    }
611
612
    /**
613
     * @Given /^([^"]+) gives ("[^"]+%") off on every product (classified as "[^"]+" or "[^"]+") if order contains any product (classified as "[^"]+" or "[^"]+")$/
614
     */
615
    public function itGivesOffOnEveryProductClassifiedAsOrIfOrderContainsAnyProductClassifiedAsOr(
616
        PromotionInterface $promotion,
617
        $discount,
618
        array $discountTaxons,
619
        array $targetTaxons
620
    ) {
621
        $discountTaxonsCodes = [$discountTaxons[0]->getCode(), $discountTaxons[1]->getCode()];
622
        $targetTaxonsCodes = [$targetTaxons[0]->getCode(), $targetTaxons[1]->getCode()];
623
624
        $rule = $this->ruleFactory->createHasTaxon($targetTaxonsCodes);
625
626
        $this->createUnitPercentagePromotion(
627
            $promotion,
628
            $discount,
629
            $this->getTaxonFilterConfiguration($discountTaxonsCodes),
630
            $rule
631
        );
632
    }
633
634
    /**
635
     * @Given /^([^"]+) gives ("[^"]+%") off on every product (classified as "[^"]+") if order contains any product (classified as "[^"]+")$/
636
     */
637
    public function itGivesOffOnEveryProductClassifiedAsIfOrderContainsAnyProductClassifiedAs(
638
        PromotionInterface $promotion,
639
        $discount,
640
        $discountTaxon,
641
        $targetTaxon
642
    ) {
643
        $rule = $this->ruleFactory->createHasTaxon([$targetTaxon->getCode()]);
644
645
        $this->createUnitPercentagePromotion(
646
            $promotion,
647
            $discount,
648
            $this->getTaxonFilterConfiguration([$discountTaxon->getCode()]),
649
            $rule
650
        );
651
    }
652
653
    /**
654
     * @Given /^(it) is coupon based promotion$/
655
     * @Given /^(it) is a coupon based promotion$/
656
     */
657
    public function itIsCouponBasedPromotion(PromotionInterface $promotion): void
658
    {
659
        $promotion->setCouponBased(true);
660
661
        $this->objectManager->flush();
662
    }
663
664
    /**
665
     * @Given /^(the promotion) was disabled for the (channel "[^"]+")$/
666
     */
667
    public function thePromotionWasDisabledForTheChannel(PromotionInterface $promotion, ChannelInterface $channel)
668
    {
669
        $promotion->removeChannel($channel);
670
671
        $this->objectManager->flush();
672
    }
673
674
    /**
675
     * @Given /^the (coupon "[^"]+") was used up to its usage limit$/
676
     */
677
    public function theCouponWasUsed(PromotionCouponInterface $coupon)
678
    {
679
        $coupon->setUsed($coupon->getUsageLimit());
680
681
        $this->objectManager->flush();
682
    }
683
684
    /**
685
     * @Given /^([^"]+) gives ("(?:€|£|\$)[^"]+") off if order contains (?:a|an) ("[^"]+" product)$/
686
     */
687
    public function thePromotionGivesOffIfOrderContainsProducts(PromotionInterface $promotion, $discount, ProductInterface $product)
688
    {
689
        $rule = $this->ruleFactory->createContainsProduct($product->getCode());
690
691
        $this->createFixedPromotion($promotion, $discount, [], $rule);
692
    }
693
694
    /**
695
     * @Given /^([^"]+) gives ("(?:€|£|\$)[^"]+") off on a ("[^"]*" product)$/
696
     */
697
    public function itGivesFixedDiscountOffOnAProduct(PromotionInterface $promotion, $discount, ProductInterface $product)
698
    {
699
        $this->createUnitFixedPromotion($promotion, $discount, $this->getProductsFilterConfiguration([$product->getCode()]));
700
    }
701
702
    /**
703
     * @Given /^([^"]+) gives ("[^"]+%") off on a ("[^"]*" product)$/
704
     */
705
    public function itGivesPercentageDiscountOffOnAProduct(PromotionInterface $promotion, $discount, ProductInterface $product)
706
    {
707
        $this->createUnitPercentagePromotion($promotion, $discount, $this->getProductsFilterConfiguration([$product->getCode()]));
708
    }
709
710
    /**
711
     * @Given /^([^"]+) gives ("[^"]+%") off the order for customers from ("[^"]*" group)$/
712
     */
713
    public function thePromotionGivesOffTheOrderForCustomersFromGroup(
714
        PromotionInterface $promotion,
715
        $discount,
716
        CustomerGroupInterface $customerGroup
717
    ) {
718
        /** @var PromotionRuleInterface $rule */
719
        $rule = $this->ruleFactory->createNew();
720
        $rule->setType(CustomerGroupRuleChecker::TYPE);
721
        $rule->setConfiguration(['group_code' => $customerGroup->getCode()]);
722
723
        $this->createPercentagePromotion($promotion, $discount, [], $rule);
724
    }
725
726
    /**
727
     * @Given /^([^"]+) gives ("[^"]+%") discount on shipping to every order over ("(?:€|£|\$)[^"]+")$/
728
     */
729
    public function itGivesDiscountOnShippingToEveryOrderOver(
730
        PromotionInterface $promotion,
731
        $discount,
732
        $itemTotal
733
    ) {
734
        $channelCode = $this->sharedStorage->get('channel')->getCode();
735
        $rule = $this->ruleFactory->createItemTotal($channelCode, $itemTotal);
736
        $action = $this->actionFactory->createShippingPercentageDiscount($discount);
737
738
        $this->persistPromotion($promotion, $action, [], $rule);
739
    }
740
741
    /**
742
     * @Given /^([^"]+) gives free shipping to every order over ("(?:€|£|\$)[^"]+")$/
743
     */
744
    public function itGivesFreeShippingToEveryOrderOver(PromotionInterface $promotion, $itemTotal)
745
    {
746
        $this->itGivesDiscountOnShippingToEveryOrderOver($promotion, 1, $itemTotal);
747
    }
748
749
    /**
750
     * @Given /^I have generated (\d+) coupons for (this promotion) with code length (\d+) and prefix "([^"]+)"$/
751
     * @Given /^I have generated (\d+) coupons for (this promotion) with code length (\d+), prefix "([^"]+)" and suffix "([^"]+)"$/
752
     */
753
    public function iHaveGeneratedCouponsForThisPromotionWithCodeLengthPrefixAndSuffix(
754
        int $amount,
755
        PromotionInterface $promotion,
756
        int $codeLength,
757
        string $prefix,
758
        ?string $suffix = null
759
    ): void {
760
        $this->generateCoupons($amount, $promotion, $codeLength, $prefix, $suffix);
761
    }
762
763
    /**
764
     * @Given /^I have generated (\d+) coupons for (this promotion) with code length (\d+) and suffix "([^"]+)"$/
765
     */
766
    public function iHaveGeneratedCouponsForThisPromotionWithCodeLengthAndSuffix(
767
        int $amount,
768
        PromotionInterface $promotion,
769
        int $codeLength,
770
        string $suffix
771
    ): void {
772
        $this->generateCoupons($amount, $promotion, $codeLength, null, $suffix);
773
    }
774
775
    /**
776
     * @return array
0 ignored issues
show
Documentation introduced by
Consider making the return type a bit more specific; maybe use array<string,array<string,array<string,array>>>.

This check looks for the generic type array as a return type and suggests a more specific type. This type is inferred from the actual code.

Loading history...
777
     */
778
    private function getTaxonFilterConfiguration(array $taxonCodes)
779
    {
780
        return ['filters' => ['taxons_filter' => ['taxons' => $taxonCodes]]];
781
    }
782
783
    /**
784
     * @return array
0 ignored issues
show
Documentation introduced by
Consider making the return type a bit more specific; maybe use array<string,array<string,array<string,array>>>.

This check looks for the generic type array as a return type and suggests a more specific type. This type is inferred from the actual code.

Loading history...
785
     */
786
    private function getProductsFilterConfiguration(array $productCodes)
787
    {
788
        return ['filters' => ['products_filter' => ['products' => $productCodes]]];
789
    }
790
791
    /**
792
     * @param int $minAmount
793
     * @param int $maxAmount
0 ignored issues
show
Documentation introduced by
Should the type for parameter $maxAmount not be integer|null?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
794
     *
795
     * @return array
0 ignored issues
show
Documentation introduced by
Consider making the return type a bit more specific; maybe use array<string,array<string,array<string,integer>>>.

This check looks for the generic type array as a return type and suggests a more specific type. This type is inferred from the actual code.

Loading history...
796
     */
797
    private function getPriceRangeFilterConfiguration($minAmount, $maxAmount = null)
798
    {
799
        $configuration = ['filters' => ['price_range_filter' => ['min' => $minAmount]]];
800
        if (null !== $maxAmount) {
801
            $configuration['filters']['price_range_filter']['max'] = $maxAmount;
802
        }
803
804
        return $configuration;
805
    }
806
807
    private function createPromotion(string $name, ?string $code = null): PromotionInterface
808
    {
809
        $promotion = $this->testPromotionFactory->createForChannel($name, $this->sharedStorage->get('channel'));
810
811
        if (null !== $code) {
812
            $promotion->setCode($code);
813
        }
814
815
        $this->promotionRepository->add($promotion);
816
        $this->sharedStorage->set('promotion', $promotion);
817
818
        return $promotion;
819
    }
820
821
    /**
822
     * @param int $discount
823
     */
824
    private function createUnitFixedPromotion(PromotionInterface $promotion, $discount, array $configuration = [], PromotionRuleInterface $rule = null)
825
    {
826
        $channelCode = $this->sharedStorage->get('channel')->getCode();
827
828
        $this->persistPromotion(
829
            $promotion,
830
            $this->actionFactory->createUnitFixedDiscount($discount, $channelCode),
831
            [$channelCode => $configuration],
832
            $rule
833
        );
834
    }
835
836
    /**
837
     * @param int $discount
838
     */
839
    private function createUnitPercentagePromotion(PromotionInterface $promotion, $discount, array $configuration = [], PromotionRuleInterface $rule = null)
840
    {
841
        $channelCode = $this->sharedStorage->get('channel')->getCode();
842
843
        $this->persistPromotion(
844
            $promotion,
845
            $this->actionFactory->createUnitPercentageDiscount($discount, $channelCode),
846
            [$channelCode => $configuration],
847
            $rule
848
        );
849
    }
850
851
    /**
852
     * @param int $discount
853
     */
854
    private function createFixedPromotion(
855
        PromotionInterface $promotion,
856
        $discount,
857
        array $configuration = [],
858
        PromotionRuleInterface $rule = null,
859
        ChannelInterface $channel = null
860
    ) {
861
        $channelCode = (null !== $channel) ? $channel->getCode() : $this->sharedStorage->get('channel')->getCode();
862
863
        $this->persistPromotion($promotion, $this->actionFactory->createFixedDiscount($discount, $channelCode), $configuration, $rule);
864
    }
865
866
    /**
867
     * @param float $discount
868
     * @param PromotionRuleInterface $rule
0 ignored issues
show
Documentation introduced by
Should the type for parameter $rule not be null|PromotionRuleInterface?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
869
     */
870
    private function createPercentagePromotion(
871
        PromotionInterface $promotion,
872
        $discount,
873
        array $configuration = [],
874
        PromotionRuleInterface $rule = null
875
    ) {
876
        $this->persistPromotion($promotion, $this->actionFactory->createPercentageDiscount($discount), $configuration, $rule);
877
    }
878
879
    private function persistPromotion(PromotionInterface $promotion, PromotionActionInterface $action, array $configuration, PromotionRuleInterface $rule = null)
880
    {
881
        $configuration = array_merge_recursive($action->getConfiguration(), $configuration);
882
        $action->setConfiguration($configuration);
883
884
        $promotion->addAction($action);
885
        if (null !== $rule) {
886
            $promotion->addRule($rule);
887
        }
888
889
        $this->objectManager->flush();
890
    }
891
892
    private function createCoupon(string $couponCode, ?int $usageLimit = null): PromotionCouponInterface
893
    {
894
        /** @var PromotionCouponInterface $coupon */
895
        $coupon = $this->couponFactory->createNew();
896
        $coupon->setCode($couponCode);
897
        $coupon->setUsageLimit($usageLimit);
898
899
        return $coupon;
900
    }
901
902
    private function generateCoupons(
903
        int $amount,
904
        PromotionInterface $promotion,
905
        int $codeLength,
906
        ?string $prefix = null,
907
        ?string $suffix = null
908
    ): void {
909
        $instruction = new PromotionCouponGeneratorInstruction();
910
        $instruction->setAmount($amount);
911
        $instruction->setCodeLength($codeLength);
912
        $instruction->setPrefix($prefix);
913
        $instruction->setSuffix($suffix);
914
915
        $this->couponGenerator->generate($promotion, $instruction);
916
    }
917
}
918