Passed
Push — main ( 622d97...3cafac )
by Gabriel
01:39
created

AccessorsTrait::hasMutator()   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
c 0
b 0
f 0
nc 1
nop 2
dl 0
loc 3
ccs 2
cts 2
cp 1
crap 1
rs 10
1
<?php
2
3
namespace ByTIC\DataObjects\Behaviors\Accessors;
4
5
use ByTIC\DataObjects\Utility\Constants;
6
use Exception;
7
use Nip\Inflector\Inflector;
8
use Nip\Utility\Str;
9
10
/**
11
 * Trait AccessorsTrait
12
 * @package ByTIC\DataObjects\Behaviors\Accessors
13
 */
14
trait AccessorsTrait
15
{
16
    /**
17
     * The attributes that should use mutators.
18
     *
19
     * @var array
20
     */
21
    protected static $accessors = [
22
        'get' => [],
23
        'set' => [],
24
    ];
25
26
    /**
27
     * @param $key
28
     * @return mixed
29
     * @noinspection PhpDocMissingThrowsInspection
30
     */
31
    public function getMutated($key)
32
    {
33
        /** @noinspection PhpUnhandledExceptionInspection */
34
        return $this->callAccessors('get', $key);
35
    }
36
37
    /**
38
     * @param $key
39
     * @param $value
40
     * @return mixed
41
     * @noinspection PhpDocMissingThrowsInspection
42
     */
43
    public function setMutated($key, $value)
44
    {
45
        /** @noinspection PhpUnhandledExceptionInspection */
46
        return $this->callAccessors('set', $key, [$value]);
47
    }
48
49 13
    /**
50
     * @param string $type
51 13
     * @param string $key
52 13
     * @param array $params
53 7
     * @return mixed
54
     * @throws Exception
55
     */
56 7
    protected function callAccessors(string $type, string $key, $params = [])
57
    {
58
        $method = static::getMutator($type, $key);
59
        if (!$method) {
60
            return Constants::NO_ACCESSORS_FOUND;
61
        }
62
        try {
63
            return $this->{$method}(...$params);
64
        } catch (Exception $exception) {
65
            $message = $exception->getMessage();
66
            if (Str::startsWith($message, 'Undefined property:') && Str::endsWith($message, '::$' . $key)) {
67
                if ($type === 'get') {
68
                    return $this->getPropertyRaw($key);
0 ignored issues
show
Bug introduced by
It seems like getPropertyRaw() 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

68
                    return $this->/** @scrutinizer ignore-call */ getPropertyRaw($key);
Loading history...
69
                }
70
            }
71
            throw $exception;
72
        }
73
    }
74
75
    /**
76
     * Determine if a set mutator exists for an attribute.
77
     *
78
     * @param string $key
79
     * @return bool
80
     */
81
    protected function hasSetMutator(string $key): bool
82
    {
83
        return static::hasMutator('set', $key);
84
    }
85
86
87
    /**
88
     * Determine if a get mutator exists for an attribute.
89
     *
90
     * @param string $key
91
     * @return bool
92
     */
93
    protected function hasGetMutator(string $key): bool
94
    {
95
        return static::hasMutator('get', $key);
96
    }
97
98
    /**
99
     * Determine if a set mutator exists for an attribute.
100
     *
101
     * @param string $type
102
     * @param string $key
103
     * @return bool
104
     */
105 13
    protected static function hasMutator(string $type, string $key): bool
106
    {
107 13
        return !empty(static::getMutator($type, $key));
108
    }
109 13
110 3
    protected static function getMutator(string $type, string $key): string
111
    {
112
        $class = static::class;
113 13
114 12
        if (empty(static::$accessors[$class])) {
115
            static::compileMutators();
116
        }
117 4
118 4
        if (isset(static::$accessors[$class][$type][$key])) {
119
            return static::$accessors[$class][$type][$key];
120
        }
121
122
        if (!empty(static::$accessors[$class])) {
123
            return static::$accessors[$class][$type][$key] = '';
124
        }
125
126
        if (!isset(static::$accessors[$class][$type][$key])) {
127
            static::$accessors[$class][$type][$key] = '';
128 3
        }
129
130 3
        return static::$accessors[$class][$type][$key];
131
    }
132 3
133 3
    protected static function compileMutators()
134 3
    {
135
        $class = static::class;
136 3
137 3
        foreach (get_class_methods($class) as $method) {
138 3
            if (in_array($method, ['get','set'])) {
139
                continue;
140
            }
141 3
            $prefix = substr($method, 0, 3);
142 3
            if ($prefix !== 'get' && $prefix !== 'set') {
143 3
                continue;
144
            }
145
146 3
            $field = substr($method, 3);
147
            if (Str::endsWith($field, 'Attribute')) {
148 3
                $field = substr($field, 0, -9);
149
            }
150
151
            static::compileAccessorsMethod($class, $prefix, $method, $field);
152
        }
153
    }
154
155
    /**
156 3
     * @param $class
157
     * @param $prefix
158 3
     * @param $method
159 3
     * @param $field
160
     */
161
    protected static function compileAccessorsMethod($class, $prefix, $method, $field)
162 3
    {
163 3
        $field = lcfirst($field);
164
        static::$accessors[$class][$prefix][$field] = $method;
165 3
166 3
        /** @noinspection PhpDynamicAsStaticMethodCallInspection */
167 3
        $snakeField = Inflector::underscore($field);
0 ignored issues
show
Bug Best Practice introduced by
The method Nip\Inflector\Inflector::underscore() is not static, but was called statically. ( Ignorable by Annotation )

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

167
        /** @scrutinizer ignore-call */ 
168
        $snakeField = Inflector::underscore($field);
Loading history...
168
        static::$accessors[$class][$prefix][$snakeField] = $method;
169
170
        $titleField = ucfirst($field);
171
        static::$accessors[$class][$prefix][$titleField] = $method;
172
    }
173
}
174