Completed
Push — master ( f51d1b...6ae4f1 )
by Scott
02:40
created

Category::afterSave()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 4
rs 10
cc 1
eloc 2
nc 1
nop 0
1
<?php namespace Bedard\Shop\Models;
2
3
use Bedard\Shop\Models\Product;
4
use Lang;
5
use Model;
6
7
/**
8
 * Category Model.
9
 */
10
class Category extends Model
11
{
12
    use \October\Rain\Database\Traits\Validation;
13
14
    /**
15
     * @var string The database table used by the model.
16
     */
17
    public $table = 'bedard_shop_categories';
18
19
    /**
20
     * @var array Default attributes
21
     */
22
    public $attributes = [
23
        'description_html' => '',
24
        'description_plain' => '',
25
    ];
26
27
    /**
28
     * @var array Attribute casting
29
     */
30
    protected $casts = [
31
        'is_active' => 'boolean',
32
        'is_visible' => 'boolean',
33
    ];
34
35
    /**
36
     * @var array Guarded fields
37
     */
38
    protected $guarded = ['*'];
39
40
    /**
41
     * @var array Fillable fields
42
     */
43
    protected $fillable = [
44
        'is_active',
45
        'is_visible',
46
        'description_html',
47
        'description_plain',
48
        'name',
49
        'parent_id',
50
        'slug',
51
    ];
52
53
    /**
54
     * @var array Relations
55
     */
56
    public $belongsTo = [
57
        'parent' => 'Bedard\Shop\Models\Category',
58
    ];
59
60
    public $belongsToMany = [
61
        'products' => [
62
            'Bedard\Shop\Models\Product',
63
            'table' => 'bedard_shop_category_product',
64
            'pivot' => ['is_inherited'],
65
        ],
66
    ];
67
68
    /**
69
     * @var array Validation
70
     */
71
    public $rules = [
72
        'name' => 'required',
73
        'slug' => 'required|unique:bedard_shop_categories',
74
    ];
75
76
    /**
77
     * After save
78
     *
79
     * @return void
80
     */
81
    public function afterSave()
82
    {
83
        $this->syncInheritedProducts();
84
    }
85
86
    /**
87
     * Before save.
88
     *
89
     * @return void
90
     */
91
    public function beforeSave()
92
    {
93
        $this->setPlainDescription();
94
        $this->setNullParentId();
95
    }
96
97
    /**
98
     * Find the child ids of a parent category.
99
     *
100
     * @param  \Bedard\Shop\Models\Category|int     $parent
101
     * @param  \October\Rain\Database\Collection    $categories
102
     * @return array
103
     */
104
    public static function getChildIds($parent, \October\Rain\Database\Collection $categories = null)
105
    {
106
        if ($categories === null) {
107
            $categories = self::whereNotNull('parent_id')
108
                ->where('id', '<>', $parent)
109
                ->select('id', 'parent_id')
110
                ->get();
111
        }
112
113
        $children = [];
114
        foreach ($categories as $category) {
115
            if ($category->parent_id == $parent) {
116
                $children[] = $category->id;
117
                $children = array_merge($children, self::getChildIds($category->id, $categories));
118
            }
119
        }
120
121
        return $children;
122
    }
123
124
    public static function getParentIds($children, \October\Rain\Database\Collection $categories = null)
125
    {
126
        if (! is_array($children)) {
127
            $children = [$children];
128
        }
129
130
        if ($categories === null) {
131
            $categories = self::select('id', 'parent_id')->get();
132
        }
133
134
        $parents = [];
135
        foreach ($children as $child) {
136
            $category = $categories->filter(function ($model) use ($child) {
137
                return $model->id == $child;
138
            })->first();
139
140
            while ($category && $category->parent_id) {
141
                $parents[] = $category->parent_id;
142
                $category = $categories->filter(function ($model) use ($category) {
143
                    return $model->id == $category->parent_id;
144
                })->first();
145
            }
146
        }
147
148
        return array_unique($parents);
149
    }
150
151
    /**
152
     * Get options for the parent form field.
153
     *
154
     * @return array
155
     */
156
    public function getParentIdOptions()
157
    {
158
        $options = $this->exists
159
            ? self::where('id', '<>', $this->id)->isNotChildOf($this->id)->orderBy('name')->lists('name', 'id')
160
            : self::orderBy('name')->lists('name', 'id');
161
162
        array_unshift($options, '<em>'.Lang::get('bedard.shop::lang.categories.form.no_parent').'</em>');
163
164
        return $options;
165
    }
166
167
    /**
168
     * Query categories that are children of another category.
169
     *
170
     * @param  \October\Rain\Database\Builder   $query
171
     * @param  \Bedard\Shop\Models\Category|int $parent
172
     * @return \October\Rain\Database\Builder
173
     */
174
    public function scopeIsChildOf($query, $parent)
175
    {
176
        return $query->whereIn('id', self::getChildIds($parent));
177
    }
178
179
    /**
180
     * Query categories that are not children of another category.
181
     *
182
     * @param  \October\Rain\Database\Builder   $query
183
     * @param  \Bedard\Shop\Models\Category|int $parent
184
     * @return \October\Rain\Database\Builder
185
     */
186
    public function scopeIsNotChildOf($query, $parent)
187
    {
188
        return $query->whereNotIn('id', self::getChildIds($parent));
189
    }
190
191
    /**
192
     * Query categories that are a parent of another category.
193
     *
194
     * @param  \October\Rain\Database\Builder   $query
195
     * @param  int                              $child
196
     * @return \October\Rain\Database\Builder
197
     */
198
    public function scopeIsParentOf($query, $child)
199
    {
200
        return $query->whereIn('id', self::getParentIds($child));
201
    }
202
203
    /**
204
     * Query categories that are not a parent of another category.
205
     *
206
     * @param  \October\Rain\Database\Builder   $query
207
     * @param  int                              $child
208
     * @return \October\Rain\Database\Builder
209
     */
210
    public function scopeIsNotParentOf($query, $child)
211
    {
212
        return $query->whereNotIn('id', self::getParentIds($child));
213
    }
214
215
    /**
216
     * Convert falsey parent id values to null.
217
     *
218
     * @return void
219
     */
220
    public function setNullParentId()
221
    {
222
        if (! $this->parent_id) {
223
            $this->parent_id = null;
224
        }
225
    }
226
227
    /**
228
     * Set the plain text description_html.
229
     *
230
     * @return void
231
     */
232
    public function setPlainDescription()
233
    {
234
        $this->description_plain = strip_tags($this->description_html);
235
    }
236
237
    /**
238
     * If the parent id has changed, resync all products
239
     *
240
     * @return void
241
     */
242
    public function syncInheritedProducts()
243
    {
244
        if ($this->isDirty('parent_id')) {
245
            Product::syncAllInheritedCategories();
246
        }
247
    }
248
249
    /**
250
     * Itterate over categories and update them with the given values.
251
     *
252
     * @param  array    $categories
253
     * @return void
254
     */
255
    public static function updateMany(array $categories)
256
    {
257
        foreach ($categories as $category) {
258
            $id = $category['id'];
259
            unset($category['id']);
260
            self::whereId($id)->update($category);
261
        }
262
    }
263
}
264