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