Completed
Pull Request — master (#399)
by Christian
03:10
created

Helper::getShopProductId()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 13
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 13
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 9
nc 1
nop 1
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
    public function getArticleModelByProduct(Product $product, $mode = Query::HYDRATE_OBJECT)
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
    /**
134
     * Get article detail by his number
135
     *
136
     * @param string $number
137
     * @return null|ProductDetail
138
     */
139
    public function getDetailByNumber($number)
140
    {
141
        return $this->manager->getRepository(ProductDetail::class)->findOneBy(['number' => $number]);
142
    }
143
144
    public function getConnectArticleModel($sourceId, $shopId)
145
    {
146
        $builder = $this->manager->createQueryBuilder();
147
        $builder->select(['ba', 'a']);
148
        $builder->from('Shopware\CustomModels\Connect\Attribute', 'ba');
149
        $builder->join('ba.article', 'a');
150
        $builder->join('a.mainDetail', 'd');
151
        $builder->leftJoin('d.attribute', 'at');
152
153
        $builder->where('ba.shopId = :shopId AND ba.sourceId = :sourceId');
154
        $query = $builder->getQuery();
155
156
        $query->setParameter('shopId', $shopId);
157
        $query->setParameter('sourceId', (string) $sourceId);
158
        $result = $query->getResult(
159
            $query::HYDRATE_OBJECT
160
        );
161
162
        if (isset($result[0])) {
163
            $attribute = $result[0];
164
165
            return $attribute->getArticle();
166
        }
167
168
        return null;
169
    }
170
171
    /**
172
     * @param array $orderNumbers
173
     * @return array
174
     */
175 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...
176
    {
177
        $builder = $this->manager->getConnection()->createQueryBuilder();
178
179
        $rows = $builder->select('d.articleID as articleId')
180
            ->from('s_articles_details', 'd')
181
            ->where('d.ordernumber IN (:orderNumbers)')
182
            ->setParameter('orderNumbers', $orderNumbers, \Doctrine\DBAL\Connection::PARAM_STR_ARRAY)
183
            ->execute()
184
            ->fetchAll();
185
186
        return array_map(function ($row) {
187
            return $row['articleId'];
188
        }, $rows);
189
    }
190
191
    /**
192
     * Returns article detail model by
193
     * given sourceId and shopId
194
     *
195
     * @param string $sourceId
196
     * @param int $shopId
197
     * @return null|ProductDetail
198
     */
199
    public function getConnectArticleDetailModel($sourceId, $shopId)
200
    {
201
        $product = new Product(['sourceId' => $sourceId, 'shopId' => $shopId]);
202
203
        return $this->getArticleDetailModelByProduct($product);
204
    }
205
206
    /**
207
     * Helper to update the connect_items table
208
     */
209
    public function updateConnectProducts()
210
    {
211
        // Insert new articles
212
        $sql = "
213
        INSERT INTO `s_plugin_connect_items` (article_id, article_detail_id, source_id)
214
        SELECT a.id, ad.id, IF(ad.kind = 1, a.id, CONCAT(a.id, '-', ad.id)) as sourceID
215
216
        FROM s_articles a
217
218
        LEFT JOIN `s_articles_details` ad
219
        ON a.id = ad.articleId
220
221
        LEFT JOIN `s_plugin_connect_items` bi
222
        ON bi.article_detail_id = ad.id
223
224
225
        WHERE a.id IS NOT NULL
226
        AND ad.id IS NOT NULL
227
        AND bi.id IS NULL
228
        ";
229
230
        $this->manager->getConnection()->exec($sql);
231
232
        // Delete removed articles from s_plugin_connect_items
233
        $sql = '
234
        DELETE bi FROM `s_plugin_connect_items`  bi
235
236
        LEFT JOIN `s_articles_details` ad
237
        ON ad.id = bi.article_detail_id
238
239
        WHERE ad.id IS NULL
240
        ';
241
242
        $this->manager->getConnection()->exec($sql);
243
    }
244
245
    /**
246
     * Returns wether connect categories have to be recreated or not
247
     * @return bool
248
     */
249
    public function checkIfConnectCategoriesHaveToBeRecreated()
250
    {
251
        $configComponent = ConfigFactory::getConfigInstance();
252
        $result = $configComponent->getConfig('recreateConnectCategories');
0 ignored issues
show
Bug introduced by
Are you sure the assignment to $result is correct as $configComponent->getCon...eateConnectCategories') (which targets ShopwarePlugins\Connect\...nts\Config::getConfig()) seems to always return null.

This check looks for function or method calls that always return null and whose return value is assigned to a variable.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
$object = $a->getObject();

The method getObject() can return nothing but null, so it makes no sense to assign that value to a variable.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
253
        if ($result === 0) {
254
            return true;
255
        }
256
257
        return false;
258
    }
259
260
    /**
261
     * Returns a remote connectProduct e.g. for checkout maniputlations
262
     *
263
     * @param array $ids
264
     * @param int $shopId
265
     * @return array
266
     */
267
    public function getRemoteProducts(array $ids, $shopId)
268
    {
269
        return $this->connectProductQuery->getRemote($ids, $shopId);
270
    }
271
272
    /**
273
     * Returns a local connectProduct for export
274
     *
275
     * @param array $sourceIds
276
     * @return Product[]
277
     */
278
    public function getLocalProduct(array $sourceIds)
279
    {
280
        return $this->connectProductQuery->getLocal($sourceIds);
281
    }
282
283
    /**
284
     * Does the current basket contain connect products?
285
     *
286
     * @param $session
287
     * @return bool
288
     */
289
    public function hasBasketConnectProducts($session, $userId = null)
290
    {
291
        $connection = $this->manager->getConnection();
292
        $sql = 'SELECT ob.articleID
293
294
            FROM s_order_basket ob
295
296
            INNER JOIN s_plugin_connect_items bi
297
            ON bi.article_id = ob.articleID
298
            AND bi.shop_id IS NOT NULL
299
300
            WHERE ob.sessionID=?
301
            ';
302
        $whereClause = [$session];
303
304
        if ($userId > 0) {
305
            $sql .= ' OR userID=?';
306
            $whereClause[] = $userId;
307
        }
308
309
        $sql .= ' LIMIT 1';
310
311
        $result = $connection->fetchArray($sql, $whereClause);
312
313
        return !empty($result);
314
    }
315
316
    /**
317
     * Will return the connectAttribute for a given model. The model can be an Article\Article or Article\Detail
318
     *
319
     * @param $model ProductModel|ProductDetail
320
     * @return ConnectAttribute
321
     */
322
    public function getConnectAttributeByModel($model)
323
    {
324
        if (!$model->getId()) {
325
            return false;
326
        }
327
        $repository = $this->manager->getRepository('Shopware\CustomModels\Connect\Attribute');
328
329
        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...
330
            if (!$model->getMainDetail()) {
331
                return false;
332
            }
333
334
            return $repository->findOneBy(['articleDetailId' => $model->getMainDetail()->getId()]);
335
        } 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...
336
            return $repository->findOneBy(['articleDetailId' => $model->getId()]);
337
        }
