Completed
Push — master ( e9a7f6...2665f3 )
by Kamil
46:03 queued 28:24
created

ProductContext   F

Complexity

Total Complexity 50

Size/Duplication

Total Lines 721
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 21

Importance

Changes 0
Metric Value
wmc 50
lcom 1
cbo 21
dl 0
loc 721
rs 2.75
c 0
b 0
f 0

40 Methods

Rating   Name   Duplication   Size   Complexity  
A storeHasAProductPricedAt() 0 12 2
A storeHasProductWithCode() 0 12 2
A storeHasAProductPricedAtAvailableInChannels() 0 12 2
A thisProductIsNamedIn() 0 12 1
A storeHasAConfigurableProduct() 0 18 2
A theStoreHasProducts() 0 6 2
A thisChannelHasProducts() 0 9 2
B __construct() 0 33 1
A theProductHasVariantPricedAt() 0 9 1
A theProductHasVariantPricedAtIdentifiedBy() 0 8 1
A thereIsProductAvailableInGivenChannel() 0 9 1
A productBelongsToTaxCategory() 0 8 1
A itComesInTheFollowingVariations() 0 15 2
A productVariantBelongsToTaxCategory() 0 7 1
A thisProductHasAttributeWithValue() 0 8 1
A thisProductHasPercentAttributeWithValue() 0 8 1
A thisProductHasCheckboxAttributeWithValue() 0 9 1
A thisProductHasPercentAttributeWithValueAtPosition() 0 10 1
A thisProductHasDateTimeAttributeWithDate() 0 9 1
A thisProductHasOptionWithValues() 0 21 2
A thereIsQuantityOfProducts() 0 8 1
A theProductIsOutOfStock() 0 9 1
A otherCustomerHasBoughtProductsByThisTime() 0 8 1
A thisProductIsTrackedByTheInventory() 0 8 1
A thisProductIsAvailableInSize() 0 14 1
A thisProductHasThisProductOption() 0 6 1
A thereAreItemsOfProductInVariantAvailableInTheInventory() 0 7 1
A theProductVariantIsTrackedByTheInventory() 0 6 1
A theProductChangedItsPriceTo() 0 8 1
A thisProductHasAnImageWithACode() 0 14 1
A itHasDifferentPricesForDifferentChannelsAndCurrencies() 0 7 1
A itHasPriceForChannelAndCurrency() 0 16 1
A createProductAttribute() 0 15 2
A createProductAttributeValue() 0 11 1
A getPriceFromString() 0 4 1
A createProduct() 0 17 1
A addProductOption() 0 13 1
A saveProduct() 0 5 1
A getParameter() 0 4 2
A createProductVariant() 0 17 1

How to fix   Complexity   

Complex Class

Complex classes like ProductContext 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 ProductContext, 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
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\Component\Attribute\Factory\AttributeFactoryInterface;
19
use Sylius\Component\Core\Formatter\StringInflector;
20
use Sylius\Component\Core\Model\ChannelInterface;
21
use Sylius\Component\Core\Model\ImageInterface;
22
use Sylius\Component\Core\Model\ProductInterface;
23
use Sylius\Component\Core\Model\ProductTranslationInterface;
24
use Sylius\Component\Core\Model\ProductVariantInterface;
25
use Sylius\Component\Core\Pricing\Calculators;
26
use Sylius\Component\Core\Repository\ProductRepositoryInterface;
27
use Sylius\Behat\Service\SharedStorageInterface;
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\ProductAttributeInterface;
32
use Sylius\Component\Product\Model\ProductAttributeValueInterface;
33
use Sylius\Component\Product\Model\ProductOptionInterface;
34
use Sylius\Component\Product\Model\ProductOptionValueInterface;
35
use Sylius\Component\Resource\Factory\FactoryInterface;
36
use Sylius\Component\Taxation\Model\TaxCategoryInterface;
37
use Sylius\Component\Product\Resolver\ProductVariantResolverInterface;
38
use Symfony\Component\HttpFoundation\File\UploadedFile;
39
40
/**
41
 * @author Arkadiusz Krakowiak <[email protected]>
42
 * @author Mateusz Zalewski <[email protected]>
43
 * @author Magdalena Banasiak <[email protected]>
44
 */
