Completed
Pull Request — master (#358)
by Simon
03:44
created

preDispatch()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 9
Code Lines 5

Duplication

Lines 9
Ratio 100 %

Importance

Changes 0
Metric Value
cc 1
eloc 5
nc 1
nop 0
dl 9
loc 9
rs 9.6666
c 0
b 0
f 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
use ShopwarePlugins\Connect\Components\Config;
9
use Shopware\Connect\Units;
10
use ShopwarePlugins\Connect\Components\ConnectExport;
11
use ShopwarePlugins\Connect\Components\Validator\ProductAttributesValidator\ProductsAttributesValidator;
12
use ShopwarePlugins\Connect\Components\Utils\UnitMapper;
13
use ShopwarePlugins\Connect\Components\Logger;
14
use ShopwarePlugins\Connect\Components\SnHttpClient;
15
use ShopwarePlugins\Connect\Components\ErrorHandler;
16
use Shopware\Connect\Gateway\ChangeGateway;
17
use ShopwarePlugins\Connect\Components\ProductQuery\BaseProductQuery;
18
19
/**
20
 * @category  Shopware
21
 * @package   Shopware\Plugins\SwagConnect
22
 * @copyright Copyright (c) 2013, shopware AG (http://www.shopware.de)
23
 */
24
class Shopware_Controllers_Backend_ConnectConfig extends Shopware_Controllers_Backend_ExtJs
0 ignored issues
show
Coding Style Compatibility introduced by
PSR1 recommends that each class must be in a namespace of at least one level to avoid collisions.

You can fix this by adding a namespace to your class:

namespace YourVendor;

class YourClass { }

When choosing a vendor namespace, try to pick something that is not too generic to avoid conflicts with other libraries.

Loading history...
25
{
26
    /**
27
     * @var \ShopwarePlugins\Connect\Components\Config
28
     */
29
    private $configComponent;
30
31
    /**
32
     * @var \ShopwarePlugins\Connect\Components\ConnectFactory
33
     */
34
    private $factory;
35
36
    /**
37
     * @var \ShopwarePlugins\Connect\Components\Utils\UnitMapper
38
     */
39
    private $unitMapper;
40
41
    /**
42
     * @var \ShopwarePlugins\Connect\Components\Logger
43
     */
44
    private $logger;
45
46
    /**
47
     * @var \Shopware\Components\Model\ModelRepository
48
     */
49
    private $customerGroupRepository;
50
51
    /**
52
     * @var \ShopwarePlugins\Connect\Components\PriceGateway
53
     */
54
    private $priceGateway;
55
56
    /**
57
     * @var \ShopwarePlugins\Connect\Components\SnHttpClient
58
     */
59
    private $snHttpClient;
60
61 View Code Duplication
    public function preDispatch()
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...
62
    {
63
        $this->container->get('template')->addTemplateDir(
64
            Shopware_Plugins_Backend_SwagConnect_Bootstrap::PLUGIN_PATH . 'Views'
65
        );
66
        $this->container->get('snippets')->addConfigDir(
67
            Shopware_Plugins_Backend_SwagConnect_Bootstrap::PLUGIN_PATH . 'Snippets/'
68
        );
69
    }
70
71
    /**
72
     * The getGeneralAction function is an ExtJs event listener method of the
73
     * connect module. The function is used to load store
74
     * required in the general config form.
75
     * @return string
76
     */
77
    public function getGeneralAction()
78
    {
79
        $generalConfig = $this->getConfigComponent()->getGeneralConfig();
80
81
        $this->View()->assign([
82
            'success' => true,
83
            'data' => $generalConfig
84
        ]);
85
    }
86
87
    /**
88
     * The saveGeneralAction function is an ExtJs event listener method of the
89
     * connect module. The function is used to save store data.
90
     * @return string
91
     */
92 View Code Duplication
    public function saveGeneralAction()
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...
93
    {
94
        try {
95
            $data = $this->Request()->getParam('data');
96
            unset($data['id']);
97
            $this->getConfigComponent()->setGeneralConfigs($data);
98
99
            $this->View()->assign([
100
                'success' => true
101
            ]);
102
        } catch (\Exception $e) {
103
            $this->View()->assign([
104
                'success' => false,
105
                'message' => $e->getMessage()
106
            ]);
107
        }
108
    }
109
110
    public function changeLoggingAction()
111
    {
112
        try {
113
            $enableLogging = $this->Request()->getParam('enableLogging');
114
            $this->getConfigComponent()->setConfig('logRequest', $enableLogging, null, 'general');
115
116
            $this->View()->assign([
117
                'success' => true
118
            ]);
119
        } catch (\Exception $e) {
120
            $this->View()->assign([
121
                'success' => false,
122
            ]);
123
        }
124
    }
125
126
    public function getLoggingEnabledAction()
127
    {
128
        $this->View()->assign([
129
            'success' => true,
130
            'enableLogging' => $this->getConfigComponent()->getConfig('logRequest', 0),
131
        ]);
132
    }
133
134
    /**
135
     * The getImportAction function is an ExtJs event listener method of the
136
     * connect module. The function is used to load store
137
     * required in the import config form.
138
     * @return string
139
     */
140
    public function getImportAction()
141
    {
142
        $importConfigArray = $this->getConfigComponent()->getImportConfig();
143
144
        $this->View()->assign(
145
            [
146
                'success' => true,
147
                'data' => $importConfigArray
148
            ]
149
        );
150
    }
151
152
    /**
153
     * The saveImportAction function is an ExtJs event listener method of the
154
     * connect module. The function is used to save store data.
155
     * @return string
156
     */
157
    public function saveImportAction()
158
    {
159
        $data = $this->Request()->getParam('data');
160
        $data = !isset($data[0]) ? [$data] : $data;
161
162
        $this->getConfigComponent()->setImportConfigs($data);
163
164
        $this->View()->assign(
165
            [
166
                'success' => true
167
            ]
168
        );
169
    }
170
171
    /**
172
     * The getExportAction function is an ExtJs event listener method of the
173
     * connect module. The function is used to load store
174
     * required in the export config form.
175
     * @return string
176
     */
177
    public function getExportAction()
178
    {
179
        $exportConfigArray = $this->getConfigComponent()->getExportConfig();
180
        if (!array_key_exists('exportPriceMode', $exportConfigArray) || $this->isPriceTypeReset()) {
181
            $exportConfigArray['exportPriceMode'] = [];
182
        }
183
184
185
        //Resets the exportPriceMode
186
        if ($this->getSDK()->getPriceType() === \Shopware\Connect\SDK::PRICE_TYPE_NONE) {
187
            $exportConfigArray['exportPriceMode'] = [];
188
        }
189
190
        if (!array_key_exists(BaseProductQuery::LONG_DESCRIPTION_FIELD, $exportConfigArray)) {
191
            $exportConfigArray[BaseProductQuery::LONG_DESCRIPTION_FIELD] = true;
192
        }
193
194
        $this->View()->assign(
195
            [
196
                'success' => true,
197
                'data' => $exportConfigArray
198
            ]
199
        );
200
    }
201
202
    /**
203
     * @return bool
204
     */
205
    public function isPriceTypeReset()
206
    {
207
        return $this->getSDK()->getPriceType() === \Shopware\Connect\SDK::PRICE_TYPE_NONE;
208
    }
209
210
    /**
211
     * ExtJS uses this action to check is price mapping allowed.
212
     * If there is at least one exported product to connect,
213
     * price mapping cannot be changed.
214
     */
215
    public function isPricingMappingAllowedAction()
216
    {
217
        $isPriceModeEnabled = false;
218
        $isPurchasePriceModeEnabled = false;
219
        $isPricingMappingAllowed = $this->isPriceTypeReset();
220
221
        if ($isPricingMappingAllowed) {
222
            $this->View()->assign(
223
                [
224
                    'success' => true,
225
                    'isPricingMappingAllowed' => $isPricingMappingAllowed,
226
                    'isPriceModeEnabled' => true,
227
                    'isPurchasePriceModeEnabled' => true,
228
                ]
229
            );
230
231
            return;
232
        }
233
234
        if ($this->getSDK()->getPriceType() === \Shopware\Connect\SDK::PRICE_TYPE_BOTH
235
        || $this->getSDK()->getPriceType() === \Shopware\Connect\SDK::PRICE_TYPE_RETAIL) {
236
            $isPriceModeEnabled = true;
237
        }
238
239
        if ($this->getSDK()->getPriceType() === \Shopware\Connect\SDK::PRICE_TYPE_BOTH
240
        || $this->getSDK()->getPriceType() === \Shopware\Connect\SDK::PRICE_TYPE_PURCHASE) {
241
            $isPurchasePriceModeEnabled = true;
242
        }
243
244
        $this->View()->assign(
245
            [
246
                'success' => true,
247
                'isPricingMappingAllowed' => $isPricingMappingAllowed,
248
                'isPriceModeEnabled' => $isPriceModeEnabled,
249
                'isPurchasePriceModeEnabled' => $isPurchasePriceModeEnabled,
250
            ]
251
        );
252
    }
253
254
    /**
255
     * The saveExportAction function is an ExtJs event listener method of the
256
     * connect module. The function is used to save store data.
257
     * @return string
258
     */
259
    public function saveExportAction()
260
    {
261
        $data = $this->Request()->getParam('data');
262
        $exportPrice = in_array('price', $data['exportPriceMode']);
263
        $exportPurchasePrice = in_array('purchasePrice', $data['exportPriceMode']);
264
265
        $isModified = $this->getConfigComponent()->compareExportConfiguration($data);
266
        $isPriceTypeReset = $this->isPriceTypeReset();
267
268
        if ($isModified === false && $this->getSDK()->getPriceType() !== \Shopware\Connect\SDK::PRICE_TYPE_NONE) {
269
            $data = !isset($data[0]) ? [$data] : $data;
270
            $this->getConfigComponent()->setExportConfigs($data);
271
            $this->View()->assign(
272
                [
273
                    'success' => true,
274
                ]
275
            );
276
277
            return;
278
        }
279
280
        if ($exportPrice && $exportPurchasePrice) {
281
            $priceType = \Shopware\Connect\SDK::PRICE_TYPE_BOTH;
282
        } elseif ($exportPrice) {
283
            $priceType = \Shopware\Connect\SDK::PRICE_TYPE_RETAIL;
284
            unset($data['priceFieldForPurchasePriceExport']);
285
            unset($data['priceGroupForPurchasePriceExport']);
286
        } elseif ($exportPurchasePrice) {
287
            $priceType = \Shopware\Connect\SDK::PRICE_TYPE_PURCHASE;
288
            unset($data['priceFieldForPriceExport']);
289
            unset($data['priceGroupForPriceExport']);
290
        } else {
291
            $this->View()->assign([
292
                'success' => false,
293
                'message' => Shopware()->Snippets()->getNamespace('backend/connect/view/main')->get(
294
                    'config/export/priceFieldIsNotSupported',
295
                    'Price field is not maintained. Some of the products have price = 0',
296
                    true
297
                )
298
            ]);
299
300
            return;
301
        }
302
303
        if ($priceType == \Shopware\Connect\SDK::PRICE_TYPE_BOTH
304
            && $data['priceFieldForPurchasePriceExport'] == $data['priceFieldForPriceExport']
305
            && $data['priceGroupForPurchasePriceExport'] == $data['priceGroupForPriceExport']
306
        ) {
307
            $this->View()->assign([
308
                'success' => false,
309
                'message' => Shopware()->Snippets()->getNamespace('backend/connect/view/main')->get(
310
                    'config/export/error/same_price_fields',
311
                    'Endkunden-VK und Listenverkaufspreis müssen an verschiedene Felder angeschlossen sein',
312
                    true
313
                )
314
            ]);
315
316
            return;
317
        }
318
319
        $detailPurchasePrice = method_exists('Shopware\Models\Article\Detail', 'setPurchasePrice');
320
        if ($exportPurchasePrice && $detailPurchasePrice) {
321
            $data['priceFieldForPurchasePriceExport'] = 'detailPurchasePrice';
322
        }
323
324 View Code Duplication
        if ($priceType == \Shopware\Connect\SDK::PRICE_TYPE_BOTH
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
325
            || $priceType == \Shopware\Connect\SDK::PRICE_TYPE_RETAIL
326
        ) {
327
            /** @var \Shopware\Models\Customer\Group $groupPrice */
328
            $groupPrice = $this->getCustomerGroupRepository()->findOneBy(['key' => $data['priceGroupForPriceExport']]);
329
            if (!$groupPrice) {
330
                $this->View()->assign([
331
                    'success' => false,
332
                    'message' => Shopware()->Snippets()->getNamespace('backend/connect/view/main')->get(
333
                        'config/export/invalid_customer_group',
334
                        'Ungültige Kundengruppe',
335
                        true
336
                    )
337
                ]);
338
339
                return;
340
            }
341
342
            if ($this->getPriceGateway()->countProductsWithConfiguredPrice($groupPrice, $data['priceFieldForPriceExport']) === 0) {
343
                $this->View()->assign([
344
                    'success' => false,
345
                    'message' => Shopware()->Snippets()->getNamespace('backend/connect/view/main')->get(
346
                        'config/export/priceFieldIsNotSupported',
347
                        'Price field is not maintained. Some of the products have price = 0',
348
                        true
349
                    )
350
                ]);
351
352
                return;
353
            }
354
        }
355
356 View Code Duplication
        if ($priceType == \Shopware\Connect\SDK::PRICE_TYPE_BOTH
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
357
            || $priceType == \Shopware\Connect\SDK::PRICE_TYPE_PURCHASE
358
        ) {
359
            /** @var \Shopware\Models\Customer\Group $groupPurchasePrice */
360
            $groupPurchasePrice = $this->getCustomerGroupRepository()->findOneBy([
361
                'key' => $data['priceGroupForPurchasePriceExport']
362
            ]);
363
            if (!$groupPurchasePrice && !$detailPurchasePrice) {
364
                $this->View()->assign([
365
                    'success' => false,
366
                    'message' => Shopware()->Snippets()->getNamespace('backend/connect/view/main')->get(
367
                        'config/export/invalid_customer_group',
368
                        'Ungültige Kundengruppe',
369
                        true
370
                    )
371
                ]);
372
373
                return;
374
            }
375
376
            if ($this->getPriceGateway()->countProductsWithConfiguredPrice($groupPurchasePrice, $data['priceFieldForPurchasePriceExport']) === 0) {
377
                $this->View()->assign([
378
                    'success' => false,
379
                    'message' => Shopware()->Snippets()->getNamespace('backend/connect/view/main')->get(
380
                        'config/export/priceFieldIsNotSupported',
381
                        'Price field is not maintained. Some of the products have price = 0',
382
                        true
383
                    )
384
                ]);
385
386
                return;
387
            }
388
        }
389
390
        $connectExport = $this->getConnectExport();
391
392
        if ($isPriceTypeReset) {
393
            //removes all hashes from from sw_connect_product
394
            //and resets all item status
395
            $connectExport->clearConnectItems();
396
        }
397
398
        try {
399
            $data = !isset($data[0]) ? [$data] : $data;
400
            $response = $this->getSnHttpClient()->sendRequestToConnect(
401
                'account/settings',
402
                ['priceType' => $priceType]
403
            );
404
405
            $responseBody = json_decode($response->getBody());
406
            if (!$responseBody->success) {
407
                throw new \RuntimeException($responseBody->message);
408
            }
409
410
            $this->getSDK()->verifySdk();
411
            $this->getConfigComponent()->setExportConfigs($data);
412
413
            //todo@sb: check this. Not possible to export all products at the same request.
414
            $ids = $connectExport->getExportArticlesIds();
415
            $sourceIds = $this->getHelper()->getArticleSourceIds($ids);
416
            $errors = $connectExport->export($sourceIds);
417
        } catch (\RuntimeException $e) {
418
            $this->getLogger()->write(true, 'Save export settings', $e->getMessage() . $e->getTraceAsString());
419
            $this->View()->assign([
420
                    'success' => false,
421
                    'message' => $e->getMessage()
422
                ]);
423
424
            return;
425
        }
426
427
        if (!empty($errors)) {
428
            $msg = null;
429
            foreach ($errors as $type) {
430
                $msg .= implode("<br>\n", $type);
431
            }
432
433
            $this->View()->assign([
434
                    'success' => false,
435
                    'message' => $msg
436
                ]);
437
438
            return;
439
        }
440
441
        $this->View()->assign(
442
            [
443
                'success' => true
444
            ]
445
        );
446
    }
447
448
    /**
449
     * @return ConnectExport
450
     */
451
    public function getConnectExport()
452
    {
453
        return new ConnectExport(
454
            $this->getHelper(),
455
            $this->getSDK(),
456
            $this->getModelManager(),
457
            new ProductsAttributesValidator(),
458
            $this->getConfigComponent(),
459
            new ErrorHandler(),
460
            $this->container->get('events')
461
        );
462
    }
463
464
    /**
465
     * It will make a call to SocialNetwork to reset the price type,
466
     * if this call return success true, then it will reset the export settings locally
467
     *
468
     * @return void
469
     */
470
    public function resetPriceTypeAction()
471
    {
472
        $response = $this->getSnHttpClient()->sendRequestToConnect('account/reset/price-type');
473
        $responseBody = json_decode($response->getBody());
474
475 View Code Duplication
        if (!$responseBody->success) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
476
            $this->View()->assign([
477
                'success' => false,
478
                'message' => $responseBody->message
479
            ]);
480
481
            return;
482
        }
483
484
        try {
485
            $this->resetExportedProducts();
486
        } catch (\Exception $e) {
487
            $this->View()->assign([
488
                'success' => false,
489
                'message' => $responseBody->message
490
            ]);
491
492
            return;
493
        }
494
495
        $this->View()->assign([
496
            'success' => true,
497
        ]);
498
    }
499
500
    /**
501
     * It will make a call to SocialNetwork to reset the exchange settings,
502
     * if this call return success true, then it will reset the export settings locally
503
     *
504
     * @return void
505
     */
506
    public function resetExchangeSettingsAction()
507
    {
508
        $response = $this->getSnHttpClient()->sendRequestToConnect('account/reset/exchange-settings');
509
510
        $responseBody = json_decode($response->getBody());
511
512 View Code Duplication
        if (!$responseBody->success) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
513
            $this->View()->assign([
514
                'success' => false,
515
                'message' => $responseBody->message
516
            ]);
517
518
            return;
519
        }
520
521
        try {
522
            $this->resetExportedProducts();
523
524
            //remove the existing api key
525
            $this->getConfigComponent()->setGeneralConfigs(['apiKey' => '']);
526
527
            //recreate the register menu
528
            $this->get('swagconnect.menu_service')->createRegisterMenu();
529
        } catch (\Exception $e) {
530
            $this->View()->assign([
531
                'success' => false,
532
                'message' => $responseBody->message
533
            ]);
534
535
            return;
536
        }
537
538
        $this->View()->assign([
539
            'success' => true,
540
        ]);
541
    }
