Completed
Push — master ( f2042d...10cdad )
by Kamil
29:04 queued 13:16
created

PromotionContext   F

Complexity

Total Complexity 63

Size/Duplication

Total Lines 817
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 14

Importance

Changes 0
Metric Value
wmc 63
lcom 1
cbo 14
dl 0
loc 817
rs 3.4782
c 0
b 0
f 0

58 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 17 1
A thereIsPromotion() 0 13 2
A thereIsAPromotionWithPriority() 0 11 1
A thereIsAnExclusivePromotionWithPriority() 0 12 1
A thereIsPromotionLimitedToUsages() 0 9 1
A thereIsPromotionWithCoupon() 0 15 1
A thisPromotionHasCoupons() 0 11 2
A thisPromotionHasExpired() 0 6 1
A thisPromotionExpiresTomorrow() 0 6 1
A thisPromotionHasStartedYesterday() 0 6 1
A thisPromotionStartsTomorrow() 0 6 1
A thisCouponHasExpired() 0 6 1
A thisCouponExpiresTomorrow() 0 6 1
A thisCouponHasReachedItsUsageLimit() 0 7 1
A thisCouponCanBeUsedNTimes() 0 6 1
A thisCouponCanBeUsedTwicePerCustomer() 0 6 1
A itGivesFixedDiscountToEveryOrder() 0 4 1
A thisPromotionGivesDiscountToEveryOrderInTheChannelAndDiscountToEveryOrderInTheChannel() 0 17 1
A itGivesPercentageDiscountToEveryOrder() 0 4 1
A itGivesFixedDiscountToEveryOrderWithQuantityAtLeast() 0 9 1
A itGivesFixedDiscountToEveryOrderWithItemsTotalAtLeast() 0 10 1
A itGivesOffOnEveryItemWhenItemTotalExceeds() 0 10 1
A itGivesPercentageDiscountOnShippingToEveryOrder() 0 7 1
A thePromotionGivesFreeShippingToEveryOrder() 0 4 1
A itGivesPercentageOffEveryProductClassifiedAs() 0 7 1
A itGivesFixedOffEveryProductClassifiedAs() 0 7 1
A thisPromotionGivesOffOnEveryProductWithMinimumPriceAt() 0 7 1
A thisPromotionGivesOffOnEveryProductPricedBetween() 0 12 1
A thisPromotionPercentageGivesOffOnEveryProductWithMinimumPriceAt() 0 7 1
A thisPromotionPercentageGivesOffOnEveryProductPricedBetween() 0 12 1
A thePromotionGivesOffIfOrderContainsProductsClassifiedAs() 0 9 1
A thePromotionGivesOffIfOrderContainsProductsClassifiedAsOr() 0 9 1
A thePromotionGivesOffIfOrderContainsProductsClassifiedAsAndPricedAt() 0 11 1
A itGivesFixedOffCustomersNthOrder() 0 6 1
A itGivesPercentageOffCustomersNthOrder() 0 6 1
A itGivesPercentageOffOnEveryProductClassifiedAsAndAmountDiscountOnOrder() 0 9 1
A itGivesOffOnEveryProductClassifiedAsAndAFreeShippingToEveryOrderWithItemsTotalEqualAtLeast() 0 14 1
A itGivesOffOnEveryProductClassifiedAsAndAFixedDiscountToEveryOrderWithItemsTotalEqualAtLeast() 0 20 1
A itGivesOffOnEveryProductClassifiedAsOrIfOrderContainsAnyProductClassifiedAsOr() 0 18 1
A itGivesOffOnEveryProductClassifiedAsIfOrderContainsAnyProductClassifiedAs() 0 15 1
A itIsCouponBasedPromotion() 0 6 1
A thePromotionWasDisabledForTheChannel() 0 6 1
A theCouponWasUsed() 0 6 1
A thePromotionGivesOffIfOrderContainsProducts() 0 6 1
A itGivesFixedDiscountOffOnAProduct() 0 4 1
A itGivesPercentageDiscountOffOnAProduct() 0 4 1
A thePromotionGivesOffTheOrderForCustomersFromGroup() 0 11 1
A itGivesDiscountOnShippingToEveryOrderOver() 0 11 1
A itGivesFreeShippingToEveryOrderOver() 0 4 1
A getTaxonFilterConfiguration() 0 4 1
A getProductsFilterConfiguration() 0 4 1
A getPriceRangeFilterConfiguration() 0 9 2
A createUnitFixedPromotion() 0 11 1
A createUnitPercentagePromotion() 0 11 1
A createFixedPromotion() 0 11 2
A createPercentagePromotion() 0 8 1
A persistPromotion() 0 12 2
A createCoupon() 0 9 1

How to fix   Complexity   

Complex Class