338
339
        return false;
340
    }
341
342
    /**
343
     * Returns connectAttributes for all article details by given article object
344
     *
345
     * @param ProductModel $article
346
     * @return \Shopware\CustomModels\Connect\Attribute[]
347
     */
348
    public function getConnectAttributesByArticle(ProductModel $article)
349
    {
350
        $builder = $this->manager->createQueryBuilder();
351
        $builder->select(['connectAttribute', 'detail']);
352
        $builder->from('Shopware\CustomModels\Connect\Attribute', 'connectAttribute');
353
        $builder->innerJoin('connectAttribute.articleDetail', 'detail');
354
355
        $builder->where('connectAttribute.articleId = :articleId');
356
        $query = $builder->getQuery();
357
358
        $query->setParameter('articleId', $article->getId());
359
360
        return $query->getResult();
361
    }
362
363
    /**
364
     * Returns true when product is exported to Connect
365
     *
366
     * @param Attribute $connectAttribute
367
     * @return bool
368
     */
369
    public function isProductExported(Attribute $connectAttribute)
370
    {
371
        $status = $connectAttribute->getExportStatus();
372
        if ($connectAttribute->isExported()) {
373
            return true;
374
        }
375
376
        if ($status == Attribute::STATUS_INSERT) {
377
            return true;
378
        }
379
380
        if ($status == Attribute::STATUS_UPDATE) {
381
            return true;
382
        }
383
384
        if ($status == Attribute::STATUS_SYNCED) {
385
            return true;
386
        }
387
388
        return false;
389
    }
