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 ( 47a99e...7cf3a1 )
by Ivan
17:29 queued 07:43
created

Category::afterSave()   B

Complexity

Conditions 5
Paths 6

Size

Total Lines 20
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 1 Features 0
Metric Value
dl 0
loc 20
rs 8.8571
c 2
b 1
f 0
cc 5
eloc 11
nc 6
nop 2
1
<?php
2
3
namespace app\modules\shop\models;
4
5
use app\behaviors\CleanRelations;
6
use app\behaviors\Tree;
7
use app\components\Helper;
8
use app\models\Object;
9
use app\modules\shop\models\FilterSets;
10
use app\properties\HasProperties;
11
use app\traits\GetImages;
12
use devgroup\TagDependencyHelper\ActiveRecordHelper;
13
use Yii;
14
use yii\behaviors\TimestampBehavior;
15
use yii\caching\TagDependency;
16
use yii\data\ActiveDataProvider;
17
use yii\db\ActiveRecord;
18
use yii\db\Expression;
19
use yii\helpers\ArrayHelper;
20
use yii\helpers\Url;
21
22
/**
23
 * This is the model class for table "category".
24
 *
25
 * @property integer $id
26
 * @property integer $category_group_id
27
 * @property integer $parent_id
28
 * @property string $name
29
 * @property string $title
30
 * @property string $h1
31
 * @property string $meta_description
32
 * @property string $breadcrumbs_label
33
 * @property string $slug
34
 * @property string $slug_compiled
35
 * @property integer $slug_absolute
36
 * @property string $content
37
 * @property string $announce
38
 * @property integer $sort_order
39
 * @property boolean $active
40
 * @property string $date_added
41
 * @property string $date_modified
42
 * @property Category[] $children
43
 * @property Category $parent
44
 */