542
543
    /**
544
     * WARNING This code remove the current product changes
545
     * This is a single call operation and its danger one
546
     */
547
    private function resetExportedProducts()
548
    {
549
        $builder = $this->getModelManager()->getConnection()->createQueryBuilder();
550
        $builder->delete('sw_connect_change')
551
            ->where('c_operation IN (:changes)')
552
            ->setParameter(
553
                'changes',
554
                [
555
                    ChangeGateway::PRODUCT_INSERT,
556
                    ChangeGateway::PRODUCT_UPDATE,
557
                    ChangeGateway::PRODUCT_DELETE,
558
                    ChangeGateway::PRODUCT_STOCK,
559
                ],
560
                \Doctrine\DBAL\Connection::PARAM_STR_ARRAY
561
            );
562
        $builder->execute();
563
564
        $itemRepo = $this->getModelManager()->getRepository('Shopware\CustomModels\Connect\Attribute');
565
        $itemRepo->resetExportedItemsStatus();
566
567
        $streamRepo = $this->getModelManager()->getRepository('Shopware\CustomModels\Connect\ProductStreamAttribute');
568
        $streamRepo->resetExportedStatus();
569
    }
570
571
    /**
572
     * @return \ShopwarePlugins\Connect\Components\Helper
573
     */
574
    public function getHelper()
