Completed
Pull Request — master (#3)
by
unknown
04:02
created

HasEnum::decodeEnum()   A

Complexity

Conditions 3
Paths 4

Size

Total Lines 11
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 12

Importance

Changes 0
Metric Value
cc 3
eloc 7
nc 4
nop 2
dl 0
loc 11
ccs 0
cts 9
cp 0
crap 12
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace Rexlabs\Enum\Traits;
4
5
use Rexlabs\Enum\Enum;
6
use Rexlabs\Enum\Exceptions\InvalidKeyException;
7
8
trait HasEnum
9
{
10
    public function getAttribute($key)
11
    {
12
        $value = parent::getAttribute($key);
13
14
        if ($this->hasEnumDecodeKey($key)) {
15
            $value = $this->decodeEnum($key, $value);
16
        }
17
18
        return $value;
19
    }
20
21
    public function setAttribute($key, $value)
22
    {
23
        if ($value !== null && $this->hasEnumDecodeKey($key)) {
24
            if ($this->hasCast($key)) {
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? ( Ignorable by Annotation )

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

24
            if ($this->/** @scrutinizer ignore-call */ hasCast($key)) {
Loading history...
25
                $value = $this->castAttribute($key, $value);
0 ignored issues
show
Bug introduced by
The method castAttribute() does not exist on Rexlabs\Enum\Traits\HasEnum. Did you maybe mean setAttribute()? ( Ignorable by Annotation )

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

25
                /** @scrutinizer ignore-call */ 
26
                $value = $this->castAttribute($key, $value);

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
26
            }
27
28
            $encoding = $this->getEnumEncoding($key);
29
            
30
            if ($value instanceof $encoding['class']) {
31
                $value = $value->key();
32
            } elseif (gettype($encoding['class']::keys()[0]) != gettype($value)) {
33
                $value = $encoding['class']::keyForValue($value);
34
            }
35
36
            if ($encoding['column'] != $key) {
37
                $this->setAttribute($encoding['column'], $value);
38
            } else {
39
                $this->attributes[$key] = $value;
0 ignored issues
show
Bug Best Practice introduced by
The property attributes does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
40
            }
41
42
            return $this;
43
        }
44
45
        return parent::setAttribute($key, $value);
46
    }
47
48
    /**
49
     * Determine whether an attribute should be decode to an enum value.
50
     *
51
     * @param  string  $key
52
     * @return bool
53
     */
54
    protected function hasEnumDecodeKey($key): bool
55
    {
56
        return array_key_exists($key, $this->getEnumEncodings());
57
    }
58
59
    protected function decodeEnum(string $key, $value)
60
    {
61
        $encoding = $this->getEnumEncoding($key);
62
63
        $enumClass = $encoding['class'];
64
        $value = $encoding['column'] == $key ? $value : $this->getAttribute($encoding['column']);
65
66
        try {
67
            return $enumClass::valueForKey($value);
68
        } catch (InvalidKeyException $ex) {
69
            return $value;
70
        }
71
    }
72
73
    protected function getEnumEncodings()
74
    {
75
        return property_exists($this, 'decodeEnums') ? $this->decodeEnums : [];
76
    }
77
78
    protected function getEnumEncoding(string $key)
79
    {
80
        $encoding = $this->getEnumEncodings()[$key];
81
82
        $class = is_string($encoding)
83
            ? $encoding : $encoding[1];
84
        $column = is_string($encoding)
85
            ? $key : $encoding[0];
86
87
        if (! is_subclass_of($class, Enum::class)) {
88
            throw new \ErrorException("{$class} is not Enum");
89
        }
90
91
        return compact('class', 'column');
92
    }
93
}
94