Passed
Branch master (480565)
by Randy
02:16
created

ObjectFacade::setValue()   B

Complexity

Conditions 5
Paths 5

Size

Total Lines 16
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 8.125

Importance

Changes 0
Metric Value
dl 0
loc 16
ccs 4
cts 8
cp 0.5
rs 8.8571
c 0
b 0
f 0
cc 5
eloc 8
nc 5
nop 2
crap 8.125
1
<?php
2
3
namespace Dgame\Object;
4
5
use ICanBoogie\Inflector;
6
use ReflectionClass;
7
use ReflectionMethod;
8
use ReflectionProperty;
9
use function Dgame\Ensurance\enforce;
10
11
/**
12
 * Class ObjectFacade
13
 * @package Dgame\Object
14
 */
15
class ObjectFacade
16
{
17
    /**
18
     * @var object
19
     */
20
    private $object;
21
    /**
22
     * @var ReflectionClass
23
     */
24
    private $reflection;
25
26
    /**
27
     * ObjectFacade constructor.
28
     *
29
     * @param object $object
30
     */
31 10
    public function __construct($object)
32
    {
33 10
        enforce(is_object($object))->orThrow('That is not a valid object');
34
35 10
        $this->object = $object;
36 10
    }
37
38
    /**
39
     * @return object
40
     */
41 3
    final public function getObject()
42
    {
43 3
        return $this->object;
44
    }
45
46
    /**
47
     * @return ReflectionClass
48
     */
49 10
    final public function getReflection(): ReflectionClass
50
    {
51 10
        if ($this->reflection === null) {
52 10
            $this->reflection = new ReflectionClass($this->object);
53
        }
54
55 10
        return $this->reflection;
56
    }
57
58
    /**
59
     * @param string $name
60
     *
61
     * @return array
62
     */
63 2
    private function getNameVariations(string $name): array
64
    {
65
        return [
66 2
            Inflector::get()->camelize($name, Inflector::DOWNCASE_FIRST_LETTER),
67 2
            Inflector::get()->camelize($name, Inflector::UPCASE_FIRST_LETTER),
68 2
            Inflector::get()->underscore($name)
69
        ];
70
    }
71
72
    /**
73
     * @param string $name
74
     * @param        $value
75
     *
76
     * @return bool
77
     */
78 2
    final public function setValue(string $name, $value): bool
79
    {
80 2
        foreach ($this->getNameVariations($name) as $attribute) {
81 2
            if ($this->setValueByProperty($attribute, $value) || $this->setValueByMethod($attribute, $value)) {
82 2
                return true;
83
            }
84
        }
85
86
        if ($this->hasMethod('__set')) {
87
            $this->invokeMethod('__set', $name, $value);
88
89
            return true;
90
        }
91
92
        return false;
93
    }
94
95
    /**
96
     * @param string $name
97
     *
98
     * @return mixed|null
99
     */
100 2
    final public function getValue(string $name)
101
    {
102 2
        foreach ($this->getNameVariations($name) as $attribute) {
103 2
            $property = $this->getPropertyByName($attribute);
104 2
            if ($property !== null && Validator::new($this)->isValidProperty($property)) {
105 1
                return $property->getValue($this->object);
106
            }
107
108 1
            $method = $this->getGetterMethod($name);
109 1
            if ($method !== null && Validator::new($this)->isValidGetterMethod($method)) {
110 1
                return $method->invoke($this->object);
111
            }
112
        }
113
114
        return $this->invokeMethod('__get', $name);
115
    }
116
117
    /**
118
     * @param string $name
119
     * @param        $value
120
     *
121
     * @return bool
122
     */
123 2
    final public function setValueByProperty(string $name, $value): bool
124
    {
125 2
        $property = $this->getPropertyByName($name);
126 2
        if ($property !== null && Validator::new($this)->isValidProperty($property)) {
127 1
            $property->setValue($this->object, $value);
128
129 1
            return true;
130
        }
131
132 1
        return false;
133
    }
134
135
    /**
136
     * @param string $name
137
     * @param        $value
138
     *
139
     * @return bool
140
     */
141 1
    final public function setValueByMethod(string $name, $value): bool
142
    {
143 1
        $method = $this->getSetterMethod($name);
144 1
        if ($method !== null && Validator::new($this)->isValidSetterMethod($method, $value)) {
145 1
            $method->invoke($this->object, $value);
146
147 1
            return true;
148
        }
149
150 1
        return false;
151
    }
152
153
    /**
154
     * @param string $name
155
     *
156
     * @return mixed|null
157
     */
158 2
    final public function getValueByMethod(string $name)
159
    {
160 2
        $method = $this->getGetterMethod($name);
161 2
        if ($method !== null && Validator::new($this)->isValidGetterMethod($method)) {
162 2
            return $method->invoke($this->object);
163
        }
164
165 1
        return null;
166
    }
167
168
    /**
169
     * @param string $name
170
     *
171
     * @return mixed|null
172
     */
173 2
    final public function getValueByProperty(string $name)
174
    {
175 2
        $property = $this->getPropertyByName($name);
176 2
        if ($property !== null && Validator::new($this)->isValidProperty($property)) {
177 2
            return $property->getValue($this->object);
178
        }
179
180 1
        return null;
181
    }
182
183
    /**
184
     * @param string $postfix
185
     *
186
     * @return null|ReflectionMethod
187
     */
188 2
    final public function getSetterMethod(string $postfix)
189
    {
190 2
        return $this->getMethod($postfix, ['set', 'append']);
191
    }
192
193
    /**
194
     * @param string $postfix
195
     *
196
     * @return null|ReflectionMethod
197
     */
198 3
    final public function getGetterMethod(string $postfix)
199
    {
200 3
        return $this->getMethod($postfix, ['get']);
201
    }
202
203
    /**
204
     * @param string $postfix
205
     * @param array  $prefixe
206
     *
207
     * @return null|ReflectionMethod
208
     */
209 4
    final public function getMethod(string $postfix, array $prefixe)
210
    {
211 4
        foreach ($prefixe as $prefix) {
212 4
            $method = $this->getMethodByName($prefix . ucfirst($postfix));
213 4
            if ($method !== null) {
214 4
                return $method;
215
            }
216
        }
217
218 1
        return null;
219
    }
220
221
    /**
222
     * @param string $name
223
     * @param array  ...$args
224
     *
225
     * @return mixed|null
226
     */
0 ignored issues
show
Documentation introduced by
Consider making the type for parameter $args a bit more specific; maybe use array[].
Loading history...
227
    final public function invokeMethod(string $name, ...$args)
228
    {
229
        $method = $this->getMethodByName($name);
230
        if ($method !== null && Validator::new($this)->areValidMethodArguments($method, ...$args)) {
231
            return $method->invokeArgs($this->object, $args);
232
        }
233
234
        return null;
235
    }
236
237
    /**
238
     * @param string $name
239
     *
240
     * @return null|ReflectionMethod
241
     */
242 5
    final public function getMethodByName(string $name)
243
    {
244 5
        return $this->hasMethod($name) ? $this->getReflection()->getMethod($name) : null;
245
    }
246
247
    /**
248
     * @param string $name
249
     *
250
     * @return null|ReflectionProperty
251
     */
252 4
    final public function getPropertyByName(string $name)
253
    {
254 4
        return $this->hasProperty($name) ? $this->getReflection()->getProperty($name) : null;
255
    }
256
257
    /**
258
     * @param string $name
259
     *
260
     * @return bool
261
     */
262 5
    final public function hasProperty(string $name): bool
263
    {
264 5
        return $this->getReflection()->hasProperty($name);
265
    }
266
267
    /**
268
     * @param string $name
269
     *
270
     * @return bool
271
     */
272 6
    final public function hasMethod(string $name): bool
273
    {
274 6
        return $this->getReflection()->hasMethod($name);
275
    }
276
}
277