575
    {
576
        if ($this->factory === null) {
577
            $this->factory = new \ShopwarePlugins\Connect\Components\ConnectFactory();
578
        }
579
580
        return $this->factory->getHelper();
581
    }
582
583
    /**
584
     * @return \Shopware\Connect\SDK
585
     */
586
    public function getSDK()
587
    {
588
        return Shopware()->Container()->get('ConnectSDK');
589
    }
590
591
    /**
592
     * @return Shopware\Components\Model\ModelManager
593
     */
594
    public function getModelManager()
595
    {
596
        return Shopware()->Models();
597
    }
598
599
    /**
600
     * The getStaticPagesAction function is an ExtJs event listener method of the
601
     * connect module. The function is used to load store
602
     * required in the general config form for static cms pages combo.
603
     * @return string
604
     */
605
    public function getStaticPagesAction()
606
    {
607
        $builder = $this->getModelManager()->createQueryBuilder();
608
        $builder->select('st.id, st.description AS name');
609
        $builder->from('Shopware\Models\Site\Site', 'st');
610
611
        $query = $builder->getQuery();
612
        $query->setFirstResult($this->Request()->getParam('start'));
613
        $query->setMaxResults($this->Request()->getParam('limit'));
614
615
        $total = Shopware()->Models()->getQueryCount($query);
616
        $data = $query->getArrayResult();
617
618
        $this->View()->assign([
619
                'success' => true,
620
                'data' => $data,
621
                'total' => $total
622
            ]);
623
    }
