Files
notes/src/Common/ReflectedClass.php
T

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;
}
}