Completed
Push — master ( 648607...0311ff )
by Paweł
28:06 queued 12:04
created

ProductFixture::loadResource()   C

Complexity

Conditions 7
Paths 64

Size

Total Lines 51
Code Lines 31

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
dl 0
loc 51
rs 6.9743
c 1
b 0
f 1
cc 7
eloc 31
nc 64
nop 1

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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\Bundle\CoreBundle\Fixture;
13
14
use Doctrine\Common\Persistence\ObjectManager;
15
use Sylius\Component\Core\Formatter\StringInflector;
16
use Sylius\Component\Core\Model\ArchetypeInterface;
17
use Sylius\Component\Core\Model\ProductInterface;
18
use Sylius\Component\Core\Model\ProductVariantInterface;
19
use Sylius\Component\Core\Model\TaxonInterface;
20
use Sylius\Component\Locale\Model\LocaleInterface;
21
use Sylius\Component\Product\Model\AttributeInterface;
22
use Sylius\Component\Product\Model\AttributeValueInterface;
23
use Sylius\Component\Resource\Factory\FactoryInterface;
24
use Sylius\Component\Resource\Repository\RepositoryInterface;
25
use Sylius\Component\Shipping\Model\ShippingCategoryInterface;
26
use Sylius\Component\Variation\Generator\VariantGeneratorInterface;
27
use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition;
28
use Symfony\Component\OptionsResolver\Options;
29
use Symfony\Component\OptionsResolver\OptionsResolver;
30
31
/**
32
 * @author Kamil Kokot <[email protected]>
33
 */
