Completed
Push — master ( 5415e6...23faee )
by Sven
09:51
created

Helper   C

Complexity

Total Complexity 64

Size/Duplication

Total Lines 769
Duplicated Lines 13.39 %

Coupling/Cohesion

Components 3
Dependencies 7

Importance

Changes 0
Metric Value
dl 103
loc 769
rs 5
c 0
b 0
f 0
wmc 64
lcom 3
cbo 7

36 Methods

Rating   Name   Duplication   Size   Complexity  
A getRemoteProducts() 0 4 1
A __construct() 0 9 1
A getDefaultCustomerGroup() 0 6 1
B getConnectArticleModel() 0 26 2
A getArticleIdsByNumber() 15 15 1
A getConnectArticleDetailModel() 0 6 1
B updateConnectProducts() 0 35 1
A getLocalProduct() 0 4 1
B hasBasketConnectProducts() 0 26 2
B getConnectAttributeByModel() 0 19 5
A getConnectAttributesByArticle() 0 14 1
B isProductExported() 0 21 5
A hasExportedVariants() 0 15 1
B getOrCreateConnectAttributeByModel() 0 31 4
A getOrCreateConnectAttributes() 0 10 2
A generateSourceId() 0 14 2
A getConnectCategoryForProduct() 0 4 1
A getMostRelevantConnectCategory() 0 12 1
A getUpdateFlags() 0 4 1
A getUnit() 0 6 1
A clearArticleCache() 0 7 1
B prepareConnectUnit() 0 24 5
A clearConnectReservation() 0 4 1
B getArticleModelByProduct() 24 24 2
B getArticleDetailModelByProduct() 26 26 2
A getArticleSourceIds() 0 14 2
A getShopProductId() 0 13 1
A isRemoteArticleDetail() 0 17 3
A isRemoteArticleDetailDBAL() 0 11 1
A explodeArticleId() 0 12 3
A createProductModel() 0 10 1
B getArticleByRemoteProduct() 25 26 2
A getSourceIdsFromArticleId() 0 11 1
A updateUnitInRelatedProducts() 0 12 1
A isMainVariant() 0 16 2
A getAllNonConnectArticleIds() 13 13 1

How to fix   Duplicated Code    Complexity   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

Complex Class

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like Helper often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use Helper, and based on these observations, apply Extract Interface, too.

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 Shopware\Connect\Struct\Product;
11
use Shopware\CustomModels\Connect\AttributeRepository;
12
use Shopware\Models\Article\Article as ProductModel;
13
use Shopware\Components\Model\ModelManager;
14
use Doctrine\ORM\Query;
15
use Shopware\CustomModels\Connect\Attribute as ConnectAttribute;
16
use Shopware\CustomModels\Connect\Attribute;
17
use Shopware\Models\Article\Detail as ProductDetail;
18
use Shopware\Models\Article\Unit;
19
use Shopware\Models\Customer\Group;
20
use ShopwarePlugins\Connect\Components\Utils\UnitMapper;
21
use ShopwarePlugins\Connect\Struct\ShopProductId;
22
23
/**
24
 * @category  Shopware
25
 * @package   Shopware\Plugins\SwagConnect
26
 */
