183 lines
6.3 KiB
PHP
183 lines
6.3 KiB
PHP
<?php
|
|
|
|
namespace Notes\Common;
|
|
|
|
class ReflectedClass implements ReflectedInterface
|
|
{
|
|
public function __construct(
|
|
public string $name,
|
|
public false|ReflectedClass $parent = false,
|
|
public array $methods = [],
|
|
public array $properties = [],
|
|
public array $attributes = [],
|
|
public array $interfaces = [],
|
|
public array $traits = [],
|
|
) {}
|
|
|
|
public function getClassName() : string
|
|
{
|
|
$exploded = explode('\\', $this->name);
|
|
|
|
return end($exploded);
|
|
}
|
|
|
|
public function getProperties(bool $deep = true) : array
|
|
{
|
|
return $deep ? array_replace(
|
|
$this->parent ? $this->parent->getProperties(true) : [],
|
|
$this->properties
|
|
) : $this->properties;
|
|
}
|
|
|
|
public function getMethods(bool $deep = true) : array
|
|
{
|
|
$m = array_merge(...array_map(fn($e) => $e->getMethods(true), $this->traits));
|
|
|
|
return $deep ? array_replace(
|
|
$this->parent ? $this->parent->getMethods(true) : [],
|
|
array_merge(...array_map(fn($e) => $e->getMethods(true), $this->interfaces)),
|
|
array_merge(...array_map(fn($e) => $e->getMethods(true), $this->traits)),
|
|
$this->methods
|
|
) : $this->methods;
|
|
}
|
|
|
|
public function getAttributes(bool $deep = true, ? string $attributeType = null) : array
|
|
{
|
|
return array_reverse($this->getOrderedAttributes($deep, $attributeType));
|
|
}
|
|
|
|
protected function getOrderedAttributes(bool $deep = true, ? string $attributeType = null) : array
|
|
{
|
|
$attributes = $deep ? array_merge(
|
|
$this->parent ? $this->parent->getOrderedAttributes(true) : [],
|
|
array_merge(...array_map(fn($e) => $e->getOrderedAttributes(true), $this->interfaces)),
|
|
array_merge(...array_map(fn($e) => $e->getOrderedAttributes(true), $this->traits)),
|
|
$this->attributes
|
|
) : $this->attributes;
|
|
|
|
if ($attributeType) {
|
|
$list = [];
|
|
|
|
foreach($attributes as $attribute) {
|
|
if ($attribute->object instanceof $attributeType) {
|
|
$list[] = $attribute;
|
|
}
|
|
}
|
|
|
|
return $list;
|
|
}
|
|
|
|
return $attributes;
|
|
}
|
|
|
|
# Get Attributes based on Native attributes's target
|
|
public function getClassAttributeList(array|string $className, bool $deepSearch, bool $throwOnError = true) : array
|
|
{
|
|
$list = [];
|
|
|
|
foreach((array) $className as $class) {
|
|
$reflection = new \ReflectionClass($class);
|
|
$attributes = $reflection->getAttributes();
|
|
|
|
foreach($attributes as $attribute) {
|
|
# Native PHP Attribute
|
|
if ($attribute->getName() === 'Attribute') {
|
|
if ($attribute->getTarget() && \Attribute::TARGET_CLASS) {
|
|
$list = $this->getClassAttributeListFromClassname($class, $deepSearch, false);
|
|
}
|
|
|
|
if ($attribute->getTarget() && \Attribute::TARGET_METHOD) {
|
|
$list = array_merge($list, $this->getMethodAttributeListFromClassname($class, $deepSearch, false));
|
|
}
|
|
|
|
if ($attribute->getTarget() && \Attribute::TARGET_PROPERTY) {
|
|
$list = array_merge($list, $this->getPropertyAttributeListFromClassname($class, $deepSearch, false));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( empty($list) && $throwOnError ) {
|
|
$className = implode(',', (array) $className);
|
|
throw new \InvalidArgumentException("Attribute(s) `$className` was not found within class {$this->name} (or it's parents / traits)");
|
|
}
|
|
|
|
return $list;
|
|
}
|
|
|
|
|
|
public function getClassAttributeListFromClassname(array|string $className, bool $deepSearch, bool $throwOnError = true) : array
|
|
{
|
|
$list = [];
|
|
|
|
foreach((array) $className as $class) {
|
|
foreach ($this->getAttributes($deepSearch) as $item) {
|
|
if ($item->object instanceof $class) {
|
|
$list[] = $item->object;
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( empty($list) && $throwOnError ) {
|
|
$className = implode(',', (array) $className);
|
|
throw new \InvalidArgumentException("Attribute(s) `$className` was not found within class {$this->name} (or it's parents / traits)");
|
|
}
|
|
|
|
return $list;
|
|
}
|
|
|
|
public function getPropertyAttributeListFromClassname(array|string $className, bool $deepSearch, bool $throwOnError = true) : array
|
|
{
|
|
$list = [];
|
|
|
|
foreach((array) $className as $class) {
|
|
foreach ($this->getProperties($deepSearch) as $property) {
|
|
foreach ($property->attributes as $item) {
|
|
if ($item->object instanceof $class) {
|
|
$list[$property->name] ??= [];
|
|
$list[$property->name][] = $item->object;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( empty($list) && $throwOnError ) {
|
|
$className = implode(',', (array) $className);
|
|
throw new \InvalidArgumentException("Attribute(s) `$className` was not found within properties of {$this->name} (or it's parents / traits)");
|
|
}
|
|
|
|
return $list;
|
|
}
|
|
|
|
public function getMethodAttributeListFromClassname(array|string $className, bool $deepSearch, bool $throwOnError = true) : array
|
|
{
|
|
$list = [];
|
|
|
|
foreach((array) $className as $class) {
|
|
foreach ($this->getMethods($deepSearch) as $method) {
|
|
foreach ($method->attributes as $item) {
|
|
if ($item->object instanceof $class) {
|
|
$list[$method->name] ??= [];
|
|
$list[$method->name][] = $item->object;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( empty($list) && $throwOnError ) {
|
|
$className = implode(',', (array) $className);
|
|
throw new \InvalidArgumentException("Attribute(s) `$className` was not found within methods of {$this->name} (or it's parents / traits)");
|
|
}
|
|
|
|
return $list;
|
|
}
|
|
|
|
public function getAttribute(string $attributeType): ?object
|
|
{
|
|
foreach($this->getAttributes(true, $attributeType) as $attribute) {
|
|
return $attribute;
|
|
}
|
|
|
|
return null;
|
|
}
|
|
} |