624
625
    /**
626
     * Helper function to get access on the Config component
627
     *
628
     * @return \ShopwarePlugins\Connect\Components\Config
629
     */
630
    private function getConfigComponent()
631
    {
632
        if ($this->configComponent === null) {
633
            $modelsManager = Shopware()->Models();
634
            $this->configComponent = new Config($modelsManager);
635
        }
636
637
        return $this->configComponent;
638
    }
639
640
    /**
641
     * The getUnitsAction function is an ExtJs event listener method of the
642
     * connect module. The function is used to load store
643
     * required in the units mapping.
644
     * @return string
645
     */
646
    public function getUnitsAction()
647
    {
648
        $repository = Shopware()->Models()->getRepository('Shopware\Models\Article\Unit');
649
        $units = $repository->findAll();
650
651
        $unitName = Shopware()->Snippets()->getNamespace('backend/connect/view/main')->get(
652
            'import/unit/take_over_units',
653
            'Take over unit',
654
            true
655
        );
656
657
        $unitsMappingArray[] = [
0 ignored issues
show
Coding Style Comprehensibility introduced by
$unitsMappingArray was never initialized. Although not strictly required by PHP, it is generally a good practice to add $unitsMappingArray = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
658
            'shopwareUnitName' => $unitName,
659
            'shopwareUnitKey' => UnitMapper::ADOPT_UNIT_KEY,
660
        ];
661
662
        foreach ($units as $unit) {
663
            $unitsMappingArray[] = [
664
                'shopwareUnitName' => $unit->getName(),
665
                'shopwareUnitKey' => $unit->getUnit()
666
            ];
667
        }
668
669
        $this->View()->assign(
670
            [
671
                'success' => true,
672
                'data' => $unitsMappingArray
673
            ]
674
        );
675
    }