390
391
    /**
392
     * Verifies that at least one variant from
393
     * same article is exported.
394
     *
395
     * @param Attribute $connectAttribute
396
     * @return bool
397
     */
398
    public function hasExportedVariants(Attribute $connectAttribute)
399
    {
400
        $builder = $this->manager->getConnection()->createQueryBuilder();
401
        $builder->select('COUNT(spci.id)')
402
            ->from('s_plugin_connect_items', 'spci')
403
            ->where('spci.article_id = :articleId AND spci.export_status IN (:exportStatus) AND spci.shop_id IS NULL')
404
            ->setParameter('articleId', $connectAttribute->getArticleId(), \PDO::PARAM_INT)
405
            ->setParameter(
406
                ':exportStatus',
407
                [Attribute::STATUS_INSERT, Attribute::STATUS_UPDATE, Attribute::STATUS_SYNCED],
408
                \Doctrine\DBAL\Connection::PARAM_STR_ARRAY
409
            );
410
411
        return $builder->execute()->fetchColumn() > 0;
412
    }
413
414
    /**
415
     * Helper method to create a connect attribute on the fly
416
     *
417
     * @param $model
418
     * @throws \RuntimeException
419
     * @return ConnectAttribute
420
     */
421
    public function getOrCreateConnectAttributeByModel($model)
422
    {
423
        $attribute = $this->getConnectAttributeByModel($model);
424
425
        if (!$attribute) {
426
            $attribute = new ConnectAttribute();
427
            $attribute->setPurchasePriceHash('');
428
            $attribute->setOfferValidUntil('');
429
            $attribute->setStream('');
430
431
            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...
432
                $attribute->setArticle($model);
433
                $attribute->setArticleDetail($model->getMainDetail());
434
                $attribute->setSourceId(
435
                    $this->generateSourceId($model->getMainDetail())
436
                );
437
            } 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...
438
                $attribute->setArticle($model->getArticle());
439
                $attribute->setArticleDetail($model);
440
                $attribute->setSourceId(
441
                    $this->generateSourceId($model)
442
                );
443
            } else {
444
                throw new \RuntimeException('Passed model needs to be an article or an article detail');
445
            }
446
            $this->manager->persist($attribute);
447
            $this->manager->flush($attribute);
448
        }
449
450
        return $attribute;
451
    }
452
453
    /**
454
     * Returns connect attributes for article
455
     * and all variants.
456
     * If connect attribute does not exist
457
     * it will be created.
458
     *
459
     * @param ProductModel $article
460
     * @return array
461
     */
462
    public function getOrCreateConnectAttributes(ProductModel $article)
463
    {
464
        $attributes = [];
465
        /** @var \Shopware\Models\Article\Detail $detail */
466
        foreach ($article->getDetails() as $detail) {
467
            $attributes[] = $this->getOrCreateConnectAttributeByModel($detail);
468
        }
469
470
        return $attributes;
471
    }
472
473
    /**
474
     * Generate sourceId
475
     *
476
     * @param ProductDetail $detail
477
     * @return string
478
     */
479
    public function generateSourceId(ProductDetail $detail)
480
    {
481
        if ($detail->getKind() == 1) {
482
            $sourceId = (string) $detail->getArticle()->getId();
483
        } else {
484
            $sourceId = sprintf(
485
                '%s-%s',
486
                $detail->getArticle()->getId(),
487
                $detail->getId()
488
            );
489
        }
490
491
        return $sourceId;
492
    }
493
494
    /**
495
     * @param $id
496
     * @return array
497
     */
498
    public function getConnectCategoryForProduct($id)
499
    {
500
        return $this->connectCategoryQuery->getConnectCategoryForProduct($id);
501
    }
502
503
    public function getMostRelevantConnectCategory($categories)
504
    {
505
        usort(
506
            $categories,
507
            [
508
                $this->connectCategoryQuery->getRelevanceSorter(),
509
                'sortConnectCategoriesByRelevance'
510
            ]
511
        );
512
513
        return array_pop($categories);
514
    }
