Passed
Push — main ( d3da7f...f4e8a4 )
by Gabriel
02:19
created

AccessorsTrait::hasMutator()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
cc 1
eloc 1
c 0
b 0
f 0
nc 1
nop 2
dl 0
loc 3
ccs 0
cts 2
cp 0
crap 2
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
    /**
50
     * @param string $type
51
     * @param string $key
52
     * @param array $params
53
     * @return mixed
54
     * @throws Exception
55
     */
56 16
    protected function callAccessors(string $type, string $key, $params = [])
57
    {
58 16
        $method = static::getMutator($type, $key);
59 16
        if (!$method) {
60 10
            return Constants::NO_ACCESSORS_FOUND;
61
        }
62 10
        if ($type !== 'get') {
63 9
            return $this->{$method}(...$params);
64
        }
65
66
        try {
67 7
            set_error_handler(
68 7
                function ($errno, $errstr, $errfile, $errline) use ($type, $key) {
0 ignored issues
show
Unused Code introduced by
The import $type is not used and could be removed.

This check looks for imports that have been defined, but are not used in the scope.

Loading history...
Unused Code introduced by
The import $key is not used and could be removed.

This check looks for imports that have been defined, but are not used in the scope.

Loading history...
69 1
                    throw new Exception($errstr, $errno);
70 7
                },
71 7
                E_NOTICE
72
            );
73 7
            $return = $this->{$method}(...$params);
74 7
            restore_error_handler();
75 7
            return $return;
76 1
        } catch (Exception $exception) {
77 1
            restore_error_handler();
78 1
            $message = $exception->getMessage();
79 1
            if (Str::startsWith($message, 'Undefined property:')
80 1
                && Str::endsWith($message, '::$' . $key)) {
81 1
                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

81
                return $this->/** @scrutinizer ignore-call */ getPropertyRaw($key);
Loading history...
82
            }
83
            throw $exception;
84
        }
85
    }
86
87
    /**
88
     * Determine if a set mutator exists for an attribute.
89
     *
90
     * @param string $key
91
     * @return bool
92
     */
93
    protected function hasSetMutator(string $key): bool
94
    {
95
        return static::hasMutator('set', $key);
96
    }
97
98
99
    /**
100
     * Determine if a get mutator exists for an attribute.
101
     *
102
     * @param string $key
103
     * @return bool
104
     */
105
    protected function hasGetMutator(string $key): bool
106
    {
107
        return static::hasMutator('get', $key);
108
    }
109
110
    /**
111
     * Determine if a set mutator exists for an attribute.
112
     *
113
     * @param string $type
114
     * @param string $key
115
     * @return bool
116
     */
117
    protected static function hasMutator(string $type, string $key): bool
118
    {
119
        return !empty(static::getMutator($type, $key));
120
    }
121
122 16
    protected static function getMutator(string $type, string $key): string
123
    {
124 16
        $class = static::class;
125
126 16
        if (empty(static::$accessors[$class])) {
127 3
            static::compileMutators();
128
        }
129
130 16
        if (isset(static::$accessors[$class][$type][$key])) {
131 15
            return static::$accessors[$class][$type][$key];
132
        }
133
134 5
        if (!empty(static::$accessors[$class])) {
135 5
            return static::$accessors[$class][$type][$key] = '';
136
        }
137
138
        if (!isset(static::$accessors[$class][$type][$key])) {
139
            static::$accessors[$class][$type][$key] = '';
140
        }
141
142
        return static::$accessors[$class][$type][$key];
143
    }
144
145 3
    protected static function compileMutators()
146
    {
147 3
        $class = static::class;
148
149 3
        foreach (get_class_methods($class) as $method) {
150 3
            if (in_array($method, ['get','set'])) {
151 3
                continue;
152
            }
153 3
            $prefix = substr($method, 0, 3);
154 3
            if ($prefix !== 'get' && $prefix !== 'set') {
155 3
                continue;
156
            }
157
158 3
            $field = substr($method, 3);
159 3
            if (Str::endsWith($field, 'Attribute')) {
160 3
                $field = substr($field, 0, -9);
161
            }
162
163 3
            static::compileAccessorsMethod($class, $prefix, $method, $field);
164
        }
165 3
    }
166
167
    /**
168
     * @param $class
169
     * @param $prefix
170
     * @param $method
171
     * @param $field
172
     */
173 3
    protected static function compileAccessorsMethod($class, $prefix, $method, $field)
174
    {
175 3
        $field = lcfirst($field);
176 3
        static::$accessors[$class][$prefix][$field] = $method;
177
178
        /** @noinspection PhpDynamicAsStaticMethodCallInspection */
179 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

179
        /** @scrutinizer ignore-call */ 
180
        $snakeField = Inflector::underscore($field);
Loading history...
180 3
        static::$accessors[$class][$prefix][$snakeField] = $method;
181
182 3
        $titleField = ucfirst($field);
183 3
        static::$accessors[$class][$prefix][$titleField] = $method;
184 3
    }
185
}
186