676
677
    /**
678
     * The saveUnitsMappingAction function is an ExtJs event listener method of the
679
     * connect module. The function is used to save units store data.
680
     * @return string
681
     */
682
    public function saveUnitsMappingAction()
683
    {
684
        $data = $this->Request()->getParam('data');
685
        $data = !isset($data[0]) ? [$data] : $data;
686
687
        //prepares units for adoption
688
        $adoptUnitKeys = [];
689
        foreach ($data as $index => $unit) {
690
            if ($unit['shopwareUnitKey'] == UnitMapper::ADOPT_UNIT_KEY) {
691
                $adoptUnitKeys[] = $unit['connectUnit'];
692
                $data[$index]['shopwareUnitKey'] = $unit['connectUnit'];
693
            }
694
        }
695
696
        if (!empty($adoptUnitKeys)) {
697
            $this->getUnitMapper()->createUnits($adoptUnitKeys);
698
        }
699
700
        $this->getConfigComponent()->setUnitsMapping($data);
701
702
        // update related products
703
        $repository = Shopware()->Models()->getRepository('Shopware\Models\Article\Unit');
704
        foreach ($data as $unit) {
705
            /** @var \Shopware\Models\Article\Unit $unitModel */
706
            $unitModel = $repository->findOneBy(['unit' => $unit['shopwareUnitKey']]);
707
            if (!$unitModel) {
708
                continue;
709
            }
710
            $this->getHelper()->updateUnitInRelatedProducts($unitModel, $unit['connectUnit']);
711
        }
712
713
        $this->View()->assign(
714
            [
715
                'success' => true
716
            ]
717
        );
718
    }
