Completed
Push — master ( eff6d0...b26934 )
by Jonas
11:16 queued 07:39
created

Shopware_Controllers_Backend_Import   B

Complexity

Total Complexity 54

Size/Duplication

Total Lines 511
Duplicated Lines 3.72 %

Coupling/Cohesion

Components 3
Dependencies 8

Importance

Changes 0
Metric Value
dl 19
loc 511
rs 7.0642
c 0
b 0
f 0
wmc 54
lcom 3
cbo 8

22 Methods

Rating   Name   Duplication   Size   Complexity  
A getHelper() 0 4 1
A getConnectFactory() 0 8 2
B loadArticlesByRemoteCategoryAction() 0 44 2
A loadBothArticleTypesAction() 0 22 2
B assignArticlesToCategoryAction() 0 53 5
A unassignRemoteArticlesFromLocalCategoryAction() 0 20 2
B getImportedProductCategoriesTreeAction() 0 58 7
C assignRemoteToLocalCategoryAction() 0 52 8
B unassignRemoteToLocalCategoryAction() 0 30 3
A activateArticlesAction() 19 20 2
B deactivateCategoryAction() 0 33 4
A getSuppliersAction() 0 19 2
A recreateRemoteCategoriesAction() 0 8 1
A getCategoryExtractor() 0 15 2
A getPdoGateway() 0 4 1
A getProductToRemoteCategoryRepository() 0 10 2
A getImportService() 0 4 1
A getAutoCategoryReverter() 0 4 1
A getCategoryRepository() 0 8 2
A getLogger() 0 8 2
A connectCategoriesNeedRecoveryAction() 0 9 1
A productCountForCategoryRecoveryAction() 0 9 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 Shopware_Controllers_Backend_Import 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 Shopware_Controllers_Backend_Import, 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
use ShopwarePlugins\Connect\Components\ConnectFactory;
9
10
/**
11
 * Class Shopware_Controllers_Backend_Import
12
 */