34
final class ProductFixture extends AbstractResourceFixture
35
{
36
    /**
37
     * @var FactoryInterface
38
     */
39
    private $productFactory;
40
41
    /**
42
     * @var VariantGeneratorInterface
43
     */
44
    private $variantGenerator;
45
46
    /**
47
     * @var FactoryInterface
48
     */
49
    private $productAttibuteValueFactory;
50
51
    /**
52
     * @var RepositoryInterface
53
     */
54
    private $taxonRepository;
55
56
    /**
57
     * @var RepositoryInterface
58
     */
59
    private $archetypeRepository;
60
61
    /**
62
     * @var RepositoryInterface
63
     */
64
    private $shippingCategoryRepository;
65
66
    /**
67
     * @var RepositoryInterface
68
     */
69
    private $channelRepository;
70
71
    /**
72
     * @var RepositoryInterface
73
     */
74
    private $localeRepository;
75
76
    /**
77
     * @var \Faker\Generator
78
     */
79
    private $faker;
80
81
    /**
82
     * @param FactoryInterface $productFactory
83
     * @param ObjectManager $productManager
84
     * @param VariantGeneratorInterface $variantGenerator
85
     * @param FactoryInterface $productAttibuteValueFactory
86
     * @param RepositoryInterface $taxonRepository
87
     * @param RepositoryInterface $archetypeRepository
88
     * @param RepositoryInterface $shippingCategoryRepository
89
     * @param RepositoryInterface $channelRepository
90
     * @param RepositoryInterface $localeRepository
91
     */
92
    public function __construct(
93
        FactoryInterface $productFactory,
94
        ObjectManager $productManager,
95
        VariantGeneratorInterface $variantGenerator,
96
        FactoryInterface $productAttibuteValueFactory,
97
        RepositoryInterface $taxonRepository,
98
        RepositoryInterface $archetypeRepository,
99
        RepositoryInterface $shippingCategoryRepository,
100
        RepositoryInterface $channelRepository,
101
        RepositoryInterface $localeRepository
102
    ) {
103
        parent::__construct($productManager, 'products', 'name');
104
105
        $this->productFactory = $productFactory;
106
        $this->variantGenerator = $variantGenerator;
107
        $this->productAttibuteValueFactory = $productAttibuteValueFactory;
108
        $this->taxonRepository = $taxonRepository;
109
        $this->archetypeRepository = $archetypeRepository;
110
        $this->shippingCategoryRepository = $shippingCategoryRepository;
111
        $this->channelRepository = $channelRepository;
112
        $this->localeRepository = $localeRepository;
113
114
        $this->faker = \Faker\Factory::create();
115
    }
116
117
    /**
118
     * {@inheritdoc}
119
     */
120
    public function getName()
121
    {
122
        return 'product';
123
    }
124
125
    /**
126
     * {@inheritdoc}
127
     */
128
    protected function loadResource(array $options)
129
    {
130
        /** @var ProductInterface $product */
131
        $product = $this->productFactory->createNew();
132
        $product->setVariantSelectionMethod(ProductInterface::VARIANT_SELECTION_MATCH);
133
        $product->setCode($options['code']);
134
        $product->setEnabled($options['enabled']);
135
        $product->setMainTaxon($options['main_taxon']);
136
        $product->setArchetype($options['archetype']);
137
        $product->setShippingCategory($options['shipping_category']);
138
139
        foreach ($this->getLocales() as $localeCode) {
140
            $product->setCurrentLocale($localeCode);
141
            $product->setFallbackLocale($localeCode);
142
143
            $product->setName(sprintf('[%s] %s', $localeCode, $options['name']));
144
            $product->setShortDescription(sprintf('[%s] %s', $localeCode, $options['short_description']));
145
            $product->setDescription(sprintf('[%s] %s', $localeCode, $options['description']));
146
        }
147
148
        foreach ($options['taxons'] as $taxon) {
149
            $product->addTaxon($taxon);
150
        }
151
152
        foreach ($options['channels'] as $channel) {
153
            $product->addChannel($channel);
154
        }
155
156
        foreach ($options['product_options'] as $option) {
157
            $product->addOption($option);
158
        }
159
160
        foreach ($options['product_attributes'] as $attribute) {
161
            $product->addAttribute($attribute);
162
        }
163
164
        $this->variantGenerator->generate($product);
165
166
        $i = 0;
167
        /** @var ProductVariantInterface $productVariant */
168
        foreach ($product->getVariants() as $productVariant) {
169
            $productVariant->setAvailableOn($this->faker->dateTimeThisYear);
170
            $productVariant->setPrice($this->faker->randomNumber(4));
171
            $productVariant->setCode(sprintf('%s-variant#%d', $options['code'], $i));
172
            $productVariant->setOnHand($this->faker->randomNumber(1));
173
174
            ++$i;
175
        }
176
177
        return $product;
178
    }
179
180
    /**
181
     * {@inheritdoc}
182
     */
183
    protected function configureResourceNode(ArrayNodeDefinition $resourceNode)
184
    {
185
        $resourceNode
0 ignored issues
show
Bug introduced by
The method arrayNode() does not seem to exist on object<Symfony\Component...odeDefinitionInterface>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
186
            ->children()
187
                ->scalarNode('code')->cannotBeEmpty()->end()
188
                ->booleanNode('enabled')->end()
189
                ->scalarNode('short_description')->cannotBeEmpty()->end()
190
                ->scalarNode('description')->cannotBeEmpty()->end()
191
                ->scalarNode('main_taxon')->cannotBeEmpty()->end()
192
                ->scalarNode('archetype')->cannotBeEmpty()->end()
193
                ->scalarNode('shipping_category')->cannotBeEmpty()->end()
194
                ->arrayNode('taxons')->prototype('scalar')->end()->end()
195
                ->arrayNode('channels')->prototype('scalar')->end()->end()
196
                ->arrayNode('product_attributes')->prototype('scalar')->end()->end()
197
                ->arrayNode('product_options')->prototype('scalar')->end()->end()
198
        ;
199
    }
200
201
    /**
202
     * {@inheritdoc}
203
     */
204
    protected function configureResourceOptionsResolver(array $options, OptionsResolver $optionsResolver)
205
    {
206
        $optionsResolver
207
            ->setRequired('name')
208
            ->setDefault('code', function (Options $options) {
209
                return StringInflector::nameToCode($options['name']);
210
            })
211
            ->setDefault('enabled', function (Options $options) {
0 ignored issues
show
Unused Code introduced by
The parameter $options is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
212
                return $this->faker->boolean(90);
213
            })
214
            ->setAllowedTypes('enabled', 'bool')
215
            ->setDefault('short_description', function (Options $options) {
0 ignored issues
show
Unused Code introduced by
The parameter $options is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
216
                return $this->faker->paragraph;
217
            })
218
            ->setDefault('description', function (Options $options) {
0 ignored issues
show
Unused Code introduced by
The parameter $options is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
219
                return $this->faker->paragraphs(3, true);
220
            })
221
            ->setAllowedTypes('enabled', 'bool')
222
            ->setDefault('main_taxon', null)
223
            ->setAllowedTypes('main_taxon', ['null', 'string', TaxonInterface::class])
224
            ->setNormalizer('main_taxon', static::createResourceNormalizer($this->taxonRepository))
225
            ->setDefault('archetype', null)
226
            ->setAllowedTypes('archetype', ['null', 'string', ArchetypeInterface::class])
227
            ->setNormalizer('archetype', static::createResourceNormalizer($this->archetypeRepository))
228
            ->setDefault('shipping_category', null)
229
            ->setAllowedTypes('shipping_category', ['null', 'string', ShippingCategoryInterface::class])
230
            ->setNormalizer('shipping_category', static::createResourceNormalizer($this->shippingCategoryRepository))
231
            ->setDefault('taxons', [])
232
            ->setAllowedTypes('taxons', 'array')
233
            ->setNormalizer('taxons', static::createResourcesNormalizer($this->taxonRepository))
234
            ->setDefault('channels', [])
235
            ->setAllowedTypes('channels', 'array')
236
            ->setNormalizer('channels', static::createResourcesNormalizer($this->channelRepository))
237
            ->setDefault('product_attributes', [])
238
            ->setAllowedTypes('product_attributes', 'array')
239
            ->setNormalizer('product_attributes', function (Options $options, array $productAttributes) {
240
                /** @var ArchetypeInterface $archetype */
241
                $archetype = $options['archetype'];
242
243
                return array_map(
244
                    function (AttributeInterface $productAttribute) {
245
                        /** @var AttributeValueInterface $productAttributeValue */
246
                        $productAttributeValue = $this->productAttibuteValueFactory->createNew();
247
                        $productAttributeValue->setAttribute($productAttribute);
248
                        $productAttributeValue->setValue($this->getRandomValueForProductAttribute($productAttribute));
249
250
                        return $productAttributeValue;
251
                    },
252
                    array_merge($productAttributes, $archetype->getAttributes()->toArray())
253
                );
254
            })
255
            ->setDefault('product_options', [])
256
            ->setAllowedTypes('product_options', 'array')
257
            ->setNormalizer('product_options', function (Options $options, array $productOptions) {
258
                /** @var ArchetypeInterface $archetype */
259
                $archetype = $options['archetype'];
260
261
                return array_merge($productOptions, $archetype->getOptions()->toArray());
262
            })
263
        ;
264
    }
265
266
    /**
267
     * {@inheritdoc}
268
     */
269
    protected function generateResourcesOptions($amount)
270
    {
271
        $resourcesOptions = [];
272
        for ($i = 0; $i < (int) $amount; ++$i) {
273
            $resourcesOptions[] = ['name' => $this->faker->words(3, true)];
274
        }
275
276
        return $resourcesOptions;
277
    }
278
279
    /**
280
     * @return array
281
     */
282
    private function getLocales()
283
    {
284
        /** @var LocaleInterface[] $locales */
285
        $locales = $this->localeRepository->findAll();
286
        foreach ($locales as $locale) {
287
            yield $locale->getCode();
288
        }
289
    }
290
291
    /**
292
     * @param AttributeInterface $productAttribute
293
     *
294
     * @return mixed
295
     */
296
    private function getRandomValueForProductAttribute(AttributeInterface $productAttribute)
297
    {
298
        switch ($productAttribute->getStorageType()) {
299
            case AttributeValueInterface::STORAGE_BOOLEAN:
300
                return $this->faker->boolean;
301
            case AttributeValueInterface::STORAGE_INTEGER:
302
                return $this->faker->numberBetween(0, 10000);
303
            case AttributeValueInterface::STORAGE_FLOAT:
304
                return $this->faker->randomFloat(4, 0, 10000);
305
            case AttributeValueInterface::STORAGE_TEXT:
306
                return $this->faker->sentence;
307
            case AttributeValueInterface::STORAGE_DATE:
308
            case AttributeValueInterface::STORAGE_DATETIME:
309
                return $this->faker->dateTimeThisCentury;
310
            default:
311
                throw new \BadMethodCallException();
312
        }
313
    }
314
}
315