515
516
    /**
517
     * Defines the update flags
518
     *
519
     * @return array
520
     */
521
    public function getUpdateFlags()
522
    {
523
        return [2 => 'shortDescription', 4 => 'longDescription', 8 => 'name', 16 => 'image', 32 => 'price', 64 => 'imageInitialImport', 128 => 'additionalDescription'];
524
    }
525
526
    /**
527
     * Returns shopware unit entity
528
     *
529
     * @param $unitKey
530
     * @return \Shopware\Models\Article\Unit
531
     */
532
    public function getUnit($unitKey)
533
    {
534
        $repository = $this->manager->getRepository('Shopware\Models\Article\Unit');
535
536
        return $repository->findOneBy(['unit' => $unitKey]);
537
    }
538
539
    /**
540
     * Clear article cache
541
     */
542
    public function clearArticleCache($articleId)
543
    {
544
        Shopware()->Events()->notify(
545
            'Shopware_Plugins_HttpCache_InvalidateCacheId',
546
            ['cacheId' => 'a' . $articleId]
547
        );
548
    }
549
550
    /**
551
     * Replace unit and ref quantity
552
     * @param $products
553
     * @return mixed
554
     */
555
    public function prepareConnectUnit($products)
556
    {
557
        foreach ($products as &$p) {
558
            if ($p->attributes['unit']) {
559
                $configComponent = ConfigFactory::getConfigInstance();
560
                /** @var \ShopwarePlugins\Connect\Components\Utils\UnitMapper $unitMapper */
561
                $unitMapper = new UnitMapper(
562
                    $configComponent,
563
                    $this->manager
564
                );
565
566
                $p->attributes['unit'] = $unitMapper->getConnectUnit($p->attributes['unit']);
567
            }
568
569
            if ($p->attributes['ref_quantity']) {
570
                $intRefQuantity = (int) $p->attributes['ref_quantity'];
571
                if ($p->attributes['ref_quantity'] - $intRefQuantity <= 0.0001) {
572
                    $p->attributes['ref_quantity'] = $intRefQuantity;
573
                }
574
            }
575
        }
576
577
        return $products;
578
    }
579
580
    /**
581
     * Removes connect reservation from session
582
     */
583
    public function clearConnectReservation()
584
    {
585
        Shopware()->Session()->connectReservation = null;
586
    }
587
588
    /**
589
     * Collect sourceIds by given article ids
590
     *
591
     * @param array $articleIds
592
     * @return array
593
     */
594
    public function getArticleSourceIds(array $articleIds)
595
    {
596
        if (empty($articleIds)) {
597
            return [];
598
        }
599
600
        /** @var AttributeRepository $repo */
601
        $repo = $this->manager->getRepository(ConnectAttribute::class);
602
603
        return array_merge(
604
            $repo->findSourceIds($articleIds, 1),
605
            $repo->findSourceIds($articleIds, 2)
606
        );
607
    }
608
609
    /**
610
     * Get ShopProductId struct by given article detail id
611
     * It contains product sourceId and shopId.
612
     * If $articleDetailId is local product, $shopProductId->shopId will be null.
613
     *
614
     * @param int $articleDetailId
615
     * @return ShopProductId
616
     */
617
    public function getShopProductId($articleDetailId)
618
    {
619
        $articleDetailId = (int) $articleDetailId;
620
        $builder = $this->manager->getConnection()->createQueryBuilder();
621
        $builder->select('items.source_id as sourceId, items.shop_id as shopId')
622
            ->from('s_plugin_connect_items', 'items')
623
            ->where('items.article_detail_id = :articleDetailIds')
624
            ->setParameter(':articleDetailIds', $articleDetailId);
625
626
        $result = $builder->execute()->fetch(\PDO::FETCH_ASSOC);
627
628
        return new ShopProductId($result);
629
    }
630
631
    /**
632
     * Check if given articleDetailId is remote product
633
     *
634
     * @param int $articleDetailId
635
     * @return bool
636
     */
637
    public function isRemoteArticleDetail($articleDetailId)