27
class Helper
28
{
29
    /**
30
     * @var ModelManager
31
     */
32
    private $manager;
33
34
    /**
35
     * @var CategoryQuery
36
     */
37
    private $connectCategoryQuery;
38
39
    /**
40
     * @var ProductQuery
41
     */
42
    private $connectProductQuery;
43
44
    /**
45
     * @param ModelManager $manager
46
     * @param CategoryQuery
47
     * @param ProductQuery
48
     */
49
    public function __construct(
50
        ModelManager $manager,
51
        CategoryQuery $connectCategoryQuery,
52
        ProductQuery $connectProductQuery
53
    ) {
54
        $this->manager = $manager;
55
        $this->connectCategoryQuery = $connectCategoryQuery;
56
        $this->connectProductQuery = $connectProductQuery;
57
    }
58
59
    /**
60
     * @return Group
61
     */
62
    public function getDefaultCustomerGroup()
63
    {
64
        $repository = $this->manager->getRepository('Shopware\Models\Customer\Group');
65
66
        return $repository->findOneBy(['key' => 'EK']);
67
    }
68
69
    /**
70
     * Returns an article model for a given (sdk) product.
71
     *
72
     * @param Product $product
73
     * @param int $mode
74
     * @return null|ProductModel
75
     */
76 View Code Duplication
    public function getArticleModelByProduct(Product $product, $mode = Query::HYDRATE_OBJECT)
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...
77
    {
78
        $builder = $this->manager->createQueryBuilder();
79
        $builder->select(['ba', 'a']);
80
        $builder->from('Shopware\CustomModels\Connect\Attribute', 'ba');
81
        $builder->join('ba.article', 'a');
82
83
        $builder->where('ba.shopId = :shopId AND ba.sourceId = :sourceId');
84
        $query = $builder->getQuery();
85
86
        $query->setParameter('shopId', $product->shopId);
87
        $query->setParameter('sourceId', (string) $product->sourceId);
88
        $result = $query->getResult(
89
            $mode
90
        );
91
92
        if (isset($result[0])) {
93
            $attribute = $result[0];
94
95
            return $attribute->getArticle();
96
        }
97
98
        return null;
99
    }
100
101
    /**
102
     * @param Product $product
103
     * @param int $mode
104
     * @return null|ProductDetail
105
     */
106 View Code Duplication
    public function getArticleDetailModelByProduct(Product $product, $mode = Query::HYDRATE_OBJECT)
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...
107
    {
108
        $builder = $this->manager->createQueryBuilder();
109
        $builder->select(['ba', 'd']);
110
        $builder->from('Shopware\CustomModels\Connect\Attribute', 'ba');
111
        $builder->join('ba.articleDetail', 'd');
112
        $builder->leftJoin('d.attribute', 'at');
113
        $builder->where('ba.shopId = :shopId AND ba.sourceId = :sourceId');
114
115
        $query = $builder->getQuery();
116
        $query->setParameter('shopId', $product->shopId);
117
        $query->setParameter('sourceId', (string) $product->sourceId);
118
119
        $result = $query->getResult(
120
            $mode
121
        );
122
123
        if (isset($result[0])) {
124
            /** @var \Shopware\CustomModels\Connect\Attribute $attribute */
125
            $attribute = $result[0];
126
127
            return $attribute->getArticleDetail();
128
        }
129
130
        return null;
131
    }
132
133
    public function getConnectArticleModel($sourceId, $shopId)
134
    {
135
        $builder = $this->manager->createQueryBuilder();
136
        $builder->select(['ba', 'a']);
137
        $builder->from('Shopware\CustomModels\Connect\Attribute', 'ba');
138
        $builder->join('ba.article', 'a');
139
        $builder->join('a.mainDetail', 'd');
140
        $builder->leftJoin('d.attribute', 'at');
141
142
        $builder->where('ba.shopId = :shopId AND ba.sourceId = :sourceId');
143
        $query = $builder->getQuery();
144
145
        $query->setParameter('shopId', $shopId);
146
        $query->setParameter('sourceId', (string) $sourceId);
147
        $result = $query->getResult(
148
            $query::HYDRATE_OBJECT
149
        );
150
151
        if (isset($result[0])) {
152
            $attribute = $result[0];
153
154
            return $attribute->getArticle();
155
        }
156
157
        return null;
158
    }
159
160
    /**
161
     * @param array $orderNumbers
162
     * @return array
163
     */
164 View Code Duplication
    public function getArticleIdsByNumber(array $orderNumbers)
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...
165
    {
166
        $builder = $this->manager->getConnection()->createQueryBuilder();
167
168
        $rows = $builder->select('d.articleID as articleId')
169
            ->from('s_articles_details', 'd')
170
            ->where('d.ordernumber IN (:orderNumbers)')
171
            ->setParameter('orderNumbers', $orderNumbers, \Doctrine\DBAL\Connection::PARAM_STR_ARRAY)
172
            ->execute()
173
            ->fetchAll();
174
175
        return array_map(function ($row) {
176
            return $row['articleId'];
177
        }, $rows);
178
    }
179
180
    /**
181
     * Returns article detail model by
182
     * given sourceId and shopId
183
     *
184
     * @param string $sourceId
185
     * @param int $shopId
186
     * @return null|ProductDetail
187
     */
188
    public function getConnectArticleDetailModel($sourceId, $shopId)
189
    {
190
        $product = new Product(['sourceId' => $sourceId, 'shopId' => $shopId]);
191
192
        return $this->getArticleDetailModelByProduct($product);
193
    }
194
195
    /**
196
     * Helper to update the connect_items table
197
     */
198
    public function updateConnectProducts()
199
    {
200
        // Insert new articles
201
        $sql = "
202
        INSERT INTO `s_plugin_connect_items` (article_id, article_detail_id, source_id)
203
        SELECT a.id, ad.id, IF(ad.kind = 1, a.id, CONCAT(a.id, '-', ad.id)) as sourceID
204
205
        FROM s_articles a
206
207
        LEFT JOIN `s_articles_details` ad
208
        ON a.id = ad.articleId
209
210
        LEFT JOIN `s_plugin_connect_items` bi
211
        ON bi.article_detail_id = ad.id
212
213
214
        WHERE a.id IS NOT NULL
215
        AND ad.id IS NOT NULL
216
        AND bi.id IS NULL
217
        ";
218
219
        $this->manager->getConnection()->exec($sql);
220
221
        // Delete removed articles from s_plugin_connect_items
222
        $sql = '
223
        DELETE bi FROM `s_plugin_connect_items`  bi
224
225
        LEFT JOIN `s_articles_details` ad
226
        ON ad.id = bi.article_detail_id
227
228
        WHERE ad.id IS NULL
229
        ';
230
231
        $this->manager->getConnection()->exec($sql);
232
    }
233
234
    /**
235
     * Returns a remote connectProduct e.g. for checkout maniputlations
236
     *
237
     * @param array $ids
238
     * @param int $shopId
239
     * @return array
240
     */
241
    public function getRemoteProducts(array $ids, $shopId)
242
    {
243
        return $this->connectProductQuery->getRemote($ids, $shopId);
244
    }
245
246
    /**
247
     * Returns a local connectProduct for export
248
     *
249
     * @param array $sourceIds
250
     * @return Product[]
251
     */
252
    public function getLocalProduct(array $sourceIds)
253
    {
254
        return $this->connectProductQuery->getLocal($sourceIds);
255
    }
256
257
    /**
258
     * Does the current basket contain connect products?
259
     *
260
     * @param $session
261
     * @return bool
262
     */
263
    public function hasBasketConnectProducts($session, $userId = null)
264
    {
265
        $connection = $this->manager->getConnection();
266
        $sql = 'SELECT ob.articleID
267
268
            FROM s_order_basket ob
269
270
            INNER JOIN s_plugin_connect_items bi
271
            ON bi.article_id = ob.articleID
272
            AND bi.shop_id IS NOT NULL
273
274
            WHERE ob.sessionID=?
275
            ';
276
        $whereClause = [$session];
277
278
        if ($userId > 0) {
279
            $sql .= ' OR userID=?';
280
            $whereClause[] = $userId;
281
        }
282
283
        $sql .= ' LIMIT 1';
284
285
        $result = $connection->fetchArray($sql, $whereClause);
286
287
        return !empty($result);
288
    }
289
290
    /**
291
     * Will return the connectAttribute for a given model. The model can be an Article\Article or Article\Detail
292
     *
293
     * @param $model ProductModel|ProductDetail
294
     * @return ConnectAttribute
295
     */
296
    public function getConnectAttributeByModel($model)
297
    {
298
        if (!$model->getId()) {
299
            return false;
300
        }
301
        $repository = $this->manager->getRepository('Shopware\CustomModels\Connect\Attribute');
302
303
        if ($model instanceof ProductModel) {
0 ignored issues
show
Bug introduced by
The class Shopware\Models\Article\Article does not exist. Did you forget a USE statement, or did you not list all dependencies?

This error could be the result of:

1. Missing dependencies

PHP Analyzer uses your composer.json file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects the composer.json to be in the root folder of your repository.

Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the require or require-dev section?

2. Missing use statement

PHP does not complain about undefined classes in ìnstanceof checks. For example, the following PHP code will work perfectly fine:

if ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

Loading history...
304
            if (!$model->getMainDetail()) {
305
                return false;
306
            }
307
308
            return $repository->findOneBy(['articleDetailId' => $model->getMainDetail()->getId()]);
309
        } elseif ($model instanceof ProductDetail) {
0 ignored issues
show
Bug introduced by
The class Shopware\Models\Article\Detail does not exist. Did you forget a USE statement, or did you not list all dependencies?

This error could be the result of:

1. Missing dependencies

PHP Analyzer uses your composer.json file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects the composer.json to be in the root folder of your repository.

Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the require or require-dev section?

2. Missing use statement

PHP does not complain about undefined classes in ìnstanceof checks. For example, the following PHP code will work perfectly fine:

if ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

Loading history...
310
            return $repository->findOneBy(['articleDetailId' => $model->getId()]);
311
        }
312
313
        return false;
314
    }
315
316
    /**
317
     * Returns connectAttributes for all article details by given article object
318
     *
319
     * @param ProductModel $article
320
     * @return \Shopware\CustomModels\Connect\Attribute[]
321
     */
322
    public function getConnectAttributesByArticle(ProductModel $article)
323
    {
324
        $builder = $this->manager->createQueryBuilder();
325
        $builder->select(['connectAttribute', 'detail']);
326
        $builder->from('Shopware\CustomModels\Connect\Attribute', 'connectAttribute');
327
        $builder->innerJoin('connectAttribute.articleDetail', 'detail');
328
329
        $builder->where('connectAttribute.articleId = :articleId');
330
        $query = $builder->getQuery();
331
332
        $query->setParameter('articleId', $article->getId());
333
334
        return $query->getResult();
335
    }
336
337
    /**
338
     * Returns true when product is exported to Connect
339
     *
340
     * @param Attribute $connectAttribute
341
     * @return bool
342
     */
343
    public function isProductExported(Attribute $connectAttribute)
344
    {
345
        $status = $connectAttribute->getExportStatus();
346
        if ($connectAttribute->isExported()) {
347
            return true;
348
        }
349
350
        if ($status == Attribute::STATUS_INSERT) {
351
            return true;
352
        }
353
354
        if ($status == Attribute::STATUS_UPDATE) {
355
            return true;
356
        }
357
358
        if ($status == Attribute::STATUS_SYNCED) {
359
            return true;
360
        }
361
362
        return false;
363
    }
364
365
    /**
366
     * Verifies that at least one variant from
367
     * same article is exported.
368
     *
369
     * @param Attribute $connectAttribute
370
     * @return bool
371
     */
372
    public function hasExportedVariants(Attribute $connectAttribute)
373
    {
374
        $builder = $this->manager->getConnection()->createQueryBuilder();
375
        $builder->select('COUNT(spci.id)')
376
            ->from('s_plugin_connect_items', 'spci')
377
            ->where('spci.article_id = :articleId AND spci.export_status IN (:exportStatus) AND spci.shop_id IS NULL')
378
            ->setParameter('articleId', $connectAttribute->getArticleId(), \PDO::PARAM_INT)
379
            ->setParameter(
380
                ':exportStatus',
381
                [Attribute::STATUS_INSERT, Attribute::STATUS_UPDATE, Attribute::STATUS_SYNCED],
382
                \Doctrine\DBAL\Connection::PARAM_STR_ARRAY
383
            );
384
385
        return $builder->execute()->fetchColumn() > 0;
386
    }
387
388
    /**
389
     * Helper method to create a connect attribute on the fly
390
     *
391
     * @param $model
392
     * @throws \RuntimeException
393
     * @return ConnectAttribute
394
     */
395
    public function getOrCreateConnectAttributeByModel($model)
396
    {
397
        $attribute = $this->getConnectAttributeByModel($model);
398
399
        if (!$attribute) {
400
            $attribute = new ConnectAttribute();
401
            $attribute->setPurchasePriceHash('');
402
            $attribute->setOfferValidUntil('');
403
            $attribute->setStream('');
404
405
            if ($model instanceof ProductModel) {
0 ignored issues
show
Bug introduced by
The class Shopware\Models\Article\Article does not exist. Did you forget a USE statement, or did you not list all dependencies?

This error could be the result of:

1. Missing dependencies

PHP Analyzer uses your composer.json file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects the composer.json to be in the root folder of your repository.

Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the require or require-dev section?

2. Missing use statement

PHP does not complain about undefined classes in ìnstanceof checks. For example, the following PHP code will work perfectly fine:

if ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

Loading history...
406
                $attribute->setArticle($model);
407
                $attribute->setArticleDetail($model->getMainDetail());
408
                $attribute->setSourceId(
409
                    $this->generateSourceId($model->getMainDetail())
410
                );
411
            } elseif ($model instanceof ProductDetail) {
0 ignored issues
show
Bug introduced by
The class Shopware\Models\Article\Detail does not exist. Did you forget a USE statement, or did you not list all dependencies?

This error could be the result of:

1. Missing dependencies

PHP Analyzer uses your composer.json file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects the composer.json to be in the root folder of your repository.

Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the require or require-dev section?

2. Missing use statement

PHP does not complain about undefined classes in ìnstanceof checks. For example, the following PHP code will work perfectly fine:

if ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

Loading history...
412
                $attribute->setArticle($model->getArticle());
413
                $attribute->setArticleDetail($model);
414
                $attribute->setSourceId(
415
                    $this->generateSourceId($model)
416
                );
417
            } else {
418
                throw new \RuntimeException('Passed model needs to be an article or an article detail');
419
            }
420
            $this->manager->persist($attribute);
421
            $this->manager->flush($attribute);
422
        }
423
424
        return $attribute;
425
    }
426
427
    /**
428
     * Returns connect attributes for article
429
     * and all variants.
430
     * If connect attribute does not exist
431
     * it will be created.
432
     *
433
     * @param ProductModel $article
434
     * @return array
435
     */
436
    public function getOrCreateConnectAttributes(ProductModel $article)
437
    {
438
        $attributes = [];
439
        /** @var \Shopware\Models\Article\Detail $detail */
440
        foreach ($article->getDetails() as $detail) {
441
            $attributes[] = $this->getOrCreateConnectAttributeByModel($detail);
442
        }
443
444
        return $attributes;
445
    }
446
447
    /**
448
     * Generate sourceId
449
     *
450
     * @param ProductDetail $detail
451
     * @return string
452
     */
453
    public function generateSourceId(ProductDetail $detail)
454
    {
455
        if ($detail->getKind() == 1) {
456
            $sourceId = (string) $detail->getArticle()->getId();
457
        } else {
458
            $sourceId = sprintf(
459
                '%s-%s',
460
                $detail->getArticle()->getId(),
461
                $detail->getId()
462
            );
463
        }
464
465
        return $sourceId;
466
    }
467
468
    /**
469
     * @param $id
470
     * @return array
471
     */
472
    public function getConnectCategoryForProduct($id)
473
    {
474
        return $this->connectCategoryQuery->getConnectCategoryForProduct($id);
475
    }
476
477
    public function getMostRelevantConnectCategory($categories)
478
    {
479
        usort(
480
            $categories,
481
            [
482
                $this->connectCategoryQuery->getRelevanceSorter(),
483
                'sortConnectCategoriesByRelevance'
484
            ]
485
        );
486
487
        return array_pop($categories);
488
    }
489
490
    /**
491
     * Defines the update flags
492
     *
493
     * @return array
494
     */
495
    public function getUpdateFlags()
496
    {
497
        return [2 => 'shortDescription', 4 => 'longDescription', 8 => 'name', 16 => 'image', 32 => 'price', 64 => 'imageInitialImport', 128 => 'additionalDescription'];
498
    }
499
500
    /**
501
     * Returns shopware unit entity
502
     *
503
     * @param $unitKey
504
     * @return \Shopware\Models\Article\Unit
505
     */
506
    public function getUnit($unitKey)
507
    {
508
        $repository = $this->manager->getRepository('Shopware\Models\Article\Unit');
509
510
        return $repository->findOneBy(['unit' => $unitKey]);
511
    }
512
513
    /**
514
     * Clear article cache
515
     */
516
    public function clearArticleCache($articleId)
517
    {
518
        Shopware()->Events()->notify(
519
            'Shopware_Plugins_HttpCache_InvalidateCacheId',
520
            ['cacheId' => 'a' . $articleId]
521
        );
522
    }
523
524
    /**
525
     * Replace unit and ref quantity
526
     * @param $products
527
     * @return mixed
528
     */
529
    public function prepareConnectUnit($products)
530
    {
531
        foreach ($products as &$p) {
532
            if ($p->attributes['unit']) {
533
                $configComponent = ConfigFactory::getConfigInstance();
534
                /** @var \ShopwarePlugins\Connect\Components\Utils\UnitMapper $unitMapper */
535
                $unitMapper = new UnitMapper(
536
                    $configComponent,
537
                    $this->manager
538
                );
539
540
                $p->attributes['unit'] = $unitMapper->getConnectUnit($p->attributes['unit']);
541
            }
542
543
            if ($p->attributes['ref_quantity']) {
544
                $intRefQuantity = (int) $p->attributes['ref_quantity'];
545
                if ($p->attributes['ref_quantity'] - $intRefQuantity <= 0.0001) {
546
                    $p->attributes['ref_quantity'] = $intRefQuantity;
547
                }
548
            }
549
        }
550
551
        return $products;
552
    }
553
554
    /**
555
     * Removes connect reservation from session
556
     */
557
    public function clearConnectReservation()
558
    {
559
        Shopware()->Session()->connectReservation = null;
560
    }
561
562
    /**
563
     * Collect sourceIds by given article ids
564
     *
565
     * @param array $articleIds
566
     * @return array
567
     */
568
    public function getArticleSourceIds(array $articleIds)
569
    {
570
        if (empty($articleIds)) {
571
            return [];
572
        }
573
574
        /** @var AttributeRepository $repo */
575
        $repo = $this->manager->getRepository(ConnectAttribute::class);
576
577
        return array_merge(
578
            $repo->findSourceIds($articleIds, 1),
579
            $repo->findSourceIds($articleIds, 2)
580
        );
581
    }
582
583
    /**
584
     * Get ShopProductId struct by given article detail id
585
     * It contains product sourceId and shopId.
586
     * If $articleDetailId is local product, $shopProductId->shopId will be null.
587
     *
588
     * @param int $articleDetailId
589
     * @return ShopProductId
590
     */
591
    public function getShopProductId($articleDetailId)
592
    {
593
        $articleDetailId = (int) $articleDetailId;
594
        $builder = $this->manager->getConnection()->createQueryBuilder();
595
        $builder->select('items.source_id as sourceId, items.shop_id as shopId')
596
            ->from('s_plugin_connect_items', 'items')
597
            ->where('items.article_detail_id = :articleDetailIds')
598
            ->setParameter(':articleDetailIds', $articleDetailId);
599
600
        $result = $builder->execute()->fetch(\PDO::FETCH_ASSOC);
601
602
        return new ShopProductId($result);
603
    }
604
605
    /**
606
     * Check if given articleDetailId is remote product
607
     *
608
     * @param int $articleDetailId
609
     * @return bool
610
     */
611
    public function isRemoteArticleDetail($articleDetailId)
612
    {
613
        $articleDetailId = (int) $articleDetailId;
614
        $articleDetailRepository = $this->manager->getRepository('Shopware\Models\Article\Detail');
615
        /** @var \Shopware\Models\Article\Detail $detail */
616
        $detail = $articleDetailRepository->find($articleDetailId);
617
        if (!$detail) {
618
            return false;
619
        }
620
621
        $connectAttribute = $this->getConnectAttributeByModel($detail);
622
        if (!$connectAttribute) {
623
            return false;
624
        }
625
626
        return ($connectAttribute->getShopId() != null);
627
    }
628
629
    /**
630
     * Check if given articleDetailId is remote product
631
     *
632
     * @param int $articleDetailId
633
     * @return bool
634
     */
635
    public function isRemoteArticleDetailDBAL($articleDetailId)
636
    {
637
        $articleDetailId = (int) $articleDetailId;
638
        $builder = $this->manager->getConnection()->createQueryBuilder();
639
        $builder->select('items.shop_id')
640
            ->from('s_plugin_connect_items', 'items')
641
            ->where('items.article_detail_id = :articleDetailId')
642
            ->setParameter(':articleDetailId', $articleDetailId);
643
644
        return (bool) $builder->execute()->fetchColumn();
645
    }
646
647
    /**
648
     * Extract article ID and detail ID
649
     * from source ID
650
     *
651
     * @param $sourceId
652
     * @return array
653
     */
654
    public function explodeArticleId($sourceId)
655
    {
656
        $articleId = explode('-', $sourceId);
657
658
        if (isset($articleId[1]) && isset($articleId[1])) {
659
            return $articleId;
660
        }
661
662
        return [
663
            $articleId[0]
664
        ];
665
    }
666
667
    /**
668
     * Creates Shopware product model
669
     *
670
     * @param Product $product
671
     * @return ProductModel
672
     */
673
    public function createProductModel(Product $product)
674
    {
675
        //todo@sb: Add test
676
        $model = new ProductModel();
677
        $model->setActive(false);
678
        $model->setName($product->title);
679
        $this->manager->persist($model);
680
681
        return $model;
682
    }
683
684
    /**
685
     * Returns main article detail by given groupId
686
     *
687
     * @param $product
688
     * @param int $mode
689
     * @return null|ProductModel
690
     */
691 View Code Duplication
    public function getArticleByRemoteProduct(Product $product, $mode = Query::HYDRATE_OBJECT)
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...
692
    {
693
        $builder = $this->manager->createQueryBuilder();
694
        $builder->select(['ba', 'd']);
695
        $builder->from('Shopware\CustomModels\Connect\Attribute', 'ba');
696
        $builder->join('ba.articleDetail', 'd');
697
        $builder->leftJoin('d.attribute', 'at');
698
699
        $builder->where('ba.groupId = :groupId AND ba.isMainVariant = 1 AND ba.shopId = :shopId');
700
        $query = $builder->getQuery();
701
702
        $query->setParameter('groupId', $product->groupId);
703
        $query->setParameter('shopId', $product->shopId);
704
        $result = $query->getResult(
705
            $mode
706
        );
707
708
        if (isset($result[0])) {
709
            /** @var \Shopware\CustomModels\Connect\Attribute $attribute */
710
            $attribute = $result[0];
711
712
            return $attribute->getArticle();
713
        }
714
715
        return null;
716
    }
717
718
    /**
719
     * @param int $articleId
720
     * @return array
721
     */
722
    public function getSourceIdsFromArticleId($articleId)
723
    {
724
        $rows = $this->manager->getConnection()->fetchAll(
725
            'SELECT source_id FROM s_plugin_connect_items WHERE article_id = ? AND exported = 1',
726
            [$articleId]
727
        );
728
729
        return array_map(function ($row) {
730
            return $row['source_id'];
731
        }, $rows);
732
    }
733
734
    /**
735
     * @param Unit $localUnit
736
     * @param string $remoteUnit
737
     */
738
    public function updateUnitInRelatedProducts(Unit $localUnit, $remoteUnit)
739
    {
740
        $statement = $this->manager->getConnection()->prepare('UPDATE s_articles_details sad
741
            LEFT JOIN s_articles_attributes saa ON sad.id = saa.articledetailsID
742
            SET sad.unitID = :unitId
743
            WHERE saa.connect_remote_unit = :remoteUnit');
744
745
        $statement->bindValue(':unitId', $localUnit->getId(), \PDO::PARAM_INT);
746
        $statement->bindValue(':remoteUnit', $remoteUnit, \PDO::PARAM_STR);
747
748
        $statement->execute();
749
    }
750
751
    /**
752
     * Checks whether given sourceId is main variant.
753
     * Works only with local products.
754
     * SourceIds pattern is articleId-variantId (58-142)
755
     *
756
     * For remote product check is_main_variant flag in
757
     * s_plugin_connect_items
758
     *
759
     * @param string $sourceId
760
     * @return bool
761
     */
762
    public function isMainVariant($sourceId)
763
    {
764
        $isMainVariant = $this->manager->getConnection()->fetchColumn(
765
            'SELECT d.kind
766
              FROM s_plugin_connect_items spci
767
              LEFT JOIN s_articles_details d ON spci.article_detail_id = d.id
768
              WHERE source_id = ?',
769
            [$sourceId]
770
        );
771
772
        if ($isMainVariant != 1) {
773
            return false;
774
        }
775
776
        return true;
777
    }
778
779
    /**
780
     * @return array
781
     */
782 View Code Duplication
    public function getAllNonConnectArticleIds()
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...
783
    {
784
        $builder = $this->manager->getConnection()->createQueryBuilder();
785
        $builder->select('DISTINCT spci.article_id');
786
        $builder->from('s_plugin_connect_items', 'spci');
787
        $builder->where('spci.shop_id IS NULL');
788
789
        $result = $builder->execute()->fetchAll();
790
791
        return array_map(function ($row) {
792
            return $row['article_id'];
793
        }, $result);
794
    }
795
}
796