719
720
    /**
721
     * The getConnectUnitsAction function is an ExtJs event listener method of the
722
     * connect module. The function is used to load store
723
     * required in the units mapping.
724
     * @return string
725
     */
726
    public function getConnectUnitsAction()
727
    {
728
        $connectUnits = new Units();
729
        $connectUnitsArray = $connectUnits->getLocalizedUnits('de');
730
        $unitsArray = [];
731
        $hideAssigned = (int) $this->Request()->getParam('hideAssignedUnits', 1);
732
733
        foreach ($this->getConfigComponent()->getUnitsMappings() as $connectUnit => $localUnit) {
734
            if ($hideAssigned == true && strlen($localUnit) > 0) {
0 ignored issues
show
Bug Best Practice introduced by
It seems like you are loosely comparing $hideAssigned of type integer to the boolean true. If you are specifically checking for non-zero, consider using something more explicit like > 0 or !== 0 instead.
Loading history...
735
                continue;
736
            }
737
            $unitsArray[] = [
738
                'connectUnit' => $connectUnit,
739
                'name' => $connectUnitsArray[$connectUnit],
740
                'shopwareUnitKey' => $localUnit
741
            ];
742
        }
743
744
        $this->View()->assign(
745
            [
746
                'success' => true,
747
                'data' => $unitsArray
748
            ]
749
        );
750
    }
751
752
    /**
753
     * Ask SocialNetwork what time is need to finish the product update
754
     */
755
    public function calculateFinishTimeAction()
756
    {
757
        $changes = $this->getConnectExport()->getChangesCount();
758
        $seconds = 0;
759
        if ($changes > 0) {
760
            $seconds = $this->getSDK()->calculateFinishTime($changes);
761
        }
762
763
        try {
764
            $this->View()->assign(
765
                [
766
                    'success' => true,
767
                    'time' => $seconds,
768
                ]
769
            );
770
        } catch (\Exception $e) {
771
            $this->View()->assign(
772
                [
773
                    'success' => false,
774
                    'message' => $e->getMessage(),
775
                ]
776
            );
777
        }
778
    }
779
780
    public function getMarketplaceAttributesAction()
