Passed
Push — main ( 84621c...2621a4 )
by Gabriel
02:39
created

AccessorsTrait::callAccessors()   A

Complexity

Conditions 6
Paths 9

Size

Total Lines 27
Code Lines 19

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 1
CRAP Score 33.0481

Importance

Changes 2
Bugs 0 Features 0
Metric Value
cc 6
eloc 19
c 2
b 0
f 0
nc 9
nop 3
dl 0
loc 27
ccs 1
cts 11
cp 0.0909
crap 33.0481
rs 9.0111
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
        if ($type !== 'get') {
63
            return $this->{$method}(...$params);
64
        }
65
66
        try {
67
            set_error_handler(
68
                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
                    throw new Exception($errstr, $errno);
70
                },
71
                E_NOTICE
72
            );
73
            $return = $this->{$method}(...$params);
74
            restore_error_handler();
75
            return $return;
76
        } catch (Exception $exception) {
77
            $message = $exception->getMessage();
78
            if (Str::startsWith($message, 'Undefined property:')
79
                && Str::endsWith($message, '::$' . $key)) {
80
                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

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

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