Completed
Push — 1.0-symfony-3.3.13 ( 577127...a3487e )
by Kamil
50:10 queued 26:38
created

createSelectProductAttributeValue()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 18
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Importance

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