781
    {
782
        try {
783
            $verified = $this->getConfigComponent()->getConfig('apiKeyVerified', false);
0 ignored issues
show
Bug introduced by
Are you sure the assignment to $verified is correct as $this->getConfigComponen...apiKeyVerified', false) (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...
784
785
            if ($verified) {
786
                $marketplaceAttributes = $this->getSDK()->getMarketplaceProductAttributes();
787
788
                $attributes = [];
789
                foreach ($marketplaceAttributes as $attributeKey => $attributeLabel) {
790
                    $attributes[] = [
791
                        'attributeKey' => $attributeKey,
792
                        'attributeLabel' => $attributeLabel,
793
                        'shopwareAttributeKey' => ''
794
                    ];
795
                }
796
            } else {
797
                $attributes = [];
798
            }
799
        } catch (\Exception $e) {
800
            // ignore this exception because sometimes
801
            // connect plugin is not configured and tries to
802
            // read marketplace attributes
803
            $attributes = [];
804
        }
805
806
        $this->View()->assign(
807
            [
808
                'success' => true,
809
                'data' => $attributes
810
            ]
811
        );
812
    }
813
814
    public function saveProductAttributesMappingAction()
815
    {
816
        try {
817
            $data = $this->Request()->getParam('data');
818
            $data = !isset($data[0]) ? [$data] : $data;
819
            $marketplaceGateway = $this->getFactory()->getMarketplaceGateway();
820
            $marketplaceGateway->setMarketplaceMapping($data);
821
822
            $this->View()->assign(['success' => true]);
823
        } catch (\Exception $e) {
824
            $this->View()->assign(
825
                [
826
                    'success' => false,
827
                    'message' => $e->getMessage()
828
                ]
829
            );
830
        }
831
    }
832
833
    public function getProductAttributesMappingAction()
834
    {
835
        $marketplaceGateway = $this->getFactory()->getMarketplaceGateway();
836
837
        $mappings = array_map(function ($attribute) use ($marketplaceGateway) {
838
            return [
839
                    'shopwareAttributeKey' => $attribute->getName(),
840
                    'shopwareAttributeLabel' => $attribute->getLabel(),
841
                    'attributeKey' => $marketplaceGateway->findMarketplaceMappingFor($attribute->getName()),
842
                ];
843
        }, array_values(
844
                array_filter(
845
                    Shopware()->Models()->getRepository('Shopware\Models\Article\Element')->findAll(),
846
                    function ($attribute) {
847
                        return $attribute->getName() != 'connectProductDescription';
848
                    }
849
                )
850
            )
851
        );
852
853
        $this->View()->assign(
854
            [
855
                'success' => true,
856
                'data' => $mappings
857
            ]
858
        );
859
    }
860
861
    /**
862
     * Loads all customer groups
863
     *
864
     * @throws Zend_Db_Statement_Exception
865
     */
866
    public function getExportCustomerGroupsAction()
867
    {
868
        $builder = $this->getCustomerGroupRepository()->createQueryBuilder('groups');
869
        $builder->select([
870
            'groups.id as id',
871
            'groups.key as key',
872
            'groups.name as name',
873
            'groups.tax as tax',
874
            'groups.taxInput as taxInput',
875
            'groups.mode as mode'
876
        ]);
877
878
        $query = $builder->getQuery();
879
880
        //get total result of the query
881
        $total = Shopware()->Models()->getQueryCount($query);
882
883
        $data = $query->getArrayResult();
884
885
        //return the data and total count
886
        $this->View()->assign(
887
            [
888
                'success' => true,
889
                'data' => $data,
890
                'total' => $total,
891
            ]
892
        );
893
    }
894
895
    /**
896
     * Loads all price groups where at least
897
     * one product with price greater than 0 exists
898
     *
899
     * @throws Zend_Db_Statement_Exception
900
     */
901
    public function getExportPriceGroupsAction()
