Completed
Push — master ( b739db...92d607 )
by Abdelrahman
02:42
created

HasAbilities::hasDirectAbility()   C

Complexity

Conditions 8
Paths 8

Size

Total Lines 24
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 8
eloc 10
nc 8
nop 2
dl 0
loc 24
rs 5.7377
c 0
b 0
f 0
1
<?php
2
3
/*
4
 * NOTICE OF LICENSE
5
 *
6
 * Part of the Rinvex Fort Package.
7
 *
8
 * This source file is subject to The MIT License (MIT)
9
 * that is bundled with this package in the LICENSE file.
10
 *
11
 * Package: Rinvex Fort Package
12
 * License: The MIT License (MIT)
13
 * Link:    https://rinvex.com
14
 */
15
16
namespace Rinvex\Fort\Traits;
17
18
use Rinvex\Fort\Models\Ability;
19
use Illuminate\Support\Collection;
20
use Illuminate\Database\Eloquent\Model;
21
22
trait HasAbilities
23
{
24
    /**
25
     * Give the given ability to the given model.
26
     *
27
     * @param int|\Illuminate\Database\Eloquent\Model                                     $id
28
     * @param string|array|\Rinvex\Fort\Models\Ability|\Illuminate\Support\Collection $ability
29
     *
30
     * @return $this
31
     */
32
    public function giveAbilityTo($id, $ability)
33
    {
34
        // Find the given instance
35
        $instance = $id instanceof Model ?: $this->find($id);
0 ignored issues
show
Bug introduced by
It seems like find() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
36
37
        if ($instance) {
38
            $origAbility = $ability;
39
40
            // Fire the ability giving event
41
            event('rinvex.fort.ability.giving', [$instance, $origAbility]);
42
43
            // Single ability slug
44
            if (is_string($ability)) {
45
                $ability = app('rinvex.fort.ability')->findBy('action', $ability);
46
            }
47
48
            // Single ability model
49
            if ($ability instanceof Ability) {
50
                if ($instance->all_abilities->contains('action', $ability->action)) {
0 ignored issues
show
Documentation introduced by
The property action does not exist on object<Rinvex\Fort\Models\Ability>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
51
                    return $this;
52
                }
53
54
                $instance->abilities()->attach($ability);
55
            }
56
57
            // Array of ability slugs
58
            if (is_array($ability)) {
59
                $ability = app('rinvex.fort.ability')->findWhereIn(['action', $ability]);
60
            }
61
62
            // Collection of ability models
63
            if ($ability instanceof Collection) {
64
                $ability = $ability->map(function ($ability) {
65
                    return $ability instanceof Ability ? $ability->id : $ability;
0 ignored issues
show
Documentation introduced by
The property id does not exist on object<Rinvex\Fort\Models\Ability>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
66
                })->toArray();
67
68
                $instance->abilities()->syncWithoutDetaching($ability);
69
            }
70
71
            // Fire the ability given event
72
            event('rinvex.fort.ability.given', [$instance, $origAbility]);
73
        }
74
75
        return $this;
76
    }
77
78
    /**
79
     * Revoke the given ability from the given model.
80
     *
81
     * @param int|\Illuminate\Database\Eloquent\Model                                     $id
82
     * @param string|array|\Rinvex\Fort\Models\Ability|\Illuminate\Support\Collection $ability
83
     *
84
     * @return $this
85
     */
86
    public function revokeAbilityTo($id, $ability)
87
    {
88
        // Find the given instance
89
        $instance = $id instanceof Model ?: $this->find($id);
0 ignored issues
show
Bug introduced by
It seems like find() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
90
91
        if ($instance) {
92
            $origAbility = $ability;
93
94
            // Fire the ability revoking event
95
            event('rinvex.fort.ability.revoking', [$instance, $origAbility]);
96
97
            // Single ability slug
98
            if (is_string($ability)) {
99
                $ability = $instance->abilities->contains('action', $ability);
100
            }
101
102
            // Single ability model
103
            if ($ability instanceof Ability) {
104
                if (! $instance->all_abilities->contains('action', $ability->action)) {
0 ignored issues
show
Documentation introduced by
The property action does not exist on object<Rinvex\Fort\Models\Ability>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
105
                    return $this;
106
                }
107
108
                $instance->abilities()->detach($ability);
109
            }
110
111
            // Array of ability slugs
112
            if (is_array($ability)) {
113
                $ability = app('rinvex.fort.ability')->findWhereIn(['action', $ability]);
114
            }
115
116
            // Collection of ability models
117
            if ($ability instanceof Collection) {
118
                $current = $instance->abilities()->getRelatedIds()->toArray();
119
                $remove  = $ability->map(function ($ability) {
120
                    return $ability instanceof Ability ? $ability->id : $ability;
0 ignored issues
show
Documentation introduced by
The property id does not exist on object<Rinvex\Fort\Models\Ability>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
121
                })->toArray();
122
123
                $instance->abilities()->sync(array_diff($current, $remove));
124
            }
125
126
            // Fire the ability revoked event
127
            event('rinvex.fort.ability.revoked', [$instance, $origAbility]);
128
        }
129
130
        return $this;
131
    }
132
}
133