Completed
Push — master ( 9a4fa3...1bdebc )
by Kamil
41s queued 22s
created

ProductAttributeContext::createProductAttribute()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 11
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 11
rs 9.4285
c 0
b 0
f 0
cc 2
eloc 6
nc 2
nop 3
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\Attribute\Factory\AttributeFactoryInterface;
20
use Sylius\Component\Core\Formatter\StringInflector;
21
use Sylius\Component\Core\Model\ProductInterface;
22
use Sylius\Component\Product\Model\ProductAttributeInterface;
23
use Sylius\Component\Product\Model\ProductAttributeValueInterface;
24
use Sylius\Component\Resource\Factory\FactoryInterface;
25
use Sylius\Component\Resource\Repository\RepositoryInterface;
26
27
/**
28
 * @author Anna Walasek <[email protected]>
29
 */
30
final class ProductAttributeContext implements Context
31
{
32
    /**
33
     * @var SharedStorageInterface
34
     */
35
    private $sharedStorage;
36
37
    /**
38
     * @var RepositoryInterface
39
     */
40
    private $productAttributeRepository;
41
42
    /**
43
     * @var AttributeFactoryInterface
44
     */
45
    private $productAttributeFactory;
46
47
    /**
48
     * @var FactoryInterface
49
     */
50
    private $productAttributeValueFactory;
51
52
    /**
53
     * @var ObjectManager
54
     */
55
    private $objectManager;
56
57
    /**
58
     * @var \Faker\Generator
59
     */
60
    private $faker;
61
62
    /**
63
     * @param SharedStorageInterface $sharedStorage
64
     * @param RepositoryInterface $productAttributeRepository
65
     * @param AttributeFactoryInterface $productAttributeFactory
66
     * @param FactoryInterface $productAttributeValueFactory
67
     * @param ObjectManager $objectManager
68
     */
69
    public function __construct(
70
        SharedStorageInterface $sharedStorage,
71
        RepositoryInterface $productAttributeRepository,
72
        AttributeFactoryInterface $productAttributeFactory,
73
        FactoryInterface $productAttributeValueFactory,
74
        ObjectManager $objectManager
75
    ) {
76
        $this->sharedStorage = $sharedStorage;
77
        $this->productAttributeRepository = $productAttributeRepository;
78
        $this->productAttributeFactory = $productAttributeFactory;
79
        $this->productAttributeValueFactory = $productAttributeValueFactory;
80
        $this->objectManager = $objectManager;
81
82
        $this->faker = \Faker\Factory::create();
83
    }
84
85
    /**
86
     * @Given the store has a :type product attribute :name with code :code
87
     */
88
    public function theStoreHasAProductAttributeWithCode($type, $name, $code)
89
    {
90
        $productAttribute = $this->createProductAttribute($type, $name, $code);
91
92
        $this->saveProductAttribute($productAttribute);
93
    }
94
95
    /**
96
     * @Given the store has( also) a :type product attribute :name at position :position
97
     */
98
    public function theStoreHasAProductAttributeWithPosition($type, $name, $position)
99
    {
100
        $productAttribute = $this->createProductAttribute($type, $name);
101
        $productAttribute->setPosition((int) $position);
102
103
        $this->saveProductAttribute($productAttribute);
104
    }
105
106
    /**
107
     * @Given the store has( also) a/an :type product attribute :name
108
     */
109
    public function theStoreHasAProductAttribute(string $type, string $name): void
110
    {
111
        $productAttribute = $this->createProductAttribute($type, $name);
112
113
        $this->saveProductAttribute($productAttribute);
114
    }
115
116
    /**
117
     * @Given the store has a select product attribute :name with value :value
118
     */
119
    public function theStoreHasASelectProductAttributeWithValue(string $name, string $value): void
120
    {
121
        $productAttribute = $this->createProductAttribute('select', $name);
122
        $productAttribute->setConfiguration([
123
            'multiple' => true,
124
            'choices' => [$this->faker->uuid => $value],
125
            'min' => null,
126
            'max' => null,
127
        ]);
128
129
        $this->saveProductAttribute($productAttribute);
130
    }
131
132
    /**
133
     * @Given /^(this product attribute) has set min value as (\d+) and max value as (\d+)$/
134
     */
135
    public function thisAttributeHasSetMinValueAsAndMaxValueAs(ProductAttributeInterface $attribute, $min, $max)
136
    {
137
        $attribute->setConfiguration(['min' => $min, 'max' => $max]);
138
139
        $this->objectManager->flush();
140
    }
141
142
    /**
143
     * @Given /^(this product) has (.+?) attribute "([^"]+)" with values "([^"]+)", "([^"]+)"$/
144
     */
145
    public function thisProductHasSelectAttributeWithValues(
146
        ProductInterface $product,
147
        $productAttributeType,
148
        $productAttributeName,
149
        $firstAttributeValue,
150
        $secondAttributeValue,
151
        $language = 'en_US'
152
    ) {
153
        $values = [$this->faker->uuid => $firstAttributeValue, $this->faker->uuid => $secondAttributeValue];
154
155
        $attribute = $this->provideProductAttribute($productAttributeType, $productAttributeName);
156
        $attribute->setConfiguration(['multiple' => true, 'choices' => $values, 'min' => null, 'max' => null]);
157
        $attributeValue = $this->createProductAttributeValue(array_keys($values), $attribute, $language);
0 ignored issues
show
Documentation introduced by
array_keys($values) is of type array<integer,string>, 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...
158
        $product->addAttribute($attributeValue);
159
160
        $this->objectManager->flush();
161
    }
162
163
    /**
164
     * @Given /^(this product) has (.+?) attribute "([^"]+)" with value "([^"]+)"$/
165
     * @Given /^(this product) has (.+?) attribute "([^"]+)" with value "([^"]+)" in ("[^"]+" locale)$/
166
     */
167
    public function thisProductHasAttributeWithValue(
168
        ProductInterface $product,
169
        $productAttributeType,
170
        $productAttributeName,
171
        $value,
172
        $language = 'en_US'
173
    ) {
174
        $attribute = $this->provideProductAttribute($productAttributeType, $productAttributeName);
175
        $attributeValue = $this->createProductAttributeValue($value, $attribute, $language);
176
        $product->addAttribute($attributeValue);
177
178
        $this->objectManager->flush();
179
    }
180
181
    /**
182
     * @Given /^(this product) has percent attribute "([^"]+)" with value ([^"]+)%$/
183
     */
184
    public function thisProductHasPercentAttributeWithValue(ProductInterface $product, $productAttributeName, $value)
185
    {
186
        $attribute = $this->provideProductAttribute('percent', $productAttributeName);
187
        $attributeValue = $this->createProductAttributeValue($value / 100, $attribute);
188
        $product->addAttribute($attributeValue);
189
190
        $this->objectManager->flush();
191
    }
192
193
    /**
194
     * @Given /^(this product) has ([^"]+) attribute "([^"]+)" set to "([^"]+)"$/
195
     */
196
    public function thisProductHasCheckboxAttributeWithValue(
197
        ProductInterface $product,
198
        $productAttributeType,
199
        $productAttributeName,
200
        $value
201
    ) {
202
        $attribute = $this->provideProductAttribute($productAttributeType, $productAttributeName);
203
        $booleanValue = ('Yes' === $value);
204
        $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...
205
        $product->addAttribute($attributeValue);
206
207
        $this->objectManager->flush();
208
    }
209
210
    /**
211
     * @Given /^(this product) has percent attribute "([^"]+)" at position (\d+)$/
212
     */
213
    public function thisProductHasPercentAttributeWithValueAtPosition(
214
        ProductInterface $product,
215
        $productAttributeName,
216
        $position
217
    ) {
218
        $attribute = $this->provideProductAttribute('percent', $productAttributeName);
219
        $attribute->setPosition((int) $position);
220
        $attributeValue = $this->createProductAttributeValue(rand(1, 100) / 100, $attribute);
221
222
        $product->addAttribute($attributeValue);
223
224
        $this->objectManager->flush();
225
    }
226
227
    /**
228
     * @Given /^(this product) has ([^"]+) attribute "([^"]+)" with date "([^"]+)"$/
229
     */
230
    public function thisProductHasDateTimeAttributeWithDate(
231
        ProductInterface $product,
232
        $productAttributeType,
233
        $productAttributeName,
234
        $date
235
    ) {
236
        $attribute = $this->provideProductAttribute($productAttributeType, $productAttributeName);
237
        $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...
238
239
        $product->addAttribute($attributeValue);
240
241
        $this->objectManager->flush();
242
    }
243
244
    /**
245
     * @param string $type
246
     * @param string $name
247
     * @param string|null $code
248
     *
249
     * @return ProductAttributeInterface
250
     */
251
    private function createProductAttribute($type, $name, $code = null)
252
    {
253
        $productAttribute = $this->productAttributeFactory->createTyped($type);
254
255
        $code = $code ?: StringInflector::nameToCode($name);
256
257
        $productAttribute->setCode($code);
258
        $productAttribute->setName($name);
259
260
        return $productAttribute;
261
    }
262
263
    /**
264
     * @param string $type
265
     * @param string $name
266
     * @param string|null $code
267
     *
268
     * @return ProductAttributeInterface
269
     */
270
    private function provideProductAttribute($type, $name, $code = null)
271
    {
272
        $code = $code ?: StringInflector::nameToCode($name);
273
274
        /** @var ProductAttributeInterface $productAttribute */
275
        $productAttribute = $this->productAttributeRepository->findOneBy(['code' => $code]);
276
        if (null !== $productAttribute) {
277
            return $productAttribute;
278
        }
279
280
        $productAttribute = $this->createProductAttribute($type, $name, $code);
281
        $this->saveProductAttribute($productAttribute);
282
283
        return $productAttribute;
284
    }
285
286
    /**
287
     * @param string $value
288
     * @param ProductAttributeInterface $attribute
289
     * @param string $localeCode
290
     *
291
     * @return ProductAttributeValueInterface
292
     */
293
    private function createProductAttributeValue($value, ProductAttributeInterface $attribute, $localeCode = 'en_US')
294
    {
295
        /** @var ProductAttributeValueInterface $attributeValue */
296
        $attributeValue = $this->productAttributeValueFactory->createNew();
297
        $attributeValue->setAttribute($attribute);
298
        $attributeValue->setValue($value);
299
        $attributeValue->setLocaleCode($localeCode);
300
301
        $this->objectManager->persist($attributeValue);
302
303
        return $attributeValue;
304
    }
305
306
    /**
307
     * @param ProductAttributeInterface $productAttribute
308
     */
309
    private function saveProductAttribute(ProductAttributeInterface $productAttribute)
310
    {
311
        $this->productAttributeRepository->add($productAttribute);
312
        $this->sharedStorage->set('product_attribute', $productAttribute);
313
    }
314
}
315