Completed
Pull Request — master (#1)
by ARCANEDEV
03:41
created

Item::toJson()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 4
c 0
b 0
f 0
ccs 2
cts 2
cp 1
rs 10
cc 1
eloc 2
nc 1
nop 1
crap 1
1
<?php namespace Arcanesoft\Sidebar\Entities;
2
3
use Arcanesoft\Contracts\Auth\Models\User;
4
use Illuminate\Contracts\Support\Arrayable;
5
use Illuminate\Support\Arr;
6
use Illuminate\Support\Fluent;
7
8
/**
9
 * Class     Item
10
 *
11
 * @package  Arcanesoft\Sidebar\Entitites
12
 * @author   ARCANEDEV <[email protected]>
13
 */
14
class Item extends Fluent
15
{
16
    /* -----------------------------------------------------------------
17
     |  Constructor
18
     | -----------------------------------------------------------------
19
     */
20
21
    /**
22
     * Item constructor.
23
     *
24
     * @param  array  $attributes
25
     */
26 28
    public function __construct(array $attributes = [])
27
    {
28 28
        $keys = ['name', 'title', 'url', 'icon'];
29
30 28
        parent::__construct(Arr::only($attributes, $keys) + [
31 28
            'extra' => Arr::except($attributes, $keys)
32
        ]);
33
34 28
        $this->attributes['active']   = false;
35 28
        $this->attributes['children'] = new ItemCollection;
36 28
        $this->setRoles([])->setPermissions([]);
37 28
    }
38
39
    /* -----------------------------------------------------------------
40
     |  Getters & Setters
41
     | -----------------------------------------------------------------
42
     */
43
44
    /**
45
     * Get the item name.
46
     *
47
     * @return string
48
     */
49 10
    public function name()
50
    {
51 10
        return $this->get('name');
52
    }
53
54
    /**
55
     * Get the item title.
56
     *
57
     * @return string
58
     */
59 10
    public function title()
60
    {
61
        /** @var \Illuminate\Translation\Translator $trans */
62 10
        $trans = trans();
63
64 10
        return $trans->has($title = $this->get('title')) ? $trans->get($title) : $title;
65
    }
66
67
    /**
68
     * Get the item url.
69
     *
70
     * @return string
71
     */
72 6
    public function url()
73
    {
74 6
        return $this->get('url');
75
    }
76
77
    /**
78
     * Get the item icon.
79
     *
80
     * @return string|null
81
     */
82 8
    public function icon()
83
    {
84 8
        return $this->get('icon');
85
    }
86
87
    /**
88
     * Set the current name.
89
     *
90
     * @param  string  $name
91
     *
92
     * @return self
93
     */
94 6
    public function setCurrent($name)
95
    {
96 6
        $this->attributes['children']->setCurrent($name);
97 6
        $this->attributes['active'] = ($this->name() === $name || $this->children()->hasActiveItem());
98
99 6
        return $this;
100
    }
101
102
    /**
103
     * Get the roles.
104
     *
105
     * @return array
106
     */
107 8
    public function getRoles()
108
    {
109 8
        return $this->get('roles', []);
110
    }
111
112
    /**
113
     * Set the roles.
114
     *
115
     * @param  array  $roles
116
     *
117
     * @return self
118
     */
119 28
    public function setRoles(array $roles)
120
    {
121 28
        $this->attributes['roles'] = $roles;
122
123 28
        return $this;
124
    }
125
126
    /**
127
     * Get the permissions.
128
     *
129
     * @return array
130
     */
131 8
    public function getPermissions()
132
    {
133 8
        return $this->get('permissions', []);
134
    }
135
136
    /**
137
     * Set the permissions.
138
     *
139
     * @param  array  $permissions
140
     *
141
     * @return self
142
     */
143 28
    public function setPermissions(array $permissions)
144
    {
145 28
        $this->attributes['permissions'] = $permissions;
146
147 28
        return $this;
148
    }
149
150
    /**
151
     * Get the sub-items.
152
     *
153
     * @return \Arcanesoft\Sidebar\Entities\ItemCollection
154
     */
155 12
    public function children()
156
    {
157 12
        return $this->get('children', new ItemCollection);
158
    }
159
160
    /**
161
     * Get the active class.
162
     *
163
     * @param  string  $class
164
     *
165
     * @return string
166
     */
167 4
    public function activeClass($class = 'active')
168
    {
169 4
        return $this->isActive() ? $class : '';
170
    }
171
172
    /**
173
     * Get the sub-items class.
174
     *
175
     * @param  string  $class
176
     *
177
     * @return string
178
     */
179 4
    public function childrenClass($class = 'treeview')
180
    {
181 4
        return $this->hasChildren() ? $class : '';
182
    }
183
184
    /* -----------------------------------------------------------------
185
     |  Main Methods
186
     | -----------------------------------------------------------------
187
     */
188
    /**
189
     * Make the item.
190
     *
191
     * @param  string       $name
192
     * @param  string       $title
193
     * @param  string       $url
194
     * @param  string|null  $icon
195
     *
196
     * @return self
197
     */
198 28
    public static function make($name, $title, $url, $icon = null)
199
    {
200 28
        return new self(compact('name', 'title', 'url', 'icon'));
201
    }
202
203
    /**
204
     * Make a Sidebar item from array.
205
     *
206
     * @param  array  $array
207
     *
208
     * @return self
209
     */
210 12
    public static function makeFromArray(array $array)
211
    {
212 12
        return tap(
213 12
            self::make($array['name'], $array['title'], self::getUrlFromArray($array), Arr::get($array, 'icon', null)),
214 12
            function (Item $item) use ($array) {
215 12
                $item->setRoles(Arr::get($array, 'roles', []));
216 12
                $item->setPermissions(Arr::get($array, 'permissions', []));
217 12
                $item->addChildren(Arr::get($array, 'children', []));
218 12
            }
219
        );
220
    }
221
222
    /**
223
     * Get url from array.
224
     *
225
     * @param  array  $array
226
     *
227
     * @return string
228
     */
229 12
    private static function getUrlFromArray(array $array)
230
    {
231 12
        return Arr::has($array, 'route')
232 2
            ? route(Arr::get($array, 'route'))
233 12
            : Arr::get($array, 'url', '#');
234
    }
235
236
    /**
237
     * Add children to the parent.
238
     *
239
     * @param  array  $children
240
     *
241
     * @return self
242
     */
243 12
    public function addChildren(array $children)
244
    {
245 12
        foreach ($children as $child) {
246 8
            $this->addChild($child);
247
        }
248
249 12
        return $this;
250
    }
251
252
    /**
253
     * Add a sub-item to the parent.
254
     *
255
     * @param  array  $child
256
     *
257
     * @return self
258
     */
259 8
    public function addChild(array $child)
260
    {
261 8
        $item = self::makeFromArray($child);
262
263 8
        if ($item->allowed())
264 8
            $this->attributes['children']->push($item);
265
266 8
        return $this;
267
    }
268
269
    /* -----------------------------------------------------------------
270
     |  Check Methods
271
     | -----------------------------------------------------------------
272
     */
273
274
    /**
275
     * Check if the item is active one.
276
     *
277
     * @return bool
278
     */
279 10
    public function isActive()
280
    {
281 10
        return (bool) $this->get('active', false);
282
    }
283
284
    /**
285
     * Check if the item has children.
286
     *
287
     * @return bool
288
     */
289 8
    public function hasChildren()
290
    {
291 8
        return ! $this->children()->isEmpty();
292
    }
293
294
    /**
295
     * Check the user is allowed to see this item.
296
     *
297
     * @return bool
298
     */
299 12
    public function allowed()
300
    {
301
        /** @var  \Arcanesoft\Contracts\Auth\Models\User  $user */
302 12
        $user = auth()->user();
303
304 12
        if (is_null($user) || ( ! $this->hasRoles() && ! $this->hasPermissions()))
305 12
            return true;
306
307 2
        return $user->isAdmin()
308 2
            || $this->checkRoles($user)
309 2
            || $this->checkPermission($user)
310 2
            || $this->hasAllowedChild();
311
    }
312
313
    /**
314
     * Check if the item has roles.
315
     *
316
     * @return bool
317
     */
318 6
    public function hasRoles()
319
    {
320 6
        return ! empty($this->getRoles());
321
    }
322
323
    /**
324
     * Check if the item has permissions.
325
     *
326
     * @return bool
327
     */
328 4
    public function hasPermissions()
329
    {
330 4
        return ! empty($this->getPermissions());
331
    }
332
333
    /* -----------------------------------------------------------------
334
     |  Other Methods
335
     | -----------------------------------------------------------------
336
     */
337
338
    /**
339
     * Convert the instance to an array.
340
     *
341
     * @return array
342
     */
343
    public function toArray()
344
    {
345 8
        return array_map(function ($value) {
346 8
            return $value instanceof Arrayable ? $value->toArray() : $value;
347 8
        }, $this->attributes);
348
    }
349
350
    /**
351
     * Check if the user has role.
352
     *
353
     * @param  \Arcanesoft\Contracts\Auth\Models\User  $user
354
     *
355
     * @return bool
356
     */
357 2
    private function checkRoles(User $user)
358
    {
359 2
        foreach ($this->getRoles() as $roleSlug) {
360 2
            if ($user->hasRoleSlug($roleSlug)) return true;
361
        }
362
363 2
        return false;
364
    }
365
366
    /**
367
     * Check if the user has permission.
368
     *
369
     * @param  \Arcanesoft\Contracts\Auth\Models\User  $user
370
     *
371
     * @return bool
372
     */
373 2
    private function checkPermission(User $user)
374
    {
375 2
        foreach ($this->getPermissions() as $permissionSlug) {
376 2
            if ($user->may($permissionSlug)) return true;
377
        }
378
379 2
        return false;
380
    }
381
382
    /**
383
     * Check if has an allowed child.
384
     *
385
     * @return bool
386
     */
387
    private function hasAllowedChild()
388
    {
389 2
        return $this->children()->filter(function (Item $child) {
390 2
            return $child->allowed();
391 2
        })->isNotEmpty();
392
    }
393
}
394