2019-12-10 19:32:44 +00:00
< ? 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 ();
}
2023-01-21 18:37:54 +00:00
2019-12-10 19:32:44 +00:00
/**
* Transform an annotation into it 's object' s counterpart
*/
2023-01-21 18:37:54 +00:00
public function getAttributeFromClassname ( array | string $className , bool $throwOnError = true ) : object | bool
2019-12-10 19:32:44 +00:00
{
2023-01-21 18:37:54 +00:00
foreach (( array ) $className as $class ) {
foreach ( array_reverse ( $this -> class [ 'tags' ]) as $item ) {
if ( $item [ 'object' ] instanceof $class ) {
2019-12-10 19:32:44 +00:00
return $this -> instanciateAnnotationObject ( $item );
}
2023-01-21 18:37:54 +00:00
foreach ( $this -> properties as $property ) {
foreach ( $property [ 'tags' ] as $tag ) {
if ( $item [ 'object' ] instanceof $class ) {
return $this -> instanciateAnnotationObject ( $tag );
2019-12-10 19:32:44 +00:00
}
}
}
2023-01-21 18:37:54 +00:00
foreach ( $this -> methods as $method ) {
foreach ( $method [ 'tags' ] as $tag ) {
if ( $item [ 'object' ] instanceof $class ) {
return $this -> instanciateAnnotationObject ( $tag );
2019-12-10 19:32:44 +00:00
}
}
}
}
}
2023-01-21 18:37:54 +00:00
if ( $throwOnError ) {
throw new \Exception ( sprintf ( " Annotation `%s` could not be found within your object `%s`. " , implode ( ', ' , ( array ) $className ), $this -> objectClass ));
2019-12-10 19:32:44 +00:00
}
2023-01-21 18:37:54 +00:00
return false ;
2019-12-10 19:32:44 +00:00
}
2023-01-21 18:37:54 +00:00
2019-12-10 19:32:44 +00:00
/**
* Transform an annotation into it 's object' s counterpart
*/
2023-01-21 18:37:54 +00:00
public function getAttributeListFromClassname ( array | string $className , bool $throwOnError = true ) : array
2019-12-10 19:32:44 +00:00
{
$list = [];
2023-01-21 18:37:54 +00:00
foreach (( array ) $className as $class ) {
foreach ( $this -> class [ 'tags' ] as $item ) {
if ( $item [ 'object' ] instanceof $class ) {
2019-12-10 19:32:44 +00:00
$list [] = $this -> instanciateAnnotationObject ( $item );
}
2021-02-16 03:07:27 +00:00
}
2019-12-10 19:32:44 +00:00
2023-01-21 18:37:54 +00:00
foreach ( $this -> properties as $property ) {
foreach ( $property [ 'tags' ] as $item ) {
if ( $item [ 'object' ] instanceof $class ) {
2021-02-16 03:07:27 +00:00
$list [ $property [ 'name' ]] ? ? = [];
$list [ $property [ 'name' ]][] = $this -> instanciateAnnotationObject ( $item );
2019-12-10 19:32:44 +00:00
}
}
2021-02-16 03:07:27 +00:00
}
2019-12-10 19:32:44 +00:00
2023-01-21 18:37:54 +00:00
foreach ( $this -> methods as $method ) {
foreach ( $method [ 'tags' ] as $item ) {
if ( $item [ 'object' ] instanceof $class ) {
2021-02-16 03:07:27 +00:00
$list [ $method [ 'name' ]] ? ? = [];
$list [ $method [ 'name' ]][] = $this -> instanciateAnnotationObject ( $item );
2019-12-10 19:32:44 +00:00
}
}
}
}
2023-01-21 18:37:54 +00:00
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 ;
}
/**
* @ 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 ) ) {
2019-12-10 19:32:44 +00:00
if ( $throwOnError ) throw new \InvalidArgumentException ( " Class ` $className ` was not found within { $this -> objectClass } uses statement (or it's children / traits) " );
}
return $list ;
}
2020-10-20 19:35:52 +00:00
2019-12-10 19:32:44 +00:00
public function instanciateAnnotationObject ( array $tagDefinition ) : Annotation
{
2023-01-21 18:37:54 +00:00
if ( isset ( $tagDefinition [ 'object' ]) && $tagDefinition [ 'object' ] instanceof \Attribute ) {
return $tagDefinition [ 'object' ];
}
2019-12-10 19:32:44 +00:00
$arguments = $this -> extractArguments ( $tagDefinition [ 'arguments' ]);
if ( false === $class = array_search ( $tagDefinition [ 'tag' ], $this -> uses ) ) {
2020-10-20 19:35:52 +00:00
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)");
2019-12-10 19:32:44 +00:00
}
$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 ) {
2023-01-21 18:37:54 +00:00
$tag [ 'object' ] ? ? = $this -> instanciateAnnotationObject ( $tag );
2019-12-10 19:32:44 +00:00
}
foreach ( $this -> properties as & $property ) {
foreach ( $property [ 'tags' ] as & $tag ){
2023-01-21 18:37:54 +00:00
$tag [ 'object' ] ? ? = $this -> instanciateAnnotationObject ( $tag );
2019-12-10 19:32:44 +00:00
}
}
foreach ( $this -> methods as & $method ) {
foreach ( $method [ 'tags' ] as & $tag ){
2023-01-21 18:37:54 +00:00
$tag [ 'object' ] ? ? = $this -> instanciateAnnotationObject ( $tag );
2019-12-10 19:32:44 +00:00
}
}
}
}