638
    {
639
        $articleDetailId = (int) $articleDetailId;
640
        $articleDetailRepository = $this->manager->getRepository('Shopware\Models\Article\Detail');
641
        /** @var \Shopware\Models\Article\Detail $detail */
642
        $detail = $articleDetailRepository->find($articleDetailId);
643
        if (!$detail) {
644
            return false;
645
        }
646
647
        $connectAttribute = $this->getConnectAttributeByModel($detail);
648
        if (!$connectAttribute) {
649
            return false;
650
        }
651
652
        return ($connectAttribute->getShopId() != null);
653
    }
654
655
    /**
656
     * Check if given articleDetailId is remote product
657
     *
658
     * @param int $articleDetailId
659
     * @return bool
660
     */
661
    public function isRemoteArticleDetailDBAL($articleDetailId)
662
    {
663
        $articleDetailId = (int) $articleDetailId;
664
        $builder = $this->manager->getConnection()->createQueryBuilder();
665
        $builder->select('items.shop_id')
666
            ->from('s_plugin_connect_items', 'items')
667
            ->where('items.article_detail_id = :articleDetailId')
668
            ->setParameter(':articleDetailId', $articleDetailId);
669
670
        return (bool) $builder->execute()->fetchColumn();
671
    }
672
673
    /**
674
     * Extract article ID and detail ID
675
     * from source ID
676
     *
677
     * @param $sourceId
678
     * @return array
679
     */
680
    public function explodeArticleId($sourceId)
681
    {
682
        $articleId = explode('-', $sourceId);
683
684
        if (isset($articleId[1]) && isset($articleId[1])) {
685
            return $articleId;
686
        }
687
688
        return [
689
            $articleId[0]
690
        ];
691
    }
692
693
    /**
694
     * Creates Shopware product model
695
     *
696
     * @param Product $product
697
     * @return ProductModel
698
     */
699
    public function createProductModel(Product $product)
700
    {
701
        //todo@sb: Add test
702
        $model = new ProductModel();
703
        $model->setActive(false);
704
        $model->setName($product->title);
705
        $this->manager->persist($model);
706
707
        return $model;
708
    }
709
710
    /**
711
     * Returns main article detail by given groupId
712
     *
713
     * @param $product
714
     * @param int $mode
715
     * @return null|ProductModel
716
     */
717 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...
718
    {
719
        $builder = $this->manager->createQueryBuilder();
720
        $builder->select(['ba', 'd']);
721
        $builder->from('Shopware\CustomModels\Connect\Attribute', 'ba');
722
        $builder->join('ba.articleDetail', 'd');
723
        $builder->leftJoin('d.attribute', 'at');
724
725
        $builder->where('ba.groupId = :groupId AND ba.isMainVariant = 1 AND ba.shopId = :shopId');
726
        $query = $builder->getQuery();
727
728
        $query->setParameter('groupId', $product->groupId);
729
        $query->setParameter('shopId', $product->shopId);
730
        $result = $query->getResult(
731
            $mode
732
        );
733
734
        if (isset($result[0])) {
735
            /** @var \Shopware\CustomModels\Connect\Attribute $attribute */
736
            $attribute = $result[0];
737
738
            return $attribute->getArticle();
739
        }
740
741
        return null;
742
    }
743
744
    /**
745
     * @param int $articleId
746
     * @return array
747
     */
748
    public function getSourceIdsFromArticleId($articleId)
749
    {
750
        $rows = $this->manager->getConnection()->fetchAll(
751
            'SELECT source_id FROM s_plugin_connect_items WHERE article_id = ? AND exported = 1',
752
            [$articleId]
753
        );
754
755
        return array_map(function ($row) {
756
            return $row['source_id'];
757
        }, $rows);
758
    }
759
760
    /**
761
     * @param Unit $localUnit
762
     * @param string $remoteUnit
763
     */
764
    public function updateUnitInRelatedProducts(Unit $localUnit, $remoteUnit)
