GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.
Completed
Pull Request — master (#25)
by Gaël
06:06 queued 05:05
created

HasEnums::getStoredValue()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 6
ccs 4
cts 4
cp 1
rs 10
c 0
b 0
f 0
cc 2
nc 2
nop 2
crap 2
1
<?php
2
3
namespace Spatie\Enum\Laravel;
4
5
use Illuminate\Database\Eloquent\Builder;
6
use Illuminate\Database\Eloquent\Model;
7
use InvalidArgumentException;
8
use Spatie\Enum\Enumerable;
9
use Spatie\Enum\Laravel\Exceptions\InvalidEnumError;
10
use Spatie\Enum\Laravel\Exceptions\NoSuchEnumField;
11
12
/**
13
 * @mixin Model
14
 */
15
trait HasEnums
16
{
17 96 View Code Duplication
    public function setAttribute($key, $value)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
18
    {
19 96
        if (! $this->isEnumAttribute($key) || $this->isNullableEnum($key, $value)) {
20 72
            return parent::setAttribute($key, $value);
21
        }
22
23 96
        return $this->setEnumAttribute($key, $value);
24
    }
25
26 40 View Code Duplication
    public function getAttribute($key)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
27
    {
28 40
        $value = parent::getAttribute($key);
29
30 40
        if (! $this->isEnumAttribute($key) || $this->isNullableEnum($key, $value)) {
31 24
            return $value;
32
        }
33
34 40
        return $this->getEnumAttribute($key, $value);
35
    }
36
37
    /**
38
     * @param \Illuminate\Database\Eloquent\Builder $builder
39
     * @param string $key
40
     * @param int|string|\Spatie\Enum\Enumerable|int[]|string[]|\Spatie\Enum\Enumerable[] $enumerables
41
     *
42
     * @see \Illuminate\Database\Eloquent\Builder::whereIn()
43
     */
44 32
    public function scopeWhereEnum(
45
        Builder $builder,
46
        string $key,
47
        $enumerables
48
    ): void {
49 32
        $this->buildEnumScope(
50 32
            $builder,
51 32
            'whereIn',
52 16
            $key,
53 16
            $enumerables
54
        );
55 28
    }
56
57
    /**
58
     * @param \Illuminate\Database\Eloquent\Builder $builder
59
     * @param string $key
60
     * @param int|string|\Spatie\Enum\Enumerable|int[]|string[]|\Spatie\Enum\Enumerable[] $enumerables
61
     *
62
     * @see \Illuminate\Database\Eloquent\Builder::orWhereIn()
63
     */
64 12
    public function scopeOrWhereEnum(
65
        Builder $builder,
66
        string $key,
67
        $enumerables
68
    ): void {
69 12
        $this->buildEnumScope(
70 12
            $builder,
71 12
            'orWhereIn',
72 6
            $key,
73 6
            $enumerables
74
        );
75 8
    }
76
77
    /**
78
     * @param \Illuminate\Database\Eloquent\Builder $builder
79
     * @param string $key
80
     * @param int|string|\Spatie\Enum\Enumerable|int[]|string[]|\Spatie\Enum\Enumerable[] $enumerables
81
     *
82
     * @see \Illuminate\Database\Eloquent\Builder::whereNotIn()
83
     */
84 20
    public function scopeWhereNotEnum(
85
        Builder $builder,
86
        string $key,
87
        $enumerables
88
    ): void {
89 20
        $this->buildEnumScope(
90 20
            $builder,
91 20
            'whereNotIn',
92 10
            $key,
93 10
            $enumerables
94
        );
95 16
    }
96
97
    /**
98
     * @param \Illuminate\Database\Eloquent\Builder $builder
99
     * @param string $key
100
     * @param int|string|\Spatie\Enum\Enumerable|int[]|string[]|\Spatie\Enum\Enumerable[] $enumerables
101
     *
102
     * @see \Illuminate\Database\Eloquent\Builder::orWhereNotIn()
103
     */
104 12
    public function scopeOrWhereNotEnum(
105
        Builder $builder,
106
        string $key,
107
        $enumerables
108
    ): void {
109 12
        $this->buildEnumScope(
110 12
            $builder,
111 12
            'orWhereNotIn',
112 6
            $key,
113 6
            $enumerables
114
        );
115 8
    }
116
117
    /**
118
     * @param string $key
119
     * @param int|string|\Spatie\Enum\Enumerable $value
120
     *
121
     * @return $this
122
     */
123 96
    protected function setEnumAttribute(string $key, $value)
124
    {
125 96
        $enumClass = $this->getEnumClass($key);
126
127 88
        if (is_string($value) || is_int($value)) {
128 16
            $value = $this->asEnum($enumClass, $value);
129
        }
130
131 88
        if (! is_a($value, $enumClass)) {
132 4
            throw InvalidEnumError::make(static::class, $key, $enumClass, get_class($value));
133
        }
134
135 84
        $this->attributes[$key] = $this->getStoredValue($key, $value);
0 ignored issues
show
Bug introduced by
The property attributes does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
136
137 84
        return $this;
138
    }
139
140
    /**
141
     * @param string $key
142
     * @param \Spatie\Enum\Enumerable $enum
143
     *
144
     * @return int|string
145
     */
146 84
    protected function getStoredValue(string $key, Enumerable $enum)
147
    {
148 84
        return $this->hasCast($key, ['int', 'integer'])
0 ignored issues
show
Bug introduced by
It seems like hasCast() 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...
149 4
            ? $enum->getIndex()
150 84
            : $enum->getValue();
151
    }
152
153
    /**
154
     * @param string $key
155
     * @param int|string $value
156
     *
157
     * @return \Spatie\Enum\Enumerable
158
     */
159 84
    protected function getEnumAttribute(string $key, $value): Enumerable
160
    {
161 84
        return $this->asEnum($this->getEnumClass($key), $value);
162
    }
163
164 112
    protected function isEnumAttribute(string $key): bool
165
    {
166 112
        return isset($this->enums[$key]);
0 ignored issues
show
Bug introduced by
The property enums does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
167
    }
168
169 96
    protected function isNullableEnum(string $key, $value): bool
170
    {
171 96
        $enum = $this->enums[$key];
172
173 96
        if (! is_array($enum)) {
174 92
            return false;
175
        }
176
177 16
        if (! isset($enum['nullable'])) {
178 4
            return false;
179
        }
180
181 12
        return $enum['nullable'] && is_null($value);
182
    }
183
184 96
    protected function getEnumClass(string $key): string
185
    {
186 96
        $enumClass = $this->enums[$key];
187
188 96
        if (is_array($enumClass)) {
189 12
            $enumClass = $enumClass['class'] ?? null;
190
        }
191
192 96
        $enumInterface = Enumerable::class;
193
194 96
        if (is_null($enumClass)) {
195 4
            throw new InvalidArgumentException("Could not find Enumerable class in \$enums property {$key}");
196
        }
197
198 92
        $classImplementsEnumerable = class_implements($enumClass)[$enumInterface] ?? false;
199
200 92
        if (! $classImplementsEnumerable) {
201 4
            throw new InvalidArgumentException("Expected {$enumClass} to implement {$enumInterface}");
202
        }
203
204 88
        return $enumClass;
205
    }
206
207
    /**
208
     * @param string $class
209
     * @param int|string $value
210
     *
211
     * @return \Spatie\Enum\Enumerable
212
     */
213 84
    protected function asEnum(string $class, $value): Enumerable
214
    {
215 84
        if ($value instanceof Enumerable) {
216 36
            return $value;
217
        }
218
219 52
        return forward_static_call(
220 52
            $class.'::make',
221 26
            $value
222
        );
223
    }
224
225
    /**
226
     * @param \Illuminate\Database\Eloquent\Builder $builder
227
     * @param string $method
228
     * @param string $key
229
     * @param int|string|\Spatie\Enum\Enumerable|int[]|string[]|\Spatie\Enum\Enumerable[] $enumerables
230
     */
231 60
    protected function buildEnumScope(
232
        Builder $builder,
233
        string $method,
234
        string $key,
235
        $enumerables
236
    ): void {
237 60
        if (! $this->isEnumAttribute($key)) {
238 16
            throw NoSuchEnumField::make($key, get_class($this));
239
        }
240
241 44
        $enumerables = is_array($enumerables) ? $enumerables : [$enumerables];
242
243 44
        $builder->$method(
244 44
            $key,
245
            array_map(function ($value) use ($key) {
246 44
                return $this->getStoredValue($key, $this->getEnumAttribute($key, $value));
247 44
            }, $enumerables)
248
        );
249 44
    }
250
}
251