Issues (81)

src/Behaviors/Accessors/AccessorsTrait.php (4 issues)

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
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...
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
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