AccessorsTrait::getMutator()   A
last analyzed

Complexity

Conditions 5
Paths 8

Size

Total Lines 21
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 7
CRAP Score 5.675

Importance

Changes 0
Metric Value
cc 5
eloc 10
c 0
b 0
f 0
nc 8
nop 2
dl 0
loc 21
ccs 7
cts 10
cp 0.7
crap 5.675
rs 9.6111
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(string $key)
32
    {
33
        if (empty($key)) {
34
            throw new \InvalidArgumentException("Please provide a key argument");
35
        }
36
        /** @noinspection PhpUnhandledExceptionInspection */
37
        return $this->callAccessors('get', $key);
38
    }
39
40
    /**
41
     * @param $key
42
     * @param $value
43
     * @return mixed
44
     * @noinspection PhpDocMissingThrowsInspection
45
     */
46
    public function setMutated($key, $value)
47
    {
48
        /** @noinspection PhpUnhandledExceptionInspection */
49
        return $this->callAccessors('set', $key, [$value]);
50
    }
51
52
    /**
53
     * @param string $type
54
     * @param string $key
55
     * @param array $params
56 16
     * @return mixed
57
     * @throws Exception
58 16
     */
59 16
    protected function callAccessors(string $type, string $key, $params = [])
60 10
    {
61
        $method = static::getMutator($type, $key);
62 10
        if (!$method) {
63 9
            return Constants::NO_ACCESSORS_FOUND;
64
        }
65
        if ($type !== 'get') {
66
            return $this->{$method}(...$params);
67 7
        }
68 7
69 1
        try {
70 7
            set_error_handler(
71 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...
72
                    throw new Exception($errstr, $errno);
73 7
                },
74 7
                E_NOTICE
75 7
            );
76 1
            $return = $this->{$method}(...$params);
77 1
            restore_error_handler();
78 1
            return $return;
79 1
        } catch (Exception $exception) {
80 1
            restore_error_handler();
81 1
            $message = $exception->getMessage();
82
            if (Str::startsWith($message, 'Undefined property:')
83
                && Str::endsWith($message, '::$' . $key)) {
84
                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

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

186
        /** @scrutinizer ignore-call */ 
187
        $snakeField = Inflector::underscore($field);
Loading history...
187
        static::$accessors[$class][$prefix][$snakeField] = $method;
188
189
        $titleField = ucfirst($field);
190
        static::$accessors[$class][$prefix][$titleField] = $method;
191
    }
192
}
193