- Totally reworked Notes to allievate most conceptions problems. Removed old annotations artifacts too
This commit is contained in:
		
							parent
							
								
									996c8fa14a
								
							
						
					
					
						commit
						61b84bfd09
					
				| @ -9,7 +9,9 @@ | ||||
|             "email": "info@mcnd.ca" | ||||
|         } | ||||
|     ], | ||||
|     "require": {}, | ||||
|     "require": { | ||||
|         "mcnd/kash" : "dev-master" | ||||
|     }, | ||||
|     "autoload": { | ||||
|         "psr-4": { | ||||
|             "Notes\\": "src/" | ||||
|  | ||||
							
								
								
									
										59
									
								
								src/AttributeReader.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										59
									
								
								src/AttributeReader.php
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,59 @@ | ||||
| <?php | ||||
| 
 | ||||
| namespace Notes; | ||||
| 
 | ||||
| use Notes\Common\ReflectedAttribute; | ||||
| use Reflector, ReflectionClass, ReflectionProperty, ReflectionMethod; | ||||
| 
 | ||||
| class AttributeReader | ||||
| { | ||||
|     const PHP_TYPES = [ "string", "int", "float", "object", "double", "closure", ]; | ||||
| 
 | ||||
|     public static function reflectAttributes(\Reflector $reflect) : array | ||||
|     { | ||||
|         $list = []; | ||||
| 
 | ||||
|         foreach($reflect->getAttributes() as $attribute) { | ||||
|             try { | ||||
|                 $list[] = new ReflectedAttribute( | ||||
|                     tag: substr(strrchr($attribute->getName(), "\\"), 1), | ||||
|                     object: $attribute->newInstance(), | ||||
|                     arguments: $attribute->getArguments(), | ||||
|                 ); | ||||
|             } | ||||
|             catch(\Throwable $e) { | ||||
|                 throw new \Exception(sprintf("%s for %s in file '%s'", $e->getMessage(), $reflect, static::getObjectName($reflect))); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         return $list; | ||||
|     } | ||||
| 
 | ||||
|     protected static function getObjectName(Reflector $reflect) : string | ||||
|     { | ||||
|         switch(true) { | ||||
|             case $reflect instanceof ReflectionMethod : | ||||
|             case $reflect instanceof ReflectionProperty : | ||||
|                 return $reflect->class . "::" . $reflect->name; | ||||
| 
 | ||||
|             case $reflect instanceof ReflectionClass : | ||||
|                 return $reflect->name; | ||||
|         } | ||||
| 
 | ||||
|         throw new \InvalidArgumentException("Given reflector is not supported within getObjectName()."); | ||||
|     } | ||||
| 
 | ||||
|     protected static function getObjectNamespace(Reflector $reflect) : string | ||||
|     { | ||||
|         switch(true) { | ||||
|             case $reflect instanceof ReflectionMethod : | ||||
|             case $reflect instanceof ReflectionProperty : | ||||
|                 return $reflect->getDeclaringClass()->getNamespaceName(); | ||||
| 
 | ||||
|             case $reflect instanceof ReflectionClass : | ||||
|                 return $reflect->getNamespaceName(); | ||||
|         } | ||||
| 
 | ||||
|         throw new \InvalidArgumentException("Given reflector is not supported within getObjectNamespace()."); | ||||
|     } | ||||
| } | ||||
| @ -87,7 +87,7 @@ class CommandFetcher { | ||||
| 
 | ||||
|                 $class = $this->generateClassname($basename, $namespace); | ||||
| 
 | ||||
|                 $objectResolver = new ObjectResolver($class, false, true, false, false); | ||||
|                 $objectResolver = new ObjectResolver($class, true, false, false); | ||||
| 
 | ||||
|                 $attributes = $objectResolver->getAttributeListFromClassname( $this->annotations['object'], false ) ; | ||||
| 
 | ||||
|  | ||||
							
								
								
									
										59
									
								
								src/Common/Reflected.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										59
									
								
								src/Common/Reflected.php
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,59 @@ | ||||
| <?php | ||||
| 
 | ||||
| namespace Notes\Common; | ||||
| 
 | ||||
| use Notes\Attribute\Ignore; | ||||
| 
 | ||||
| abstract class Reflected | ||||
| { | ||||
|     public function hasIgnoreAttribute() : bool | ||||
|     { | ||||
|         return [] !== array_filter($this->attributes, fn($e) => $e->object instanceof Ignore); | ||||
|     } | ||||
| 
 | ||||
|     public function allowsNull() : bool | ||||
|     { | ||||
|         return empty($this->type) || $this->expectType("null"); | ||||
|     } | ||||
| 
 | ||||
|     public function expectType(string $type) : bool | ||||
|     { | ||||
|         $type = strtolower($type); | ||||
| 
 | ||||
|         foreach($this->getTypes() as $item) { | ||||
| 
 | ||||
|             if ($type === "null") { | ||||
|                 if ($item->type === "null" || $item->nullable) { | ||||
|                      return true; | ||||
|                 } | ||||
|             } | ||||
|             elseif ($type === $item->type) { | ||||
|                 return true; | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         return false; | ||||
|     } | ||||
| 
 | ||||
|     public function getTypes() : array | ||||
|     { | ||||
|         return is_array($this->type) ? $this->type : [ $this->type ]; | ||||
|     } | ||||
| 
 | ||||
|     public function typeFromReflection(\ReflectionProperty|\ReflectionParameter $property) : void | ||||
|     { | ||||
|         if ( $property->hasType() ) { | ||||
|             $type = $property->getType(); | ||||
| 
 | ||||
|             if ($type instanceof \ReflectionUnionType ) { | ||||
|                 foreach($type->getTypes() as $item) { | ||||
|                     $this->type[] = new ReflectedPropertyType($item->getName(), $item->isBuiltIn(), $item->allowsNull()); | ||||
|                 } | ||||
|             } | ||||
|             else { | ||||
|                 $this->type = new ReflectedPropertyType($type->getName(), $type->isBuiltIn(), $type->allowsNull()); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
| } | ||||
							
								
								
									
										12
									
								
								src/Common/ReflectedAttribute.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								src/Common/ReflectedAttribute.php
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,12 @@ | ||||
| <?php | ||||
| 
 | ||||
| namespace Notes\Common; | ||||
| 
 | ||||
| class ReflectedAttribute | ||||
| { | ||||
|     public function __construct( | ||||
|         public mixed $tag, | ||||
|         public object $object, | ||||
|         public array $arguments = [], | ||||
|     ){} | ||||
| } | ||||
							
								
								
									
										149
									
								
								src/Common/ReflectedClass.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										149
									
								
								src/Common/ReflectedClass.php
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,149 @@ | ||||
| <?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 getProperties(bool $deep = true) : array | ||||
|     { | ||||
|         return $deep ? array_replace( | ||||
|             # $this->parent ? $this->parent->getProperties(true) : [],
 | ||||
|             $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) : array | ||||
|     { | ||||
|         return $deep ? array_merge( | ||||
|             $this->parent ? $this->parent->getAttributes(true) : [], | ||||
|             array_merge(...array_map(fn($e) => $e->getAttributes(true), $this->interfaces)), | ||||
|             array_merge(...array_map(fn($e) => $e->getAttributes(true), $this->traits)), | ||||
|             $this->attributes | ||||
|         ) : $this->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; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										8
									
								
								src/Common/ReflectedInterface.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								src/Common/ReflectedInterface.php
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,8 @@ | ||||
| <?php | ||||
| 
 | ||||
| namespace Notes\Common; | ||||
| 
 | ||||
| interface ReflectedInterface | ||||
| { | ||||
|     public function getAttributes() : array; | ||||
| } | ||||
							
								
								
									
										22
									
								
								src/Common/ReflectedMethod.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								src/Common/ReflectedMethod.php
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,22 @@ | ||||
| <?php | ||||
| 
 | ||||
| namespace Notes\Common; | ||||
| 
 | ||||
| class ReflectedMethod extends Reflected implements ReflectedInterface | ||||
| { | ||||
|     public function __construct( | ||||
|         public string $name, | ||||
|         public string $classname, | ||||
|         public false|ReflectedMethodType|\ReflectionNamedType|\ReflectionUnionType|array $type = false, | ||||
|         public bool $isConstructor = false, | ||||
|         public bool $isDestructor = false, | ||||
|         public bool $isAbstract = false, | ||||
|         public array $attributes = [], | ||||
|         public array $parameters = [], | ||||
|     ) {} | ||||
| 
 | ||||
|     public function getAttributes(): array | ||||
|     { | ||||
|         return $this->attributes; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										12
									
								
								src/Common/ReflectedMethodProperty.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								src/Common/ReflectedMethodProperty.php
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,12 @@ | ||||
| <?php | ||||
| 
 | ||||
| namespace Notes\Common; | ||||
| 
 | ||||
| class ReflectedMethodProperty extends ReflectedProperty | ||||
| { | ||||
|     public int $position; | ||||
| 
 | ||||
|     public bool $optional = false; | ||||
| 
 | ||||
|     public bool $byReference = false; | ||||
| } | ||||
							
								
								
									
										8
									
								
								src/Common/ReflectedMethodType.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								src/Common/ReflectedMethodType.php
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,8 @@ | ||||
| <?php | ||||
| 
 | ||||
| namespace Notes\Common; | ||||
| 
 | ||||
| class ReflectedMethodType extends ReflectedPropertyType | ||||
| { | ||||
| 
 | ||||
| } | ||||
							
								
								
									
										47
									
								
								src/Common/ReflectedProperty.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										47
									
								
								src/Common/ReflectedProperty.php
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,47 @@ | ||||
| <?php | ||||
| 
 | ||||
| namespace Notes\Common; | ||||
| 
 | ||||
| use Notes\Attribute\Ignore; | ||||
| 
 | ||||
| class ReflectedProperty extends Reflected implements ReflectedInterface, \ArrayAccess | ||||
| { | ||||
|     public mixed $value; | ||||
| 
 | ||||
|     public function __construct( | ||||
|         public string $name, | ||||
|         public false|ReflectedPropertyType|array $type = false, | ||||
|         public array $attributes = [], | ||||
|     ) {} | ||||
| 
 | ||||
|     public function getAttributes(): array | ||||
|     { | ||||
|         return $this->attributes; | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     ## BACKWARD COMPATIBILITY ONLY To be removed really soon !
 | ||||
|     public function offsetExists(mixed $offset): bool | ||||
|     { | ||||
|         return isset($this->$offset); | ||||
|     } | ||||
| 
 | ||||
|     public function offsetGet(mixed $offset): mixed | ||||
|     { | ||||
|         if ($offset === 'tags') { | ||||
|             return $this->attributes; | ||||
|         } | ||||
| 
 | ||||
|         return $this->$offset; | ||||
|     } | ||||
| 
 | ||||
|     public function offsetSet(mixed $offset, mixed $value): void | ||||
|     { | ||||
|         $this->$offset = $value; | ||||
|     } | ||||
| 
 | ||||
|     public function offsetUnset(mixed $offset): void | ||||
|     { | ||||
|         unset($this->$offset); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										21
									
								
								src/Common/ReflectedPropertyType.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								src/Common/ReflectedPropertyType.php
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,21 @@ | ||||
| <?php | ||||
| 
 | ||||
| namespace Notes\Common; | ||||
| 
 | ||||
| class ReflectedPropertyType | ||||
| { | ||||
|     public function __construct( | ||||
|         public string $type, | ||||
|         public bool $builtIn, | ||||
|         public bool $nullable, | ||||
|     ) {} | ||||
| 
 | ||||
|     public function isType(string $type) : bool | ||||
|     { | ||||
|         if ($type === "null" || $this->nullable) { | ||||
|             return true; | ||||
|         } | ||||
| 
 | ||||
|         return $this->type === $type; | ||||
|     } | ||||
| } | ||||
| @ -78,9 +78,9 @@ class TaskFetcher { | ||||
|                 $class = $this->generateClassname($file->getBasename(".php"), $namespace); | ||||
| 
 | ||||
|                 # Should generate an equivalent of Ulmus's object reflection here !
 | ||||
|                 $objectResolver = new ObjectResolver($class, true, true, false, true); | ||||
|                 $objectResolver = new ObjectResolver($class, $this->cache); | ||||
| 
 | ||||
|                 foreach($objectResolver->getAttributeListFromClassname( $this->annotations['method'], false ) as $func => $cronard) { | ||||
|                 foreach($objectResolver->reflectedClass->getMethodAttributeListFromClassname( $this->annotations['method'], false, false ) as $func => $cronard) { | ||||
|                     foreach($cronard as $task) { | ||||
|                         $list[] = [ 'class' => $class, 'method' => $func, 'annotation' => $task ]; | ||||
|                     } | ||||
|  | ||||
| @ -78,9 +78,9 @@ class EventFetcher { | ||||
|                 $class = $this->generateClassname($file->getBasename(".php"), $namespace); | ||||
| 
 | ||||
|                 # Should generate an equivalent of Ulmus's object reflection here !
 | ||||
|                 $objectResolver = new ObjectResolver($class, true, true, false, true); | ||||
|                 $objectResolver = new ObjectResolver($class, $this->cache ?? null); | ||||
| 
 | ||||
|                 foreach($objectResolver->getAttributeListFromClassname( $this->annotations['method'], false ) as $func => $events) { | ||||
|                 foreach($objectResolver->reflectedClass->getMethodAttributeListFromClassname($this->annotations['method'], false, false ) as $func => $events) { | ||||
|                     foreach($events as $ev) { | ||||
|                         $list[] = new \Mcnd\Event\Event(name: $ev->name, class: $class, method: $func, attribute: $ev); | ||||
|                     } | ||||
|  | ||||
| @ -4,6 +4,11 @@ namespace Notes; | ||||
| 
 | ||||
| use Kash\HandleCacheTrait; | ||||
| use Notes\Attribute\Ignore; | ||||
| use Notes\Common\ReflectedClass; | ||||
| use Notes\Common\ReflectedMethod; | ||||
| use Notes\Common\ReflectedMethodProperty; | ||||
| use Notes\Common\ReflectedProperty; | ||||
| use Notes\Common\ReflectedPropertyType; | ||||
| use Psr\SimpleCache\CacheInterface; | ||||
| use Reflector, ReflectionClass, ReflectionProperty, ReflectionMethod, ReflectionUnionType, ReflectionNamedType, ReflectionParameter; | ||||
| 
 | ||||
| @ -14,81 +19,37 @@ class ObjectReflection { | ||||
| 
 | ||||
|     protected ReflectionClass $classReflection; | ||||
| 
 | ||||
|     public AnnotationReader $annotationReader; | ||||
|     public function __construct(ReflectionClass|string $class, ? CacheInterface $cache = null) { | ||||
|         $this->classname = ltrim($class instanceof ReflectionClass ? $class->getName() : $class, '\\'); | ||||
| 
 | ||||
|     public function __construct($class, AnnotationReader $annotationReader = null, ? CacheInterface $cache = null) { | ||||
|         $this->classname = ltrim($class, '\\'); | ||||
|         $this->cache = $cache; | ||||
| 
 | ||||
|         #if ( ! $this->cache || ! $this->cache->has($class) ) {
 | ||||
|             $this->classReflection = $class instanceof ReflectionClass ? $class : new ReflectionClass($class); | ||||
|             $this->annotationReader = $annotationReader ?: AnnotationReader::fromClass($class); | ||||
|        # }
 | ||||
|     } | ||||
| 
 | ||||
|     public static function fromClass($class, ? CacheInterface $cache = null) : self | ||||
|     public static function fromClass(ReflectionClass|string $class, ? CacheInterface $cache = null) : self | ||||
|     { | ||||
|         return new static($class, null, $cache); | ||||
|     } | ||||
| 
 | ||||
|     public function read(bool $fullUses = true, bool $fullObject = true, $fullMethod = true, $fullProperty = true) : array | ||||
|     public function reflectClass() : ReflectedClass | ||||
|     { | ||||
|         return $this->handleCaching(implode('', [ $this->classname, (int)$fullObject, (int) $fullMethod, (int) $fullProperty ]), fn() => [ | ||||
|             'uses'     => $this->gatherUses($fullUses), | ||||
|             'class'    => $this->gatherClass($fullObject), | ||||
|             'method'   => $this->gatherMethods($fullMethod), | ||||
|             'property' => $this->gatherProperties($fullProperty), | ||||
|         ]); | ||||
|         $parentClass = $this->classReflection->getParentClass(); | ||||
| 
 | ||||
|         return new ReflectedClass( | ||||
|             name: $this->classReflection->getName(), | ||||
|             parent: $parentClass ? static::fromClass($parentClass)->reflectClass() : false, | ||||
|             methods: $this->reflectMethods(), | ||||
|             properties: $this->reflectProperties(), | ||||
|             attributes: AttributeReader::reflectAttributes($this->classReflection), | ||||
|             interfaces: array_map(fn($interface) => static::fromClass($interface)->reflectClass(), array_keys($this->classReflection->getInterfaces())), | ||||
|             traits: array_map(fn($trait) => static::fromClass($trait)->reflectClass(), array_keys($this->classReflection->getTraits())), | ||||
|         ); | ||||
|     } | ||||
| 
 | ||||
|     public function gatherUses(bool $full = true) : array | ||||
|     { | ||||
|         if ( $full ) { | ||||
|             if ( $parentClass = $this->classReflection->getParentClass() ) { | ||||
|                 $list = static::fromClass($parentClass)->gatherUses(true); | ||||
|             } | ||||
| 
 | ||||
|             foreach($this->classReflection->getTraits() as $trait) { | ||||
|                 $list = array_replace(static::fromClass($trait->name)->gatherUses(true), $list ?? []); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         return array_replace($list ?? [], $this->getUsesStatements()); | ||||
|     } | ||||
| 
 | ||||
|     public function gatherClass(bool $full = true) : array | ||||
|     { | ||||
|         if ( $full ) { | ||||
|             if ( $parentClass = $this->classReflection->getParentClass() ) { | ||||
|                 $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) { | ||||
|                 return $item->getName(); | ||||
|             }; | ||||
|         } | ||||
| 
 | ||||
|         return array_merge_recursive($class ?? [], $traitTags ?? [], $interfaceTags ?? [], [ | ||||
|                 'tags' => $this->annotationReader->getClass($this->classReflection) | ||||
|             ] + ( ! $full ? [] : [ | ||||
|                 'traits' => array_map($itemName, $traits), | ||||
|                 'interfaces' => array_map($itemName, $interfaces), | ||||
|             ] )); | ||||
|     } | ||||
| 
 | ||||
|     public function gatherProperties(bool $full = true, int $filter = | ||||
|      | ||||
|     public function reflectProperties(int $filter = | ||||
|         ReflectionProperty::IS_PUBLIC    | | ||||
|         ReflectionProperty::IS_PROTECTED | | ||||
|         ReflectionProperty::IS_PRIVATE | ||||
| @ -96,48 +57,31 @@ class ObjectReflection { | ||||
|     { | ||||
|         $defaultValues = $this->classReflection->getDefaultProperties(); | ||||
| 
 | ||||
|         if ( $full ) { | ||||
|             if ( $parentClass = $this->classReflection->getParentClass() ) { | ||||
|                 $properties = static::fromClass($parentClass)->gatherProperties($full, $filter); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         $list = []; | ||||
| 
 | ||||
|         foreach($this->classReflection->getProperties($filter) as $property) { | ||||
|             $current = [ | ||||
|                 'name' => $property->getName() | ||||
|             ]; | ||||
|             $reflected = new ReflectedProperty($property->getName()); | ||||
| 
 | ||||
|             # Default value can be 'null', so isset() it not suitable here
 | ||||
|             if ( array_key_exists($current['name'], $defaultValues) ) { | ||||
|                 $current['value'] = $defaultValues[ $current['name'] ]; | ||||
|             } | ||||
|             $reflected->attributes = AttributeReader::reflectAttributes($property); | ||||
| 
 | ||||
| 
 | ||||
|             if ( $property->hasType() ) { | ||||
|                 $type = $property->getType(); | ||||
| 
 | ||||
|                 if (! $type instanceof \ReflectionUnionType ) { | ||||
|                     $current['type'] = $type->getName(); | ||||
|                     $current['builtin'] = $type->isBuiltIn(); | ||||
|                     $current['nullable'] = $type->allowsNull(); | ||||
|                 } | ||||
|             } | ||||
| 
 | ||||
|             $current['tags'] = $this->annotationReader->getProperty($property); | ||||
| 
 | ||||
|             if ( $this->ignoreElementAnnotation($current['tags']) ) { | ||||
|             if ( $reflected->hasIgnoreAttribute() ) { | ||||
|                 continue; | ||||
|             } | ||||
| 
 | ||||
|             $list[ $current['name'] ] = $current; | ||||
|             # Default value can be 'null', so isset() it not suitable here
 | ||||
|             if ( array_key_exists($reflected->name, $defaultValues) ) { | ||||
|                 $reflected->value = $defaultValues[ $reflected->name ]; | ||||
|             } | ||||
| 
 | ||||
|             $reflected->typeFromReflection($property); | ||||
| 
 | ||||
|             $list[ $reflected->name ] = $reflected; | ||||
|         } | ||||
| 
 | ||||
|         return array_merge($properties ?? [], $list); | ||||
|     } | ||||
| 
 | ||||
|     public function gatherMethods(bool $full = true, int $filter = | ||||
|     public function reflectMethods(int $filter = | ||||
|         ReflectionMethod::IS_PUBLIC    | | ||||
|         ReflectionMethod::IS_PROTECTED | | ||||
|         ReflectionMethod::IS_PRIVATE   | | ||||
| @ -147,163 +91,47 @@ class ObjectReflection { | ||||
|     { | ||||
|         $list = []; | ||||
| 
 | ||||
|         if ( $full ) { | ||||
|             if ( $parentClass = $this->classReflection->getParentClass() ) { | ||||
|                 $methods = static::fromClass($parentClass)->gatherMethods($full, $filter); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         foreach($this->classReflection->getMethods($filter) as $method) { | ||||
|             if ( ! $full && ( $method->class !== $this->classname ) ) { | ||||
|             # Skipping parent's methods, we'll retrieve them in its own reflection
 | ||||
|             if ( $method->class !== $this->classname ) { | ||||
|                 continue; | ||||
|             } | ||||
| 
 | ||||
|             $parameters = []; | ||||
|             $reflectedMethod = new ReflectedMethod( | ||||
|                 name: $method->getName(), | ||||
|                 classname: $method->class, | ||||
|                 type: $method->hasReturnType() ? $method->getReturnType() : false, | ||||
|                 isConstructor: $method->isConstructor(), | ||||
|                 isDestructor: $method->isDestructor(), | ||||
|                 isAbstract: $method->isAbstract(), | ||||
|                 attributes: AttributeReader::reflectAttributes($method), | ||||
|             ); | ||||
| 
 | ||||
|             if ( $reflectedMethod->hasIgnoreAttribute() ) { | ||||
|                 continue; | ||||
|             } | ||||
| 
 | ||||
|             foreach($method->getParameters() as $parameter) { | ||||
|                 $parameters[$parameter->getName()] = [ | ||||
|                     'null' => $parameter->allowsNull(), | ||||
|                     'position' => $parameter->getPosition(), | ||||
|                     'type' => $parameter->hasType() && $parameter->getType() instanceof \ReflectionNamedType ? $parameter->getType()->getName() : false, | ||||
|                     'array' => $this->isType('array', $parameter), | ||||
|                     'callable' => $this->isType('callable', $parameter), | ||||
|                     'optional' => $parameter->isOptional(), | ||||
|                     'byReference' => $parameter->isPassedByReference(), | ||||
|                 ]; | ||||
|                 $reflectedParameter = new ReflectedMethodProperty( | ||||
|                     name: $parameter->getName(), | ||||
|                     attributes: AttributeReader::reflectAttributes($parameter), | ||||
|                 ); | ||||
| 
 | ||||
|                 if ( $reflectedParameter->hasIgnoreAttribute() ) { | ||||
|                     continue; | ||||
|                 } | ||||
| 
 | ||||
|                 $reflectedParameter->position = $parameter->getPosition(); | ||||
|                 $reflectedParameter->typeFromReflection($parameter); | ||||
|                 $reflectedParameter->byReference = $parameter->isPassedByReference(); | ||||
|                 $reflectedParameter->optional = $parameter->isOptional(); | ||||
| 
 | ||||
|                 $reflectedMethod->parameters[$reflectedParameter->name] = $reflectedParameter; | ||||
|             } | ||||
| 
 | ||||
|             $current = [ | ||||
|                 'name' => $method->getName(), | ||||
|                 'classname' => $method->class, | ||||
|                 'type' => $method->hasReturnType() && $method->getReturnType() instanceof \ReflectionNamedType ? $method->getReturnType()->getName() : false, | ||||
|                 'constructor' => $method->isConstructor(), | ||||
|                 'destructor' => $method->isDestructor(), | ||||
|                 'parameters' => $parameters, | ||||
|             ]; | ||||
| 
 | ||||
|             $current['tags'] = $this->annotationReader->getMethod($method); | ||||
| 
 | ||||
|             if ( $this->ignoreElementAnnotation($current['tags']) ) { | ||||
|                 continue; | ||||
|             } | ||||
| 
 | ||||
|             $list[ $current['name'] ] = $current; | ||||
|             $list[$reflectedMethod->name] = $reflectedMethod; | ||||
|         } | ||||
| 
 | ||||
|         return array_merge($methods ?? [], $list); | ||||
|     } | ||||
| 
 | ||||
|     protected function ignoreElementAnnotation($tags) : bool | ||||
|     { | ||||
|         return [] !== array_filter($tags, fn($e) => ( $e['object'] ?? null ) instanceof Ignore); | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     protected function readCode() : string | ||||
|     { | ||||
|         static $code = []; | ||||
|         $fileName = $this->classReflection->getFilename(); | ||||
|         return $code[$fileName] ?? $code[$fileName] = file_get_contents($fileName); | ||||
|     } | ||||
| 
 | ||||
|     # From https://www.php.net/manual/en/reflectionparameter.isarray.php
 | ||||
|     public static function isType(string $type, ReflectionParameter $reflectionParameter) : bool | ||||
|     { | ||||
|         if ( $reflectionType = $reflectionParameter->getType() ) { | ||||
|             $types = $reflectionType instanceof ReflectionUnionType ? $reflectionType->getTypes() : [$reflectionType]; | ||||
| 
 | ||||
|             return in_array($type, array_map(fn(ReflectionNamedType $t) => $t->getName(), $types)); | ||||
|         } | ||||
| 
 | ||||
|         return false; | ||||
|     } | ||||
| 
 | ||||
|     protected function getUsesStatements() : array | ||||
|     { | ||||
|         $uses = []; | ||||
|         $tokens = token_get_all( $c = $this->readCode() ); | ||||
| 
 | ||||
|         while ( $token = array_shift($tokens) ) { | ||||
| 
 | ||||
|             if ( is_array($token) ) { | ||||
|                 list($token, $value) = $token; | ||||
|             } | ||||
| 
 | ||||
|             switch ($token) { | ||||
|                 case T_CLASS: | ||||
|                 case T_TRAIT: | ||||
|                 case T_INTERFACE: | ||||
|                     break 2; | ||||
| 
 | ||||
|                 case T_USE: | ||||
|                     $isUse = true; | ||||
|                     break; | ||||
| 
 | ||||
|                 case T_NS_SEPARATOR: | ||||
|                     $isNamespace = $isUse; | ||||
|                     break; | ||||
| 
 | ||||
|                 case T_NAME_QUALIFIED: | ||||
|                 case T_STRING: | ||||
|                     if ( $isNamespace && $latestString ) { | ||||
|                         $statement[] = $latestString; | ||||
|                     } | ||||
| 
 | ||||
|                     $latestString = $value; | ||||
|                     break; | ||||
| 
 | ||||
|                 case T_AS: | ||||
|                     # My\Name\Space\aClassHere `as` ClassAlias;
 | ||||
|                     $replacedClass = implode("\\", array_merge($statement, [ $latestString ])); | ||||
|                     $latestString = null; | ||||
|                     break; | ||||
| 
 | ||||
|                 case T_WHITESPACE: | ||||
|                 case T_COMMENT: | ||||
|                 case T_DOC_COMMENT: | ||||
|                     break; | ||||
| 
 | ||||
|                 case '{': | ||||
|                     # opening a sub-namespace -> \My\Name\Space\`{`OneItem, AnotherItem}
 | ||||
|                     if ( $isNamespace ) { | ||||
|                         $inNamespace = true; | ||||
|                     } | ||||
|                     break; | ||||
| 
 | ||||
|                 case ';'; | ||||
|                 case ',': | ||||
|                 case '}': | ||||
|                     if ( $isUse ) { | ||||
|                         $clsName = ltrim(substr($latestString, strrpos($latestString, "\\")  ), '\\'); | ||||
|                         if ( $replacedClass ) { | ||||
|                             $uses[$replacedClass] = $clsName; | ||||
|                             $replacedClass = ""; | ||||
|                         } | ||||
|                         elseif ( $latestString ) { | ||||
|                             $uses[implode("\\", array_merge($statement, [ $latestString ]))] = $clsName; | ||||
|                         } | ||||
|                     } | ||||
| 
 | ||||
|                     if ( $inNamespace ) { | ||||
|                         $latestString = ""; | ||||
| 
 | ||||
|                         # \My\Name\Space\{OneItem, AnotherItem`}` <- closing a sub-namespace
 | ||||
|                         if ( $token !== "}" ) { | ||||
|                             break; | ||||
|                         } | ||||
|                     } | ||||
| 
 | ||||
|                 case T_OPEN_TAG: | ||||
|                 default: | ||||
|                     $statement = []; | ||||
|                     $latestString = ""; | ||||
|                     $replacedClass = null; | ||||
|                     $isNamespace = $inNamespace = false; | ||||
|                     $isUse = ( $isUse ?? false ) && ( $token === ',' ); | ||||
|                     break; | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         return $uses; | ||||
|         return $list; | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -2,16 +2,13 @@ | ||||
| 
 | ||||
| namespace Notes; | ||||
| 
 | ||||
| use Notes\Common\ReflectedClass; | ||||
| use Psr\SimpleCache\CacheInterface; | ||||
| 
 | ||||
| class ObjectResolver { | ||||
| 
 | ||||
|     const KEY_ENTITY_NAME = 01; | ||||
|     const KEY_COLUMN_NAME = 02; | ||||
| 
 | ||||
|     public string $objectClass; | ||||
| 
 | ||||
|     public array $uses; | ||||
|     public ReflectedClass $reflectedClass; | ||||
| 
 | ||||
|     public array $class; | ||||
| 
 | ||||
| @ -19,52 +16,11 @@ class ObjectResolver { | ||||
| 
 | ||||
|     public array $methods; | ||||
| 
 | ||||
|     public function __construct(string $objectClass, bool $fullUses = true, bool $fullObject = true, $fullMethod = true, $fullProperty = true, ? CacheInterface $cache = null) | ||||
|     public function __construct(string $objectClass, ? CacheInterface $cache = null) | ||||
|     { | ||||
|         $this->objectClass = $objectClass; | ||||
| 
 | ||||
|         list($this->uses, $this->class, $this->methods, $this->properties) = array_values( | ||||
|             ObjectReflection::fromClass($objectClass, $cache)->read($fullUses, $fullObject, $fullMethod, $fullProperty) | ||||
|         ); | ||||
| 
 | ||||
|         $this->resolveAnnotations(); | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     /** | ||||
|      * Transform an annotation into it's object's counterpart | ||||
|      */ | ||||
|     public function getAttributeFromClassname(array|string $className, bool $throwOnError = true) : object|bool | ||||
|     { | ||||
|         foreach((array) $className as $class) { | ||||
|             foreach (array_reverse($this->class['tags']) as $item) { | ||||
|                 if ($item['object'] instanceof $class) { | ||||
|                     return $this->instanciateAnnotationObject($item); | ||||
|                 } | ||||
| 
 | ||||
|                 foreach ($this->properties as $property) { | ||||
|                     foreach ($property['tags'] as $tag) { | ||||
|                         if ($item['object'] instanceof $class) { | ||||
|                             return $this->instanciateAnnotationObject($tag); | ||||
|                         } | ||||
|                     } | ||||
|                 } | ||||
| 
 | ||||
|                 foreach ($this->methods as $method) { | ||||
|                     foreach ($method['tags'] as $tag) { | ||||
|                         if ($item['object'] instanceof $class) { | ||||
|                             return $this->instanciateAnnotationObject($tag); | ||||
|                         } | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         if ($throwOnError) { | ||||
|             throw new \Exception(sprintf("Annotation `%s` could not be found within your object `%s`.", implode(', ', (array)$className), $this->objectClass)); | ||||
|         } | ||||
| 
 | ||||
|         return false; | ||||
|         $this->reflectedClass = ObjectReflection::fromClass($objectClass, $cache)->reflectClass(); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
| @ -75,26 +31,26 @@ class ObjectResolver { | ||||
|         $list = []; | ||||
| 
 | ||||
|         foreach((array) $className as $class) { | ||||
|             foreach ($this->class['tags'] as $item) { | ||||
|                 if ($item['object'] instanceof $class) { | ||||
|                     $list[] = $this->instanciateAnnotationObject($item); | ||||
|             foreach ($this->reflectedClass->getAttributes() as $item) { | ||||
|                 if ($item->object instanceof $class) { | ||||
|                     $list[] = $item->object; | ||||
|                 } | ||||
|             } | ||||
| 
 | ||||
|             foreach ($this->properties as $property) { | ||||
|                 foreach ($property['tags'] as $item) { | ||||
|                     if ($item['object'] instanceof $class) { | ||||
|                         $list[$property['name']] ??= []; | ||||
|                         $list[$property['name']][] = $this->instanciateAnnotationObject($item); | ||||
|             foreach ($this->reflectedClass->getProperties(true) as $property) { | ||||
|                 foreach ($property->attributes as $item) { | ||||
|                     if ($item->object instanceof $class) { | ||||
|                         $list[$property->name] ??= []; | ||||
|                         $list[$property->name][] = $item->object; | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
| 
 | ||||
|             foreach ($this->methods as $method) { | ||||
|                 foreach ($method['tags'] as $item) { | ||||
|                     if ($item['object'] instanceof $class) { | ||||
|                         $list[$method['name']] ??= []; | ||||
|                         $list[$method['name']][] = $this->instanciateAnnotationObject($item); | ||||
|             foreach ($this->reflectedClass->getMethods(true) as $method) { | ||||
|                 foreach ($method->attributes as $item) { | ||||
|                     if ($item->object instanceof $class) { | ||||
|                         $list[$method->name] ??= []; | ||||
|                         $list[$method->name][] = $item->object; | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
| @ -106,157 +62,4 @@ class ObjectResolver { | ||||
| 
 | ||||
|         return $list; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * @deprecated Will soon be deprecated in favour of PHP's native attributes | ||||
|      * Transform an annotation into it's object's counterpart | ||||
|      */ | ||||
|     public function getAnnotationFromClassname(array|string $className, bool $throwOnError = true) : object|bool | ||||
|     { | ||||
|         foreach((array) $className as $class) { | ||||
| 
 | ||||
|             if ( $name = $this->uses[$class] ?? false) { | ||||
|                 foreach (array_reverse($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); | ||||
|                             } | ||||
|                         } | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         if ($throwOnError) { | ||||
|             throw new \Exception(sprintf("Annotation `%s` could not be found within your object `%s`.", implode(', ', (array)$className), $this->objectClass)); | ||||
|         } | ||||
| 
 | ||||
|         return false; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Transform an annotation into it's object's counterpart | ||||
|      */ | ||||
|     public function getAnnotationListFromClassname(array|string $className, bool $throwOnError = true) : array | ||||
|     { | ||||
|         $list = []; | ||||
| 
 | ||||
|         foreach((array) $className as $class) { | ||||
|             if ($name = $this->uses[$class] ?? 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']] ??= []; | ||||
| 
 | ||||
|                             $list[$property['name']][] = $this->instanciateAnnotationObject($item); | ||||
|                         } | ||||
|                     } | ||||
|                 } | ||||
| 
 | ||||
|                 foreach ($this->methods as $method) { | ||||
|                     foreach ($method['tags'] as $item) { | ||||
|                         if ($item['tag'] === $name) { | ||||
|                             $list[$method['name']] ??= []; | ||||
| 
 | ||||
|                             $list[$method['name']][] = $this->instanciateAnnotationObject($item); | ||||
|                         } | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         if ( empty($list) ) { | ||||
|             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|\Notes\Attribute | ||||
|     { | ||||
|         if (isset($tagDefinition['object']) && $tagDefinition['object'] instanceof \Notes\Attribute) { | ||||
|             return $tagDefinition['object']; | ||||
|         } | ||||
| 
 | ||||
|         $arguments = $this->extractArguments($tagDefinition['arguments']); | ||||
| 
 | ||||
|         if ( false === $class = array_search($tagDefinition['tag'], $this->uses) ) { | ||||
|             return new class() implements Annotation {}; | ||||
|             # throw new \InvalidArgumentException("Annotation class `{$tagDefinition['tag']}` was not found within {$this->objectClass} uses statement (or it's children / traits)");
 | ||||
|         } | ||||
|         try { | ||||
|             $obj = new $class(... $arguments['constructor']); | ||||
|         } | ||||
|         catch (\Throwable $e) { | ||||
|             $err = $e::class; | ||||
|             throw new $err(sprintf("An error occured trying to instanciate class definition '%s' given argument '%s' : %s", var_export($tagDefinition, true), var_export($arguments['constructor'], true), $e->getMessage())); | ||||
|         } | ||||
| 
 | ||||
|         foreach($arguments['setter'] as $key => $value) { | ||||
|             $obj->$key = $value; | ||||
|         } | ||||
| 
 | ||||
|         if ( ! $obj instanceof \Notes\Attribute ) { | ||||
|             throw new \RuntimeException(sprintf("An error occurred trying to retrieve an Attribute def:%s from class %s", json_encode($tagDefinition), $this->objectClass)); | ||||
|         } | ||||
| 
 | ||||
|         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); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -93,11 +93,11 @@ class RouteFetcher { | ||||
|                 $class = $this->generateClassname($file->getBasename(".php"), $namespace); | ||||
|                 $methods = null; | ||||
| 
 | ||||
|                 $objectResolver = new ObjectResolver($class, true, true, false, true, $this->cache); | ||||
|                 $objectResolver = new ObjectResolver($class, $this->cache); | ||||
| 
 | ||||
|                 if ( isset($attributes['object']) ) { | ||||
| 
 | ||||
|                     $objects = $objectResolver->getAttributeListFromClassname($attributes['object'], false); | ||||
|                     $objects = $objectResolver->reflectedClass->getClassAttributeListFromClassname($attributes['object'], true, false); | ||||
| 
 | ||||
|                     foreach(array_reverse($objects) as $object) { | ||||
|                         if ($object->method ?? false ) { | ||||
| @ -109,7 +109,7 @@ class RouteFetcher { | ||||
|                 } | ||||
| 
 | ||||
|                 if ( isset($attributes['method']) ) { | ||||
|                     $routeList = $objectResolver->getAttributeListFromClassname( $attributes['method'], false ); | ||||
|                     $routeList = $objectResolver->reflectedClass->getMethodAttributeListFromClassname( $attributes['method'], false, false ); | ||||
| 
 | ||||
|                     foreach($routeList as $func => $routes) { | ||||
|                         if (is_array($routes)) { | ||||
|  | ||||
| @ -58,10 +58,12 @@ class SecurityHandler { | ||||
| 
 | ||||
|     protected function getClassAttributes(string $annotationClass, string $className, string $methodName)/* : \Notes\Attribute|array */ | ||||
|     { | ||||
|         $objectResolver = new ObjectResolver($className, true, true, false, true); | ||||
|         $objectResolver = new ObjectResolver($className); | ||||
| 
 | ||||
|         try { | ||||
|             $method = $objectResolver->getAttributeListFromClassname( $annotationClass, false ); | ||||
|             $method = $objectResolver->reflectedClass->getClassAttributeList( $annotationClass, true, false ); | ||||
| 
 | ||||
|            # var_dump($method);
 | ||||
|         } | ||||
|         catch(\Exception $e) { } | ||||
| 
 | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user