45
final class ProductContext implements Context
46
{
47
    /**
48
     * @var SharedStorageInterface
49
     */
50
    private $sharedStorage;
51
52
    /**
53
     * @var ProductRepositoryInterface
54
     */
55
    private $productRepository;
56
57
    /**
58
     * @var ProductFactoryInterface
59
     */
60
    private $productFactory;
61
62
    /**
63
     * @var FactoryInterface
64
     */
65
    private $productTranslationFactory;
66
67
    /**
68
     * @var AttributeFactoryInterface
69
     */
70
    private $productAttributeFactory;
71
72
    /**
73
     * @var FactoryInterface
74
     */
75
    private $productVariantFactory;
76
77
    /**
78
     * @var FactoryInterface
79
     */
80
    private $attributeValueFactory;
81
82
    /**
83
     * @var FactoryInterface
84
     */
85
    private $productOptionFactory;
86
87
    /**
88
     * @var FactoryInterface
89
     */
90
    private $productOptionValueFactory;
91
92
    /**
93
     * @var FactoryInterface
94
     */
95
    private $productImageFactory;
96
97
    /**
98
     * @var ObjectManager
99
     */
100
    private $objectManager;
101
102
    /**
103
     * @var ProductVariantResolverInterface
104
     */
105
    private $defaultVariantResolver;
106
107
    /**
108
     * @var ImageUploaderInterface
109
     */
110
    private $imageUploader;
111
112
    /**
113
     * @var SlugGeneratorInterface
114
     */
115
    private $slugGenerator;
116
117
    /**
118
     * @var array
119
     */
120
    private $minkParameters;
121
122
    /**
123
     * @param SharedStorageInterface $sharedStorage
124
     * @param ProductRepositoryInterface $productRepository
125
     * @param ProductFactoryInterface $productFactory
126
     * @param FactoryInterface $productTranslationFactory
127
     * @param AttributeFactoryInterface $productAttributeFactory
128
     * @param FactoryInterface $attributeValueFactory
129
     * @param FactoryInterface $productVariantFactory
130
     * @param FactoryInterface $productOptionFactory
131
     * @param FactoryInterface $productOptionValueFactory
132
     * @param FactoryInterface $productImageFactory
133
     * @param ObjectManager $objectManager
134
     * @param ProductVariantResolverInterface $defaultVariantResolver
135
     * @param ImageUploaderInterface $imageUploader
136
     * @param SlugGeneratorInterface $slugGenerator
137
     * @param array $minkParameters
138
     */
139
    public function __construct(
140
        SharedStorageInterface $sharedStorage,
141
        ProductRepositoryInterface $productRepository,
142
        ProductFactoryInterface $productFactory,
143
        FactoryInterface $productTranslationFactory,
144
        AttributeFactoryInterface $productAttributeFactory,
145
        FactoryInterface $attributeValueFactory,
146
        FactoryInterface $productVariantFactory,
147
        FactoryInterface $productOptionFactory,
148
        FactoryInterface $productOptionValueFactory,
149
        FactoryInterface $productImageFactory,
150
        ObjectManager $objectManager,
151
        ProductVariantResolverInterface $defaultVariantResolver,
152
        ImageUploaderInterface $imageUploader,
153
        SlugGeneratorInterface $slugGenerator,
154
        array $minkParameters
155
    ) {
156
        $this->sharedStorage = $sharedStorage;
157
        $this->productRepository = $productRepository;
158
        $this->productFactory = $productFactory;
159
        $this->productTranslationFactory = $productTranslationFactory;
160
        $this->productAttributeFactory = $productAttributeFactory;
161
        $this->attributeValueFactory = $attributeValueFactory;
162
        $this->productVariantFactory = $productVariantFactory;
163
        $this->productOptionFactory = $productOptionFactory;
164
        $this->productOptionValueFactory = $productOptionValueFactory;
165
        $this->productImageFactory = $productImageFactory;
166
        $this->objectManager = $objectManager;
167
        $this->defaultVariantResolver = $defaultVariantResolver;
168
        $this->imageUploader = $imageUploader;
169
        $this->slugGenerator = $slugGenerator;
170
        $this->minkParameters = $minkParameters;
171
    }
172
173
    /**
174
     * @Given the store has a product :productName
175
     * @Given the store has a :productName product
176
     * @Given I added a product :productName
177
     * @Given /^the store(?:| also) has a product "([^"]+)" priced at ("[^"]+")$/
178
     */
179
    public function storeHasAProductPricedAt($productName, $price = 0)
180
    {
181
        $product = $this->createProduct($productName, $price);
182
183
        $product->setDescription('Awesome '.$productName);
184
185
        if ($this->sharedStorage->has('channel')) {
186
            $product->addChannel($this->sharedStorage->get('channel'));
187
        }
188
189
        $this->saveProduct($product);
190
    }
191
192
    /**
193
     * @Given the store( also) has a product :productName with code :code
194
     * @Given the store( also) has a product :productName with code :code, created at :date
195
     */
196
    public function storeHasProductWithCode($productName, $code, $date = null)
197
    {
198
        $product = $this->createProduct($productName, 0, $date);
199
200
        $product->setCode($code);
201
202
        if ($this->sharedStorage->has('channel')) {
203
            $product->addChannel($this->sharedStorage->get('channel'));
204
        }
205
206
        $this->saveProduct($product);
207
    }
208
209
    /**
210
     * @Given /^the store(?:| also) has a product "([^"]+)" priced at ("[^"]+") available in (channel "[^"]+") and (channel "[^"]+")$/
211
     */
212
    public function storeHasAProductPricedAtAvailableInChannels($productName, $price = 0, ...$channels)
213
    {
214
        $product = $this->createProduct($productName, $price);
215
216
        $product->setDescription('Awesome '.$productName);
217
218
        foreach ($channels as $channel) {
219
            $product->addChannel($channel);
220
        }
221
222
        $this->saveProduct($product);
223
    }
224
225
    /**
226
     * @Given /^(this product) is named "([^"]+)" (in the "([^"]+)" locale)$/
227
     * @Given /^the (product "[^"]+") is named "([^"]+)" (in the "([^"]+)" locale)$/
228
     */
229
    public function thisProductIsNamedIn(ProductInterface $product, $name, $locale)
230
    {
231
        /** @var ProductTranslationInterface $translation */
232
        $translation = $this->productTranslationFactory->createNew();
233
        $translation->setLocale($locale);
234
        $translation->setName($name);
235
        $translation->setSlug($this->slugGenerator->generate($name));
236
237
        $product->addTranslation($translation);
0 ignored issues
show
Documentation introduced by
$translation is of type object<Sylius\Component\...ctTranslationInterface>, but the function expects a object<Sylius\Component\...l\TranslationInterface>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
238
239
        $this->objectManager->flush();
240
    }
241
242
    /**
243
     * @Given the store has a :productName configurable product
244
     */
245
    public function storeHasAConfigurableProduct($productName)
246
    {
247
        /** @var ProductInterface $product */
248
        $product = $this->productFactory->createNew();
249
250
        $product->setName($productName);
251
        $product->setCode(StringInflector::nameToUppercaseCode($productName));
252
        $product->setSlug($this->slugGenerator->generate($productName));
253
254
        $product->setDescription('Awesome '.$productName);
255
256
        if ($this->sharedStorage->has('channel')) {
257
            $channel = $this->sharedStorage->get('channel');
258
            $product->addChannel($channel);
259
        }
260
261
        $this->saveProduct($product);
262
    }
263
264
    /**
265
     * @Given the store has( also) :firstProductName and :secondProductName products
266
     * @Given the store has( also) :firstProductName, :secondProductName and :thirdProductName products
267
     * @Given the store has( also) :firstProductName, :secondProductName, :thirdProductName and :fourthProductName products
268
     */
269
    public function theStoreHasProducts(...$productsNames)
270
    {
271
        foreach ($productsNames as $productName) {
272
            $this->saveProduct($this->createProduct($productName));
273
        }
274
    }
275
276
    /**
277
     * @Given /^(this channel) has "([^"]+)", "([^"]+)", "([^"]+)" and "([^"]+)" products$/
278
     */
279
    public function thisChannelHasProducts(ChannelInterface $channel, ...$productsNames)
280
    {
281
        foreach ($productsNames as $productName) {
282
            $product = $this->createProduct($productName);
283
            $product->addChannel($channel);
284
285
            $this->saveProduct($product);
286
        }
287
    }
288
289
    /**
290
     * @Given /^the (product "[^"]+") has(?:| a) "([^"]+)" variant priced at ("[^"]+")$/
291
     * @Given /^(this product) has "([^"]+)" variant priced at ("[^"]+")$/
292
     */
293
    public function theProductHasVariantPricedAt(ProductInterface $product, $productVariantName, $price)
294
    {
295
        $this->createProductVariant(
296
            $product,
297
            $productVariantName,
298
            $price,
299
            StringInflector::nameToUppercaseCode($productVariantName)
300
        );
301
    }
302
303
    /**
304
     * @Given /^(this product) has "([^"]+)" variant priced at ("[^"]+") identified by "([^"]+)"$/
305
     */
306
    public function theProductHasVariantPricedAtIdentifiedBy(
307
        ProductInterface $product,
308
        $productVariantName,
309
        $price,
310
        $code
311
    ) {
312
        $this->createProductVariant($product, $productVariantName, $price, $code);
313
    }
314
315
    /**
316
     * @Given /^there is product "([^"]+)" available in ((?:this|that|"[^"]+") channel)$/
317
     * @Given /^the store has a product "([^"]+)" available in ("([^"]+)" channel)$/
318
     */
319
    public function thereIsProductAvailableInGivenChannel($productName, ChannelInterface $channel)
320
    {
321
        $product = $this->createProduct($productName);
322
323
        $product->setDescription('Awesome ' . $productName);
324
        $product->addChannel($channel);
325
326
        $this->saveProduct($product);
327
    }
328
329
    /**
330
     * @Given /^([^"]+) belongs to ("[^"]+" tax category)$/
331
     */
332
    public function productBelongsToTaxCategory(ProductInterface $product, TaxCategoryInterface $taxCategory)
333
    {
334
        /** @var ProductVariantInterface $variant */
335
        $variant = $this->defaultVariantResolver->getVariant($product);
336
        $variant->setTaxCategory($taxCategory);
337
338
        $this->objectManager->flush();
339
    }
340
341
    /**
342
     * @Given /^(it) comes in the following variations:$/
343
     */
344
    public function itComesInTheFollowingVariations(ProductInterface $product, TableNode $table)
345
    {
346
        foreach ($table->getHash() as $variantHash) {
347
            /** @var ProductVariantInterface $variant */
348
            $variant = $this->productVariantFactory->createNew();
349
350
            $variant->setName($variantHash['name']);
351
            $variant->setCode(StringInflector::nameToUppercaseCode($variantHash['name']));
352
            $variant->setPrice($this->getPriceFromString(str_replace(['$', '€', '£'], '', $variantHash['price'])));
353
            $variant->setProduct($product);
354
            $product->addVariant($variant);
355
        }
356
357
        $this->objectManager->flush();
358
    }
359
360
    /**
361
     * @Given /^("[^"]+" variant of product "[^"]+") belongs to ("[^"]+" tax category)$/
362
     */
363
    public function productVariantBelongsToTaxCategory(
364
        ProductVariantInterface $productVariant,
365
        TaxCategoryInterface $taxCategory
366
    ) {
367
        $productVariant->setTaxCategory($taxCategory);
368
        $this->objectManager->flush($productVariant);
369
    }
370
371
    /**
372
     * @Given /^(this product) has ([^"]+) attribute "([^"]+)" with value "([^"]+)"$/
373
     */
374
    public function thisProductHasAttributeWithValue(ProductInterface $product, $productAttributeType, $productAttributeName, $value)
375
    {
376
        $attribute = $this->createProductAttribute($productAttributeType,$productAttributeName);
377
        $attributeValue = $this->createProductAttributeValue($value, $attribute);
378
        $product->addAttribute($attributeValue);
379
380
        $this->objectManager->flush();
381
    }
382
383
    /**
384
     * @Given /^(this product) has percent attribute "([^"]+)" with value ([^"]+)%$/
385
     */
386
    public function thisProductHasPercentAttributeWithValue(ProductInterface $product, $productAttributeName, $value)
387
    {
388
        $attribute = $this->createProductAttribute('percent',$productAttributeName);
389
        $attributeValue = $this->createProductAttributeValue($value/100, $attribute);
390
        $product->addAttribute($attributeValue);
391
392
        $this->objectManager->flush();
393
    }
394
395
    /**
396
     * @Given /^(this product) has ([^"]+) attribute "([^"]+)" set to "([^"]+)"$/
397
     */
398
    public function thisProductHasCheckboxAttributeWithValue(ProductInterface $product, $productAttributeType, $productAttributeName, $value)
399
    {
400
        $attribute = $this->createProductAttribute($productAttributeType, $productAttributeName);
401
        $booleanValue = ('Yes' === $value);
402
        $attributeValue = $this->createProductAttributeValue($booleanValue, $attribute);
0 ignored issues
show
Documentation introduced by
$booleanValue is of type boolean, but the function expects a string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
403
        $product->addAttribute($attributeValue);
404
405
        $this->objectManager->flush();
406
    }
407
408
    /**
409
     * @Given /^(this product) has percent attribute "([^"]+)" at position (\d+)$/
410
     */
411
    public function thisProductHasPercentAttributeWithValueAtPosition(ProductInterface $product, $productAttributeName, $position)
412
    {
413
        $attribute = $this->createProductAttribute('percent',$productAttributeName);
414
        $attribute->setPosition($position);
415
        $attributeValue = $this->createProductAttributeValue(rand(1,100)/100, $attribute);
416
417
        $product->addAttribute($attributeValue);
418
419
        $this->objectManager->flush();
420
    }
421
422
    /**
423
     * @Given /^(this product) has ([^"]+) attribute "([^"]+)" with date "([^"]+)"$/
424
     */
425
    public function thisProductHasDateTimeAttributeWithDate(ProductInterface $product, $productAttributeType, $productAttributeName, $date)
426
    {
427
        $attribute = $this->createProductAttribute($productAttributeType, $productAttributeName);
428
        $attributeValue = $this->createProductAttributeValue(new \DateTime($date), $attribute);
0 ignored issues
show
Documentation introduced by
new \DateTime($date) is of type object<DateTime>, but the function expects a string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
429
430
        $product->addAttribute($attributeValue);
431
432
        $this->objectManager->flush();
433
    }
434
435
    /**
436
     * @Given /^(this product) has option "([^"]+)" with values "([^"]+)" and "([^"]+)"$/
437
     * @Given /^(this product) has option "([^"]+)" with values "([^"]+)", "([^"]+)" and "([^"]+)"$/
438
     */
439
    public function thisProductHasOptionWithValues(ProductInterface $product, $optionName, ...$values)
440
    {
441
        /** @var ProductOptionInterface $option */
442
        $option = $this->productOptionFactory->createNew();
443
444
        $option->setName($optionName);
445
        $option->setCode(StringInflector::nameToUppercaseCode($optionName));
446
447
        $this->sharedStorage->set(sprintf('%s_option', $optionName), $option);
448
449
        foreach ($values as $key => $value) {
450
            $optionValue = $this->addProductOption($option, $value, StringInflector::nameToUppercaseCode($value));
451
            $this->sharedStorage->set(sprintf('%s_option_%s_value', $value, strtolower($optionName)), $optionValue);
452
        }
453
454
        $product->addOption($option);
455
        $product->setVariantSelectionMethod(ProductInterface::VARIANT_SELECTION_MATCH);
456
457
        $this->objectManager->persist($option);
458
        $this->objectManager->flush();
459
    }
460
461
    /**
462
     * @Given /^there (?:is|are) (\d+) unit(?:|s) of (product "([^"]+)") available in the inventory$/
463
     * @When product :product quantity is changed to :quantity
464
     */
465
    public function thereIsQuantityOfProducts($quantity, ProductInterface $product)
466
    {
467
        /** @var ProductVariantInterface $productVariant */
468
        $productVariant = $this->defaultVariantResolver->getVariant($product);
469
        $productVariant->setOnHand($quantity);
470
471
        $this->objectManager->flush();
472
    }
473
474
    /**
475
     * @Given /^the (product "([^"]+)") is out of stock$/
476
     */
477
    public function theProductIsOutOfStock(ProductInterface $product)
478
    {
479
        /** @var ProductVariantInterface $productVariant */
480
        $productVariant = $this->defaultVariantResolver->getVariant($product);
481
        $productVariant->setTracked(true);
482
        $productVariant->setOnHand(0);
483
484
        $this->objectManager->flush();
485
    }
486
487
    /**
488
     * @When other customer has bought :quantity :product products by this time
489
     */
490
    public function otherCustomerHasBoughtProductsByThisTime($quantity, ProductInterface $product)
491
    {
492
        /** @var ProductVariantInterface $productVariant */
493
        $productVariant = $this->defaultVariantResolver->getVariant($product);
494
        $productVariant->setOnHand($productVariant->getOnHand() - $quantity);
495
496
        $this->objectManager->flush();
497
    }
498
499
    /**
500
     * @Given /^(this product) is tracked by the inventory$/
501
     * @Given /^(?:|the )("[^"]+" product) is(?:| also) tracked by the inventory$/
502
     */
503
    public function thisProductIsTrackedByTheInventory(ProductInterface $product)
504
    {
505
        /** @var ProductVariantInterface $productVariant */
506
        $productVariant = $this->defaultVariantResolver->getVariant($product);
507
        $productVariant->setTracked(true);
508
509
        $this->objectManager->flush();
510
    }
511
512
    /**
513
     * @Given /^(this product) is available in "([^"]+)" ([^"]+) priced at ("[^"]+")$/
514
     */
515
    public function thisProductIsAvailableInSize(ProductInterface $product, $optionValueName, $optionName, $price)
516
    {
517
        /** @var ProductVariantInterface $variant */
518
        $variant = $this->productVariantFactory->createNew();
519
520
        $optionValue = $this->sharedStorage->get(sprintf('%s_option_%s_value', $optionValueName, $optionName));
521
522
        $variant->addOptionValue($optionValue);
523
        $variant->setPrice($price);
524
        $variant->setCode(sprintf("%s_%s", $product->getCode(), $optionValueName));
0 ignored issues
show
Coding Style Comprehensibility introduced by
The string literal %s_%s does not require double quotes, as per coding-style, please use single quotes.

PHP provides two ways to mark string literals. Either with single quotes 'literal' or with double quotes "literal". The difference between these is that string literals in double quotes may contain variables with are evaluated at run-time as well as escape sequences.

String literals in single quotes on the other hand are evaluated very literally and the only two characters that needs escaping in the literal are the single quote itself (\') and the backslash (\\). Every other character is displayed as is.

Double quoted string literals may contain other variables or more complex escape sequences.

<?php

$singleQuoted = 'Value';
$doubleQuoted = "\tSingle is $singleQuoted";

print $doubleQuoted;

will print an indented: Single is Value

If your string literal does not contain variables or escape sequences, it should be defined using single quotes to make that fact clear.

For more information on PHP string literals and available escape sequences see the PHP core documentation.

Loading history...
525
526
        $product->addVariant($variant);
527
        $this->objectManager->flush();
528
    }
529
530
    /**
531
     * @Given /^(this product) has (this product option)$/
532
     * @Given /^(this product) has a ("[^"]+" option)$/
533
     * @Given /^(this product) has an ("[^"]+" option)$/
534
     */
535
    public function thisProductHasThisProductOption(ProductInterface $product, ProductOptionInterface $option)
536
    {
537
        $product->addOption($option);
538
539
        $this->objectManager->flush();
540
    }
541
542
    /**
543
     * @Given /^there are ([^"]+) units of ("[^"]+" variant of product "[^"]+") available in the inventory$/
544
     */
545
    public function thereAreItemsOfProductInVariantAvailableInTheInventory($quantity, ProductVariantInterface $productVariant)
546
    {
547
        $productVariant->setTracked(true);
548
        $productVariant->setOnHand($quantity);
549
550
        $this->objectManager->flush();
551
    }
552
553
    /**
554
     * @Given /^the ("[^"]+" product variant) is tracked by the inventory$/
555
     */
556
    public function theProductVariantIsTrackedByTheInventory(ProductVariantInterface $productVariant)
557
    {
558
        $productVariant->setTracked(true);
559
560
        $this->objectManager->flush();
561
    }
562
563
    /**
564
     * @Given /^(this product)'s price is ("[^"]+")$/
565
     * @Given /^the (product "[^"]+") changed its price to ("[^"]+")$/
566
     */
567
    public function theProductChangedItsPriceTo(ProductInterface $product, $price)
568
    {
569
        /** @var ProductVariantInterface $productVariant */
570
        $productVariant = $this->defaultVariantResolver->getVariant($product);
571
        $productVariant->setPrice($price);
572
573
        $this->objectManager->flush();
574
    }
575
576
    /**
577
     * @Given /^(this product) has(?:| also) an image "([^"]+)" with a code "([^"]+)"$/
578
     * @Given /^the ("[^"]+" product) has(?:| also) an image "([^"]+)" with a code "([^"]+)"$/
579
     */
580
    public function thisProductHasAnImageWithACode(ProductInterface $product, $imagePath, $imageCode)
581
    {
582
        $filesPath = $this->getParameter('files_path');
583
584
        /** @var ImageInterface $productImage */
585
        $productImage = $this->productImageFactory->createNew();
586
        $productImage->setFile(new UploadedFile($filesPath.$imagePath, basename($imagePath)));
587
        $productImage->setCode($imageCode);
588
        $this->imageUploader->upload($productImage);
589
590
        $product->addImage($productImage);
591
592
        $this->objectManager->flush($product);
593
    }
594
595
    /**
596
     * @Given /^(it) has different prices for different channels and currencies$/
597
     */
598
    public function itHasDifferentPricesForDifferentChannelsAndCurrencies(ProductInterface $product)
599
    {
600
        /** @var ProductVariantInterface $variant */
601
        $variant = $this->defaultVariantResolver->getVariant($product);
602
603
        $variant->setPricingCalculator(Calculators::CHANNEL_AND_CURRENCY_BASED);
604
    }
605
606
    /**
607
     * @Given /^(it) has price ("[^"]+") for ("[^"]+" channel) and "([^"]+)" currency$/
608
     */
609
    public function itHasPriceForChannelAndCurrency(
610
        ProductInterface $product,
611
        $price,
612
        ChannelInterface $channel,
613
        $currency
614
    ) {
615
        /** @var ProductVariantInterface $variant */
616
        $variant = $this->defaultVariantResolver->getVariant($product);
617
618
        $pricingConfiguration = $variant->getPricingConfiguration();
619
        $pricingConfiguration[$channel->getCode()][$currency] = $price;
620
621
        $variant->setPricingConfiguration($pricingConfiguration);
622
623
        $this->objectManager->flush();
624
    }
625
626
    /**
627
     * @param string $type
628
     * @param string $name
629
     * @param string|null $code
630
     *
631
     * @return ProductAttributeInterface
632
     */
633
    private function createProductAttribute($type, $name, $code = null)
634
    {
635
        $productAttribute = $this->productAttributeFactory->createTyped($type);
636
637
        if (null === $code) {
638
            $code = StringInflector::nameToCode($name);
639
        }
640
641
        $productAttribute->setCode($code);
642
        $productAttribute->setName($name);
643
644
        $this->objectManager->persist($productAttribute);
645
646
        return $productAttribute;
647
    }
648
649
    /**
650
     * @param string $value
651
     * @param ProductAttributeInterface $attribute
652
     *
653
     * @return ProductAttributeValueInterface
654
     */
655
    private function createProductAttributeValue($value, ProductAttributeInterface $attribute)
656
    {
657
        /** @var ProductAttributeValueInterface $attributeValue */
658
        $attributeValue = $this->attributeValueFactory->createNew();
659
        $attributeValue->setAttribute($attribute);
660
        $attributeValue->setValue($value);
661
662
        $this->objectManager->persist($attributeValue);
663
664
        return $attributeValue;
665
    }
666
667
    /**
668
     * @param string $price
669
     *
670
     * @return int
671
     */
672
    private function getPriceFromString($price)
673
    {
674
        return (int) round(($price * 100), 2);
675
    }
676
677
    /**
678
     * @param string $productName
679
     * @param int $price
680
     * @param string $date
0 ignored issues
show
Documentation introduced by
Should the type for parameter $date not be string|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...
681
     *
682
     * @return ProductInterface
683
     */
684
    private function createProduct($productName, $price = 0, $date = null)
685
    {
686
        /** @var ProductInterface $product */
687
        $product = $this->productFactory->createWithVariant();
688
689
        $product->setName($productName);
690
        $product->setCode(StringInflector::nameToUppercaseCode($productName));
691
        $product->setSlug($this->slugGenerator->generate($productName));
692
        $product->setCreatedAt(new \DateTime($date));
693
694
        /** @var ProductVariantInterface $productVariant */
695
        $productVariant = $this->defaultVariantResolver->getVariant($product);
696
        $productVariant->setPrice($price);
697
        $productVariant->setCode($product->getCode());
698
699
        return $product;
700
    }
701
702
    /**
703
     * @param ProductOptionInterface $option
704
     * @param string $value
705
     * @param string $code
706
     *
707
     * @return ProductOptionValueInterface
708
     */
709
    private function addProductOption(ProductOptionInterface $option, $value, $code)
710
    {
711
        /** @var ProductOptionValueInterface $optionValue */
712
        $optionValue = $this->productOptionValueFactory->createNew();
713
714
        $optionValue->setValue($value);
715
        $optionValue->setCode($code);
716
        $optionValue->setOption($option);
717
718
        $option->addValue($optionValue);
719
720
        return $optionValue;
721
    }
722
723
    /**
724
     * @param ProductInterface $product
725
     */
726
    private function saveProduct(ProductInterface $product)
727
    {
728
        $this->productRepository->add($product);
729
        $this->sharedStorage->set('product', $product);
730
    }
731
732
    /**
733
     * @param string $name
734
     *
735
     * @return NodeElement
736
     */
737
    private function getParameter($name)
738
    {
739
        return isset($this->minkParameters[$name]) ? $this->minkParameters[$name] : null;
740
    }
741
742
    /**
743
     * @param ProductInterface $product
744
     * @param $productVariantName
745
     * @param int $price
746
     * @param string $code
747
     */
748
    private function createProductVariant(ProductInterface $product, $productVariantName, $price, $code)
749
    {
750
        $product->setVariantSelectionMethod(ProductInterface::VARIANT_SELECTION_CHOICE);
751
752
        /** @var ProductVariantInterface $variant */
753
        $variant = $this->productVariantFactory->createNew();
754
755
        $variant->setName($productVariantName);
756
        $variant->setCode($code);
757
        $variant->setPrice($price);
758
        $variant->setProduct($product);
759
        $product->addVariant($variant);
760
761
        $this->objectManager->flush();
762
763
        $this->sharedStorage->set('variant', $variant);
764
    }
765
}
766