Passed
Push — master ( 5f88dd...10f6bc )
by Smoren
12:50
created

ObjectAccessHelper::hasMethod()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 1
nc 1
nop 2
dl 0
loc 3
rs 10
c 1
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Smoren\Schemator\Helpers;
6
7
use ReflectionMethod;
8
use ReflectionProperty;
9
use stdClass;
10
11
/**
12
 * Tool for reflecting and accessing object properties and methods.
13
 */
14
class ObjectAccessHelper
15
{
16
    /**
17
     * Returns value of the object property.
18
     *
19
     * Can access property by its name or by getter.
20
     *
21
     * @param object $object
22
     * @param string $propertyName
23
     *
24
     * @return mixed
25
     *
26
     * @throws \InvalidArgumentException
27
     */
28
    public static function getPropertyValue(object $object, string $propertyName)
29
    {
30
        if (static::hasPropertyAccessibleByGetter($object, $propertyName)) {
31
            return static::getPropertyValueByGetter($object, $propertyName);
32
        }
33
34
        if (static::hasPublicProperty($object, $propertyName)) {
35
            return $object->{$propertyName};
36
        }
37
38
        $className = get_class($object);
39
        throw new \InvalidArgumentException("Property '{$className}::{$propertyName}' is not readable");
40
    }
41
42
    /**
43
     * Returns reference to the object property.
44
     *
45
     * @param object $object
46
     * @param string $propertyName
47
     * @param mixed $defaultValue
48
     *
49
     * @return mixed
50
     *
51
     * @throws \InvalidArgumentException
52
     */
53
    public static function &getPropertyRef(object &$object, string $propertyName, $defaultValue = null)
54
    {
55
        if (static::hasPublicProperty($object, $propertyName)) {
56
            return $object->{$propertyName};
57
        }
58
59
        if ($object instanceof stdClass) {
60
            $object->{$propertyName} = $defaultValue;
61
            return $object->{$propertyName};
62
        }
63
64
        $className = get_class($object);
65
        throw new \InvalidArgumentException("Property '{$className}::{$propertyName}' is not readable");
66
    }
67
68
    /**
69
     * Returns value of the object property.
70
     *
71
     * Can access property by its name or by getter.
72
     *
73
     * @param object $object
74
     * @param string $propertyName
75
     * @param mixed $value
76
     *
77
     * @return void
78
     *
79
     * @throws \InvalidArgumentException
80
     */
81
    public static function setPropertyValue(object $object, string $propertyName, $value): void
82
    {
83
        if (static::hasPropertyAccessibleBySetter($object, $propertyName)) {
84
            static::setPropertyValueBySetter($object, $propertyName, $value);
85
            return;
86
        }
87
88
        if (static::hasPublicProperty($object, $propertyName) || $object instanceof stdClass) {
89
            $object->{$propertyName} = $value;
90
            return;
91
        }
92
93
        $className = get_class($object);
94
        throw new \InvalidArgumentException("Property '{$className}::{$propertyName}' is not writable");
95
    }
96
97
    /**
98
     * Returns true if object has property that is accessible to read by name or by getter.
99
     *
100
     * @param object $object
101
     * @param string $propertyName
102
     *
103
     * @return bool
104
     */
105
    public static function hasReadableProperty(object $object, string $propertyName): bool
106
    {
107
        return static::hasPublicProperty($object, $propertyName)
108
            || static::hasPropertyAccessibleByGetter($object, $propertyName);
109
    }
110
111
    /**
112
     * Returns true if object has property that is accessible to write by name or by setter.
113
     *
114
     * @param object $object
115
     * @param string $propertyName
116
     *
117
     * @return bool
118
     */
119
    public static function hasWritableProperty(object $object, string $propertyName): bool
120
    {
121
        return static::hasPublicProperty($object, $propertyName)
122
            || static::hasPropertyAccessibleBySetter($object, $propertyName);
123
    }
124
125
    /**
126
     * Returns true if object has public property.
127
     *
128
     * @param object $object
129
     * @param string $propertyName
130
     *
131
     * @return bool
132
     */
133
    public static function hasPublicProperty(object $object, string $propertyName): bool
134
    {
135
        if ($object instanceof stdClass) {
136
            return static::hasProperty($object, $propertyName);
137
        }
138
139
        return
140
            static::hasProperty($object, $propertyName) &&
141
            static::getReflectionProperty($object, $propertyName)->isPublic();
142
    }
143
144
    /**
145
     * Returns true if object has property.
146
     *
147
     * @param object $object
148
     * @param string $propertyName
149
     *
150
     * @return bool
151
     */
152
    public static function hasProperty(object $object, string $propertyName): bool
153
    {
154
        return property_exists($object, $propertyName);
155
    }
156
157
    /**
158
     * Returns true if object has public method.
159
     *
160
     * @param object $object
161
     * @param string $methodName
162
     *
163
     * @return bool
164
     */
165
    public static function hasPublicMethod(object $object, string $methodName): bool
166
    {
167
        return
168
            static::hasMethod($object, $methodName) &&
169
            static::getReflectionMethod($object, $methodName)->isPublic();
170
    }
171
172
    /**
173
     * Returns true if object has method.
174
     *
175
     * @param object $object
176
     * @param string $methodName
177
     *
178
     * @return bool
179
     */
180
    public static function hasMethod(object $object, string $methodName): bool
181
    {
182
        return method_exists($object, $methodName);
183
    }
184
185
    /**
186
     * Returns true if object has property that is accessible by getter.
187
     *
188
     * @param object $object
189
     * @param string $propertyName
190
     *
191
     * @return bool
192
     */
193
    protected static function hasPropertyAccessibleByGetter(object $object, string $propertyName): bool
194
    {
195
        return static::hasPublicMethod($object, static::getPropertyGetterName($propertyName));
196
    }
197
198
    /**
199
     * Returns true if object has property that is accessible by setter.
200
     *
201
     * @param object $object
202
     * @param string $propertyName
203
     *
204
     * @return bool
205
     */
206
    protected static function hasPropertyAccessibleBySetter(object $object, string $propertyName): bool
207
    {
208
        return static::hasPublicMethod($object, static::getPropertySetterName($propertyName));
209
    }
210
211
    /**
212
     * Returns property value by getter.
213
     *
214
     * @param object $object
215
     * @param string $propertyName
216
     *
217
     * @return mixed
218
     */
219
    protected static function getPropertyValueByGetter(object $object, string $propertyName)
220
    {
221
        return $object->{static::getPropertyGetterName($propertyName)}();
222
    }
223
224
    /**
225
     * Sets property value by setter.
226
     *
227
     * @param object $object
228
     * @param string $propertyName
229
     * @param mixed $value
230
     *
231
     * @return void
232
     */
233
    protected static function setPropertyValueBySetter(object $object, string $propertyName, $value): void
234
    {
235
        $object->{static::getPropertySetterName($propertyName)}($value);
236
    }
237
238
    /**
239
     * Returns reflection object of the object property.
240
     *
241
     * @param object $object
242
     * @param string $propertyName
243
     *
244
     * @return ReflectionProperty
245
     */
246
    protected static function getReflectionProperty(object $object, string $propertyName): ReflectionProperty
247
    {
248
        return new ReflectionProperty(get_class($object), $propertyName);
249
    }
250
251
    /**
252
     * Returns reflection object of the object method.
253
     *
254
     * @param object $object
255
     * @param string $methodName
256
     *
257
     * @return ReflectionMethod
258
     */
259
    protected static function getReflectionMethod(object $object, string $methodName): ReflectionMethod
260
    {
261
        return new ReflectionMethod(get_class($object), $methodName);
262
    }
263
264
    /**
265
     * Returns property getter name.
266
     *
267
     * @param string $propertyName
268
     *
269
     * @return string
270
     */
271
    protected static function getPropertyGetterName(string $propertyName): string
272
    {
273
        return 'get' . ucfirst($propertyName);
274
    }
275
276
    /**
277
     * Returns property setter name.
278
     *
279
     * @param string $propertyName
280
     *
281
     * @return string
282
     */
283
    protected static function getPropertySetterName(string $propertyName): string
284
    {
285
        return 'set' . ucfirst($propertyName);
286
    }
287
}
288