|
17 | 17 | * Reflection utilities. |
18 | 18 | */ |
19 | 19 | class Reflection { |
| 20 | + /** |
| 21 | + * Get the class name for a target. |
| 22 | + * |
| 23 | + * @param string|object $target The target to get the class name for. |
| 24 | + * @return string |
| 25 | + */ |
| 26 | + private static function get_classname( string|object $target ): string { |
| 27 | + if ( \is_string( $target ) ) { |
| 28 | + return $target; |
| 29 | + } |
| 30 | + |
| 31 | + return $target instanceof ReflectionClass |
| 32 | + ? $target->getName() |
| 33 | + : $target::class; |
| 34 | + } |
| 35 | + |
20 | 36 | /** |
21 | 37 | * Get a reflector for the target. |
22 | 38 | * |
@@ -96,7 +112,7 @@ public static function is_valid_function( callable|array|string|object $target ) |
96 | 112 | * @return bool |
97 | 113 | */ |
98 | 114 | public static function class_implements( string|object $thing, string $iname, bool $autoload = true ): bool { |
99 | | - $cname = \is_object( $thing ) ? $thing::class : $thing; |
| 115 | + $cname = static::get_classname( $thing ); |
100 | 116 |
|
101 | 117 | return \class_exists( $cname ) && \in_array( $iname, \class_implements( $thing, $autoload ), true ); |
102 | 118 | } |
@@ -211,44 +227,55 @@ public static function get_decorator( |
211 | 227 | ?? null; |
212 | 228 | } |
213 | 229 |
|
| 230 | + /** |
| 231 | + * Get traits used by a class. |
| 232 | + * |
| 233 | + * @param string|object $target The class to get the traits for. |
| 234 | + * @param bool $autoload Whether to allow this function to load the class automatically through the __autoload() magic method. |
| 235 | + * @return array<class-string,class-string> |
| 236 | + */ |
| 237 | + public static function class_uses( string|object $target, bool $autoload = true ): array { |
| 238 | + return \array_reduce( |
| 239 | + \class_uses( $target, $autoload ), |
| 240 | + static fn( $ts, $t ) => $ts + array( $t => $t ) + \class_uses( $t, $autoload ), |
| 241 | + array(), |
| 242 | + ); |
| 243 | + } |
| 244 | + |
214 | 245 | /** |
215 | 246 | * Get all the traits used by a class. |
216 | 247 | * |
217 | 248 | * @param string|object $target Class or object to get the traits for. |
218 | 249 | * @param bool $autoload Whether to allow this function to load the class automatically through the __autoload() magic method. |
219 | | - * @return array<class-string> Array of traits. |
| 250 | + * @return array<class-string,class-string> |
220 | 251 | */ |
221 | 252 | public static function class_uses_deep( string|object $target, bool $autoload = true ) { |
222 | | - $traits = array(); |
223 | | - |
224 | | - do { |
225 | | - $traits = \array_merge( \class_uses( $target, $autoload ), $traits ); |
226 | | - $target = \get_parent_class( $target ); |
227 | | - } while ( $target ); |
| 253 | + $target = static::get_classname( $target ); |
| 254 | + $traits = array(); |
228 | 255 |
|
229 | | - foreach ( $traits as $trait ) { |
230 | | - $traits = \array_merge( \class_uses( $trait, $autoload ), $traits ); |
231 | | - } |
| 256 | + do { |
| 257 | + $traits += static::class_uses( $target, $autoload ); |
| 258 | + $target = \get_parent_class( $target ); |
| 259 | + } while ( $target ); |
232 | 260 |
|
233 | | - return \array_values( \array_unique( $traits ) ); |
| 261 | + return $traits; |
234 | 262 | } |
235 | 263 |
|
236 | 264 | /** |
237 | 265 | * Get the inheritance chain for a class. |
238 | 266 | * |
239 | 267 | * @template T of object |
240 | 268 | * |
241 | | - * @param class-string<T>|T $target The class to get the inheritance chain for. |
242 | | - * @param bool $inclusive Whether to include the target class in the chain. |
| 269 | + * @param class-string<T>|ReflectionClass<T>|T $target The class to get the inheritance chain for. |
| 270 | + * @param bool $inclusive Whether to include the target class in the chain. |
243 | 271 | * @return array<class-string> |
244 | 272 | */ |
245 | 273 | public static function get_inheritance_chain( string|object $target, bool $inclusive = false ): array { |
246 | | - $refl = static::get_reflector( $target ); |
247 | | - $chain = $inclusive ? array( $refl->getName() ) : array(); |
| 274 | + $target = static::get_classname( $target ); |
| 275 | + $chain = $inclusive ? array( $target ) : array(); |
248 | 276 |
|
249 | | - while ( $refl->getParentClass() ) { |
250 | | - $refl = $refl->getParentClass(); |
251 | | - $chain[] = $refl->getName(); |
| 277 | + while ( $target = \get_parent_class( $target ) ) { |
| 278 | + $chain[] = $target; |
252 | 279 | } |
253 | 280 |
|
254 | 281 | return $chain; |
|
0 commit comments