902
    {
903
        $groups = [];
904
905
        $customerGroupKey = $this->Request()->getParam('customerGroup', 'EK');
906
        $priceExportMode = $this->Request()->getParam('priceExportMode');
907
        /** @var \Shopware\Models\Customer\Group $customerGroup */
908
        $customerGroup = $this->getCustomerGroupRepository()->findOneBy(['key' => $customerGroupKey]);
909
        if (!$customerGroup) {
910
            $this->View()->assign(
911
                [
912
                    'success' => true,
913
                    'data' => $groups,
914
                    'total' => count($groups),
915
                ]
916
            );
917
918
            return;
919
        }
920
921
        $exportConfigArray = $this->getConfigComponent()->getExportConfig();
922
923
        if (array_key_exists('exportPriceMode', $exportConfigArray)
924
            && count($exportConfigArray['exportPriceMode']) > 0
925
            && $this->getSDK()->getPriceType() != \Shopware\Connect\SDK::PRICE_TYPE_NONE
926
        ) {
927
            $groups[] = $this->getConfigComponent()->collectExportPrice($priceExportMode, $customerGroupKey);
928
        } else {
929
            $productCount = $this->getPriceGateway()->countProducts($customerGroup);
930
            $priceConfiguredProducts = $this->getPriceGateway()->countProductsWithConfiguredPrice($customerGroup, 'price');
931
            $basePriceConfiguredProducts = $this->getPriceGateway()->countProductsWithConfiguredPrice($customerGroup, 'baseprice');
932
            $pseudoPriceConfiguredProducts = $this->getPriceGateway()->countProductsWithConfiguredPrice($customerGroup, 'pseudoprice');
933
934
            $groups[] = [
935
                'price' => false,
936
                'priceAvailable' => $priceConfiguredProducts > 0,
937
                'priceConfiguredProducts' => $priceConfiguredProducts,
938
                'basePrice' => false,
939
                'basePriceAvailable' => $basePriceConfiguredProducts > 0,
940
                'basePriceConfiguredProducts' => $basePriceConfiguredProducts,
941
                'pseudoPrice' => false,
942
                'pseudoPriceAvailable' => $pseudoPriceConfiguredProducts > 0,
943
                'pseudoPriceConfiguredProducts' => $pseudoPriceConfiguredProducts,
944
                'productCount' => $productCount
945
            ];
946
        }
947
948
        $this->View()->assign(
949
            [
950
                'success' => true,
951
                'data' => $groups,
952
                'total' => count($groups),
953
            ]
954
        );
955
    }
956
957
    public function adoptUnitsAction()
958
    {
959
        $connection = $this->getModelManager()->getConnection();
960
        $connection->beginTransaction();
961
962
        try {
963
            $units = array_filter($this->getConfigComponent()->getUnitsMappings(), function ($unit) {
964
                return strlen($unit) == 0;
965
            });
966
967
            $models = $this->getUnitMapper()->createUnits(array_keys($units));
968
            foreach ($models as $unit) {
969
                $this->getHelper()->updateUnitInRelatedProducts($unit, $unit->getUnit());
970
            }
971
            $connection->commit();
972
        } catch (\Exception $e) {
973
            $connection->rollBack();
974
            $this->getLogger()->write(true, $e->getMessage(), $e);
975
            $this->View()->assign(
976
                [
977
                    'success' => false,
978
                ]
979
            );
980
981
            return;
982
        }
983
984
        $this->View()->assign(
985
            [
986
                'success' => true,
987
            ]
988
        );
989
    }
990
991
    /**
992
     * @return \ShopwarePlugins\Connect\Components\ConnectFactory
993
     */
994
    public function getFactory()
995
    {
996
        if ($this->factory === null) {
997
            $this->factory = new \ShopwarePlugins\Connect\Components\ConnectFactory();
998
        }
999
1000
        return $this->factory;
1001
    }
1002
1003
    /**
1004
     * @return UnitMapper
1005
     */
1006
    private function getUnitMapper()
1007
    {
1008
        if (!$this->unitMapper) {
1009
            $this->unitMapper = new UnitMapper(
1010
                $this->getConfigComponent(),
1011
                $this->getModelManager()
1012
            );
1013
        }
1014
1015
        return $this->unitMapper;
1016
    }
1017
1018
    /**
1019
     * @return Logger
1020
     */
1021
    private function getLogger()
1022
    {
1023
        if (!$this->logger) {
1024
            $this->logger = new Logger(Shopware()->Db());
1025
        }
1026
1027
        return $this->logger;
1028
    }
1029
1030
    /**
1031
     * @return \Shopware\Components\Model\ModelRepository
1032
     */
1033
    private function getCustomerGroupRepository()
1034
    {
1035
        if (!$this->customerGroupRepository) {
1036
            $this->customerGroupRepository = Shopware()->Models()->getRepository('Shopware\Models\Customer\Group');
1037
        }
1038
1039
        return $this->customerGroupRepository;
1040
    }
1041
1042
    private function getPriceGateway()
1043
    {
1044
        if (!$this->priceGateway) {
1045
            $this->priceGateway = new \ShopwarePlugins\Connect\Components\PriceGateway(
1046
                Shopware()->Db()
1047
            );
1048
        }
1049
1050
        return $this->priceGateway;
1051
    }
1052
1053 View Code Duplication
    private function getSnHttpClient()
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...
1054
    {
1055
        if (!$this->snHttpClient) {
1056
            $this->snHttpClient = new SnHttpClient(
1057
                $this->get('http_client'),
1058
                new \Shopware\Connect\Gateway\PDO(Shopware()->Db()->getConnection()),
1059
                $this->getConfigComponent()
1060
            );
1061
        }
1062
1063
        return $this->snHttpClient;
1064
    }
1065
}
1066