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