765
    {
766
        $statement = $this->manager->getConnection()->prepare('UPDATE s_articles_details sad
767
            LEFT JOIN s_articles_attributes saa ON sad.id = saa.articledetailsID
768
            SET sad.unitID = :unitId
769
            WHERE saa.connect_remote_unit = :remoteUnit');
770
771
        $statement->bindValue(':unitId', $localUnit->getId(), \PDO::PARAM_INT);
772
        $statement->bindValue(':remoteUnit', $remoteUnit, \PDO::PARAM_STR);
773
774
        $statement->execute();
775
    }
776
777
    /**
778
     * Checks whether given sourceId is main variant.
779
     * Works only with local products.
780
     * SourceIds pattern is articleId-variantId (58-142)
781
     *
782
     * For remote product check is_main_variant flag in
783
     * s_plugin_connect_items
784
     *
785
     * @param string $sourceId
786
     * @return bool
787
     */
788
    public function isMainVariant($sourceId)
789
    {
790
        $isMainVariant = $this->manager->getConnection()->fetchColumn(
791
            'SELECT d.kind
792
              FROM s_plugin_connect_items spci
793
              LEFT JOIN s_articles_details d ON spci.article_detail_id = d.id
794
              WHERE source_id = ?',
795
            [$sourceId]
796
        );
797
798
        if ($isMainVariant != 1) {
799
            return false;
800
        }
801
802
        return true;
803
    }
804
805
    public function getLocalArticleCount()
806
    {
807
        return $this->manager->getRepository(ConnectAttribute::class)->getLocalArticleCount();
808
    }
809
810
    /**
811
     * Recreates ConnectCategories wit the specified offset and batchsize
812
     * @param int $offset
813
     * @param int $batchsize
814
     */
815
    public function recreateConnectCategories($offset, $batchsize)
816
    {
817
        $result = $this->manager->getConnection()->executeQuery('SELECT `article_id`, `category` FROM `s_plugin_connect_items` WHERE shop_id IS NOT NULL GROUP BY `article_id` ORDER BY `id` LIMIT ? OFFSET ?',
818
            [$batchsize, $offset],
819
            [\PDO::PARAM_INT, \PDO::PARAM_INT]
820
        );
821
822
        while ($row = $result->fetch()) {
823
            $categories = json_decode($row['category'], true);
824
            $countAssignedCategories = $this->manager->getConnection()->executeQuery('SELECT COUNT(`connect_category_id`) AS categories_count FROM s_plugin_connect_product_to_categories WHERE articleID = ?',
825
                [$row['article_id']]
826
            )->fetchColumn();
827
828
            if (count($categories) != $countAssignedCategories) {
829
                foreach ($categories as $categoryKey => $category) {
830
                    $selectedCategory = $this->manager->getConnection()->executeQuery('SELECT `id` FROM s_plugin_connect_categories WHERE category_key = ?',
831
                        [$categoryKey]);
832
                    if (!($res = $selectedCategory->fetch())) {
833
                        $this->manager->getConnection()->executeQuery('INSERT INTO s_plugin_connect_categories (category_key, label) VALUES (?, ?)',
834
                            [$categoryKey, $category]);
835
                        $categoryId = (int) $this->manager->getConnection()->lastInsertId();
836
                    } else {
837
                        $categoryId = (int) $res['id'];
838
                    }
839
                    $selectedProductToCategory = $this->manager->getConnection()->executeQuery('SELECT COUNT(*) FROM s_plugin_connect_product_to_categories WHERE connect_category_id = ? AND articleID = ?',
840
                        [$categoryId, (int) $row['article_id']]
841
                    )->fetchColumn();
842
                    if ((int) $selectedProductToCategory === 0) {
843
                        $this->manager->getConnection()->executeQuery('INSERT INTO s_plugin_connect_product_to_categories (connect_category_id, articleID) VALUES (?, ?)',
844
                            [$categoryId, (int) $row['article_id']]
845
                            );
846
                    }
847
                }
848
            }
849
        }
850
851
        $totalCount = $this->getProductCountForCategoryRecovery();
852
        if ($batchsize + $offset >= $totalCount) {
853
            $configComponent = ConfigFactory::getConfigInstance();
854
            $configComponent->setConfig('recreateConnectCategories', 1);
855
        }
856
    }
857
858
    /**
859
     * @return int
860
     */
861
    public function getProductCountForCategoryRecovery()
862
    {
863
        return (int) $this->manager->getConnection()->executeQuery('
864
          SELECT COUNT(*) 
865
          FROM (
866
            SELECT COUNT(*) FROM `s_plugin_connect_items` WHERE shop_id IS NOT NULL GROUP BY `article_id`
867
          ) AS Z')->fetchColumn();
868
    }
869
}
870