Passed
Branch feature/deny (0fd688)
by Enea
02:29
created

Authorizable::permissions()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 0
dl 0
loc 3
ccs 2
cts 2
cp 1
crap 1
rs 10
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
/**
6
 * @author enea dhack <[email protected]>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
namespace Enea\Authorization\Traits;
13
14
use Closure;
15
use Enea\Authorization\Contracts\Grantable;
0 ignored issues
show
Bug introduced by
This use statement conflicts with another class in this namespace, Enea\Authorization\Traits\Grantable. Consider defining an alias.

Let?s assume that you have a directory layout like this:

.
|-- OtherDir
|   |-- Bar.php
|   `-- Foo.php
`-- SomeDir
    `-- Foo.php

and let?s assume the following content of Bar.php:

// Bar.php
namespace OtherDir;

use SomeDir\Foo; // This now conflicts the class OtherDir\Foo

If both files OtherDir/Foo.php and SomeDir/Foo.php are loaded in the same runtime, you will see a PHP error such as the following:

PHP Fatal error:  Cannot use SomeDir\Foo as Foo because the name is already in use in OtherDir/Foo.php

However, as OtherDir/Foo.php does not necessarily have to be loaded and the error is only triggered if it is loaded before OtherDir/Bar.php, this problem might go unnoticed for a while. In order to prevent this error from surfacing, you must import the namespace with a different alias:

// Bar.php
namespace OtherDir;

use SomeDir\Foo as SomeDirFoo; // There is no conflict anymore.
Loading history...
16
use Enea\Authorization\Contracts\PermissionContract;
17
use Enea\Authorization\Contracts\RoleContract;
18
use Enea\Authorization\Facades\Authorizer;
19
use Enea\Authorization\Facades\Denier;
20
use Enea\Authorization\Facades\Granter;
21
use Enea\Authorization\Facades\Revoker;
22
use Enea\Authorization\Support\Config;
23
use Illuminate\Database\Eloquent\Collection as EloquentCollection;
24
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
25
use Illuminate\Support\Collection;
26
27
/**
28
 * Trait Authorizable.
29
 *
30
 * @package Enea\Authorization\Traits
31
 *
32
 * @property EloquentCollection permissions
33
 * @property EloquentCollection roles
34
 * @property EloquentCollection denied
35
 */
36
trait Authorizable
37
{
38
    use Model;
39
40 55
    public function getIdentificationKey(): string
41
    {
42 55
        return (string) $this->getKey();
43
    }
44
45 28
    public function grant(Grantable $grantable): void
46
    {
47 28
        $this->grantMultiple([$grantable]);
48 28
    }
49
50
    public function grantMultiple(array $grantables): void
51
    {
52 45
        $this->operateOn(RoleContract::class, function (Collection $roles) {
53 24
            Granter::roles($this, $roles);
54 45
        }, $grantables);
55
56 45
        $this->operateOn(PermissionContract::class, function (Collection $permissions) {
57 23
            Granter::permissions($this, $permissions);
58 45
        }, $grantables);
59 45
    }
60
61 8
    public function deny(PermissionContract $permission): void
62
    {
63 8
        $this->denyMultiple([$permission]);
64 8
    }
65
66 8
    public function denyMultiple(array $permissions): void
67
    {
68 8
        Denier::deny($this, collect($permissions));
0 ignored issues
show
Bug introduced by
$this of type Enea\Authorization\Traits\Authorizable is incompatible with the type Enea\Authorization\Contracts\DeniableOwner expected by parameter $owner of Enea\Authorization\Facades\Denier::deny(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

68
        Denier::deny(/** @scrutinizer ignore-type */ $this, collect($permissions));
Loading history...
69 8
    }
70
71 8
    public function revoke(Grantable $grantable): void
72
    {
73 8
        $this->revokeMultiple([$grantable]);
74 8
    }
75
76
    public function revokeMultiple(array $grantables): void
77
    {
78 10
        $this->operateOn(RoleContract::class, function (Collection $roles) {
79 5
            Revoker::roles($this, $roles);
80 10
        }, $grantables);
81
82 10
        $this->operateOn(PermissionContract::class, function (Collection $permissions) {
83 5
            Revoker::permissions($this, $permissions);
84 10
        }, $grantables);
85 10
    }
86
87 10
    public function can(string $permission): bool
88
    {
89 10
        return Authorizer::can($this, $permission);
90
    }
91
92 2
    public function cannot(string $permission): bool
93
    {
94 2
        return ! $this->can($permission);
95
    }
96
97 6
    public function isMemberOf(string $role): bool
98
    {
99 6
        return Authorizer::is($this, $role);
100
    }
101
102 2
    public function isntMemberOf(string $role): bool
103
    {
104 2
        return ! $this->isMemberOf($role);
105
    }
106
107 31
    public function permissions(): BelongsToMany
108
    {
109 31
        return $this->morphToMany(Config::permissionModel(), 'authorizable', Config::userPermissionTableName());
110
    }
111
112 34
    public function denied(): BelongsToMany
113
    {
114 34
        return $this->morphToMany(Config::permissionModel(), 'authorizable', Config::deniedUserPermissionTableName());
115
    }
116
117 56
    public function roles(): BelongsToMany
118
    {
119 56
        return $this->morphToMany(Config::roleModel(), 'authorizable', Config::userRoleTableName());
120
    }
121
122 1
    public function getPermissionModels(): EloquentCollection
123
    {
124 1
        return $this->permissions;
125
    }
126
127 1
    public function getRoleModels(): EloquentCollection
128
    {
129 1
        return $this->roles;
130
    }
131
132
    public function deniedModels(): EloquentCollection
133
    {
134
        return $this->denied;
135
    }
136
137 45
    private function operateOn(string $contract, Closure $closure, array $grantables): void
138
    {
139 45
        $collection = $this->filterOnly($contract)($grantables);
140 45
        if (! $collection->isEmpty()) {
141 45
            $closure($collection);
142
        }
143 45
    }
144
145
    private function filterOnly(string $abstract): Closure
146
    {
147
        return function (array $grantables) use ($abstract): Collection {
148 45
            return collect($grantables)->filter(function (Grantable $grantable) use ($abstract) {
149 45
                return $grantable instanceof $abstract;
150 45
            });
151 45
        };
152
    }
153
}
154