45
class Category extends ActiveRecord implements \JsonSerializable
46
{
47
    use GetImages;
48
49
    const DELETE_MODE_SINGLE_CATEGORY = 1;
50
    const DELETE_MODE_ALL = 2;
51
    const DELETE_MODE_MAIN_CATEGORY = 3;
52
    const CATEGORY_PARENT = 0;
53
    const CATEGORY_ACTIVE = 1;
54
    const CATEGORY_INACTIVE = 0;
55
56
    /**
57
     * Category identity map
58
     * [
59
     *      'category_id' => $category_model_instance,
60
     * ]
61
     *
62
     * Used by findById
63
     * @var array
64
     */
65
    public static $identity_map = [];
66
67
    /**
68
     * Special caching for findBySlug
69
     * Stores category->id for pair slug:category_group_id:parent_id
70
     * @var array
71
     */
72
    private static $id_by_slug_group_parent = [];
73
    private static $id_by_name_group_parent = [];
74
75
    public $deleteMode = 1;
76
77
    /**
78
     * @var null|string Url path caching variable
79
     */
80
    private $urlPath = null;
81
82
    /** @var null|array Array of parent categories ids including root category */
83
    private $parentIds = null;
84
85
    /** @var FilterSets[] */
86
    private $filterSets = null;
87
88
    public function behaviors()
89
    {
90
        return [
91
            [
92
                'class' => HasProperties::className(),
93
            ],
94
            [
95
                'class' => \devgroup\TagDependencyHelper\ActiveRecordHelper::className(),
96
            ],
97
            [
98
                'class' => CleanRelations::className(),
99
            ],
100
            [
101
                'class' => Tree::className(),
102
                'activeAttribute' => 'active',
103
                'sortOrder' => [
104
                    'sort_order' => SORT_ASC,
105
                    'id' => SORT_ASC
106
                ],
107
            ],
108
            [
109
                'class' => TimestampBehavior::className(),
110
                'createdAtAttribute' => 'date_added',
111
                'updatedAtAttribute' => 'date_modified',
112
                'value' => new Expression('NOW()'),
113
                'attributes' => [
114
                    ActiveRecord::EVENT_BEFORE_INSERT => ['date_added'],
115
                    ActiveRecord::EVENT_BEFORE_UPDATE => ['date_modified'],
116
                ],
117
            ],
118
        ];
119
    }
120
121
    /**
122
     * Return delete modes list
123
     * @return array
124
     */
125 View Code Duplication
    public static function deleteModesList()
126
    {
127
        return [
128
            self::DELETE_MODE_SINGLE_CATEGORY => Yii::t('app', 'Delete only that products that exists ONLY in that category'),
0 ignored issues
show
Coding Style introduced by
This line exceeds maximum limit of 120 characters; contains 126 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...
129
            self::DELETE_MODE_ALL => Yii::t('app', 'Delete along with it no matter what'),
130
            self::DELETE_MODE_MAIN_CATEGORY => Yii::t('app', 'Delete all products that relate to this category as main'),
0 ignored issues
show
Coding Style introduced by
This line exceeds maximum limit of 120 characters; contains 121 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...
131
        ];
132
    }
133
134
    /**
135
     * @inheritdoc
136
     */
137
    public static function tableName()
138
    {
139
        return '{{%category}}';
140
    }
141
142
    /**
143
     * @inheritdoc
144
     */
145 View Code Duplication
    public function rules()
146
    {
147
        return [
148
            [['category_group_id', 'parent_id', 'name', 'slug'], 'required'],
149
            [['category_group_id', 'parent_id', 'slug_absolute', 'sort_order', 'active'], 'integer'],
150
            [['name', 'title', 'h1', 'meta_description', 'breadcrumbs_label', 'content', 'announce'], 'string'],
151
            [['slug'], 'string', 'max' => 80],
152
            [['slug_compiled'], 'string', 'max' => 180],
153
            [['title_append'], 'string'],
154
            [['active'], 'default', 'value' => 1],
155
            [['date_added', 'date_modified'], 'safe'],
156
            ['sort_order', 'default', 'value' => 0],
157
        ];
158
    }
159
160
    /**
161
     * @inheritdoc
162
     */
163
    public function beforeValidate()
0 ignored issues
show
Documentation introduced by
The return type could not be reliably inferred; please add a @return annotation.

Our type inference engine in quite powerful, but sometimes the code does not provide enough clues to go by. In these cases we request you to add a @return annotation as described here.

Loading history...
164
    {
165
        if (empty($this->slug) && !empty($this->name)) {
166
            $this->slug = Helper::createSlug($this->name);
167
        }
168
        if (empty($this->title) && !empty($this->name)) {
169
            $this->title = $this->name;
170
        }
171
        if (empty($this->h1) && !empty($this->title)) {
172
            $this->h1 = $this->title;
173
        }
174
        if (empty($this->breadcrumbs_label) && !empty($this->name)) {
175
            $this->breadcrumbs_label = $this->name;
176
        }
177
        return parent::beforeValidate();
178
    }
179
180
    /**
181
     * @inheritdoc
182
     */
183
    public function attributeLabels()
184
    {
185
        return [
186
            'id' => Yii::t('app', 'ID'),
187
            'category_group_id' => Yii::t('app', 'Category Group ID'),
188
            'parent_id' => Yii::t('app', 'Parent ID'),
189
            'name' => Yii::t('app', 'Name'),
190
            'title' => Yii::t('app', 'Title'),
191
            'h1' => Yii::t('app', 'H1'),
192
            'meta_description' => Yii::t('app', 'Meta Description'),
193
            'breadcrumbs_label' => Yii::t('app', 'Breadcrumbs Label'),
194
            'slug' => Yii::t('app', 'Slug'),
195
            'slug_compiled' => Yii::t('app', 'Slug Compiled'),
196
            'slug_absolute' => Yii::t('app', 'Slug Absolute'),
197
            'content' => Yii::t('app', 'Content'),
198
            'announce' => Yii::t('app', 'Announce'),
199
            'sort_order' => Yii::t('app', 'Sort Order'),
200
            'active' => Yii::t('app', 'Active'),
201
            'title_append' => Yii::t('app', 'Title Append'),
202
            'date_added' => Yii::t('app', 'Date Added'),
203
            'date_modified' => Yii::t('app', 'Date Modified'),
204
        ];
205
    }
206
207
    /**
208
     * Search tasks
209
     * @param $params
210
     * @return ActiveDataProvider
211
     */
212
    public function search($params)
213
    {
214
        /* @var $query \yii\db\ActiveQuery */
215
        $query = self::find()->where(['parent_id' => $this->parent_id])->with('images');
216
        $dataProvider = new ActiveDataProvider(
217
            [
218
                'query' => $query,
219
                'pagination' => [
220
                    'pageSize' => 10,
221
                ],
222
            ]
223
        );
224
        if (!($this->load($params))) {
225
            return $dataProvider;
226
        }
227
        $query->andFilterWhere(['id' => $this->id]);
228
        $query->andFilterWhere(['like', 'name', $this->name]);
229
        $query->andFilterWhere(['like', 'slug', $this->slug]);
230
        $query->andFilterWhere(['like', 'slug_compiled', $this->slug_compiled]);
231
        $query->andFilterWhere(['like', 'slug_absolute', $this->slug_absolute]);
232
        $query->andFilterWhere(['like', 'title', $this->title]);
233
        $query->andFilterWhere(['like', 'h1', $this->h1]);
234
        $query->andFilterWhere(['like', 'meta_description', $this->meta_description]);
235
        $query->andFilterWhere(['like', 'breadcrumbs_label', $this->breadcrumbs_label]);
236
        $query->andFilterWhere(['active' => $this->active]);
237
        return $dataProvider;
238
    }
239
240
    /**
241
     * Returns model using indentity map and cache
242
     * @param int $id
243
     * @param int|null $isActive
0 ignored issues
show
Documentation introduced by
Consider making the type for parameter $isActive a bit more specific; maybe use integer.
Loading history...
244
     * @return Category|null
245
     */
246
    public static function findById($id, $isActive = 1)
247
    {
248
        if (!is_numeric($id)) {
249
            return null;
250
        }
251
        if (!isset(static::$identity_map[$id])) {
252
            $cacheKey = static::tableName() . ":$id:$isActive";
253
            if (false === $model = Yii::$app->cache->get($cacheKey)) {
254
                $model = static::find()->where(['id' => $id])->with('images');
255
                if (null !== $isActive) {
256
                    $model->andWhere(['active' => $isActive]);
257
                }
258
                if (null !== $model = $model->one()) {
259
                    Yii::$app->cache->set(
260
                        $cacheKey,
261
                        $model,
262
                        86400,
263
                        new TagDependency(
264
                            [
265
                                'tags' => [
266
                                    ActiveRecordHelper::getObjectTag($model, $model->id)
267
                                ]
268
                            ]
269
                        )
270
                    );
271
                }
272
            }
273
            static::$identity_map[$id] = $model;
274
        }
275
276
        return static::$identity_map[$id];
277
    }
278
279
    /**
280
     * Finds category by slug inside category_group_id
281
     * Uses cache and identity_map
282
     */
283
    public static function findBySlug($slug, $category_group_id, $parent_id = 0)
0 ignored issues
show
Documentation introduced by
The return type could not be reliably inferred; please add a @return annotation.

Our type inference engine in quite powerful, but sometimes the code does not provide enough clues to go by. In these cases we request you to add a @return annotation as described here.

Loading history...
284
    {
285
        $params = [
286
            'slug' => $slug,
287
            'category_group_id' => $category_group_id,
288
        ];
289
        if ($parent_id >= 0) {
290
            $params['parent_id'] = $parent_id;
291
        }
292
293
        $identity_key = $slug . ':' . $category_group_id . ':' . $parent_id;
294
        if (isset(static::$id_by_slug_group_parent[$identity_key]) === true) {
295
            return static::findById(static::$id_by_slug_group_parent[$identity_key], null);
296
        }
297
        $category = Yii::$app->cache->get("Category:bySlug:" . $identity_key);
298
        if ($category === false) {
299
            $category = Category::find()->where($params)->one();
0 ignored issues
show
Coding Style introduced by
As per coding style, self should be used for accessing local static members.

This check looks for accesses to local static members using the fully qualified name instead of self::.

<?php

class Certificate {
    const TRIPLEDES_CBC = 'ASDFGHJKL';

    private $key;

    public function __construct()
    {
        $this->key = Certificate::TRIPLEDES_CBC;
    }
}

While this is perfectly valid, the fully qualified name of Certificate::TRIPLEDES_CBC could just as well be replaced by self::TRIPLEDES_CBC. Referencing local members with self:: assured the access will still work when the class is renamed, makes it perfectly clear that the member is in fact local and will usually be shorter.

Loading history...
300
            if (is_object($category) === true) {
301
                static::$identity_map[$category->id] = $category;
302
                static::$id_by_slug_group_parent[$identity_key] = $category->id;
303
                Yii::$app->cache->set(
304
                    "Category:bySlug:" . $identity_key,
305
                    $category,
306
                    86400,
307
                    new TagDependency(
308
                        [
309
                            'tags' => ActiveRecordHelper::getObjectTag($category, $category->id)
310
                        ]
311
                    )
312
                );
313
                return $category;
314 View Code Duplication
            } else {
315
                Yii::$app->cache->set(
316
                    "Category:bySlug:" . $identity_key,
317
                    $category,
318
                    86400,
319
                    new TagDependency(
320
                        [
321
                            'tags' => ActiveRecordHelper::getCommonTag(Category::className())
0 ignored issues
show
Coding Style introduced by
As per coding style, self should be used for accessing local static members.

This check looks for accesses to local static members using the fully qualified name instead of self::.

<?php

class Certificate {
    const TRIPLEDES_CBC = 'ASDFGHJKL';

    private $key;

    public function __construct()
    {
        $this->key = Certificate::TRIPLEDES_CBC;
    }
}

While this is perfectly valid, the fully qualified name of Certificate::TRIPLEDES_CBC could just as well be replaced by self::TRIPLEDES_CBC. Referencing local members with self:: assured the access will still work when the class is renamed, makes it perfectly clear that the member is in fact local and will usually be shorter.

Loading history...
322
                        ]
323
                    )
324
                );
325
                return null;
326
            }
327
        } else {
328
            return $category;
329
        }
330
    }
331
332
    /**
333
     * Ищет по name в рамках category_group_id
334
     * Заносит в identity_map
335
     */
336
    public static function findByName($name, $category_group_id, $parent_id = 0)
337
    {
338
        $params = [
339
            'name' => $name,
340
            'category_group_id' => $category_group_id,
341
        ];
342
        if ($parent_id >= 0) {
343
            $params['parent_id'] = $parent_id;
344
        }
345
346
        $identity_key = $name . ':' . $category_group_id . ':' . $parent_id;
347
        if (isset(static::$id_by_name_group_parent[$identity_key])) {
348
            return static::findById(static::$id_by_name_group_parent[$identity_key], null);
349
        }
350
        $category = Yii::$app->cache->get("Category:byName:" . $identity_key);
351
        if (!is_object($category)) {
352
            $category = Category::find()->where($params)->one();
0 ignored issues
show
Coding Style introduced by
As per coding style, self should be used for accessing local static members.

This check looks for accesses to local static members using the fully qualified name instead of self::.

<?php

class Certificate {
    const TRIPLEDES_CBC = 'ASDFGHJKL';

    private $key;

    public function __construct()
    {
        $this->key = Certificate::TRIPLEDES_CBC;
    }
}

While this is perfectly valid, the fully qualified name of Certificate::TRIPLEDES_CBC could just as well be replaced by self::TRIPLEDES_CBC. Referencing local members with self:: assured the access will still work when the class is renamed, makes it perfectly clear that the member is in fact local and will usually be shorter.

Loading history...
353
            if (is_object($category)) {
354
                static::$identity_map[$category->id] = $category;
355
                static::$id_by_name_group_parent[$identity_key] = $category->id;
356
                Yii::$app->cache->set(
357
                    "Category:byName:" . $identity_key,
358
                    $category,
359
                    86400,
360
                    new TagDependency(
361
                        [
362
                            'tags' => ActiveRecordHelper::getObjectTag($category, $category->id)
363
                        ]
364
                    )
365
                );
366
                return $category;
367
            } else {
368
                return null;
369
            }
370
        } else {
371
            return $category;
372
        }
373
    }
374
375
    public function getUrlPath($include_parent_category = true)
376
    {
377
        if ($this->urlPath === null) {
378
            if ($this->parent_id == 0) {
379
                if ($include_parent_category) {
380
                    return $this->slug;
381
                } else {
382
                    return '';
383
                }
384
            }
385
            $slugs = [$this->slug];
386
387
            $this->parentIds = [];
388
389
            $parent_category = $this->parent_id > 0 ? $this->parent : 0;
390 View Code Duplication
            while ($parent_category !== null) {
391
                $this->parentIds[] = intval($parent_category->id);
392
                $slugs[] = $parent_category->slug;
393
                $parent_category = $parent_category->parent;
394
            }
395
            if ($include_parent_category === false) {
396
                array_pop($slugs);
397
            }
398
            $this->urlPath = implode("/", array_reverse($slugs));
399
        }
400
        return $this->urlPath;
401
    }
402
403
    /**
404
     * @return array Returns array of ids of parent categories(breadcrumbs ids)
405
     */
406
    public function getParentIds()
407
    {
408
        if ($this->parentIds === null) {
409
            $this->parentIds = [];
410
            $parent_category = $this->parent_id > 0 ? $this->parent : null;
411 View Code Duplication
            while ($parent_category !== null) {
412
                $this->parentIds[] = intval($parent_category->id);
413
                $parent_category = $parent_category->parent;
414
            }
415
        }
416
        return $this->parentIds;
417
    }
418
419
    /**
420
     * Ищет root для группы категорий
421
     * Использует identity_map
422
     * @return Category|null
423
     */
424
    public static function findRootForCategoryGroup($id = null)
425
    {
426
        if (null === $id) {
427
            return null;
428
        }
429
430
        return static::find()
431
            ->where([
432
                'category_group_id' => $id,
433
                'parent_id' => static::CATEGORY_PARENT,
434
                'active' => static::CATEGORY_ACTIVE,
435
            ])
436
            ->orderBy(['sort_order' => SORT_ASC, 'id' => SORT_ASC])
437
            ->one();
438
    }
439
440
    /**
441
     * @deprecated
442
     * @param $category_group_id
443
     * @param int $level
444
     * @param int $is_active
445
     * @return Category[]
446
     */
447
    public static function getByLevel($category_group_id, $level = 0, $is_active = 1)
448
    {
449
        $cacheKey = "CategoriesByLevel:$category_group_id:$level";
450
        if (false === $models = Yii::$app->cache->get($cacheKey)) {
451
            $models = Category::find()->where(
0 ignored issues
show
Coding Style introduced by
As per coding style, self should be used for accessing local static members.

This check looks for accesses to local static members using the fully qualified name instead of self::.

<?php

class Certificate {
    const TRIPLEDES_CBC = 'ASDFGHJKL';

    private $key;

    public function __construct()
    {
        $this->key = Certificate::TRIPLEDES_CBC;
    }
}

While this is perfectly valid, the fully qualified name of Certificate::TRIPLEDES_CBC could just as well be replaced by self::TRIPLEDES_CBC. Referencing local members with self:: assured the access will still work when the class is renamed, makes it perfectly clear that the member is in fact local and will usually be shorter.

Loading history...
452
                ['category_group_id' => $category_group_id, 'parent_id' => $level, 'active' => $is_active]
453
            )->orderBy('sort_order')->with('images')->all();
454
455
            if (null !== $models) {
456
457
                $cache_tags = [];
458
                foreach ($models as $model) {
459
                    $cache_tags [] = ActiveRecordHelper::getObjectTag($model, $model->id);
460
                }
461
                $cache_tags [] = ActiveRecordHelper::getObjectTag(static::className(), $level);
462
463
464
                Yii::$app->cache->set(
465
                    $cacheKey,
466
                    $models,
467
                    86400,
468
                    new TagDependency(
469
                        [
470
                            'tags' => $cache_tags
471
                        ]
472
                    )
473
                );
474
            }
475
        }
476
        foreach ($models as $model) {
477
            static::$identity_map[$model->id] = $model;
478
        }
479
        return $models;
480
    }
481
482
    /**
483
     * @param int $parentId
0 ignored issues
show
Documentation introduced by
Should the type for parameter $parentId not be integer|null?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
484
     * @param int|null $isActive
0 ignored issues
show
Documentation introduced by
Consider making the type for parameter $isActive a bit more specific; maybe use integer.
Loading history...
485
     * @return Category[]|array
486
     */
487
    public static function getByParentId($parentId = null, $isActive = 1)
488
    {
489
        if (null === $parentId) {
490
            return [];
491
        }
492
        $parentId = intval($parentId);
493
        $cacheKey = "CategoriesByParentId:$parentId" . ':' . (null === $isActive ? 'null' : $isActive);
494
        if (false !== $models = Yii::$app->cache->get($cacheKey)) {
495
            return $models;
496
        }
497
        $query = static::find()
498
            ->where(['parent_id' => $parentId]);
499
        if (null !== $isActive) {
500
            $query->andWhere(['active' => $isActive]);
501
        }
502
        $models = $query->orderBy(['sort_order' => SORT_ASC, 'id' => SORT_ASC])
503
            ->with('images')
504
            ->all();
505
506
        if (empty($models)) {
507
            return [];
508
        }
509
        Yii::$app->cache->set(
510
            $cacheKey,
511
            $models,
512
            0,
513
            new TagDependency([
514
                'tags' => array_reduce($models,
515
                    function ($result, $item)
516
                    {
517
                        /** @var Category $item */
518
                        $result[] = ActiveRecordHelper::getObjectTag(static::className(), $item->id);
519
                        return $result;
520
                    },
521
                    [ActiveRecordHelper::getObjectTag(static::className(), $parentId)]
522
                )
523
            ])
524
        );
525
        return $models;
526
    }
527
528
    public function afterSave($insert, $changedAttributes)
529
    {
530
        parent::afterSave($insert, $changedAttributes);
531
532
        static::$identity_map[$this->id] = $this;
533
534
        if (isset($changedAttributes['category_group_id'])) {
535
            foreach ($this->children as $child) {
536
                $child->category_group_id = $this->category_group_id;
537
                $child->save(true, ['category_group_id']);
538
            }
539
        }
540
541
        if (isset($changedAttributes['parent_id'])) {
542
            if (is_null($this->parent) != 0) {
543
                $this->category_group_id = $this->parent->category_group_id;
544
                $this->save(true, ['category_group_id']);
545
            }
546
        }
547
    }
548
549
    /**
550
     * Preparation to delete category.
551
     * Deleting related products and inserted categories.
552
     * @return bool
553
     */
554
    public function beforeDelete()
555
    {
556
        if (!parent::beforeDelete()) {
557
            return false;
558
        }
559
        $productObject = Object::getForClass(Product::className());
560
        switch ($this->deleteMode) {
561
            case self::DELETE_MODE_ALL:
562
                $products =
563
                    !is_null($productObject)
564
                        ? Product::find()
565
                        ->join(
566
                            'INNER JOIN',
567
                            $productObject->categories_table_name . ' pc',
568
                            'pc.object_model_id = product.id'
569
                        )
570
                        ->where('pc.category_id = :id', [':id' => $this->id])
571
                        ->all()
572
                        : [];
573
                break;
574
            case self::DELETE_MODE_MAIN_CATEGORY:
575
                $products = Product::findAll(['main_category_id' => $this->id]);
576
                break;
577
            default:
578
                $products =
579
                    !is_null($productObject)
580
                        ? Product::find()
581
                        ->join(
582
                            'INNER JOIN',
583
                            $productObject->categories_table_name . ' pc',
584
                            'pc.object_model_id = product.id'
585
                        )
586
                        ->join(
587
                            'INNER JOIN',
588
                            $productObject->categories_table_name . ' pc2',
589
                            'pc2.object_model_id = product.id'
590
                        )
591
                        ->where('pc.category_id = :id', [':id' => $this->id])
592
                        ->groupBy('pc2.object_model_id')
593
                        ->having('COUNT(*) = 1')
594
                        ->all()
595
                        : [];
596
                break;
597
        }
598
        foreach ($products as $product) {
599
            $product->delete();
600
        }
601
        foreach ($this->children as $child) {
602
            $child->deleteMode = $this->deleteMode;
603
            $child->delete();
604
        }
605
        if (!is_null($productObject)) {
606
            Yii::$app->db
607
                ->createCommand()
608
                ->delete($productObject->categories_table_name, ['category_id' => $this->id])
609
                ->execute();
610
        }
611
        return true;
612
    }
613
614
    public function afterDelete()
615
    {
616
        FilterSets::deleteAll(['category_id' => $this->id]);
617
        parent::afterDelete();
618
    }
619
620
621
    /**
622
     * Get children menu items with selected depth
623
     * @param int $parentId
624
     * @param null|integer $depth
625
     * @return array
626
     */
627
    public static function getMenuItems($parentId = 0, $depth = null, $fetchModels = false)
628
    {
629
        if ($depth === 0) {
630
            return [];
631
        }
632
        $cacheKey = 'CategoryMenuItems:' . implode(':', [
633
            $parentId,
634
            null === $depth ? 'null' : intval($depth),
635
            intval($fetchModels)
636
        ]) ;
637
        $items = Yii::$app->cache->get($cacheKey);
638
        if ($items !== false) {
639
            return $items;
640
        }
641
        $items = [];
642
        $categories = static::find()->select(['id', 'name', 'category_group_id'])->where(
643
            ['parent_id' => $parentId, 'active' => 1]
644
        )->orderBy(['sort_order' => SORT_ASC, 'id' => SORT_ASC])->with('images')->all();
645
        $cache_tags = [
646
            ActiveRecordHelper::getCommonTag(static::className()),
647
        ];
648
649
        /** @var Category $category */
650
        foreach ($categories as $category) {
651
            $items[] = [
652
                'label' => $category->name,
653
                'url' => Url::toRoute(
654
                    [
655
                        '@category',
656
                        'category_group_id' => $category->category_group_id,
657
                        'last_category_id' => $category->id,
658
                    ]
659
                ),
660
                'id' => $category->id,
661
                'model' => $fetchModels ? $category : null,
662
                'items' => static::getMenuItems($category->id, null === $depth ? null : $depth - 1),
663
            ];
664
            $cache_tags[] = ActiveRecordHelper::getObjectTag(static::className(), $category->id);
665
        }
666
        $cache_tags [] = ActiveRecordHelper::getObjectTag(static::className(), $parentId);
667
        Yii::$app->cache->set(
668
            $cacheKey,
669
            $items,
670
            86400,
671
            new TagDependency(
672
                [
673
                    'tags' => $cache_tags,
674
                ]
675
            )
676
        );
677
        return $items;
678
    }
679
680
    /**
681
     * @return FilterSets[]
682
     */
683
    public function filterSets()
684
    {
685
        if ($this->filterSets === null) {
686
            $this->filterSets = FilterSets::getForCategoryId($this->id);
687
        }
688
        return $this->filterSets;
689
    }
690
691
    /**
692
     * @param int $parentId
693
     * @param int|null $categoryGroupId
694
     * @param string $name
695
     * @param bool $dummyObject
696
     * @return Category|null
697
     */
698
    public static function createEmptyCategory($parentId = 0, $categoryGroupId = null, $name = 'Catalog', $dummyObject = false)
0 ignored issues
show
Coding Style introduced by
This line exceeds maximum limit of 120 characters; contains 127 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...
699
    {
700
        $categoryGroupId = null === $categoryGroupId ? CategoryGroup::getFirstModel()->id : intval($categoryGroupId);
701
702
        $model = new static();
703
        $model->loadDefaultValues();
704
        $model->parent_id = $parentId;
705
        $model->category_group_id = $categoryGroupId;
706
        $model->h1 = $model->title = $model->name = $name;
707
        $model->slug = Helper::createSlug($model->name);
708
709
        if (!$dummyObject) {
710
            if (!$model->save()) {
711
                return null;
712
            }
713
            $model->refresh();
714
        }
715
716
        return $model;
717
    }
718
719
    /**
720
     * @param int|Product|null $product
721
     * @param bool $asMainCategory
722
     * @return bool
723
     */
724
    public function linkProduct($product = null, $asMainCategory = false)
725
    {
726
        if ($product instanceof Product) {
727
            return $product->linkToCategory($this->id, $asMainCategory);
728
        } elseif (is_int($product) || is_string($product)) {
729
            $product = intval($product);
730
            if (null !== $product = Product::findById($product, null)) {
731
                return $product->linkToCategory($this->id, $asMainCategory);
732
            }
733
        }
734
735
        return false;
736
    }
737
738
    /**
739
     * @return string
740
     */
741
    public function __toString()
742
    {
743
        return ($this->className() . ':' . $this->id);
744
    }
745
746
    /**
747
     * @return string
748
     */
749
    public function jsonSerialize()
750
    {
751
        return ($this->className() . ':' . $this->id);
752
    }
753
}
754