Completed
Push — master ( 23b980...7c13a2 )
by Paweł
36:20 queued 26:12
created

src/Sylius/Behat/Context/Setup/ProductContext.php (3 issues)

a method exists on all of the called types.

Bug Major

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

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\Behat\Context\Setup;
13
14
use Behat\Behat\Context\Context;
15
use Behat\Gherkin\Node\TableNode;
16
use Behat\Mink\Element\NodeElement;
17
use Doctrine\Common\Persistence\ObjectManager;
18
use Sylius\Behat\Service\SharedStorageInterface;
19
use Sylius\Component\Attribute\Factory\AttributeFactoryInterface;
20
use Sylius\Component\Core\Formatter\StringInflector;
21
use Sylius\Component\Core\Model\ChannelInterface;
22
use Sylius\Component\Core\Model\ChannelPricingInterface;
23
use Sylius\Component\Core\Model\ImageInterface;
24
use Sylius\Component\Core\Model\ProductInterface;
25
use Sylius\Component\Core\Model\ProductTranslationInterface;
26
use Sylius\Component\Core\Model\ProductVariantInterface;
27
use Sylius\Component\Core\Repository\ProductRepositoryInterface;
28
use Sylius\Component\Core\Uploader\ImageUploaderInterface;
29
use Sylius\Component\Product\Factory\ProductFactoryInterface;
30
use Sylius\Component\Product\Generator\SlugGeneratorInterface;
31
use Sylius\Component\Product\Model\ProductOptionInterface;
32
use Sylius\Component\Product\Model\ProductOptionValueInterface;
33
use Sylius\Component\Product\Model\ProductVariantTranslationInterface;
34
use Sylius\Component\Product\Resolver\ProductVariantResolverInterface;
35
use Sylius\Component\Resource\Factory\FactoryInterface;
36
use Sylius\Component\Resource\Model\TranslationInterface;
37
use Sylius\Component\Resource\Repository\RepositoryInterface;
38
use Sylius\Component\Shipping\Model\ShippingCategoryInterface;
39
use Sylius\Component\Taxation\Model\TaxCategoryInterface;
40
use Symfony\Component\HttpFoundation\File\UploadedFile;
41
use Webmozart\Assert\Assert;
42
43
/**
44
 * @author Arkadiusz Krakowiak <[email protected]>
45
 * @author Mateusz Zalewski <[email protected]>
46
 * @author Magdalena Banasiak <[email protected]>
47
 */
