Completed
Push — master ( 310bdb...aee174 )
by Jonas
05:01
created

VariantConfigurator::getShopRepository()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 8
rs 9.4285
c 0
b 0
f 0
cc 2
eloc 4
nc 2
nop 0
1
<?php
2
/**
3
 * (c) shopware AG <[email protected]>
4
 * For the full copyright and license information, please view the LICENSE
5
 * file that was distributed with this source code.
6
 */
7
8
namespace ShopwarePlugins\Connect\Components;
9
10
use Doctrine\Common\Collections\ArrayCollection;
11
use ShopwarePlugins\Connect\Components\Gateway\ProductTranslationsGateway;
12
use ShopwarePlugins\Connect\Components\Translations\LocaleMapper;
13
use Shopware\Components\Model\ModelManager;
14
use Shopware\Connect\Struct\Product;
15
use Shopware\Models\Article\Detail;
16
use Shopware\Models\Article\Configurator\Group;
17
use Shopware\Models\Article\Configurator\Option;
18
use Shopware\Models\Article\Configurator\Set;
19
20
/**
21
 * @category  Shopware
22
 * @package   Shopware\Plugins\SwagConnect
23
 */
24
class VariantConfigurator
25
{
26
    /**
27
     * @var ModelManager
28
     */
29
    private $manager;
30
31
    private $translationGateway;
32
33
    private $localeRepository;
34
35
    private $shopRepository;
36
37
    public function __construct(ModelManager $manager, ProductTranslationsGateway $translationsGateway)
38
    {
39
        $this->manager = $manager;
40
        $this->translationGateway = $translationsGateway;
41
    }
42
43
    /**
44
     * Configure variant group, options and configurator set
45
     *
46
     * @param \Shopware\Connect\Struct\Product $product
47
     * @param \Shopware\Models\Article\Detail $detail
48
     */
49
    public function configureVariantAttributes(Product $product, Detail $detail)
50
    {
51
        if (count($product->variant) === 0) {
52
            return;
53
        }
54
55
        $article = $detail->getArticle();
56
        $detailOptions = $detail->getConfiguratorOptions();
57
        if (!$article->getConfiguratorSet()) {
58
            $configSet = new Set();
59
            $configSet->setName('Set-' . $article->getName());
60
            $configSet->setArticles([$article]);
61
            $configSet->setType(0);
62
            $article->setConfiguratorSet($configSet);
63
        } else {
64
            $configSet = $article->getConfiguratorSet();
65
        }
66
        if ($product->configuratorSetType !== null) {
67
            $configSet->setType($product->configuratorSetType);
68
        }
69
70
        foreach ($product->variant as $key => $value) {
71
            $group = $this->getGroupByName($configSet, $key);
72
73
            $option = $this->getOrCreateOptionByName($configSet, $group, $value);
74
75
            $configSet = $this->addGroupToConfiguratorSet($configSet, $group);
76
            $configSet = $this->addOptionToConfiguratorSet($configSet, $option);
0 ignored issues
show
Documentation introduced by
$option is of type null|object, but the function expects a object<Shopware\Models\A...le\Configurator\Option>.

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...
77
78
            $this->manager->persist($option);
79
            $this->manager->persist($group);
80
            if (!$detailOptions->contains($option)) {
81
                $detailOptions->add($option);
82
            }
83
        }
84
85
        $this->manager->persist($configSet);
86
87
        $detail->setConfiguratorOptions($detailOptions);
88
        $this->manager->persist($detail);
89
        $this->manager->persist($article);
90
91
        $this->deleteUnusedOptions($product, $detailOptions, $configSet);
92
93
        $this->manager->flush();
94
95
        foreach ($product->variant as $key => $value) {
96
            $group = $this->getGroupByName($configSet, $key);
97
            $option = $this->getOrCreateOptionByName($configSet, $group, $value);
98
99
            //translate configurator groups and configurator options
100
            $this->addGroupTranslation($group, $product);
101
            $this->addOptionTranslation($option, $product);
0 ignored issues
show
Documentation introduced by
$option is of type null|object, but the function expects a object<Shopware\Models\A...le\Configurator\Option>.

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...
102
        }
103
    }
104
105
106
    /**
107
     * @param Product $product
108
     * @param $detailOptions
109
     * @param Set $configSet
110
     * @throws \Doctrine\DBAL\DBALException
111
     */
112
    private function deleteUnusedOptions(Product $product, $detailOptions, Set $configSet)
113
    {
114
        /** @var Option $detailOption */
115
        foreach ($detailOptions as $detailOption) {
116
            if (!in_array($detailOption->getName(), $product->variant)) {
117
118
                $detailOptions->removeElement($detailOption);
119
120
                $configSet->getOptions()->removeElement($detailOption);
121
122
                $this->manager->flush();
123
124
                if (!($this->isOptionUsed($detailOption))) {
125
                    $this->manager->remove($detailOption);
126
                }
127
            }
128
        }
129
    }
130
131
132
    /**
133
     * @param $detailOption
134
     * @return bool
135
     * @throws \Doctrine\DBAL\DBALException
136
     */
137
    private function isOptionUsed(Option $detailOption)
138
    {
139
        $connection = $this->manager->getConnection();
140
        $query = $connection->prepare(
141
            'SELECT option_id FROM s_article_configurator_set_option_relations WHERE option_id = :optionId UNION 
142
              SELECT option_id FROM s_article_configurator_option_relations WHERE option_id = :optionId
143
              LIMIT 1'
144
        );
145
        $query->bindValue('optionId', $detailOption->getId());
146
        $query->execute();
147
        $result = $query->fetchColumn();
148
149
        return $result !== false;
150
    }
151
152
    /**
153
     * Creates variant configurator group
154
     *
155
     * @param string $name
156
     * @return \Shopware\Models\Article\Configurator\Group
157
     */
158
    public function createConfiguratorGroup($name)
159
    {
160
        $latestGroup = $this->manager
161
            ->getRepository('Shopware\Models\Article\Configurator\Group')
162
            ->findOneBy([], ['position' => 'DESC']);
163
164
        $position = $latestGroup ? $latestGroup->getPosition() + 1 : 1;
165
166
        $group = new Group();
167
        $group->setName($name);
168
        $group->setPosition($position);
169
170
        return $group;
171
    }
172
173
    /**
174
     * Adds group to configurator set if it does not exist
175
     *
176
     * @param Set $set
177
     * @param Group $group
178
     * @return Set
179
     */
180
    private function addGroupToConfiguratorSet(Set $set, Group $group)
181
    {
182
        $configuratorGroups = $set->getGroups();
183
        /** @var \Shopware\Models\Article\Configurator\Group $configuratorGroup */
184
        foreach ($configuratorGroups as $configuratorGroup) {
185
            if ($configuratorGroup->getName() === $group->getName()) {
186
                return $set;
187
            }
188
        }
189
190
        $configuratorGroups[] = $group;
191
        $set->setGroups($configuratorGroups);
192
        $this->manager->persist($set);
193
194
        return $set;
195
    }
196
197
    /**
198
     * Adds option to configurator set if it does not exist
199
     *
200
     * @param Set $set
201
     * @param Option $option
202
     * @return Set
203
     */
204
    private function addOptionToConfiguratorSet(Set $set, Option $option)
205
    {
206
        $configSetOptions = $set->getOptions();
207
        /** @var \Shopware\Models\Article\Configurator\Option $option */
208
        foreach ($configSetOptions as $configSetOption) {
209
            if ($configSetOption->getName() === $option->getName()
210
                && $configSetOption->getGroup()->getName() === $option->getGroup()->getName()) {
211
                return $set;
212
            }
213
        }
214
215
        $configSetOptions[] = $option;
216
        $set->setOptions($configSetOptions);
217
218
        return $set;
219
    }
220
221
    /**
222
     * Finds group in already assigned configurator set groups.
223
     * If it does not exist, then create it.
224
     *
225
     * @param Set $set
226
     * @param $groupName
227
     * @return Group
228
     */
229
    private function getGroupByName(Set $set, $groupName)
230
    {
231
        /** @var \Shopware\Models\Article\Configurator\Group $group */
232
        foreach ($set->getGroups() as $group) {
233
            if ($group->getName() === $groupName) {
234
                return $group;
235
            }
236
        }
237
238
        $repository = $this->manager->getRepository('Shopware\Models\Article\Configurator\Group');
239
        $group = $repository->findOneBy(['name' => $groupName]);
240
241
        if (empty($group)) {
242
            $group = $this->createConfiguratorGroup($groupName);
243
        }
244
245
        return $group;
246
    }
247
248
    /**
249
     * Find option in already assigned configurator set options.
250
     * If it does not exist, then create it.
251
     *
252
     * @param Set $set
253
     * @param Group $group
254
     * @param $optionName
255
     * @return null|object|Option
256
     */
257
    private function getOrCreateOptionByName(Set $set, Group $group, $optionName)
258
    {
259
        $configSetOptions = $set->getOptions();
260
261
        /** @var \Shopware\Models\Article\Configurator\Option $configSetOption */
262
        foreach ($configSetOptions as $configSetOption) {
263
            if ($configSetOption->getName() === $optionName
264
                && $configSetOption->getGroup()->getName() == $group->getName()
265
            ) {
266
                return $configSetOption;
267
            }
268
        }
269
270
        $optionsRepository = $this->manager->getRepository('Shopware\Models\Article\Configurator\Option');
271
        $option = $optionsRepository->findOneBy(['name' => $optionName, 'group' => $group]);
272
273
        if (empty($option)) {
274
            $option = new Option();
275
            $option->setName($optionName);
276
            $option->setGroup($group);
277
            $optionPositionsCount = count($group->getOptions());
278
            ++$optionPositionsCount;
279
            $option->setPosition($optionPositionsCount);
280
            $groupOptions = $group->getOptions();
281
            $groupOptions->add($option);
282
            $group->setOptions($groupOptions);
283
            $this->manager->persist($group);
284
            $this->manager->persist($option);
285
        }
286
287
        return $option;
288
    }
289
290 View Code Duplication
    private function addGroupTranslation(Group $group, Product $product)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
291
    {
292
        /** @var \Shopware\Connect\Struct\Translation $translation */
293
        foreach ($product->translations as $key => $translation) {
294
            if (!array_key_exists($group->getName(), $translation->variantLabels)) {
295
                continue;
296
            }
297
298
            /** @var \Shopware\Models\Shop\Locale $locale */
299
            $locale = $this->getLocaleRepository()->findOneBy(['locale' => LocaleMapper::getShopwareLocale($key)]);
300
301
            /** @var \Shopware\Models\Shop\Shop $shop */
302
            $shop = $this->getShopRepository()->findOneBy(['locale' => $locale]);
303
            if (!$shop) {
304
                continue;
305
            }
306
307
            foreach ($translation->variantLabels as $groupKey => $groupTranslation) {
308
                if ($groupKey === $group->getName()) {
309
                    $this->translationGateway->addGroupTranslation($groupTranslation, $group->getId(), $shop->getId());
310
                }
311
            }
312
        }
313
    }
314
315 View Code Duplication
    private function addOptionTranslation(Option $option, Product $product)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
316
    {
317
        /** @var \Shopware\Connect\Struct\Translation $translation */
318
        foreach ($product->translations as $key => $translation) {
319
            if (!array_key_exists($option->getName(), $translation->variantValues)) {
320
                continue;
321
            }
322
323
            /** @var \Shopware\Models\Shop\Locale $locale */
324
            $locale = $this->getLocaleRepository()->findOneBy(['locale' => LocaleMapper::getShopwareLocale($key)]);
325
326
            /** @var \Shopware\Models\Shop\Shop $shop */
327
            $shop = $this->getShopRepository()->findOneBy(['locale' => $locale]);
328
            if (!$shop) {
329
                continue;
330
            }
331
332
            foreach ($translation->variantValues as $optionKey => $optionTranslation) {
333
                if ($optionKey === $option->getName()) {
334
                    $this->translationGateway->addOptionTranslation($optionTranslation, $option->getId(), $shop->getId());
335
                }
336
            }
337
        }
338
    }
339
340
    private function getShopRepository()
341
    {
342
        if (!$this->shopRepository) {
343
            $this->shopRepository = $this->manager->getRepository('Shopware\Models\Shop\Shop');
344
        }
345
346
        return $this->shopRepository;
347
    }
348
349
    private function getLocaleRepository()
350
    {
351
        if (!$this->localeRepository) {
352
            $this->localeRepository = $this->manager->getRepository('Shopware\Models\Shop\Locale');
353
        }
354
355
        return $this->localeRepository;
356
    }
357
}
358