Complex classes like PromotionContext often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use PromotionContext, and based on these observations, apply Extract Interface, too.

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\Model\PromotionActionInterface;
31
use Sylius\Component\Promotion\Model\PromotionRuleInterface;
32
use Sylius\Component\Promotion\Repository\PromotionRepositoryInterface;
33
34
final class PromotionContext implements Context
35
{
36
    /**
37
     * @var SharedStorageInterface
38
     */
39
    private $sharedStorage;
40
41
    /**
42
     * @var PromotionActionFactoryInterface
43
     */
44
    private $actionFactory;
45
46
    /**
47
     * @var PromotionCouponFactoryInterface
48
     */
49
    private $couponFactory;
50
51
    /**
52
     * @var PromotionRuleFactoryInterface
53
     */
54
    private $ruleFactory;
55
56
    /**
57
     * @var TestPromotionFactoryInterface
58
     */
59
    private $testPromotionFactory;
60
61
    /**
62
     * @var PromotionRepositoryInterface
63
     */
64
    private $promotionRepository;
65
66
    /**
67
     * @var ObjectManager
68
     */
69
    private $objectManager;
70
71
    /**
72
     * @param SharedStorageInterface $sharedStorage
73
     * @param PromotionActionFactoryInterface $actionFactory
74
     * @param PromotionCouponFactoryInterface $couponFactory
75
     * @param PromotionRuleFactoryInterface $ruleFactory
76
     * @param TestPromotionFactoryInterface $testPromotionFactory
77
     * @param PromotionRepositoryInterface $promotionRepository
78
     * @param ObjectManager $objectManager
79
     */
80
    public function __construct(
81
        SharedStorageInterface $sharedStorage,
82
        PromotionActionFactoryInterface $actionFactory,
83
        PromotionCouponFactoryInterface $couponFactory,
84
        PromotionRuleFactoryInterface $ruleFactory,
85
        TestPromotionFactoryInterface $testPromotionFactory,
86
        PromotionRepositoryInterface $promotionRepository,
87
        ObjectManager $objectManager
88
    ) {
89
        $this->sharedStorage = $sharedStorage;
90
        $this->actionFactory = $actionFactory;
91
        $this->couponFactory = $couponFactory;
92
        $this->ruleFactory = $ruleFactory;
93
        $this->testPromotionFactory = $testPromotionFactory;
94
        $this->promotionRepository = $promotionRepository;
95
        $this->objectManager = $objectManager;
96
    }
97
98
    /**
99
     * @Given there is (also) a promotion :promotionName
100
     * @Given there is a promotion :promotionName identified by :promotionCode code
101
     */
102
    public function thereIsPromotion(string $promotionName, ?string $promotionCode = null): void
103
    {
104
        $promotion = $this->testPromotionFactory
105
            ->createForChannel($promotionName, $this->sharedStorage->get('channel'))
106
        ;
107
108
        if (null !== $promotionCode) {
109
            $promotion->setCode($promotionCode);
110
        }
111
112
        $this->promotionRepository->add($promotion);
113
        $this->sharedStorage->set('promotion', $promotion);
114
    }
115
116
    /**
117
     * @Given /^there is a promotion "([^"]+)" with priority ([^"]+)$/
118
     */
119
    public function thereIsAPromotionWithPriority($promotionName, $priority)
120
    {
121
        $promotion = $this->testPromotionFactory
122
            ->createForChannel($promotionName, $this->sharedStorage->get('channel'))
123
        ;
124
125
        $promotion->setPriority((int) $priority);
126
127
        $this->promotionRepository->add($promotion);
128
        $this->sharedStorage->set('promotion', $promotion);
129
    }
130
131
    /**
132
     * @Given /^there is an exclusive promotion "([^"]+)"(?:| with priority ([^"]+))$/
133
     */
134
    public function thereIsAnExclusivePromotionWithPriority($promotionName, $priority = 0)
135
    {
136
        $promotion = $this->testPromotionFactory
137
            ->createForChannel($promotionName, $this->sharedStorage->get('channel'))
138
        ;
139
140
        $promotion->setExclusive(true);
141
        $promotion->setPriority((int) $priority);
142
143
        $this->promotionRepository->add($promotion);
144
        $this->sharedStorage->set('promotion', $promotion);
145
    }
146
147
    /**
148
     * @Given there is a promotion :promotionName limited to :usageLimit usages
149
     */
150
    public function thereIsPromotionLimitedToUsages($promotionName, $usageLimit)
151
    {
152
        $promotion = $this->testPromotionFactory->createForChannel($promotionName, $this->sharedStorage->get('channel'));
153
154
        $promotion->setUsageLimit((int) $usageLimit);
155
156
        $this->promotionRepository->add($promotion);
157
        $this->sharedStorage->set('promotion', $promotion);
158
    }
159
160
    /**
161
     * @Given the store has promotion :promotionName with coupon :couponCode
162
     * @Given the store has a promotion :promotionName with a coupon :couponCode that is limited to :usageLimit usages
163
     */
164
    public function thereIsPromotionWithCoupon(string $promotionName, string $couponCode, ?int $usageLimit = null): void
165
    {
166
        $coupon = $this->createCoupon($couponCode, $usageLimit);
167
168
        $promotion = $this->testPromotionFactory
169
            ->createForChannel($promotionName, $this->sharedStorage->get('channel'))
170
        ;
171
        $promotion->addCoupon($coupon);
172
        $promotion->setCouponBased(true);
173
174
        $this->promotionRepository->add($promotion);
175
176
        $this->sharedStorage->set('promotion', $promotion);
177
        $this->sharedStorage->set('coupon', $coupon);
178
    }
179
180
    /**
181
     * @Given /^(this promotion) has "([^"]+)", "([^"]+)" and "([^"]+)" coupons/
182
     */
183
    public function thisPromotionHasCoupons(PromotionInterface $promotion, string ...$couponCodes): void
184
    {
185
        foreach ($couponCodes as $couponCode) {
186
            $coupon = $this->createCoupon($couponCode);
187
            $promotion->addCoupon($coupon);
188
        }
189
190
        $promotion->setCouponBased(true);
191
192
        $this->objectManager->flush();
193
    }
194
195
    /**
196
     * @Given /^(this promotion) has already expired$/
197
     */
198
    public function thisPromotionHasExpired(PromotionInterface $promotion)
199
    {
200
        $promotion->setEndsAt(new \DateTime('1 day ago'));
201
202
        $this->objectManager->flush();
203
    }
204
205
    /**
206
     * @Given /^(this promotion) expires tomorrow$/
207
     */
208
    public function thisPromotionExpiresTomorrow(PromotionInterface $promotion)
209
    {
210
        $promotion->setEndsAt(new \DateTime('tomorrow'));
211
212
        $this->objectManager->flush();
213
    }
214
215
    /**
216
     * @Given /^(this promotion) has started yesterday$/
217
     */
218
    public function thisPromotionHasStartedYesterday(PromotionInterface $promotion)
219
    {
220
        $promotion->setStartsAt(new \DateTime('1 day ago'));
221
222
        $this->objectManager->flush();
223
    }
224
225
    /**
226
     * @Given /^(this promotion) starts tomorrow$/
227
     */
228
    public function thisPromotionStartsTomorrow(PromotionInterface $promotion)
229
    {
230
        $promotion->setStartsAt(new \DateTime('tomorrow'));
231
232
        $this->objectManager->flush();
233
    }
234
235
    /**
236
     * @Given /^(this coupon) has already expired$/
237
     */
238
    public function thisCouponHasExpired(PromotionCouponInterface $coupon)
239
    {
240
        $coupon->setExpiresAt(new \DateTime('1 day ago'));
241
242
        $this->objectManager->flush();
243
    }
244
245
    /**
246
     * @Given /^(this coupon) expires tomorrow$/
247
     */
248
    public function thisCouponExpiresTomorrow(PromotionCouponInterface $coupon)
249
    {
250
        $coupon->setExpiresAt(new \DateTime('tomorrow'));
251
252
        $this->objectManager->flush();
253
    }
254
255
    /**
256
     * @Given /^(this coupon) has already reached its usage limit$/
257
     */
258
    public function thisCouponHasReachedItsUsageLimit(PromotionCouponInterface $coupon)
259
    {
260
        $coupon->setUsed(42);
261
        $coupon->setUsageLimit(42);
262
263
        $this->objectManager->flush();
264
    }
265
266
    /**
267
     * @Given /^(this coupon) can be used (\d+) times?$/
268
     */
269
    public function thisCouponCanBeUsedNTimes(PromotionCouponInterface $coupon, $usageLimit)
270
    {
271
        $coupon->setUsageLimit((int) $usageLimit);
272
273
        $this->objectManager->flush();
274
    }
275
276
    /**
277
     * @Given /^(this coupon) can be used twice per customer$/
278
     */
279
    public function thisCouponCanBeUsedTwicePerCustomer(PromotionCouponInterface $coupon)
280
    {
281
        $coupon->setPerCustomerUsageLimit(2);
282
283
        $this->objectManager->flush();
284
    }
285
286
    /**
287
     * @Given /^([^"]+) gives ("(?:€|£|\$)[^"]+") discount to every order$/
288
     */
289
    public function itGivesFixedDiscountToEveryOrder(PromotionInterface $promotion, $discount)
290
    {
291
        $this->createFixedPromotion($promotion, $discount);
292
    }
293
294
    /**
295
     * @Given /^([^"]+) gives ("(?:€|£|\$)[^"]+") discount to every order in the ("[^"]+" channel) and ("(?:€|£|\$)[^"]+") discount to every order in the ("[^"]+" channel)$/
296
     */
297
    public function thisPromotionGivesDiscountToEveryOrderInTheChannelAndDiscountToEveryOrderInTheChannel(
298
        PromotionInterface $promotion,
299
        $firstChannelDiscount,
300
        ChannelInterface $firstChannel,
301
        $secondChannelDiscount,
302
        ChannelInterface $secondChannel
303
    ) {
304
        /** @var PromotionActionInterface $action */
305
        $action = $this->actionFactory->createFixedDiscount($firstChannelDiscount, $firstChannel->getCode());
306
        $action->setConfiguration(array_merge($action->getConfiguration(), [$secondChannel->getCode() => ['amount' => $secondChannelDiscount]]));
307
308
        $promotion->addChannel($firstChannel);
309
        $promotion->addChannel($secondChannel);
310
        $promotion->addAction($action);
311
312
        $this->objectManager->flush();
313
    }
314
315
    /**
316
     * @Given /^([^"]+) gives ("[^"]+%") discount to every order$/
317
     */
318
    public function itGivesPercentageDiscountToEveryOrder(PromotionInterface $promotion, $discount)
319
    {
320
        $this->createPercentagePromotion($promotion, $discount);
321
    }
322
323
    /**
324
     * @Given /^([^"]+) gives ("(?:€|£|\$)[^"]+") discount to every order with quantity at least ([^"]+)$/
325
     */
326
    public function itGivesFixedDiscountToEveryOrderWithQuantityAtLeast(
327
        PromotionInterface $promotion,
328
        $discount,
329
        $quantity
330
    ) {
331
        $rule = $this->ruleFactory->createCartQuantity((int) $quantity);
332
333
        $this->createFixedPromotion($promotion, $discount, [], $rule);
334
    }
335
336
    /**
337
     * @Given /^([^"]+) gives ("(?:€|£|\$)[^"]+") discount to every order with items total at least ("[^"]+")$/
338
     */
339
    public function itGivesFixedDiscountToEveryOrderWithItemsTotalAtLeast(
340
        PromotionInterface $promotion,
341
        $discount,
342
        $targetAmount
343
    ) {
344
        $channelCode = $this->sharedStorage->get('channel')->getCode();
345
        $rule = $this->ruleFactory->createItemTotal($channelCode, $targetAmount);
346
347
        $this->createFixedPromotion($promotion, $discount, [], $rule);
348
    }
349
350
    /**
351
     * @Given /^([^"]+) gives ("[^"]+%") off on every product when the item total is at least ("(?:€|£|\$)[^"]+")$/
352
     */
353
    public function itGivesOffOnEveryItemWhenItemTotalExceeds(
354
        PromotionInterface $promotion,
355
        $discount,
356
        $targetAmount
357
    ) {
358
        $channelCode = $this->sharedStorage->get('channel')->getCode();
359
        $rule = $this->ruleFactory->createItemTotal($channelCode, $targetAmount);
360
361
        $this->createUnitPercentagePromotion($promotion, $discount, [], $rule);
362
    }
363
364
    /**
365
     * @Given /^([^"]+) gives ("[^"]+%") discount on shipping to every order$/
366
     */
367
    public function itGivesPercentageDiscountOnShippingToEveryOrder(PromotionInterface $promotion, $discount)
368
    {
369
        $action = $this->actionFactory->createShippingPercentageDiscount($discount);
370
        $promotion->addAction($action);
371
372
        $this->objectManager->flush();
373
    }
374
375
    /**
376
     * @Given /^([^"]+) gives free shipping to every order$/
377
     */
378
    public function thePromotionGivesFreeShippingToEveryOrder(PromotionInterface $promotion)
379
    {
380
        $this->itGivesPercentageDiscountOnShippingToEveryOrder($promotion, 1);
381
    }
382
383
    /**
384
     * @Given /^([^"]+) gives(?:| another) ("[^"]+%") off every product (classified as "[^"]+")$/
385
     */
386
    public function itGivesPercentageOffEveryProductClassifiedAs(
387
        PromotionInterface $promotion,
388
        $discount,
389
        TaxonInterface $taxon
390
    ) {
391
        $this->createUnitPercentagePromotion($promotion, $discount, $this->getTaxonFilterConfiguration([$taxon->getCode()]));
392
    }
393
394
    /**
395
     * @Given /^([^"]+) gives(?:| another) ("(?:€|£|\$)[^"]+") off on every product (classified as "[^"]+")$/
396
     */
397
    public function itGivesFixedOffEveryProductClassifiedAs(
398
        PromotionInterface $promotion,
399
        $discount,
400
        TaxonInterface $taxon
401
    ) {
402
        $this->createUnitFixedPromotion($promotion, $discount, $this->getTaxonFilterConfiguration([$taxon->getCode()]));
403
    }
404
405
    /**
406
     * @Given /^([^"]+) gives ("(?:€|£|\$)[^"]+") off on every product with minimum price at ("(?:€|£|\$)[^"]+")$/
407
     */
408
    public function thisPromotionGivesOffOnEveryProductWithMinimumPriceAt(
409
        PromotionInterface $promotion,
410
        $discount,
411
        $amount
412
    ) {
413
        $this->createUnitFixedPromotion($promotion, $discount, $this->getPriceRangeFilterConfiguration($amount));
414
    }
415
416
    /**
417
     * @Given /^([^"]+) gives ("(?:€|£|\$)[^"]+") off on every product priced between ("(?:€|£|\$)[^"]+") and ("(?:€|£|\$)[^"]+")$/
418
     */
419
    public function thisPromotionGivesOffOnEveryProductPricedBetween(
420
        PromotionInterface $promotion,
421
        $discount,
422
        $minAmount,
423
        $maxAmount
424
    ) {
425
        $this->createUnitFixedPromotion(
426
            $promotion,
427
            $discount,
428
            $this->getPriceRangeFilterConfiguration($minAmount, $maxAmount)
429
        );
430
    }
431
432
    /**
433
     * @Given /^([^"]+) gives ("[^"]+%") off on every product with minimum price at ("(?:€|£|\$)[^"]+")$/
434
     */
435
    public function thisPromotionPercentageGivesOffOnEveryProductWithMinimumPriceAt(
436
        PromotionInterface $promotion,
437
        $discount,
438
        $amount
439
    ) {
440
        $this->createUnitPercentagePromotion($promotion, $discount, $this->getPriceRangeFilterConfiguration($amount));
441
    }
442
443
    /**
444
     * @Given /^([^"]+) gives ("[^"]+%") off on every product priced between ("(?:€|£|\$)[^"]+") and ("(?:€|£|\$)[^"]+")$/
445
     */
446
    public function thisPromotionPercentageGivesOffOnEveryProductPricedBetween(
447
        PromotionInterface $promotion,
448
        $discount,
449
        $minAmount,
450
        $maxAmount
451
    ) {
452
        $this->createUnitPercentagePromotion(
453
            $promotion,
454
            $discount,
455
            $this->getPriceRangeFilterConfiguration($minAmount, $maxAmount)
456
        );
457
    }
458
459
    /**
460
     * @Given /^([^"]+) gives ("(?:€|£|\$)[^"]+") off if order contains products (classified as "[^"]+")$/
461
     */
462
    public function thePromotionGivesOffIfOrderContainsProductsClassifiedAs(
463
        PromotionInterface $promotion,
464
        $discount,
465
        TaxonInterface $taxon
466
    ) {
467
        $rule = $this->ruleFactory->createHasTaxon([$taxon->getCode()]);
468
469
        $this->createFixedPromotion($promotion, $discount, [], $rule);
470
    }
471
472
    /**
473
     * @Given /^([^"]+) gives ("(?:€|£|\$)[^"]+") off if order contains products (classified as "[^"]+" or "[^"]+")$/
474
     */
475
    public function thePromotionGivesOffIfOrderContainsProductsClassifiedAsOr(
476
        PromotionInterface $promotion,
477
        $discount,
478
        array $taxons
479
    ) {
480
        $rule = $this->ruleFactory->createHasTaxon([$taxons[0]->getCode(), $taxons[1]->getCode()]);
481
482
        $this->createFixedPromotion($promotion, $discount, [], $rule);
483
    }
484
485
    /**
486
     * @Given /^([^"]+) gives ("(?:€|£|\$)[^"]+") off if order contains products (classified as "[^"]+") with a minimum value of ("(?:€|£|\$)[^"]+")$/
487
     */
488
    public function thePromotionGivesOffIfOrderContainsProductsClassifiedAsAndPricedAt(
489
        PromotionInterface $promotion,
490
        $discount,
491
        TaxonInterface $taxon,
492
        $amount
493
    ) {
494
        $channelCode = $this->sharedStorage->get('channel')->getCode();
495
        $rule = $this->ruleFactory->createItemsFromTaxonTotal($channelCode, $taxon->getCode(), $amount);
496
497
        $this->createFixedPromotion($promotion, $discount, [], $rule);
498
    }
499
500
    /**
501
     * @Given /^([^"]+) gives ("(?:€|£|\$)[^"]+") off customer's (\d)(?:st|nd|rd|th) order$/
502
     */
503
    public function itGivesFixedOffCustomersNthOrder(PromotionInterface $promotion, $discount, $nth)
504
    {
505
        $rule = $this->ruleFactory->createNthOrder((int) $nth);
506
507
        $this->createFixedPromotion($promotion, $discount, [], $rule);
508
    }
509
510
    /**
511
     * @Given /^([^"]+) gives ("[^"]+%") off on the customer's (\d)(?:st|nd|rd|th) order$/
512
     */
513
    public function itGivesPercentageOffCustomersNthOrder(PromotionInterface $promotion, $discount, $nth)
514
    {
515
        $rule = $this->ruleFactory->createNthOrder((int) $nth);
516
517
        $this->createPercentagePromotion($promotion, $discount, [], $rule);
518
    }
519
520
    /**
521
     * @Given /^([^"]+) gives ("[^"]+%") off on every product (classified as "[^"]+") and ("(?:€|£|\$)[^"]+") discount on every order$/
522
     */
523
    public function itGivesPercentageOffOnEveryProductClassifiedAsAndAmountDiscountOnOrder(
524
        PromotionInterface $promotion,
525
        $productDiscount,
526
        TaxonInterface $discountTaxon,
527
        $orderDiscount
528
    ) {
529
        $this->createUnitPercentagePromotion($promotion, $productDiscount, $this->getTaxonFilterConfiguration([$discountTaxon->getCode()]));
530
        $this->createFixedPromotion($promotion, $orderDiscount);
531
    }
532
533
    /**
534
     * @Given /^([^"]+) gives ("(?:€|£|\$)[^"]+") off on every product (classified as "[^"]+") and a free shipping to every order with items total equal at least ("[^"]+")$/
535
     */
536
    public function itGivesOffOnEveryProductClassifiedAsAndAFreeShippingToEveryOrderWithItemsTotalEqualAtLeast(
537
        PromotionInterface $promotion,
538
        $discount,
539
        TaxonInterface $taxon,
0 ignored issues
show
Unused Code introduced by
The parameter $taxon is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
540
        $targetAmount
541
    ) {
542
        $freeShippingAction = $this->actionFactory->createShippingPercentageDiscount(1);
543
        $promotion->addAction($freeShippingAction);
544
545
        $channelCode = $this->sharedStorage->get('channel')->getCode();
546
        $rule = $this->ruleFactory->createItemTotal($channelCode, $targetAmount);
547
548
        $this->createUnitFixedPromotion($promotion, $discount, [], $rule);
549
    }
550
551
    /**
552
     * @Given /^([^"]+) gives ("[^"]+%") off on every product (classified as "[^"]+") and a ("(?:€|£|\$)[^"]+") discount to every order with items total equal at least ("(?:€|£|\$)[^"]+")$/
553
     */
554
    public function itGivesOffOnEveryProductClassifiedAsAndAFixedDiscountToEveryOrderWithItemsTotalEqualAtLeast(
555
        PromotionInterface $promotion,
556
        $taxonDiscount,
557
        TaxonInterface $taxon,
558
        $orderDiscount,
559
        $targetAmount
560
    ) {
561
        $orderDiscountAction = $this->actionFactory->createFixedDiscount($orderDiscount, $this->sharedStorage->get('channel')->getCode());
562
        $promotion->addAction($orderDiscountAction);
563
564
        $channelCode = $this->sharedStorage->get('channel')->getCode();
565
        $rule = $this->ruleFactory->createItemTotal($channelCode, $targetAmount);
566
567
        $this->createUnitPercentagePromotion(
568
            $promotion,
569
            $taxonDiscount,
570
            $this->getTaxonFilterConfiguration([$taxon->getCode()]),
571
            $rule
572
        );
573
    }
574
575
    /**
576
     * @Given /^([^"]+) gives ("[^"]+%") off on every product (classified as "[^"]+" or "[^"]+") if order contains any product (classified as "[^"]+" or "[^"]+")$/
577
     */
578
    public function itGivesOffOnEveryProductClassifiedAsOrIfOrderContainsAnyProductClassifiedAsOr(
579
        PromotionInterface $promotion,
580
        $discount,
581
        array $discountTaxons,
582
        array $targetTaxons
583
    ) {
584
        $discountTaxonsCodes = [$discountTaxons[0]->getCode(), $discountTaxons[1]->getCode()];
585
        $targetTaxonsCodes = [$targetTaxons[0]->getCode(), $targetTaxons[1]->getCode()];
586
587
        $rule = $this->ruleFactory->createHasTaxon($targetTaxonsCodes);
588
589
        $this->createUnitPercentagePromotion(
590
            $promotion,
591
            $discount,
592
            $this->getTaxonFilterConfiguration($discountTaxonsCodes),
593
            $rule
594
        );
595
    }
596
597
    /**
598
     * @Given /^([^"]+) gives ("[^"]+%") off on every product (classified as "[^"]+") if order contains any product (classified as "[^"]+")$/
599
     */
600
    public function itGivesOffOnEveryProductClassifiedAsIfOrderContainsAnyProductClassifiedAs(
601
        PromotionInterface $promotion,
602
        $discount,
603
        $discountTaxon,
604
        $targetTaxon
605
    ) {
606
        $rule = $this->ruleFactory->createHasTaxon([$targetTaxon->getCode()]);
607
608
        $this->createUnitPercentagePromotion(
609
            $promotion,
610
            $discount,
611
            $this->getTaxonFilterConfiguration([$discountTaxon->getCode()]),
612
            $rule
613
        );
614
    }
615
616
    /**
617
     * @Given /^(it) is coupon based promotion$/
618
     */
619
    public function itIsCouponBasedPromotion(PromotionInterface $promotion)
620
    {
621
        $promotion->setCouponBased(true);
622
623
        $this->objectManager->flush();
624
    }
625
626
    /**
627
     * @Given /^(the promotion) was disabled for the (channel "[^"]+")$/
628
     */
629
    public function thePromotionWasDisabledForTheChannel(PromotionInterface $promotion, ChannelInterface $channel)
630
    {
631
        $promotion->removeChannel($channel);
632
633
        $this->objectManager->flush();
634
    }
635
636
    /**
637
     * @Given /^the (coupon "[^"]+") was used up to its usage limit$/
638
     */
639
    public function theCouponWasUsed(PromotionCouponInterface $coupon)
640
    {
641
        $coupon->setUsed($coupon->getUsageLimit());
642
643
        $this->objectManager->flush();
644
    }
645
646
    /**
647
     * @Given /^([^"]+) gives ("(?:€|£|\$)[^"]+") off if order contains (?:a|an) ("[^"]+" product)$/
648
     */
649
    public function thePromotionGivesOffIfOrderContainsProducts(PromotionInterface $promotion, $discount, ProductInterface $product)
650
    {
651
        $rule = $this->ruleFactory->createContainsProduct($product->getCode());
652
653
        $this->createFixedPromotion($promotion, $discount, [], $rule);
654
    }
655
656
    /**
657
     * @Given /^([^"]+) gives ("(?:€|£|\$)[^"]+") off on a ("[^"]*" product)$/
658
     */
659
    public function itGivesFixedDiscountOffOnAProduct(PromotionInterface $promotion, $discount, ProductInterface $product)
660
    {
661
        $this->createUnitFixedPromotion($promotion, $discount, $this->getProductsFilterConfiguration([$product->getCode()]));
662
    }
663
664
    /**
665
     * @Given /^([^"]+) gives ("[^"]+%") off on a ("[^"]*" product)$/
666
     */
667
    public function itGivesPercentageDiscountOffOnAProduct(PromotionInterface $promotion, $discount, ProductInterface $product)
668
    {
669
        $this->createUnitPercentagePromotion($promotion, $discount, $this->getProductsFilterConfiguration([$product->getCode()]));
670
    }
671
672
    /**
673
     * @Given /^([^"]+) gives ("[^"]+%") off the order for customers from ("[^"]*" group)$/
674
     */
675
    public function thePromotionGivesOffTheOrderForCustomersFromGroup(
676
        PromotionInterface $promotion,
677
        $discount,
678
        CustomerGroupInterface $customerGroup
679
    ) {
680
        $rule = $this->ruleFactory->createNew();
681
        $rule->setType(CustomerGroupRuleChecker::TYPE);
682
        $rule->setConfiguration(['group_code' => $customerGroup->getCode()]);
683
684
        $this->createPercentagePromotion($promotion, $discount, [], $rule);
685
    }
686
687
    /**
688
     * @Given /^([^"]+) gives ("[^"]+%") discount on shipping to every order over ("(?:€|£|\$)[^"]+")$/
689
     */
690
    public function itGivesDiscountOnShippingToEveryOrderOver(
691
        PromotionInterface $promotion,
692
        $discount,
693
        $itemTotal
694
    ) {
695
        $channelCode = $this->sharedStorage->get('channel')->getCode();
696
        $rule = $this->ruleFactory->createItemTotal($channelCode, $itemTotal);
697
        $action = $this->actionFactory->createShippingPercentageDiscount($discount);
698
699
        $this->persistPromotion($promotion, $action, [], $rule);
700
    }
701
702
    /**
703
     * @Given /^([^"]+) gives free shipping to every order over ("(?:€|£|\$)[^"]+")$/
704
     */
705
    public function itGivesFreeShippingToEveryOrderOver(PromotionInterface $promotion, $itemTotal)
706
    {
707
        $this->itGivesDiscountOnShippingToEveryOrderOver($promotion, 1, $itemTotal);
708
    }
709
710
    /**
711
     * @param array $taxonCodes
712
     *
713
     * @return array
714
     */
715
    private function getTaxonFilterConfiguration(array $taxonCodes)
716
    {
717
        return ['filters' => ['taxons_filter' => ['taxons' => $taxonCodes]]];
718
    }
719
720
    /**
721
     * @param array $productCodes
722
     *
723
     * @return array
724
     */
725
    private function getProductsFilterConfiguration(array $productCodes)
726
    {
727
        return ['filters' => ['products_filter' => ['products' => $productCodes]]];
728
    }
729
730
    /**
731
     * @param int $minAmount
732
     * @param int $maxAmount
733
     *
734
     * @return array
735
     */
736
    private function getPriceRangeFilterConfiguration($minAmount, $maxAmount = null)
737
    {
738
        $configuration = ['filters' => ['price_range_filter' => ['min' => $minAmount]]];
739
        if (null !== $maxAmount) {
740
            $configuration['filters']['price_range_filter']['max'] = $maxAmount;
741
        }
742
743
        return $configuration;
744
    }
745
746
    /**
747
     * @param PromotionInterface $promotion
748
     * @param int $discount
749
     * @param array $configuration
750
     * @param PromotionRuleInterface|null $rule
751
     */
752
    private function createUnitFixedPromotion(PromotionInterface $promotion, $discount, array $configuration = [], PromotionRuleInterface $rule = null)
753
    {
754
        $channelCode = $this->sharedStorage->get('channel')->getCode();
755
756
        $this->persistPromotion(
757
            $promotion,
758
            $this->actionFactory->createUnitFixedDiscount($discount, $channelCode),
759
            [$channelCode => $configuration],
760
            $rule
761
        );
762
    }
763
764
    /**
765
     * @param PromotionInterface $promotion
766
     * @param int $discount
767
     * @param array $configuration
768
     * @param PromotionRuleInterface|null $rule
769
     */
770
    private function createUnitPercentagePromotion(PromotionInterface $promotion, $discount, array $configuration = [], PromotionRuleInterface $rule = null)
771
    {
772
        $channelCode = $this->sharedStorage->get('channel')->getCode();
773
774
        $this->persistPromotion(
775
            $promotion,
776
            $this->actionFactory->createUnitPercentageDiscount($discount, $channelCode),
777
            [$channelCode => $configuration],
778
            $rule
779
        );
780
    }
781
782
    /**
783
     * @param PromotionInterface $promotion
784
     * @param int $discount
785
     * @param array $configuration
786
     * @param PromotionRuleInterface|null $rule
787
     * @param ChannelInterface|null $channel
788
     */
789
    private function createFixedPromotion(
790
        PromotionInterface $promotion,
791
        $discount,
792
        array $configuration = [],
793
        PromotionRuleInterface $rule = null,
794
        ChannelInterface $channel = null
795
    ) {
796
        $channelCode = (null !== $channel) ? $channel->getCode() : $this->sharedStorage->get('channel')->getCode();
797
798
        $this->persistPromotion($promotion, $this->actionFactory->createFixedDiscount($discount, $channelCode), $configuration, $rule);
799
    }
800
801
    /**
802
     * @param PromotionInterface $promotion
803
     * @param float $discount
804
     * @param array $configuration
805
     * @param PromotionRuleInterface $rule
806
     */
807
    private function createPercentagePromotion(
808
        PromotionInterface $promotion,
809
        $discount,
810
        array $configuration = [],
811
        PromotionRuleInterface $rule = null
812
    ) {
813
        $this->persistPromotion($promotion, $this->actionFactory->createPercentageDiscount($discount), $configuration, $rule);
814
    }
815
816
    /**
817
     * @param PromotionInterface $promotion
818
     * @param PromotionActionInterface $action
819
     * @param array $configuration
820
     * @param PromotionRuleInterface|null $rule
821
     */
822
    private function persistPromotion(PromotionInterface $promotion, PromotionActionInterface $action, array $configuration, PromotionRuleInterface $rule = null)
823
    {
824
        $configuration = array_merge_recursive($action->getConfiguration(), $configuration);
825
        $action->setConfiguration($configuration);
826
827
        $promotion->addAction($action);
828
        if (null !== $rule) {
829
            $promotion->addRule($rule);
830
        }
831
832
        $this->objectManager->flush();
833
    }
834
835
    /**
836
     * @param string $couponCode
837
     * @param int|null $usageLimit
838
     *
839
     * @return PromotionCouponInterface
840
     */
841
    private function createCoupon(string $couponCode, ?int $usageLimit = null): PromotionCouponInterface
842
    {
843
        /** @var PromotionCouponInterface $coupon */
844
        $coupon = $this->couponFactory->createNew();
845
        $coupon->setCode($couponCode);
846
        $coupon->setUsageLimit($usageLimit);
847
848
        return $coupon;
849
    }
850
}
851