48
final class ProductContext implements Context
49
{
50
    /**
51
     * @var SharedStorageInterface
52
     */
53
    private $sharedStorage;
54
55
    /**
56
     * @var ProductRepositoryInterface
57
     */
58
    private $productRepository;
59
60
    /**
61
     * @var ProductFactoryInterface
62
     */
63
    private $productFactory;
64
65
    /**
66
     * @var FactoryInterface
67
     */
68
    private $productTranslationFactory;
69
70
    /**
71
     * @var FactoryInterface
72
     */
73
    private $productVariantFactory;
74
75
    /**
76
     * @var FactoryInterface
77
     */
78
    private $productVariantTranslationFactory;
79
80
    /**
81
     * @var FactoryInterface
82
     */
83
    private $channelPricingFactory;
84
85
    /**
86
     * @var FactoryInterface
87
     */
88
    private $productOptionFactory;
89
90
    /**
91
     * @var FactoryInterface
92
     */
93
    private $productOptionValueFactory;
94
95
    /**
96
     * @var FactoryInterface
97
     */
98
    private $productImageFactory;
99
100
    /**
101
     * @var ObjectManager
102
     */
103
    private $objectManager;
104
105
    /**
106
     * @var ProductVariantResolverInterface
107
     */
108
    private $defaultVariantResolver;
109
110
    /**
111
     * @var ImageUploaderInterface
112
     */
113
    private $imageUploader;
114
115
    /**
116
     * @var SlugGeneratorInterface
117
     */
118
    private $slugGenerator;
119
120
    /**
121
     * @var array
122
     */
123
    private $minkParameters;
124
125
    /**
126
     * @param SharedStorageInterface $sharedStorage
127
     * @param ProductRepositoryInterface $productRepository
128
     * @param ProductFactoryInterface $productFactory
129
     * @param FactoryInterface $productTranslationFactory
130
     * @param FactoryInterface $productVariantFactory
131
     * @param FactoryInterface $productVariantTranslationFactory
132
     * @param FactoryInterface $channelPricingFactory
133
     * @param FactoryInterface $productOptionFactory
134
     * @param FactoryInterface $productOptionValueFactory
135
     * @param FactoryInterface $productImageFactory
136
     * @param ObjectManager $objectManager
137
     * @param ProductVariantResolverInterface $defaultVariantResolver
138
     * @param ImageUploaderInterface $imageUploader
139
     * @param SlugGeneratorInterface $slugGenerator
140
     * @param array $minkParameters
141
     */
142
    public function __construct(
143
        SharedStorageInterface $sharedStorage,
144
        ProductRepositoryInterface $productRepository,
145
        ProductFactoryInterface $productFactory,
146
        FactoryInterface $productTranslationFactory,
147
        FactoryInterface $productVariantFactory,
148
        FactoryInterface $productVariantTranslationFactory,
149
        FactoryInterface $channelPricingFactory,
150
        FactoryInterface $productOptionFactory,
151
        FactoryInterface $productOptionValueFactory,
152
        FactoryInterface $productImageFactory,
153
        ObjectManager $objectManager,
154
        ProductVariantResolverInterface $defaultVariantResolver,
155
        ImageUploaderInterface $imageUploader,
156
        SlugGeneratorInterface $slugGenerator,
157
        array $minkParameters
158
    ) {
159
        $this->sharedStorage = $sharedStorage;
160
        $this->productRepository = $productRepository;
161
        $this->productFactory = $productFactory;
162
        $this->productTranslationFactory = $productTranslationFactory;
163
        $this->productVariantFactory = $productVariantFactory;
164
        $this->productVariantTranslationFactory = $productVariantTranslationFactory;
165
        $this->channelPricingFactory = $channelPricingFactory;
166
        $this->productOptionFactory = $productOptionFactory;
167
        $this->productOptionValueFactory = $productOptionValueFactory;
168
        $this->productImageFactory = $productImageFactory;
169
        $this->objectManager = $objectManager;
170
        $this->defaultVariantResolver = $defaultVariantResolver;
171
        $this->imageUploader = $imageUploader;
172
        $this->slugGenerator = $slugGenerator;
173
        $this->minkParameters = $minkParameters;
174
    }
175
176
    /**
177
     * @Given the store has a product :productName
178
     * @Given the store has a :productName product
179
     * @Given I added a product :productName
180
     * @Given /^the store(?:| also) has a product "([^"]+)" priced at ("[^"]+")$/
181
     * @Given /^the store(?:| also) has a product "([^"]+)" priced at ("[^"]+") in ("[^"]+" channel)$/
182
     */
183
    public function storeHasAProductPricedAt($productName, $price = 100, ChannelInterface $channel = null)
184
    {
185
        if (null === $channel && $this->sharedStorage->has('channel')) {
186
            $channel = $this->sharedStorage->get('channel');
187
        }
188
        $product = $this->createProduct($productName, $price, null, $channel);
189
        $product->setDescription('Awesome '.$productName);
190
191
        if (null !== $channel) {
192
            $product->addChannel($channel);
193
        }
194
195
        $this->saveProduct($product);
196
    }
197
198
    /**
199
     * @Given /^(this product) is also priced at ("[^"]+") in ("[^"]+" channel)$/
200
     */
201
    public function thisProductIsAlsoPricedAtInChannel(ProductInterface $product, $price, ChannelInterface $channel)
202
    {
203
        $product->addChannel($channel);
204
205
        /** @var ProductVariantInterface $productVariant */
206
        $productVariant = $this->defaultVariantResolver->getVariant($product);
207
208
        /** @var ChannelPricingInterface $channelPricing */
209
        $channelPricing = $this->channelPricingFactory->createNew();
210
        $channelPricing->setPrice($price);
211
        $channelPricing->setChannel($channel);
212
213
        $productVariant->addChannelPricing($channelPricing);
214
215
        $this->objectManager->flush();
216
    }
217
218
    /**
219
     * @Given the store( also) has a product :productName with code :code
220
     * @Given the store( also) has a product :productName with code :code, created at :date
221
     */
222
    public function storeHasProductWithCode($productName, $code, $date = null)
223
    {
224
        $product = $this->createProduct($productName, 0, $date);
225
226
        $product->setCode($code);
227
228
        if ($this->sharedStorage->has('channel')) {
229
            $product->addChannel($this->sharedStorage->get('channel'));
230
        }
231
232
        $this->saveProduct($product);
233
    }
234
235
    /**
236
     * @Given /^the store(?:| also) has a product "([^"]+)" priced at ("[^"]+") available in (channel "[^"]+") and (channel "[^"]+")$/
237
     */
238
    public function storeHasAProductPricedAtAvailableInChannels($productName, $price = 100, ...$channels)
239
    {
240
        $product = $this->createProduct($productName, $price);
241
        /** @var ProductVariantInterface $productVariant */
242
        $productVariant = $this->defaultVariantResolver->getVariant($product);
243
244
        $product->setDescription('Awesome '.$productName);
245
246
        foreach ($channels as $channel) {
247
            $product->addChannel($channel);
248
            if (!$productVariant->hasChannelPricingForChannel($channel)) {
249
                $productVariant->addChannelPricing($this->createChannelPricingForChannel($price, $channel));
250
            }
251
        }
252
253
        $this->saveProduct($product);
254
    }
255
256
    /**
257
     * @Given /^(this product) is named "([^"]+)" (in the "([^"]+)" locale)$/
258
     * @Given /^the (product "[^"]+") is named "([^"]+)" (in the "([^"]+)" locale)$/
259
     */
260
    public function thisProductIsNamedIn(ProductInterface $product, $name, $locale)
261
    {
262
        $this->addProductTranslation($product, $name, $locale);
263
264
        $this->objectManager->flush();
265
    }
266
267
    /**
268
     * @Given /^the store has a product named "([^"]+)" in ("[^"]+" locale) and "([^"]+)" in ("[^"]+" locale)$/
269
     */
270
    public function theStoreHasProductNamedInAndIn($firstName, $firstLocale, $secondName, $secondLocale)
271
    {
272
        $product = $this->createProduct($firstName);
273
274
        $names = [$firstName => $firstLocale, $secondName => $secondLocale];
275
        foreach ($names as $name => $locale) {
276
            $this->addProductTranslation($product, $name, $locale);
277
        }
278
279
        $this->saveProduct($product);
280
    }
281
282
    /**
283
     * @Given /^the store has(?:| a| an) "([^"]+)" configurable product$/
284
     * @Given /^the store has(?:| a| an) "([^"]+)" configurable product with "([^"]+)" slug$/
285
     */
286
    public function storeHasAConfigurableProduct($productName, $slug = null)
287
    {
288
        /** @var ProductInterface $product */
289
        $product = $this->productFactory->createNew();
290
291
        $product->setName($productName);
292
        $product->setCode(StringInflector::nameToUppercaseCode($productName));
293
        $product->setSlug($slug?:$this->slugGenerator->generate($productName));
294
295
        $product->setDescription('Awesome '.$productName);
296
297
        if ($this->sharedStorage->has('channel')) {
298
            $channel = $this->sharedStorage->get('channel');
299
            $product->addChannel($channel);
300
        }
301
302
        $this->saveProduct($product);
303
    }
304
305
    /**
306
     * @Given the store has( also) :firstProductName and :secondProductName products
307
     * @Given the store has( also) :firstProductName, :secondProductName and :thirdProductName products
308
     * @Given the store has( also) :firstProductName, :secondProductName, :thirdProductName and :fourthProductName products
309
     */
310
    public function theStoreHasProducts(...$productsNames)
311
    {
312
        foreach ($productsNames as $productName) {
313
            $this->saveProduct($this->createProduct($productName));
314
        }
315
    }
316
317
    /**
318
     * @Given /^(this channel) has "([^"]+)", "([^"]+)", "([^"]+)" and "([^"]+)" products$/
319
     */
320
    public function thisChannelHasProducts(ChannelInterface $channel, ...$productsNames)
321
    {
322
        foreach ($productsNames as $productName) {
323
            $product = $this->createProduct($productName);
324
            $product->addChannel($channel);
325
326
            $this->saveProduct($product);
327
        }
328
    }
329
330
    /**
331
     * @Given /^the (product "[^"]+") has(?:| a) "([^"]+)" variant priced at ("[^"]+")$/
332
     * @Given /^(this product) has "([^"]+)" variant priced at ("[^"]+")$/
333
     * @Given /^(this product) has "([^"]+)" variant priced at ("[^"]+") in ("([^"]+)" channel)$/
334
     */
335
    public function theProductHasVariantPricedAt(
336
        ProductInterface $product,
337
        $productVariantName,
338
        $price,
339
        ChannelInterface $channel = null
340
    ) {
341
        $this->createProductVariant(
342
            $product,
343
            $productVariantName,
344
            $price,
345
            StringInflector::nameToUppercaseCode($productVariantName),
346
            (null !== $channel) ? $channel : $this->sharedStorage->get('channel')
347
        );
348
    }
349
350
    /**
351
     * @Given /^(this product) has "([^"]+)" variant priced at ("[^"]+") which does not require shipping$/
352
     */
353
    public function theProductHasVariantWhichDoesNotRequireShipping(
354
        ProductInterface $product,
355
        $productVariantName,
356
        $price
357
    ) {
358
        $this->createProductVariant(
359
            $product,
360
            $productVariantName,
361
            $price,
362
            StringInflector::nameToUppercaseCode($productVariantName),
363
            $this->sharedStorage->get('channel'),
364
            null,
365
            false
366
        );
367
    }
368
369
    /**
370
     * @Given /^the (product "[^"]+") has(?:| also)(?:| a| an) "([^"]+)" variant$/
371
     * @Given /^the (product "[^"]+") has(?:| also)(?:| a| an) "([^"]+)" variant at position ([^"]+)$/
372
     * @Given /^(this product) has(?:| also)(?:| a| an) "([^"]+)" variant at position ([^"]+)$/
373
     */
374
    public function theProductHasVariantAtPosition(
375
        ProductInterface $product,
376
        $productVariantName,
377
        $position = null
378
    ) {
379
        $this->createProductVariant(
380
            $product,
381
            $productVariantName,
382
            0,
383
            StringInflector::nameToUppercaseCode($productVariantName),
384
            $this->sharedStorage->get('channel'),
385
            $position
386
        );
387
    }
388
389
    /**
390
     * @Given /^(this variant) is also priced at ("[^"]+") in ("([^"]+)" channel)$/
391
     */
392
    public function thisVariantIsAlsoPricedAtInChannel(ProductVariantInterface $productVariant, $price, ChannelInterface $channel)
393
    {
394
        $productVariant->addChannelPricing($this->createChannelPricingForChannel(
395
            $this->getPriceFromString(str_replace(['$', '€', '£'], '', $price)),
396
            $channel
397
        ));
398
399
        $this->objectManager->flush();
400
    }
401
402
    /**
403
     * @Given /^(it|this product) has(?:| also) variant named "([^"]+)" in ("[^"]+" locale) and "([^"]+)" in ("[^"]+" locale)$/
404
     */
405
    public function itHasVariantNamedInAndIn(ProductInterface $product, $firstName, $firstLocale, $secondName, $secondLocale)
406
    {
407
        $productVariant = $this->createProductVariant(
408
            $product,
409
            $firstName,
410
            100,
411
            StringInflector::nameToUppercaseCode($firstName),
412
            $this->sharedStorage->get('channel')
413
        );
414
415
        $names = [$firstName => $firstLocale, $secondName => $secondLocale];
416
        foreach ($names as $name => $locale) {
417
            $this->addProductVariantTranslation($productVariant, $name, $locale);
418
        }
419
420
        $this->objectManager->flush();
421
    }
422
423
    /**
424
     * @Given /^(this product) has "([^"]+)" variant priced at ("[^"]+") identified by "([^"]+)"$/
425
     */
426
    public function theProductHasVariantPricedAtIdentifiedBy(
427
        ProductInterface $product,
428
        $productVariantName,
429
        $price,
430
        $code
431
    ) {
432
        $this->createProductVariant($product, $productVariantName, $price, $code, $this->sharedStorage->get('channel'));
433
    }
434
435
    /**
436
     * @Given /^there is product "([^"]+)" available in ((?:this|that|"[^"]+") channel)$/
437
     * @Given /^the store has a product "([^"]+)" available in ("([^"]+)" channel)$/
438
     */
439
    public function thereIsProductAvailableInGivenChannel($productName, ChannelInterface $channel)
440
    {
441
        $product = $this->createProduct($productName, 0, null, $channel);
442
443
        $product->setDescription('Awesome ' . $productName);
444
        $product->addChannel($channel);
445
446
        $this->saveProduct($product);
447
    }
448
449
    /**
450
     * @Given /^([^"]+) belongs to ("[^"]+" tax category)$/
451
     */
452
    public function productBelongsToTaxCategory(ProductInterface $product, TaxCategoryInterface $taxCategory)
453
    {
454
        /** @var ProductVariantInterface $variant */
455
        $variant = $this->defaultVariantResolver->getVariant($product);
456
        $variant->setTaxCategory($taxCategory);
457
458
        $this->objectManager->flush();
459
    }
460
461
    /**
462
     * @Given /^(it) comes in the following variations:$/
463
     */
464
    public function itComesInTheFollowingVariations(ProductInterface $product, TableNode $table)
465
    {
466
        foreach ($table->getHash() as $variantHash) {
467
            /** @var ProductVariantInterface $variant */
468
            $variant = $this->productVariantFactory->createNew();
469
470
            $variant->setName($variantHash['name']);
471
            $variant->setCode(StringInflector::nameToUppercaseCode($variantHash['name']));
472
            $variant->addChannelPricing($this->createChannelPricingForChannel(
473
                $this->getPriceFromString(str_replace(['$', '€', '£'], '', $variantHash['price'])),
474
                $this->sharedStorage->get('channel')
475
            ));
476
            $variant->setProduct($product);
477
            $product->addVariant($variant);
478
        }
479
480
        $this->objectManager->flush();
481
    }
482
483
    /**
484
     * @Given /^("[^"]+" variant of product "[^"]+") belongs to ("[^"]+" tax category)$/
485
     */
486
    public function productVariantBelongsToTaxCategory(
487
        ProductVariantInterface $productVariant,
488
        TaxCategoryInterface $taxCategory
489
    ) {
490
        $productVariant->setTaxCategory($taxCategory);
491
        $this->objectManager->flush($productVariant);
492
    }
493
494
    /**
495
     * @Given /^(this product) has option "([^"]+)" with values "([^"]+)" and "([^"]+)"$/
496
     * @Given /^(this product) has option "([^"]+)" with values "([^"]+)", "([^"]+)" and "([^"]+)"$/
497
     */
498
    public function thisProductHasOptionWithValues(ProductInterface $product, $optionName, ...$values)
499
    {
500
        /** @var ProductOptionInterface $option */
501
        $option = $this->productOptionFactory->createNew();
502
503
        $option->setName($optionName);
504
        $option->setCode(StringInflector::nameToUppercaseCode($optionName));
505
506
        $this->sharedStorage->set(sprintf('%s_option', $optionName), $option);
507
508
        foreach ($values as $key => $value) {
509
            $optionValue = $this->addProductOption($option, $value, StringInflector::nameToUppercaseCode($value));
510
            $this->sharedStorage->set(sprintf('%s_option_%s_value', $value, strtolower($optionName)), $optionValue);
511
        }
512
513
        $product->addOption($option);
514
        $product->setVariantSelectionMethod(ProductInterface::VARIANT_SELECTION_MATCH);
515
516
        $this->objectManager->persist($option);
517
        $this->objectManager->flush();
518
    }
519
520
    /**
521
     * @Given /^there (?:is|are) (\d+) unit(?:|s) of (product "([^"]+)") available in the inventory$/
522
     */
523
    public function thereIsQuantityOfProducts($quantity, ProductInterface $product)
524
    {
525
        /** @var ProductVariantInterface $productVariant */
526
        $productVariant = $this->defaultVariantResolver->getVariant($product);
527
        $productVariant->setOnHand($quantity);
528
529
        $this->objectManager->flush();
530
    }
531
532
    /**
533
     * @Given /^the (product "([^"]+)") is out of stock$/
534
     */
535
    public function theProductIsOutOfStock(ProductInterface $product)
536
    {
537
        /** @var ProductVariantInterface $productVariant */
538
        $productVariant = $this->defaultVariantResolver->getVariant($product);
539
        $productVariant->setTracked(true);
540
        $productVariant->setOnHand(0);
541
542
        $this->objectManager->flush();
543
    }
544
545
    /**
546
     * @When other customer has bought :quantity :product products by this time
547
     */
548
    public function otherCustomerHasBoughtProductsByThisTime($quantity, ProductInterface $product)
549
    {
550
        /** @var ProductVariantInterface $productVariant */
551
        $productVariant = $this->defaultVariantResolver->getVariant($product);
552
        $productVariant->setOnHand($productVariant->getOnHand() - $quantity);
553
554
        $this->objectManager->flush();
555
    }
556
557
    /**
558
     * @Given /^(this product) is tracked by the inventory$/
559
     * @Given /^(?:|the )("[^"]+" product) is(?:| also) tracked by the inventory$/
560
     */
561
    public function thisProductIsTrackedByTheInventory(ProductInterface $product)
562
    {
563
        /** @var ProductVariantInterface $productVariant */
564
        $productVariant = $this->defaultVariantResolver->getVariant($product);
565
        $productVariant->setTracked(true);
566
567
        $this->objectManager->flush();
568
    }
569
570
    /**
571
     * @Given /^(this product) is available in "([^"]+)" ([^"]+) priced at ("[^"]+")$/
572
     */
573
    public function thisProductIsAvailableInSize(ProductInterface $product, $optionValueName, $optionName, $price)
574
    {
575
        /** @var ProductVariantInterface $variant */
576
        $variant = $this->productVariantFactory->createNew();
577
578
        $optionValue = $this->sharedStorage->get(sprintf('%s_option_%s_value', $optionValueName, $optionName));
579
580
        $variant->addOptionValue($optionValue);
581
        $variant->addChannelPricing($this->createChannelPricingForChannel($price, $this->sharedStorage->get('channel')));
582
        $variant->setCode(sprintf('%s_%s', $product->getCode(), $optionValueName));
583
        $variant->setName($product->getName());
584
585
        $product->addVariant($variant);
586
        $this->objectManager->flush();
587
    }
588
589
    /**
590
     * @Given the :product product's :optionValueName size belongs to :shippingCategory shipping category
591
     */
592
    public function thisProductSizeBelongsToShippingCategory(ProductInterface $product, $optionValueName, ShippingCategoryInterface $shippingCategory)
593
    {
594
        $code = sprintf('%s_%s', $product->getCode(), $optionValueName);
595
        /** @var ProductVariantInterface $productVariant */
596
        $productVariant = $product->getVariants()->filter(function ($variant) use ($code) {
597
            return $code === $variant->getCode();
598
        })->first();
599
600
        Assert::notNull($productVariant, sprintf('Product variant with given code %s not exists!', $code));
601
602
        $productVariant->setShippingCategory($shippingCategory);
603
        $this->objectManager->flush();
604
    }
605
606
    /**
607
     * @Given /^(this product) has (this product option)$/
608
     * @Given /^(this product) has (?:a|an) ("[^"]+" option)$/
609
     */
610
    public function thisProductHasThisProductOption(ProductInterface $product, ProductOptionInterface $option)
611
    {
612
        $product->addOption($option);
613
614
        $this->objectManager->flush();
615
    }
616
617
    /**
618
     * @Given /^there are ([^"]+) units of ("[^"]+" variant of product "[^"]+") available in the inventory$/
619
     */
620
    public function thereAreItemsOfProductInVariantAvailableInTheInventory($quantity, ProductVariantInterface $productVariant)
621
    {
622
        $productVariant->setTracked(true);
623
        $productVariant->setOnHand($quantity);
624
625
        $this->objectManager->flush();
626
    }
627
628
    /**
629
     * @Given /^the ("[^"]+" product variant) is tracked by the inventory$/
630
     */
631
    public function theProductVariantIsTrackedByTheInventory(ProductVariantInterface $productVariant)
632
    {
633
        $productVariant->setTracked(true);
634
635
        $this->objectManager->flush();
636
    }
637
638
    /**
639
     * @Given /^(this product)'s price is ("[^"]+")$/
640
     * @Given /^the (product "[^"]+") changed its price to ("[^"]+")$/
641
     * @Given /^(this product) price has been changed to ("[^"]+")$/
642
     */
643
    public function theProductChangedItsPriceTo(ProductInterface $product, $price)
644
    {
645
        /** @var ProductVariantInterface $productVariant */
646
        $productVariant = $this->defaultVariantResolver->getVariant($product);
647
        $channelPricing = $productVariant->getChannelPricingForChannel($this->sharedStorage->get('channel'));
648
        $channelPricing->setPrice($price);
649
650
        $this->objectManager->flush();
651
    }
652
653
    /**
654
     * @Given /^(this product)(?:| also) has an image "([^"]+)" with "([^"]+)" type$/
655
     * @Given /^the ("[^"]+" product)(?:| also) has an image "([^"]+)" with "([^"]+)" type$/
656
     * @Given /^(it)(?:| also) has an image "([^"]+)" with "([^"]+)" type$/
657
     */
658
    public function thisProductHasAnImageWithType(ProductInterface $product, $imagePath, $imageType)
659
    {
660
        $filesPath = $this->getParameter('files_path');
661
662
        /** @var ImageInterface $productImage */
663
        $productImage = $this->productImageFactory->createNew();
664
        $productImage->setFile(new UploadedFile($filesPath.$imagePath, basename($imagePath)));
665
        $productImage->setType($imageType);
666
        $this->imageUploader->upload($productImage);
667
668
        $product->addImage($productImage);
669
670
        $this->objectManager->flush($product);
671
    }
672
673
    /**
674
     * @Given /^(this product) belongs to ("([^"]+)" shipping category)$/
675
     * @Given product :product shipping category has been changed to :shippingCategory
676
     */
677
    public function thisProductBelongsToShippingCategory(ProductInterface $product, ShippingCategoryInterface $shippingCategory)
678
    {
679
        $product->getVariants()->first()->setShippingCategory($shippingCategory);
680
        $this->objectManager->flush();
681
    }
682
683
    /**
684
     * @Given /^(this product) has been disabled$/
685
     */
686
    public function thisProductHasBeenDisabled(ProductInterface $product)
687
    {
688
        $product->disable();
689
        $this->objectManager->flush();
690
    }
691
692
    /**
693
     * @param string $price
694
     *
695
     * @return int
696
     */
697
    private function getPriceFromString($price)
698
    {
699
        return (int) round($price * 100, 2);
700
    }
701
702
    /**
703
     * @param string $productName
704
     * @param int $price
705
     * @param string|null $date
706
     * @param ChannelInterface|null $channel
707
     *
708
     * @return ProductInterface
709
     */
710
    private function createProduct($productName, $price = 100, $date = null, ChannelInterface $channel = null)
711
    {
712
        /** @var ProductInterface $product */
713
        $product = $this->productFactory->createWithVariant();
714
715
        $product->setName($productName);
716
        $product->setCode(StringInflector::nameToUppercaseCode($productName));
717
        $product->setSlug($this->slugGenerator->generate($productName));
718
        $product->setCreatedAt(new \DateTime($date));
719
720
        /** @var ProductVariantInterface $productVariant */
721
        $productVariant = $this->defaultVariantResolver->getVariant($product);
722
723
        if (null === $channel && $this->sharedStorage->has('channel')) {
724
            $channel = $this->sharedStorage->get('channel');
725
        }
726
727
        if (null !== $channel) {
728
            $productVariant->addChannelPricing($this->createChannelPricingForChannel($price, $channel));
729
        }
730
        $productVariant->setCode($product->getCode());
731
        $productVariant->setName($product->getName());
732
733
        return $product;
734
    }
735
736
    /**
737
     * @param ProductOptionInterface $option
738
     * @param string $value
739
     * @param string $code
740
     *
741
     * @return ProductOptionValueInterface
742
     */
743
    private function addProductOption(ProductOptionInterface $option, $value, $code)
744
    {
745
        /** @var ProductOptionValueInterface $optionValue */
746
        $optionValue = $this->productOptionValueFactory->createNew();
747
748
        $optionValue->setValue($value);
749
        $optionValue->setCode($code);
750
        $optionValue->setOption($option);
751
752
        $option->addValue($optionValue);
753
754
        return $optionValue;
755
    }
756
757
    /**
758
     * @param ProductInterface $product
759
     */
760
    private function saveProduct(ProductInterface $product)
761
    {
762
        $this->productRepository->add($product);
763
        $this->sharedStorage->set('product', $product);
764
    }
765
766
    /**
767
     * @param string $name
768
     *
769
     * @return NodeElement
770
     */
771
    private function getParameter($name)
772
    {
773
        return isset($this->minkParameters[$name]) ? $this->minkParameters[$name] : null;
774
    }
775
776
    /**
777
     * @param ProductInterface $product
778
     * @param $productVariantName
779
     * @param int $price
780
     * @param string $code
781
     * @param ChannelInterface $channel
782
     * @param int $position
783
     * @param bool $shippingRequired
784
     *
785
     * @return ProductVariantInterface
786
     */
787
    private function createProductVariant(
788
        ProductInterface $product,
789
        $productVariantName,
790
        $price,
791
        $code,
792
        ChannelInterface $channel = null,
793
        $position = null,
794
        $shippingRequired = true
795
    ) {
796
        $product->setVariantSelectionMethod(ProductInterface::VARIANT_SELECTION_CHOICE);
797
798
        /** @var ProductVariantInterface $variant */
799
        $variant = $this->productVariantFactory->createNew();
800
801
        $variant->setName($productVariantName);
802
        $variant->setCode($code);
803
        $variant->setProduct($product);
804
        $variant->addChannelPricing($this->createChannelPricingForChannel($price, $channel));
805
        $variant->setPosition($position);
806
        $variant->setShippingRequired($shippingRequired);
807
808
        $product->addVariant($variant);
809
810
        $this->objectManager->flush();
811
        $this->sharedStorage->set('variant', $variant);
812
813
        return $variant;
814
    }
815
816
    /**
817
     * @param ProductInterface $product
818
     * @param string $name
819
     * @param string $locale
820
     */
821
    private function addProductTranslation(ProductInterface $product, $name, $locale)
822
    {
823
        /** @var ProductTranslationInterface|TranslationInterface $translation */
824
        $translation = $this->productTranslationFactory->createNew();
825
        $translation->setLocale($locale);
0 ignored issues
show
The method setLocale does only exist in Sylius\Component\Resourc...el\TranslationInterface, but not in Sylius\Component\Core\Mo...uctTranslationInterface.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
826
        $translation->setName($name);
0 ignored issues
show
The method setName does only exist in Sylius\Component\Core\Mo...uctTranslationInterface, but not in Sylius\Component\Resourc...el\TranslationInterface.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
827
        $translation->setSlug($this->slugGenerator->generate($name));
0 ignored issues
show
The method setSlug does only exist in Sylius\Component\Core\Mo...uctTranslationInterface, but not in Sylius\Component\Resourc...el\TranslationInterface.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
828
829
        $product->addTranslation($translation);
830
    }
831
832
    /**
833
     * @param ProductVariantInterface $productVariant
834
     * @param string $name
835
     * @param string $locale
836
     */
837
    private function addProductVariantTranslation(ProductVariantInterface $productVariant, $name, $locale)
838
    {
839
        /** @var ProductVariantTranslationInterface|TranslationInterface $translation */
840
        $translation = $this->productVariantTranslationFactory->createNew();
841
        $translation->setLocale($locale);
842
        $translation->setName($name);
843
844
        $productVariant->addTranslation($translation);
845
    }
846
847
    /**
848
     * @param int $price
849
     * @param ChannelInterface|null $channel
850
     *
851
     * @return ChannelPricingInterface
852
     */
853
    private function createChannelPricingForChannel($price, ChannelInterface $channel = null)
854
    {
855
        /** @var ChannelPricingInterface $channelPricing */
856
        $channelPricing = $this->channelPricingFactory->createNew();
857
        $channelPricing->setPrice($price);
858
        $channelPricing->setChannel($channel);
859
860
        return $channelPricing;
861
    }
862
}
863