Completed
Pull Request — master (#27)
by ARCANEDEV
07:32
created

PermissionsGroup   B

Complexity

Total Complexity 23

Size/Duplication

Total Lines 300
Duplicated Lines 0 %

Coupling/Cohesion

Components 2
Dependencies 16

Test Coverage

Coverage 100%

Importance

Changes 0
Metric Value
wmc 23
lcom 2
cbo 16
dl 0
loc 300
rs 8.4614
c 0
b 0
f 0
ccs 78
cts 78
cp 1

16 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 8 1
A permissions() 0 7 1
A setNameAttribute() 0 5 1
A setSlugAttribute() 0 4 1
A createPermission() 0 6 1
A attachPermission() 0 10 2
A attachPermissionById() 0 9 2
A attachPermissions() 0 10 1
A detachPermission() 0 14 2
A detachPermissionById() 0 7 2
A detachPermissions() 0 10 1
A detachAllPermissions() 0 10 1
A hasPermission() 0 6 2
A getPermissionFromGroup() 0 12 2
A getPermissionById() 0 4 1
A loadPermissions() 0 4 2
1
<?php namespace Arcanedev\LaravelAuth\Models;
2
3
use Arcanedev\LaravelAuth\Events\PermissionsGroups\AttachedPermissionsToGroup;
4
use Arcanedev\LaravelAuth\Events\PermissionsGroups\AttachedPermissionToGroup;
5
use Arcanedev\LaravelAuth\Events\PermissionsGroups\AttachingPermissionsToGroup;
6
use Arcanedev\LaravelAuth\Events\PermissionsGroups\AttachingPermissionToGroup;
7
use Arcanedev\LaravelAuth\Events\PermissionsGroups\CreatedPermissionsGroup;
8
use Arcanedev\LaravelAuth\Events\PermissionsGroups\CreatingPermissionsGroup;
9
use Arcanedev\LaravelAuth\Events\PermissionsGroups\DeletedPermissionsGroup;
10
use Arcanedev\LaravelAuth\Events\PermissionsGroups\DeletingPermissionsGroup;
11
use Arcanedev\LaravelAuth\Events\PermissionsGroups\DetachedAllPermissions;
12
use Arcanedev\LaravelAuth\Events\PermissionsGroups\DetachedPermissionFromGroup;
13
use Arcanedev\LaravelAuth\Events\PermissionsGroups\DetachedPermissionsFromGroup;
14
use Arcanedev\LaravelAuth\Events\PermissionsGroups\DetachingAllPermissions;
15
use Arcanedev\LaravelAuth\Events\PermissionsGroups\DetachingPermissionFromGroup;
16
use Arcanedev\LaravelAuth\Events\PermissionsGroups\DetachingPermissionsFromGroup;
17
use Arcanedev\LaravelAuth\Events\PermissionsGroups\SavedPermissionsGroup;
18
use Arcanedev\LaravelAuth\Events\PermissionsGroups\SavingPermissionsGroup;
19
use Arcanedev\LaravelAuth\Events\PermissionsGroups\UpdatedPermissionsGroup;
20
use Arcanedev\LaravelAuth\Events\PermissionsGroups\UpdatingPermissionsGroup;
21
use Arcanesoft\Contracts\Auth\Models\Permission as PermissionContract;
22
use Arcanesoft\Contracts\Auth\Models\PermissionsGroup as PermissionsGroupContract;
23
use Illuminate\Database\Eloquent\Model as Eloquent;
24
use Illuminate\Support\Str;
25
26
/**
27
 * Class     PermissionsGroup
28
 *
29
 * @package  Arcanedev\LaravelAuth\Models
30
 * @author   ARCANEDEV <[email protected]>
31
 *
32
 * @property  int                                       id
33
 * @property  string                                    name
34
 * @property  string                                    slug
35
 * @property  string                                    description
36
 * @property  \Carbon\Carbon                            created_at
37
 * @property  \Carbon\Carbon                            updated_at
38
 * @property  \Illuminate\Database\Eloquent\Collection  permissions
39
 */
40
class PermissionsGroup extends AbstractModel implements PermissionsGroupContract
41
{
42
    /* -----------------------------------------------------------------
43
     |  Properties
44
     | -----------------------------------------------------------------
45
     */
46
    /**
47
     * The attributes that are mass assignable.
48
     *
49
     * @var array
50
     */
51
    protected $fillable = ['name', 'slug', 'description'];
52
53
    /**
54
     * The event map for the model.
55
     *
56
     * @var array
57
     */
58
    protected $dispatchesEvents = [
59
        'creating' => CreatingPermissionsGroup::class,
60
        'created'  => CreatedPermissionsGroup::class,
61
        'updating' => UpdatingPermissionsGroup::class,
62
        'updated'  => UpdatedPermissionsGroup::class,
63
        'saving'   => SavingPermissionsGroup::class,
64
        'saved'    => SavedPermissionsGroup::class,
65
        'deleting' => DeletingPermissionsGroup::class,
66
        'deleted'  => DeletedPermissionsGroup::class,
67
    ];
68
69
    /* -----------------------------------------------------------------
70
     |  Constructor
71
     | -----------------------------------------------------------------
72
     */
73
    /**
74
     * Create a new Eloquent model instance.
75
     *
76
     * @param  array  $attributes
77
     */
78 32
    public function __construct(array $attributes = [])
79
    {
80 32
        parent::__construct($attributes);
81
82 32
        $this->setTable(
83 32
            config('laravel-auth.permissions-groups.table', 'permissions_groups')
84
        );
85 32
    }
86
87
    /* ------------------------------------------------------------------------------------------------
88
     |  Relationships
89
     | ------------------------------------------------------------------------------------------------
90
     */
91
    /**
92
     * Permissions Groups has many permissions.
93
     *
94
     * @return \Illuminate\Database\Eloquent\Relations\HasMany
95
     */
96 26
    public function permissions()
97
    {
98 26
        return $this->hasMany(
99 26
            config('laravel-auth.permissions.model', Permission::class),
100 26
            'group_id'
101
        );
102
    }
103
104
    /* -----------------------------------------------------------------
105
     |  Getters & Setters
106
     | -----------------------------------------------------------------
107
     */
108
    /**
109
     * Set the name attribute.
110
     *
111
     * @param  string  $name
112
     */
113 26
    public function setNameAttribute($name)
114
    {
115 26
        $this->attributes['name'] = $name;
116 26
        $this->setSlugAttribute($name);
117 26
    }
118
119
    /**
120
     * Set the slug attribute.
121
     *
122
     * @param  string  $slug
123
     */
124 26
    public function setSlugAttribute($slug)
125
    {
126 26
        $this->attributes['slug'] = Str::slug($slug, config('laravel-auth.permissions-groups.slug-separator', '-'));
127 26
    }
128
129
    /* -----------------------------------------------------------------
130
     |  Main Methods
131
     | -----------------------------------------------------------------
132
     */
133
    /**
134
     * Create and attach a permission.
135
     *
136
     * @param  array  $attributes
137
     * @param  bool   $reload
138
     */
139 4
    public function createPermission(array $attributes, $reload = true)
140
    {
141 4
        $this->permissions()->create($attributes);
142
143 4
        $this->loadPermissions($reload);
144 4
    }
145
146
    /**
147
     * Attach the permission to a group.
148
     *
149
     * @param  \Arcanesoft\Contracts\Auth\Models\Permission  $permission
150
     * @param  bool                                          $reload
151
     */
152 12
    public function attachPermission(&$permission, $reload = true)
153
    {
154 12
        if ($this->hasPermission($permission)) return;
155
156 12
        event(new AttachingPermissionToGroup($this, $permission));
157 12
        $permission = $this->permissions()->save($permission);
0 ignored issues
show
Compatibility introduced by
$permission of type object<Arcanesoft\Contra...Auth\Models\Permission> is not a sub-type of object<Illuminate\Database\Eloquent\Model>. It seems like you assume a concrete implementation of the interface Arcanesoft\Contracts\Auth\Models\Permission to be always present.

This check looks for parameters that are defined as one type in their type hint or doc comment but seem to be used as a narrower type, i.e an implementation of an interface or a subclass.

Consider changing the type of the parameter or doing an instanceof check before assuming your parameter is of the expected type.

Loading history...
158 12
        event(new AttachedPermissionToGroup($this, $permission));
0 ignored issues
show
Security Bug introduced by
It seems like $permission defined by $this->permissions()->save($permission) on line 157 can also be of type false; however, Arcanedev\LaravelAuth\Ev...nToGroup::__construct() does only seem to accept object<Arcanesoft\Contra...Auth\Models\Permission>, did you maybe forget to handle an error condition?

This check looks for type mismatches where the missing type is false. This is usually indicative of an error condtion.

Consider the follow example

<?php

function getDate($date)
{
    if ($date !== null) {
        return new DateTime($date);
    }

    return false;
}

This function either returns a new DateTime object or false, if there was an error. This is a typical pattern in PHP programming to show that an error has occurred without raising an exception. The calling code should check for this returned false before passing on the value to another function or method that may not be able to handle a false.

Loading history...
159
160 12
        $this->loadPermissions($reload);
161 12
    }
162
163
    /**
164
     * Attach the permission by id to a group.
165
     *
166
     * @param  int   $id
167
     * @param  bool  $reload
168
     *
169
     * @return \Arcanesoft\Contracts\Auth\Models\Permission|null
170
     */
171 2
    public function attachPermissionById($id, $reload = true)
172
    {
173 2
        $permission = $this->getPermissionById($id);
174
175 2
        if ($permission !== null)
176 2
            $this->attachPermission($permission, $reload);
177
178 2
        return $permission;
179
    }
180
181
    /**
182
     * Attach a collection of permissions to the group.
183
     *
184
     * @param  \Illuminate\Database\Eloquent\Collection|array  $permissions
185
     * @param  bool                                            $reload
186
     *
187
     * @return \Illuminate\Database\Eloquent\Collection|array
188
     */
189 6
    public function attachPermissions($permissions, $reload = true)
190
    {
191 6
        event(new AttachingPermissionsToGroup($this, $permissions));
192 6
        $permissions = $this->permissions()->saveMany($permissions);
193 6
        event(new AttachedPermissionsToGroup($this, $permissions));
0 ignored issues
show
Bug introduced by
It seems like $permissions defined by $this->permissions()->saveMany($permissions) on line 192 can also be of type object<Traversable>; however, Arcanedev\LaravelAuth\Ev...sToGroup::__construct() does only seem to accept object<Illuminate\Support\Collection>|array, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
194
195 6
        $this->loadPermissions($reload);
196
197 6
        return $permissions;
198
    }
199
200
    /**
201
     * Attach the permission from a group.
202
     *
203
     * @param  \Arcanesoft\Contracts\Auth\Models\Permission  $permission
204
     * @param  bool                                          $reload
205
     */
206 6
    public function detachPermission(&$permission, $reload = true)
207
    {
208 6
        if ( ! $this->hasPermission($permission))
209 4
            return;
210
211
        /** @var  \Arcanesoft\Contracts\Auth\Models\Permission  $permission */
212 6
        $permission = $this->getPermissionFromGroup($permission);
213
214 6
        event(new DetachingPermissionFromGroup($this, $permission));
215 6
        $permission->update(['group_id' => 0]);
216 6
        event(new DetachedPermissionFromGroup($this, $permission));
217
218 6
        $this->loadPermissions($reload);
219 6
    }
220
221
    /**
222
     * Attach the permission by id to a group.
223
     *
224
     * @param  int   $id
225
     * @param  bool  $reload
226
     *
227
     * @return \Arcanesoft\Contracts\Auth\Models\Permission
228
     */
229 2
    public function detachPermissionById($id, $reload = true)
230
    {
231 2
        if ( ! is_null($permission = $this->getPermissionById($id)))
232 2
            $this->detachPermission($permission, $reload);
233
234 2
        return $permission;
235
    }
236
237
    /**
238
     * Detach multiple permissions by ids.
239
     *
240
     * @param  array  $ids
241
     * @param  bool   $reload
242
     *
243
     * @return int
244
     */
245 2
    public function detachPermissions(array $ids, $reload = true)
246
    {
247 2
        event(new DetachingPermissionsFromGroup($this, $ids));
248 2
        $detached = $this->permissions()->whereIn('id', $ids)->update(['group_id' => 0]);
249 2
        event(new DetachedPermissionsFromGroup($this, $ids, $detached));
250
251 2
        $this->loadPermissions($reload);
252
253 2
        return $detached;
254
    }
255
256
    /**
257
     * Detach all permissions from the group.
258
     *
259
     * @param  bool  $reload
260
     *
261
     * @return int
262
     */
263 4
    public function detachAllPermissions($reload = true)
264
    {
265 4
        event(new DetachingAllPermissions($this));
266 4
        $detached = $this->permissions()->update(['group_id' => 0]);
267 4
        event(new DetachedAllPermissions($this, $detached));
268
269 4
        $this->loadPermissions($reload);
270
271 4
        return $detached;
272
    }
273
274
    /* -----------------------------------------------------------------
275
     |  Check Methods
276
     | -----------------------------------------------------------------
277
     */
278
    /**
279
     * Check if role has the given permission (Permission Model or Id).
280
     *
281
     * @param  \Arcanesoft\Contracts\Auth\Models\Permission|int  $id
282
     *
283
     * @return bool
284
     */
285 16
    public function hasPermission($id)
286
    {
287 16
        if ($id instanceof Eloquent) $id = $id->getKey();
288
289 16
        return $this->getPermissionFromGroup($id) !== null;
290
    }
291
292
    /* -----------------------------------------------------------------
293
     |  Other Methods
294
     | -----------------------------------------------------------------
295
     */
296
    /**
297
     * Get a permission from the group.
298
     *
299
     * @param  \Arcanesoft\Contracts\Auth\Models\Permission|int  $id
300
     *
301
     * @return \Arcanesoft\Contracts\Auth\Models\Permission|null
302
     */
303 16
    private function getPermissionFromGroup($id)
304
    {
305 16
        if ($id instanceof Eloquent) $id = $id->getKey();
306
307 16
        $this->loadPermissions();
308
309 16
        return $this->permissions
310 16
            ->filter(function (PermissionContract $permission) use ($id) {
311 16
                return $permission->getKey() == $id;
312 16
            })
313 16
            ->first();
314
    }
315
316
    /**
317
     * Get a permission by id.
318
     *
319
     * @param  int  $id
320
     *
321
     * @return \Arcanesoft\Contracts\Auth\Models\Permission|null
322
     */
323 4
    private function getPermissionById($id)
324
    {
325 4
        return $this->permissions()->getRelated()->where('id', $id)->first();
326
    }
327
328
    /**
329
     * Load the permissions.
330
     *
331
     * @param  bool  $load
332
     *
333
     * @return self
334
     */
335 22
    protected function loadPermissions($load = true)
336
    {
337 22
        return $load ? $this->load('permissions') : $this;
338
    }
339
}
340