13
class Shopware_Controllers_Backend_Import 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...
14
{
15
    private $categoryExtractor;
16
17
    /**
18
     * @var \Shopware\CustomModels\Connect\ProductToRemoteCategory
19
     */
20
    private $productToRemoteCategoryRepository;
21
22
    private $remoteCategoryRepository;
0 ignored issues
show
Unused Code introduced by
The property $remoteCategoryRepository is not used and could be removed.

This check marks private properties in classes that are never used. Those properties can be removed.

Loading history...
23
24
    private $categoryRepository;
25
26
    private $logger;
27
28
    private $factory;
29
30
    /**
31
     * @return \ShopwarePlugins\Connect\Components\Helper
32
     */
33
    public function getHelper()
34
    {
35
        return $this->getConnectFactory()->getHelper();
36
    }
37
38
    /**
39
     * @return ConnectFactory
40
     */
41
    public function getConnectFactory()
42
    {
43
        if ($this->factory === null) {
44
            $this->factory = new ConnectFactory();
45
        }
46
47
        return $this->factory;
48
    }
49
50
    public function getImportedProductCategoriesTreeAction()
51
    {
52
        $parent = $this->request->getParam('categoryId', 'root');
53
        $hideMapped = (bool) $this->request->getParam('hideMappedProducts', false);
54
55
        $query = $this->request->getParam('remoteCategoriesQuery', '');
56
        $node = $this->request->getParam('id');
57
58
        if (trim($query) !== '') {
59
            try {
60
                $categories = $this->getCategoryExtractor()->getNodesByQuery($hideMapped, $query, $parent, $node);
61
                $this->View()->assign([
62
                    'success' => true,
63
                    'data' => $categories,
64
                ]);
65
            } catch (\InvalidArgumentException $e) {
66
                $this->View()->assign([
67
                    'success' => false,
68
                    'message' => $e->getMessage(),
69
                ]);
70
            }
71
72
            return;
73
        }
74
75
        switch ($parent) {
76
            case 'root':
77
                $categories = $this->getCategoryExtractor()->getMainNodes($hideMapped);
78
                break;
79
            case is_numeric($parent):
80
                $categories = $this->getCategoryExtractor()->getStreamsByShopId($parent);
81
                break;
82
            case strpos($parent, '_stream_') > 0:
83
                list($shopId, $stream) = explode('_stream_', $parent);
84
                $categories = $this->getCategoryExtractor()->getRemoteCategoriesTreeByStream($stream, $shopId, $hideMapped);
85
                break;
86
            default:
87
                // given id must have following structure:
88
                // shopId5~stream~AwesomeProducts~/english/boots/nike
89
                // shopId is required parameter to fetch all child categories of this parent
90
                try {
91
                    list($shopId, $stream) = $this->getCategoryExtractor()->extractNode($node);
92
                } catch (\InvalidArgumentException $e) {
93
                    $this->View()->assign([
94
                        'success' => false,
95
                        'message' => $e->getMessage(),
96
                    ]);
97
98
                    return;
99
                }
100
                $categories = $this->getCategoryExtractor()->getRemoteCategoriesTree($parent, false, $hideMapped, $shopId, $stream);
101
        }
102
103
        $this->View()->assign([
104
            'success' => true,
105
            'data' => $categories,
106
        ]);
107
    }
108
109
    public function loadArticlesByRemoteCategoryAction()
110
    {
111
        $category = $this->request->getParam('category', null);
112
        $shopId = $this->request->getParam('shopId', 0);
113
        $limit = (int) $this->request->getParam('limit', 10);
114
        $offset = (int) $this->request->getParam('start', 0);
115
        $hideMapped = (bool) $this->request->getParam('hideMappedProducts', false);
116
        $searchQuery = $this->request->getParam('remoteArticlesQuery', '');
117
118
        $stream = $this->request->getParam('stream', null);
119
120
        if (strpos($category, '_stream_') > 0) {
121
            $snippets = $this->get('snippets')->getNamespace('backend/connect/view/main');
122
123
            $this->View()->assign([
124
                'success' => false,
125
                'message' => $snippets->get(
126
                    'import/message/dont_select_streams',
127
                    'Please select a Category to display its products',
128
                    true
129
                ),
130
            ]);
131
132
            return;
133
        }
134
135
        $query = $this->getProductToRemoteCategoryRepository()->findArticlesByRemoteCategory($category,
136
            $shopId,
137
            $stream,
138
            $limit,
139
            $offset,
140
            $hideMapped,
141
            $searchQuery);
142
143
        $query->setHydrationMode($query::HYDRATE_OBJECT);
144
145
        $paginator = new \Doctrine\ORM\Tools\Pagination\Paginator($query);
146
        $totalCount = $paginator->count();
147
        $this->View()->assign([
148
            'success' => true,
149
            'data' => $query->getArrayResult(),
150
            'total' => $totalCount,
151
        ]);
152
    }
153
154
    public function loadBothArticleTypesAction()
155
    {
156
        $categoryId = (int) $this->request->getParam('categoryId', 0);
157
        $limit = (int) $this->request->getParam('limit', 10);
158
        $offset = (int) $this->request->getParam('start', 0);
159
        $showOnlyConnectArticles = $this->request->getParam('showOnlyConnectArticles', null);
160
        $query = $this->request->getParam('localArticlesQuery', '');
161
162
        $result = $this->getImportService()->findBothArticlesType(
163
            $categoryId,
164
            $query,
165
            $showOnlyConnectArticles ? true : false,
166
            $limit,
167
            $offset
168
        );
169
170
        $this->View()->assign([
171
            'success' => true,
172
            'data' => $result['data'],
173
            'total' => $result['total'],
174
        ]);
175
    }
176
177
    public function assignArticlesToCategoryAction()
178
    {
179
        $categoryId = (int) $this->request->getParam('categoryId', 0);
180
        $articleIds = $this->request->getParam('articleIds', []);
181
182
        $snippets = Shopware()->Snippets()->getNamespace('backend/connect/view/main');
183
184
        if ($categoryId == 0 || empty($articleIds)) {
185
            $this->View()->assign([
186
                'success' => false,
187
                'message' => $snippets->get(
188
                    'import/message/category_has_children',
189
                    'Invalid category or articles',
190
                    true
191
                ),
192
            ]);
193
194
            return;
195
        }
196
197
        if ($this->getImportService()->hasCategoryChildren($categoryId)) {
198
            $this->View()->assign([
199
                'success' => false,
200
                'message' => $snippets->get(
201
                    'import/message/category_has_children',
202
                    'Category has subcategories, please make sure you have selected single one',
203
                    true
204
                ),
205
            ]);
206
207
            return;
208
        }
209
210
        try {
211
            $this->getImportService()->assignCategoryToArticles($categoryId, $articleIds);
212
        } catch (\RuntimeException $e) {
213
            $this->getLogger()->write(true, $e->getMessage(), $e);
214
            $this->View()->assign([
215
                'success' => false,
216
                'message' => $snippets->get(
217
                    'import/message/failed_product_to_category_assignment',
218
                    'Category could not be assigned to products!',
219
                    true
220
                ),
221
            ]);
222
223
            return;
224
        }
225
226
        $this->View()->assign([
227
            'success' => true
228
        ]);
229
    }
230
231
    /**
232
     * Unassign all categories from articles
233
     */
234
    public function unassignRemoteArticlesFromLocalCategoryAction()
235
    {
236
        $articleIds = $this->request->getParam('articleIds', []);
237
        $categoryId = (int) $this->request->getParam('categoryId');
238
        try {
239
            $this->getImportService()->unAssignArticleCategories($articleIds, $categoryId);
240
        } catch (\Exception $e) {
241
            $this->getLogger()->write(true, $e->getMessage(), $e);
242
            $this->View()->assign([
243
                'success' => false,
244
                'error' => 'Categories could not be unassigned from products!',
245
            ]);
246
247
            return;
248
        }
249
250
        $this->View()->assign([
251
            'success' => true
252
        ]);
253
    }
254
255
    public function assignRemoteToLocalCategoryAction()
256
    {
257
        $localCategoryId = (int) $this->request->getParam('localCategoryId', 0);
258
        $remoteCategoryKey = $this->request->getParam('remoteCategoryKey', null);
259
        $remoteCategoryLabel = $this->request->getParam('remoteCategoryLabel', null);
260
        $node = $this->request->getParam('node', null);
261
262
        if ($localCategoryId == 0 || !$remoteCategoryKey || !$remoteCategoryLabel) {
263
            $this->View()->assign([
264
                'success' => false,
265
                'error' => 'Invalid local or remote category',
266
            ]);
267
268
            return;
269
        }
270
271
        try {
272
            list($shopId, $stream) = $this->getCategoryExtractor()->extractNode($node);
273
        } catch (\InvalidArgumentException $e) {
274
            $this->View()->assign([
275
                'success' => false,
276
                'message' => $e->getMessage(),
277
            ]);
278
279
            return;
280
        }
281
282
        if (!$shopId || !$stream) {
283
            $this->View()->assign([
284
                'success' => false,
285
                'message' => 'Node must contain shopId and stream',
286
            ]);
287
288
            return;
289
        }
290
291
        try {
292
            $this->getImportService()->importRemoteCategory($localCategoryId, $remoteCategoryKey, $remoteCategoryLabel, $shopId, $stream);
293
        } catch (\RuntimeException $e) {
294
            $this->getLogger()->write(true, $e->getMessage(), $e);
295
            $this->View()->assign([
296
                'success' => false,
297
                'error' => 'Remote category could not be mapped to local category!',
298
            ]);
299
300
            return;
301
        }
302
303
        $this->View()->assign([
304
            'success' => true
305
        ]);
306
    }
307
308
    /**
309
     * Unassign all remote articles from local category
310
     */
311
    public function unassignRemoteToLocalCategoryAction()
312
    {
313
        $localCategoryId = (int) $this->request->getParam('localCategoryId', 0);
314
315
        if ($localCategoryId == 0) {
316
            $this->View()->assign([
317
                'success' => false,
318
                'error' => 'Invalid local or remote category',
319
            ]);
320
321
            return;
322
        }
323
324
        try {
325
            $articleIds = $this->getImportService()->findRemoteArticleIdsByCategoryId($localCategoryId);
326
            $this->getImportService()->unAssignArticleCategories($articleIds);
327
        } catch (\Exception $e) {
328
            $this->getLogger()->write(true, $e->getMessage(), $e);
329
            $this->View()->assign([
330
                'success' => false,
331
                'error' => 'Products from remote category could not be unassigned!',
332
            ]);
333
334
            return;
335
        }
336
337
        $this->View()->assign([
338
            'success' => true
339
        ]);
340
    }
341
342 View Code Duplication
    public function activateArticlesAction()
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...
343
    {
344
        $articleIds = $this->request->getParam('ids', 0);
345
346
        try {
347
            $this->getImportService()->activateArticles($articleIds);
348
        } catch (\Exception $e) {
349
            $this->getLogger()->write(true, $e->getMessage(), $e);
350
            $this->View()->assign([
351
                'success' => false,
352
                'error' => 'There is a problem with products activation!',
353
            ]);
354
355
            return;
356
        }
357
358
        $this->View()->assign([
359
            'success' => true,
360
        ]);
361
    }
362
363
    /**
364
     * Deactivates connect categories
365
     */
366
    public function deactivateCategoryAction()
367
    {
368
        $categoryId = $this->request->getParam('categoryId', 0);
369
370
        if (!$categoryId) {
371
            return $this->View()->assign([
372
                'success' => false,
373
                'error' => 'Please select a category for deactivation',
374
            ]);
375
        }
376
377
        /** @var \Shopware\Models\Category\Category $category */
378
        $category = $this->getCategoryRepository()->findOneBy(['id' => $categoryId]);
379
380
        if (!$category) {
381
            $this->View()->assign([
382
                'success' => false,
383
                'error' => 'Please select a valid category for deactivation',
384
            ]);
385
        }
386
387
        $categoryIds = $this->getCategoryExtractor()->getCategoryIdsCollection($category);
388
389
        $changedCount = 0;
390
        if (count($categoryIds) > 0) {
391
            $changedCount = $this->getImportService()->deactivateLocalCategoriesByIds($categoryIds);
392
        }
393
394
        $this->View()->assign([
395
            'success' => true,
396
            'deactivatedCategoriesCount' => $changedCount,
397
        ]);
398
    }
399
400
    /**
401
     * @return Enlight_View|Enlight_View_Default
402
     */
403
    public function getSuppliersAction()
404
    {
405
        $suppliers = [];
406
        $pdoGateway = $this->getPdoGateway();
407
408
        foreach ($pdoGateway->getConnectedShopIds() as $shopId) {
409
            $configuration = $pdoGateway->getShopConfiguration($shopId);
410
            $suppliers = [
411
                'id' => $shopId,
412
                'name' => $configuration->displayName,
413
                'logoUrl' => $configuration->logoUrl,
414
            ];
415
        }
416
417
        return $this->View()->assign([
418
            'success' => true,
419
            'data' => $suppliers,
420
        ]);
421
    }
422
423
    public function recreateRemoteCategoriesAction()
424
    {
425
        $this->getAutoCategoryReverter()->recreateRemoteCategories();
426
427
        return $this->View()->assign([
428
            'success' => true,
429
        ]);
430
    }
431
432
    private function getCategoryExtractor()
433
    {
434
        if (!$this->categoryExtractor) {
435
            $modelManager = Shopware()->Models();
436
            $this->categoryExtractor = new \ShopwarePlugins\Connect\Components\CategoryExtractor(
437
                $modelManager->getRepository('Shopware\CustomModels\Connect\Attribute'),
438
                $this->container->get('swagconnect.auto_category_resolver'),
439
                $this->getPdoGateway(),
440
                new \ShopwarePlugins\Connect\Components\RandomStringGenerator(),
441
                Shopware()->Db()
442
            );
443
        }
444
445
        return $this->categoryExtractor;
446
    }
447
448
    /**
449
     * @return \Shopware\Connect\Gateway\PDO
450
     */
451
    private function getPdoGateway()
452
    {
453
        return new \Shopware\Connect\Gateway\PDO(Shopware()->Db()->getConnection());
454
    }
455
456
    /**
457
     * @return \Shopware\CustomModels\Connect\ProductToRemoteCategoryRepository
458
     */
459
    private function getProductToRemoteCategoryRepository()
460
    {
461
        if (!$this->productToRemoteCategoryRepository) {
462
            $this->productToRemoteCategoryRepository = Shopware()->Models()->getRepository(
463
                'Shopware\CustomModels\Connect\ProductToRemoteCategory'
464
            );
465
        }
466
467
        return $this->productToRemoteCategoryRepository;
468
    }
469
470
    /**
471
     * @return \ShopwarePlugins\Connect\Components\ImportService
472
     */
473
    private function getImportService()
474
    {
475
        return $this->container->get('swagconnect.import_service');
476
    }
477
478
    private function getAutoCategoryReverter()
479
    {
480
        return $this->container->get('swagconnect.auto_category_reverter');
481
    }
482
483
    /**
484
     * @return \Shopware\Models\Category\Repository
485
     */
486
    private function getCategoryRepository()
487
    {
488
        if (!$this->categoryRepository) {
489
            $this->categoryRepository = $this->getModelManager()->getRepository('Shopware\Models\Category\Category');
490
        }
491
492
        return $this->categoryRepository;
493
    }
494
495
    private function getLogger()
496
    {
497
        if (!$this->logger) {
498
            $this->logger = new \ShopwarePlugins\Connect\Components\Logger(Shopware()->Db());
499
        }
500
501
        return $this->logger;
502
    }
503
504
    public function connectCategoriesNeedRecoveryAction()
505
    {
506
        $this->View()->assign([
507
            'success' => true,
508
            'data' => [
509
                'recreateConnectCategories' => $this->getHelper()->checkIfConnectCategoriesHaveToBeRecreated(),
510
            ]
511
        ]);
512
    }
513
514
    public function productCountForCategoryRecoveryAction()
515
    {
516
        $this->View()->assign([
517
            'success' => true,
518
            'data' => [
519
                'totalCount' => $this->getHelper()->getProductCountForCategoryRecovery(),
520
            ]
521
        ]);
522
    }
523
}
524