- Added a new ObjectResolver which is code comming from ObjectReflection.
This commit is contained in:
parent
504c87b134
commit
9f8bc3c0d5
|
@ -6,9 +6,12 @@ use Reflector, ReflectionClass, ReflectionProperty, ReflectionMethod;
|
||||||
|
|
||||||
class ObjectReflection {
|
class ObjectReflection {
|
||||||
|
|
||||||
|
protected string $classname;
|
||||||
|
|
||||||
public AnnotationReader $annotationReader;
|
public AnnotationReader $annotationReader;
|
||||||
|
|
||||||
public function __construct($class, AnnotationReader $annotationReader = null) {
|
public function __construct($class, AnnotationReader $annotationReader = null) {
|
||||||
|
$this->classname = ltrim($class, '\\');
|
||||||
$this->classReflection = $class instanceof ReflectionClass ? $class : new ReflectionClass($class);
|
$this->classReflection = $class instanceof ReflectionClass ? $class : new ReflectionClass($class);
|
||||||
$this->annotationReader = $annotationReader ?: AnnotationReader::fromClass($class);
|
$this->annotationReader = $annotationReader ?: AnnotationReader::fromClass($class);
|
||||||
}
|
}
|
||||||
|
@ -18,53 +21,61 @@ class ObjectReflection {
|
||||||
return new static($class);
|
return new static($class);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function read() : array
|
public function read(bool $fullUses = true, bool $fullObject = true, $fullMethod = true, $fullProperty = true) : array
|
||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
'uses' => $this->gatherUses(true),
|
'uses' => $this->gatherUses($fullUses),
|
||||||
'class' => $this->gatherClass(true),
|
'class' => $this->gatherClass($fullObject),
|
||||||
'method' => $this->gatherMethods(true),
|
'method' => $this->gatherMethods($fullMethod),
|
||||||
'property' => $this->gatherProperties(true),
|
'property' => $this->gatherProperties($fullProperty),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
public function gatherUses(bool $full = true) : array
|
public function gatherUses(bool $full = true) : array
|
||||||
{
|
{
|
||||||
$list = [];
|
|
||||||
|
|
||||||
if ( $full ) {
|
if ( $full ) {
|
||||||
if ( $parentClass = $this->classReflection->getParentClass() ) {
|
if ( $parentClass = $this->classReflection->getParentClass() ) {
|
||||||
$list = static::fromClass($parentClass)->gatherUses(true);
|
$list = static::fromClass($parentClass)->gatherUses(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach($this->classReflection->getTraits() as $trait) {
|
foreach($this->classReflection->getTraits() as $trait) {
|
||||||
$list = array_merge($list, static::fromClass($trait)->gatherUses(true));
|
$list = array_replace(static::fromClass($trait)->gatherUses(true), $list ?? []);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return array_merge($this->getUsesStatements(), $list);
|
return array_replace($list ?? [], $this->getUsesStatements());
|
||||||
}
|
}
|
||||||
|
|
||||||
public function gatherClass(bool $full = true) : array
|
public function gatherClass(bool $full = true) : array
|
||||||
{
|
{
|
||||||
$class = [];
|
|
||||||
|
|
||||||
if ( $full ) {
|
if ( $full ) {
|
||||||
if ( $parentClass = $this->classReflection->getParentClass() ) {
|
if ( $parentClass = $this->classReflection->getParentClass() ) {
|
||||||
$class = static::fromClass($parentClass)->gatherClass(true);
|
$class = static::fromClass($parentClass)->gatherClass(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ( $traits = $this->classReflection->getTraits() ) {
|
||||||
|
foreach($traits as $key => $value) {
|
||||||
|
$traitTags = static::fromClass($key)->gatherClass(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( $interfaces = $this->classReflection->getInterfaces() ) {
|
||||||
|
foreach($interfaces as $key => $value) {
|
||||||
|
$interfaceTags = static::fromClass($key)->gatherClass(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
$itemName = function($item) {
|
$itemName = function($item) {
|
||||||
return $item->getName();
|
return $item->getName();
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
return [
|
return array_merge_recursive($class ?? [], $traitTags ?? [], $interfaceTags ?? [], [
|
||||||
'tags' => array_merge($class, $this->annotationReader->getClass($this->classReflection))
|
'tags' => $this->annotationReader->getClass($this->classReflection)
|
||||||
] + ( ! $full ? [] : [
|
] + ( ! $full ? [] : [
|
||||||
'traits' => array_map($itemName, $this->classReflection->getTraits()),
|
'traits' => array_map($itemName, $traits),
|
||||||
'interfaces' => array_map($itemName, $this->classReflection->getInterfaces()),
|
'interfaces' => array_map($itemName, $interfaces),
|
||||||
]);
|
] ));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function gatherProperties(bool $full = true, int $filter =
|
public function gatherProperties(bool $full = true, int $filter =
|
||||||
|
@ -73,7 +84,6 @@ class ObjectReflection {
|
||||||
ReflectionProperty::IS_PRIVATE
|
ReflectionProperty::IS_PRIVATE
|
||||||
) : array
|
) : array
|
||||||
{
|
{
|
||||||
$properties = [];
|
|
||||||
$defaultValues = $this->classReflection->getDefaultProperties();
|
$defaultValues = $this->classReflection->getDefaultProperties();
|
||||||
|
|
||||||
if ( $full ) {
|
if ( $full ) {
|
||||||
|
@ -82,11 +92,9 @@ class ObjectReflection {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$properties = array_merge($properties, $this->classReflection->getProperties($filter));
|
|
||||||
|
|
||||||
$list = [];
|
$list = [];
|
||||||
|
|
||||||
foreach($properties as $property) {
|
foreach($this->classReflection->getProperties($filter) as $property) {
|
||||||
$current = [
|
$current = [
|
||||||
'name' => $property->getName()
|
'name' => $property->getName()
|
||||||
];
|
];
|
||||||
|
@ -110,7 +118,7 @@ class ObjectReflection {
|
||||||
$list[ $current['name'] ] = $current;
|
$list[ $current['name'] ] = $current;
|
||||||
}
|
}
|
||||||
|
|
||||||
return $list;
|
return array_merge($properties ?? [], $list);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function gatherMethods(bool $full = true, int $filter =
|
public function gatherMethods(bool $full = true, int $filter =
|
||||||
|
@ -120,7 +128,7 @@ class ObjectReflection {
|
||||||
ReflectionMethod::IS_STATIC
|
ReflectionMethod::IS_STATIC
|
||||||
) : array
|
) : array
|
||||||
{
|
{
|
||||||
$list = $methods = [];
|
$list = [];
|
||||||
|
|
||||||
if ( $full ) {
|
if ( $full ) {
|
||||||
if ( $parentClass = $this->classReflection->getParentClass() ) {
|
if ( $parentClass = $this->classReflection->getParentClass() ) {
|
||||||
|
@ -128,9 +136,11 @@ class ObjectReflection {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$methods = array_merge($methods, $this->classReflection->getMethods($filter));
|
foreach($this->classReflection->getMethods($filter) as $method) {
|
||||||
|
if ( ! $full && ( $method->class !== $this->classname ) ) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
foreach($methods as $method) {
|
|
||||||
$parameters = [];
|
$parameters = [];
|
||||||
|
|
||||||
foreach($method->getParameters() as $parameter) {
|
foreach($method->getParameters() as $parameter) {
|
||||||
|
@ -162,7 +172,7 @@ class ObjectReflection {
|
||||||
$list[ $current['name'] ] = $current;
|
$list[ $current['name'] ] = $current;
|
||||||
}
|
}
|
||||||
|
|
||||||
return $list;
|
return array_merge($methods ?? [], $list);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function ignoreElementAnnotation($tags) : bool
|
protected function ignoreElementAnnotation($tags) : bool
|
||||||
|
|
|
@ -0,0 +1,158 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Notes;
|
||||||
|
|
||||||
|
class ObjectResolver {
|
||||||
|
|
||||||
|
const KEY_ENTITY_NAME = 01;
|
||||||
|
const KEY_COLUMN_NAME = 02;
|
||||||
|
|
||||||
|
public string $objectClass;
|
||||||
|
|
||||||
|
public array $uses;
|
||||||
|
|
||||||
|
public array $class;
|
||||||
|
|
||||||
|
public array $properties;
|
||||||
|
|
||||||
|
public array $methods;
|
||||||
|
|
||||||
|
public function __construct(string $objectClass, bool $fullUses = true, bool $fullObject = true, $fullMethod = true, $fullProperty = true)
|
||||||
|
{
|
||||||
|
$this->objectClass = $objectClass;
|
||||||
|
|
||||||
|
list($this->uses, $this->class, $this->methods, $this->properties) = array_values(
|
||||||
|
ObjectReflection::fromClass($objectClass)->read($fullUses, $fullObject, $fullMethod, $fullProperty)
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->resolveAnnotations();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Transform an annotation into it's object's counterpart
|
||||||
|
*/
|
||||||
|
public function getAnnotationFromClassname(string $className) : ? object
|
||||||
|
{
|
||||||
|
if ( $name = $this->uses[$className] ?? false) {
|
||||||
|
foreach($this->class['tags'] as $item) {
|
||||||
|
if ( $item['tag'] === $name ) {
|
||||||
|
return $this->instanciateAnnotationObject($item);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach($this->properties as $property) {
|
||||||
|
foreach($property['tags'] as $item) {
|
||||||
|
if ( $item['tag'] === $name ) {
|
||||||
|
return $this->instanciateAnnotationObject($item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach($this->methods as $method) {
|
||||||
|
foreach($method['tags'] as $item) {
|
||||||
|
if ( $item['tag'] === $name ) {
|
||||||
|
return $this->instanciateAnnotationObject($item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new \TypeError("Annotation `$className` could not be found within your object `{$this->objectClass}`");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw new \InvalidArgumentException("Class `$className` was not found within {$this->objectClass} uses statement (or it's children / traits)");
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Transform an annotation into it's object's counterpart
|
||||||
|
*/
|
||||||
|
public function getAnnotationListFromClassname(string $className, bool $throwOnError = true) : array
|
||||||
|
{
|
||||||
|
$list = [];
|
||||||
|
|
||||||
|
if ( $name = $this->uses[$className] ?? false) {
|
||||||
|
foreach($this->class['tags'] as $item) {
|
||||||
|
if ( $item['tag'] === $name ) {
|
||||||
|
$list[] = $this->instanciateAnnotationObject($item);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach($this->properties as $property) {
|
||||||
|
foreach($property['tags'] as $item) {
|
||||||
|
if ( $item['tag'] === $name ) {
|
||||||
|
$list[$property['name']] = $this->instanciateAnnotationObject($item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach($this->methods as $method) {
|
||||||
|
foreach($method['tags'] as $item) {
|
||||||
|
if ( $item['tag'] === $name ) {
|
||||||
|
$list[$method['name']] = $this->instanciateAnnotationObject($item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if ($throwOnError) throw new \InvalidArgumentException("Class `$className` was not found within {$this->objectClass} uses statement (or it's children / traits)");
|
||||||
|
}
|
||||||
|
|
||||||
|
return $list;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function instanciateAnnotationObject(array $tagDefinition) : Annotation
|
||||||
|
{
|
||||||
|
$arguments = $this->extractArguments($tagDefinition['arguments']);
|
||||||
|
|
||||||
|
if ( false === $class = array_search($tagDefinition['tag'], $this->uses) ) {
|
||||||
|
throw new \InvalidArgumentException("Annotation class `{$tagDefinition['tag']}` was not found within {$this->objectClass} uses statement (or it's children / traits)");
|
||||||
|
}
|
||||||
|
|
||||||
|
$obj = new $class(... $arguments['constructor']);
|
||||||
|
|
||||||
|
foreach($arguments['setter'] as $key => $value) {
|
||||||
|
$obj->$key = $value;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extracts arguments from an Annotation definition, easing object's declaration.
|
||||||
|
*/
|
||||||
|
protected function extractArguments(array $arguments) : array
|
||||||
|
{
|
||||||
|
$list = [
|
||||||
|
'setter' => [],
|
||||||
|
'constructor' => [],
|
||||||
|
];
|
||||||
|
|
||||||
|
ksort($arguments);
|
||||||
|
|
||||||
|
foreach($arguments as $key => $value) {
|
||||||
|
$list[ is_int($key) ? 'constructor' : 'setter' ][$key] = $value;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $list;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function resolveAnnotations()
|
||||||
|
{
|
||||||
|
foreach($this->class['tags'] as $key => &$tag) {
|
||||||
|
$tag['object'] = $this->instanciateAnnotationObject($tag);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach($this->properties as &$property) {
|
||||||
|
foreach($property['tags'] as &$tag){
|
||||||
|
$tag['object'] = $this->instanciateAnnotationObject($tag);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach($this->methods as &$method) {
|
||||||
|
foreach($method['tags'] as &$tag){
|
||||||
|
$tag['object'] = $this->instanciateAnnotationObject($tag);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue