GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.
Passed
Push — master ( f95cc0...b08239 )
by Ivan
10:56
created

BackendProductController   D

Complexity

Total Complexity 82

Size/Duplication

Total Lines 700
Duplicated Lines 23.43 %

Coupling/Cohesion

Components 1
Dependencies 10

Importance

Changes 4
Bugs 0 Features 0
Metric Value
wmc 82
c 4
b 0
f 0
lcom 1
cbo 10
dl 164
loc 700
rs 4.4444

12 Methods

Rating   Name   Duplication   Size   Complexity  
A actionAjaxRelatedProduct() 0 22 2
C actions() 27 77 7
A actionIndex() 0 20 2
B actionDelete() 0 23 5
A actionRemoveAll() 0 12 3
A sortModels() 19 19 2
B generateOptions() 0 24 6
A generateCase() 8 8 2
A behaviors() 14 14 1
F actionEdit() 15 140 22
F actionGenerate() 34 137 17
D actionClone() 47 122 13

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 BackendProductController 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 BackendProductController, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
namespace app\modules\shop\controllers;
4
5
use app\backend\actions\PropertyHandler;
6
use app\backend\components\BackendController;
7
use app\backend\events\BackendEntityEditEvent;
8
use app\modules\image\widgets\views\AddImageAction;
9
use app\modules\shop\models\Category;
10
use app\modules\image\models\Image;
11
use app\models\Object;
12
use app\models\ObjectPropertyGroup;
13
use app\modules\shop\models\Currency;
14
use app\modules\shop\models\Product;
15
use app\models\Property;
16
use app\models\PropertyStaticValues;
17
use app\models\ViewObject;
18
use app\properties\HasProperties;
19
use app\modules\image\widgets\RemoveAction;
20
use app\modules\image\widgets\SaveInfoAction;
21
use app\modules\image\widgets\UploadAction;
22
use app\backend\actions\UpdateEditable;
23
use devgroup\JsTreeWidget\AdjacencyFullTreeDataAction;
24
use Yii;
25
use yii\data\ActiveDataProvider;
26
use yii\db\Query;
27
use yii\filters\AccessControl;
28
use yii\helpers\ArrayHelper;
29
use yii\helpers\Json;
30
use yii\helpers\Url;
31
use yii\web\NotFoundHttpException;
32
use yii\web\ServerErrorHttpException;
33
use app\backend\actions\MassPublishAction;
34
use app\backend\actions\CategoryMovementsAction;
35
36
class BackendProductController extends BackendController
37
{
38
    const EVENT_BACKEND_PRODUCT_EDIT = 'backend-product-edit';
39
    const EVENT_BACKEND_PRODUCT_EDIT_SAVE = 'backend-product-edit-save';
40
    const EVENT_BACKEND_PRODUCT_EDIT_FORM = 'backend-product-edit-form';
41
    const EVENT_BACKEND_PRODUCT_AFTER_SAVE = 'backend-product-after-save';
42
43
    /**
44
     * @inheritdoc
45
     * @return array
0 ignored issues
show
Documentation introduced by
Consider making the return type a bit more specific; maybe use array<string,array>.

This check looks for the generic type array as a return type and suggests a more specific type. This type is inferred from the actual code.

Loading history...
46
     */
47 View Code Duplication
    public function behaviors()
48
    {
49
        return [
50
            'access' => [
51
                'class' => AccessControl::className(),
52
                'rules' => [
53
                    [
54
                        'allow' => true,
55
                        'roles' => ['product manage'],
56
                    ],
57
                ],
58
            ],
59
        ];
60
    }
61
62
    /**
63
     * @inheritdoc
64
     * @return array
0 ignored issues
show
Documentation introduced by
Consider making the return type a bit more specific; maybe use array<string,array>.

This check looks for the generic type array as a return type and suggests a more specific type. This type is inferred from the actual code.

Loading history...
65
     */
66
    public function actions()
67
    {
68
        return [
69
            'getTree' => [
70
                'class' => AdjacencyFullTreeDataAction::className(),
71
                'class_name' => Category::className(),
72
                'model_label_attribute' => 'name',
73
            ],
74
            'getCatTree' => [
75
                'class' => 'app\backend\actions\JSSelectableTreeGetTree',
76
                'modelName' => 'app\modules\shop\models\Category',
77
                'label_attribute' => 'name',
78
                'vary_by_type_attribute' => null,
79
            ],
80
            'addImage' => [
81
                'class' => AddImageAction::className(),
82
            ],
83
            'upload' => [
84
                'class' => UploadAction::className(),
85
                'upload' => 'theme/resources/product-images',
86
            ],
87
            'remove' => [
88
                'class' => RemoveAction::className(),
89
                'uploadDir' => 'theme/resources/product-images',
90
            ],
91
            'save-info' => [
92
                'class' => SaveInfoAction::className(),
93
            ],
94
            'update-editable' => [
95
                'class' => UpdateEditable::className(),
96
                'modelName' => Product::className(),
97
                'allowedAttributes' => [
98 View Code Duplication
                    'currency_id' => function (Product $model, $attribute) {
0 ignored issues
show
Unused Code introduced by
The parameter $attribute is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
99
                        if ($model === null || $model->currency === null || $model->currency_id === 0) {
100
                            return null;
101
                        }
102
                        return \yii\helpers\Html::tag(
103
                            'div',
104
                            $model->currency->name,
105
                            ['class' => $model->currency->name]
106
                        );
107
                    },
108
                    'price',
109
                    'old_price',
110 View Code Duplication
                    'active' => function (Product $model) {
111
                        if ($model === null || $model->active === null) {
112
                            return null;
113
                        }
114
                        if ($model->active === 1) {
115
                            $label_class = 'label-success';
116
                            $value = 'Active';
117
                        } else {
118
                            $value = 'Inactive';
119
                            $label_class = 'label-default';
120
                        }
121
                        return \yii\helpers\Html::tag(
122
                            'span',
123
                            Yii::t('app', $value),
124
                            ['class' => "label $label_class"]
125
                        );
126
                    },
127
                ],
128
            ],
129
            'property-handler' => [
130
                'class' => PropertyHandler::className(),
131
                'modelName' => Product::className()
132
            ],
133
            'publish-switch' => [
134
                'class' => MassPublishAction::className(),
135
                'modelName' => Product::className(),
136
                'attribute' => 'active',
137
            ],
138
            'categoryMovements' => [
139
                'class' => CategoryMovementsAction::className(),
140
            ]
141
        ];
142
    }
143
144
    /**
145
     * @return string
146
     * @throws ServerErrorHttpException
147
     */
148
    public function actionIndex()
149
    {
150
        $searchModel = new Product();
151
        $params = Yii::$app->request->get();
152
        /** @var ActiveDataProvider $dataProvider */
153
        $dataProvider = $searchModel->search($params);
154
        if (null !== $catId = Yii::$app->request->get('parent_id')) {
155
            $dataProvider->query->leftJoin(
156
                Object::getForClass(Product::className())->categories_table_name . ' cp',
157
                'cp.object_model_id=product.id'
158
            )->andWhere('product.parent_id=0 AND cp.category_id=:cur', [':cur' => $catId]);
159
        }
160
        return $this->render(
161
            'index',
162
            [
163
                'dataProvider' => $dataProvider,
164
                'searchModel' => $searchModel,
165
            ]
166
        );
167
    }
168
169
    /**
170
     * @param null $id
171
     * @return string|\yii\web\Response
172
     * @throws NotFoundHttpException
173
     * @throws ServerErrorHttpException
174
     * @throws \Exception
175
     * @throws \yii\base\InvalidRouteException
176
     */
177
    public function actionEdit($id = null)
178
    {
179
        /*
180
         * @todo Продумать механизм сохранения изображений для нового продукта.
0 ignored issues
show
Coding Style Best Practice introduced by
Comments for TODO tasks are often forgotten in the code; it might be better to use a dedicated issue tracker.
Loading history...
181
         * Сейчас для нового продукта скрывается форма добавления изображений.
182
         */
183
        if (null === $object = Object::getForClass(Product::className())) {
184
            throw new ServerErrorHttpException;
185
        }
186
187
        /** @var null|Product|HasProperties|\devgroup\TagDependencyHelper\ActiveRecordHelper $model */
188
        $model = null;
189
        $parent = null;
190
        if (null === $id) {
191
            $model = new Product();
192
            $model->loadDefaultValues();
193
            $model->currency_id = Currency::getMainCurrency()->id;
194
            $parent_id = Yii::$app->request->get('owner_id', 0);
195 View Code Duplication
            if (0 !== intval($parent_id) && null !== Product::findById($parent_id)) {
196
                $model->parent_id = $parent_id;
197
            }
198
            $model->measure_id = $this->module->defaultMeasureId;
199
        } else {
200
            $model = Product::findById($id, null);
201 View Code Duplication
            if ((null !== $model) && ($model->parent_id > 0)) {
202
                $parent = Product::findById($model->parent_id, null);
203
            }
204
        }
205
206
        if (null === $model) {
207
            throw new NotFoundHttpException();
208
        }
209
210
        $model->loadRelatedProductsArray();
211
212
        $event = new BackendEntityEditEvent($model);
213
        $this->trigger(self::EVENT_BACKEND_PRODUCT_EDIT, $event);
214
215
        $post = \Yii::$app->request->post();
216
217
        if ($event->isValid && $model->load($post)) {
218
            $saveStateEvent = new BackendEntityEditEvent($model);
219
            $this->trigger(self::EVENT_BACKEND_PRODUCT_EDIT_SAVE, $saveStateEvent);
220
221
            if ($model->validate()) {
222
                if (isset($post['GeneratePropertyValue'])) {
223
                    $generateValues = $post['GeneratePropertyValue'];
224
                } else {
225
                    $generateValues = [];
226
                }
227
                if (isset($post['PropertyGroup'])) {
228
                    $model->option_generate = Json::encode(
229
                        [
230
                            'group' => $post['PropertyGroup']['id'],
231
                            'values' => $generateValues
232
                        ]
233
                    );
234
                } else {
235
                    $model->option_generate = '';
236
                }
237
238
                $save_result = $model->save();
239
                $model->saveProperties($post);
240
                $model->saveRelatedProducts();
241
242 View Code Duplication
                if (null !== $view_object = ViewObject::getByModel($model, true)) {
243
                    if ($view_object->load($post, 'ViewObject')) {
244
                        if ($view_object->view_id <= 0) {
245
                            $view_object->delete();
246
                        } else {
247
                            $view_object->save();
248
                        }
249
                    }
250
                }
251
252
                if ($save_result) {
253
                    $modelAfterSaveEvent = new BackendEntityEditEvent($model);
254
                    $this->trigger(self::EVENT_BACKEND_PRODUCT_AFTER_SAVE, $modelAfterSaveEvent);
255
256
                    $categories = isset($post['Product']['categories']) ? $post['Product']['categories'] : [];
257
258
                    $model->saveCategoriesBindings($categories);
259
260
                    $this->runAction('save-info', ['model_id'=>$model->id]);
261
                    $model->invalidateTags();
262
263
264
                    $action = Yii::$app->request->post('action', 'save');
265
                    if (Yii::$app->request->post(HasProperties::FIELD_ADD_PROPERTY_GROUP)
266
                        || Yii::$app->request->post(HasProperties::FIELD_REMOVE_PROPERTY_GROUP)) {
267
                        $action = 'save';
268
                    }
269
                    $returnUrl = Yii::$app->request->get('returnUrl', ['index']);
270
                    switch ($action) {
271
                        case 'next':
272
                            return $this->redirect(
273
                                [
274
                                    'edit',
275
                                    'returnUrl' => $returnUrl,
276
                                    'parent_id' => Yii::$app->request->get('parent_id', null)
277
                                ]
278
                            );
279
                        case 'back':
280
                            return $this->redirect($returnUrl);
281
                        default:
282
                            return $this->redirect(
283
                                Url::toRoute([
284
                                    'edit',
285
                                    'id' => $model->id,
286
                                    'returnUrl' => $returnUrl,
287
                                    'parent_id' => $model->main_category_id
288
                                ])
289
                            );
290
                    }
291
                } else {
292
                    Yii::$app->session->setFlash('error', Yii::t('app', 'Cannot save data'));
293
                }
294
            } else {
295
                Yii::$app->session->setFlash('error', Yii::t('app', 'Cannot save data'));
296
            }
297
        }
298
299
        $items = ArrayHelper::map(
300
            Category::find()->all(),
301
            'id',
302
            'name'
303
        );
304
305
306
        return $this->render(
307
            'product-form',
308
            [
309
                'object' => $object,
310
                'model' => $model,
311
                'items' => $items,
312
                'selected' => $model->getCategoryIds(),
313
                'parent' => $parent,
314
            ]
315
        );
316
    }
317
318
    /**
319
     * @param $id
320
     * @throws NotFoundHttpException
321
     * @throws \yii\db\Exception
322
     */
323
    public function actionGenerate($id)
324
    {
325
        $post = \Yii::$app->request->post();
326
        if (!isset($post['GeneratePropertyValue'])) {
327
            throw new NotFoundHttpException();
328
        }
329
        $parent = Product::findById($id, null);
330
        if ($parent === null) {
331
            throw new NotFoundHttpException();
332
        }
333
334
        $object = Object::getForClass(Product::className());
335
        $catIds = (new Query())->select('category_id')->from([$object->categories_table_name])->where(
336
            'object_model_id = :id',
337
            [':id' => $id]
338
        )->orderBy(['sort_order' => SORT_ASC, 'id' => SORT_ASC])->column();
339
340
341
        if (isset($post['GeneratePropertyValue'])) {
342
            $generateValues = $post['GeneratePropertyValue'];
343
            $post[HasProperties::FIELD_ADD_PROPERTY_GROUP]['Product'] = $post['PropertyGroup']['id'];
344
        } else {
345
            $generateValues = [];
346
        }
347
        $parent->option_generate = Json::encode(
348
            [
349
                'group' => $post['PropertyGroup']['id'],
350
                'values' => $generateValues
351
            ]
352
        );
353
        $parent->save();
354
355
        $postProperty = [];
356
        foreach ($post['GeneratePropertyValue'] as $key_property => $values) {
357
            $inner = [];
358
            foreach ($values as $key_value => $trash) {
359
                $inner[] = [$key_property => $key_value];
360
            }
361
            $postProperty[] = $inner;
362
        }
363
364
        $optionProperty = self::generateOptions($postProperty);
365
366
        foreach ($optionProperty as $option) {
367
            /** @var Product|HasProperties $model */
368
            $model = new Product;
369
            $model->load($post);
370
371
            $model->parent_id = $parent->id;
372
            $nameAppend = [];
373
            $slugAppend = [];
374
            $tempPost = [];
375
376
            // @todo something
0 ignored issues
show
Coding Style Best Practice introduced by
Comments for TODO tasks are often forgotten in the code; it might be better to use a dedicated issue tracker.
Loading history...
377
            foreach ($option as $optionValue) {
378
                $valueModels = [];
379
                foreach ($optionValue as $propertyKey => $propertyValue) {
380
                    if (false === in_array($propertyKey, $valueModels)) {
381
                        /** @var  $propertyStaticValues  PropertyStaticValues */
382
                        $propertyStaticValues = PropertyStaticValues::findOne($propertyValue);
383
                        $key = $propertyStaticValues->property->key;
384
                        $tempPost[$key] = $propertyValue;
385
                        $valueModels[] = $propertyKey;
386
                        $nameAppend[] = $propertyStaticValues->name;
387
                        $slugAppend[] = $propertyStaticValues->id;
388
                    }
389
                }
390
            }
391
            $model->measure_id = $parent->measure_id;
392
            $model->name = $parent->name . ' (' . implode(', ', $nameAppend) . ')';
393
            $model->slug = $parent->slug . '-' . implode('-', $slugAppend);
394
            $save_model = $model->save();
395
            if ($save_model) {
396
                $groups = [
397
                    [$parent->object->id, $model->id, $post['PropertyGroup']['id']]
398
                ];
399
                foreach (array_keys($parent->propertyGroups) as $key) {
400
                    if ($key === $post['PropertyGroup']['id']) {
401
                        continue;
402
                    }
403
                    $groups[] = [$parent->object->id, $model->id, $key];
404
                }
405
                Yii::$app->db->createCommand()->batchInsert(
406
                    ObjectPropertyGroup::tableName(),
407
                    ['object_id', 'object_model_id', 'property_group_id'],
408
                    $groups
409
                )->execute();
410
                $newValues = array_merge($parent->abstractModel->attributes, $tempPost);
411
                $model->saveProperties([
412
                    'Properties_Product_' . $model->id => $newValues,
413
                ]);
414
                $add = [];
415
                foreach ($catIds as $value) {
416
                    $add[] = [
417
                        $value,
418
                        $model->id
419
                    ];
420
                }
421 View Code Duplication
                if (!empty($add)) {
422
                    Yii::$app->db->createCommand()->batchInsert(
423
                        $object->categories_table_name,
424
                        ['category_id', 'object_model_id'],
425
                        $add
426
                    )->execute();
427
                }
428
429
                $params = $parent->images;
430 View Code Duplication
                if (!empty($params)) {
431
                    $rows = [];
432
                    foreach ($params as $param) {
433
                        $rows[] = [
434
                            $param['object_id'],
435
                            $model->id,
436
                            $param['filename'],
437
                            $param['image_title'],
438
                            $param['image_alt'],
439
                            $param['sort_order'],
440
                        ];
441
                    }
442
443
                    Yii::$app->db->createCommand()->batchInsert(
444
                        Image::tableName(),
445
                        [
446
                            'object_id',
447
                            'object_model_id',
448
                            'filename',
449
                            'image_title',
450
                            'image_alt',
451
                            'sort_order',
452
                        ],
453
                        $rows
454
                    )->execute();
455
456
                }
457
            }
458
        }
459
    }
460
461
    /**
462
     * Clone product action.
463
     * @param integer $id
464
     * @throws \yii\web\NotFoundHttpException
465
     */
466
    public function actionClone($id, $returnUrl = ['index'])
467
    {
468
        /** @var Product|HasProperties $model */
469
        $model = Product::findOne($id);
470
        if ($model === null) {
471
            throw new NotFoundHttpException;
472
        }
473
474
        /** @var Product|HasProperties $newModel */
475
        $newModel = new Product;
476
        $newModel->setAttributes($model->attributes, false);
477
        $time = time();
478
        $newModel->name .= ' (copy ' . date('Y-m-d h:i:s', $time) . ')';
479
        $newModel->slug .= '-copy-' . date('Ymdhis', $time);
480
        $newModel->id = null;
481 View Code Duplication
        if ($newModel->validate() === false) {
482
            $newModel->slug = substr(uniqid() . "-" . $model->slug, 0, 80);
483
        }
484
        if ($newModel->save()) {
485
            $object = Object::getForClass(get_class($newModel));
486
            // save categories
487
            $categoriesTableName = Object::getForClass(Product::className())->categories_table_name;
488
            $query = new Query();
489
            $params = $query->select(['category_id', 'sort_order'])->from($categoriesTableName)->where(
490
                ['object_model_id' => $model->id]
491
            )->all();
492
            if (!empty($params)) {
493
                $rows = [];
494
                foreach ($params as $param) {
495
                    $rows[] = [
496
                        $param['category_id'],
497
                        $newModel->id,
498
                        $param['sort_order'],
499
                    ];
500
                }
501
                Yii::$app->db->createCommand()->batchInsert(
502
                    $categoriesTableName,
503
                    [
504
                        'category_id',
505
                        'object_model_id',
506
                        'sort_order'
507
                    ],
508
                    $rows
509
                )->execute();
510
            }
511
512
            // save images bindings
513
            $params = $query->select(
514
                ['object_id', 'filename', 'image_title', 'image_alt', 'sort_order']
515
            )->from(Image::tableName())->where(
516
                [
517
                    'object_id' => $object->id,
518
                    'object_model_id' => $model->id
519
                ]
520
            )->all();
521 View Code Duplication
            if (!empty($params)) {
522
                $rows = [];
523
                foreach ($params as $param) {
524
                    $rows[] = [
525
                        $param['object_id'],
526
                        $newModel->id,
527
                        $param['filename'],
528
                        $param['image_title'],
529
                        $param['image_alt'],
530
                        $param['sort_order'],
531
                    ];
532
                }
533
                Yii::$app->db->createCommand()->batchInsert(
534
                    Image::tableName(),
535
                    [
536
                        'object_id',
537
                        'object_model_id',
538
                        'filename',
539
                        'image_title',
540
                        'image_alt',
541
                        'sort_order',
542
                    ],
543
                    $rows
544
                )->execute();
545
            }
546
            $newModelProps = [];
547 View Code Duplication
            foreach (array_keys($model->propertyGroups) as $key) {
548
                $opg = new ObjectPropertyGroup();
549
                $opg->attributes = [
550
                    'object_id' => $object->id,
551
                    'object_model_id' => $newModel->id,
552
                    'property_group_id' => $key,
553
                ];
554
                $opg->save();
555
                $props = Property::getForGroupId($key);
556
                foreach ($props as $prop) {
0 ignored issues
show
Bug introduced by
The expression $props of type null|array<integer,object<app\models\Property>> is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
557
                    $propValues = $model->getPropertyValuesByPropertyId($prop->id);
558
                    if ($propValues !== null) {
559
                        foreach ($propValues->values as $val) {
560
                            $valueToSave = ArrayHelper::getValue($val, 'psv_id', $val['value']);
561
                            $newModelProps[$prop->key][] = $valueToSave;
562
                        }
563
                    }
564
                }
565
            }
566
            $newModel->saveProperties(
567
                [
568
                    'Properties_Product_' . $newModel->id => $newModelProps,
569
                ]
570
            );
571
572
            // addons cloning
573
            foreach ($model->bindedAddons as $index => $addon) {
574
                $newModel->link(
575
                    'bindedAddons',
576
                    $addon,
577
                    [
578
                        'sort_order'=>$index,
579
                        'appliance_object_id' => $object->id,
580
                    ]
581
                );
582
            }
583
584
            Yii::$app->session->setFlash('success', Yii::t('app', 'Product has been cloned successfully.'));
585
            $this->redirect(['edit', 'id' => $newModel->id, 'returnUrl' => $returnUrl]);
586
        }
587
    }
588
589
    /**
590
     * @param $id
591
     * @return \yii\web\Response
592
     * @throws NotFoundHttpException
593
     * @throws \Exception
594
     */
595
    public function actionDelete($id)
596
    {
597
        /** @var Product $model */
598
        if (null === $model = Product::findOne($id)) {
599
            throw new NotFoundHttpException;
600
        }
601
602
        if (Yii::$app->request->get('returnUrl') !== null) {
603
            $redirect = Yii::$app->request->get('returnUrl');
604
        } elseif ($model->parent_id == 0) {
605
            $redirect = Url::toRoute(['index']);
606
        } else {
607
            $redirect = Url::toRoute(['edit', 'id' => $model->parent_id]);
608
        }
609
610
        if (!$model->delete()) {
611
            Yii::$app->session->setFlash('info', Yii::t('app', 'The object is placed in the cart'));
612
        } else {
613
            Yii::$app->session->setFlash('info', Yii::t('app', 'Object has been removed'));
614
        }
615
616
        return $this->redirect($redirect);
617
    }
618
619
    /**
620
     * @param $parent_id
621
     * @return \yii\web\Response
622
     * @throws \Exception
623
     */
624
    public function actionRemoveAll($parent_id)
625
    {
626
        $items = Yii::$app->request->post('items', []);
627
        if (!empty($items)) {
628
            $items = Product::find()->where(['in', 'id', $items])->all();
629
            foreach ($items as $item) {
630
                $item->delete();
631
            }
632
        }
633
634
        return $this->redirect(['index', 'parent_id' => $parent_id]);
635
    }
636
637
    /**
638
     * @param $tableName
639
     * @param $ids
640
     * @param string $field
641
     * @return bool
642
     * @throws \yii\db\Exception
643
     */
644 View Code Duplication
    public static function sortModels($tableName, $ids, $field = 'sort_order')
645
    {
646
        $priorities = [];
647
        $start = 0;
648
        $ids_sorted = $ids;
649
        sort($ids_sorted);
650
        foreach ($ids as $id) {
651
            $priorities[$id] = $ids_sorted[$start++];
652
        }
653
        $sql = "UPDATE " . $tableName . " SET $field = " . self::generateCase($priorities) . " WHERE id IN(" . implode(
654
                ', ',
655
                $ids
656
            ) . ")";
657
658
        return Yii::$app->db->createCommand(
659
            $sql
660
        )->execute() > 0;
661
662
    }
663
664
    /**
665
     * Рекурсивный генератор свойств для создания комплектаций.
666
     * @param array $array Трехмерный массив вида:
667
     * [[['{property1}' => '{value1}']], [['{property1}' => '{value2}']], [['{property2}' => '{value1}']], [['{property2}' => '{value1}']]]
0 ignored issues
show
Coding Style introduced by
This line exceeds maximum limit of 120 characters; contains 139 characters

Overly long lines are hard to read on any screen. Most code styles therefor impose a maximum limit on the number of characters in a line.

Loading history...
668
     * @param array $result Используется для передачи результатов внутри рекурсии
669
     * @param integer $count Счетчик внутри рекурсии
670
     * @return array
671
     */
672
    public static function generateOptions($array, $result = [], $count = 0)
673
    {
674
        if (empty($result)) {
675
            foreach ($array[$count] as $value) {
676
                $result[] = [$value];
677
            }
678
            $count++;
679
            $arResult = self::generateOptions($array, $result, $count);
680
        } else {
681
            if (isset($array[$count])) {
682
                $nextResult = [];
683
                foreach ($array[$count] as $value) {
684
                    foreach ($result as $resValue) {
685
                        $nextResult[] = array_merge($resValue, [$value]);
686
                    }
687
                }
688
                $count++;
689
                $arResult = self::generateOptions($array, $nextResult, $count);
690
            } else {
691
                return $result;
692
            }
693
        }
694
        return $arResult;
695
    }
696
697
    /**
698
     * @param $priorities
699
     * @return string
700
     */
701 View Code Duplication
    private static function generateCase($priorities)
702
    {
703
        $result = 'CASE `id`';
704
        foreach ($priorities as $k => $v) {
705
            $result .= ' when "' . $k . '" then "' . $v . '"';
706
        }
707
        return $result . ' END';
708
    }
709
710
    /**
711
     * @return array
0 ignored issues
show
Documentation introduced by
Consider making the return type a bit more specific; maybe use array<string,false|array>.

This check looks for the generic type array as a return type and suggests a more specific type. This type is inferred from the actual code.

Loading history...
712
     */
713
    public function actionAjaxRelatedProduct()
714
    {
715
        Yii::$app->response->format = \yii\web\Response::FORMAT_JSON;
716
717
        $result = [
718
            'more' => false,
719
            'results' => []
720
        ];
721
        $search = Yii::$app->request->get('search');
722
        if (!empty($search['term'])) {
723
            $query = new \yii\db\Query();
724
            $query->select('id, name AS text')->from(Product::tableName())->andWhere(
725
                ['like', 'name', $search['term']]
726
            )->andWhere(['active' => 1])->orderBy(['sort_order' => SORT_ASC, 'name' => SORT_ASC]);
727
            $command = $query->createCommand();
728
            $data = $command->queryAll();
729
730
            $result['results'] = array_values($data);
731
        }
732
733
        return $result;
734
    }
735
}