2019-08-21 20:13:00 +00:00
< ? php
namespace Ulmus\Common ;
use Ulmus\Annotation\Annotation ,
Ulmus\Annotation\Classes\Table ,
Ulmus\Annotation\Property\Field ;
class EntityResolver {
const KEY_ENTITY_NAME = 01 ;
const KEY_COLUMN_NAME = 02 ;
public string $entityClass ;
public array $uses ;
public array $class ;
public array $properties ;
public array $methods ;
2019-12-10 20:27:45 +00:00
protected array $fieldList = [];
2019-08-21 20:13:00 +00:00
public function __construct ( string $entityClass )
{
$this -> entityClass = $entityClass ;
list ( $this -> uses , $this -> class , $this -> methods , $this -> properties ) = array_values (
ObjectReflection :: fromClass ( $entityClass ) -> read ()
);
2019-12-10 20:27:45 +00:00
2019-08-21 20:13:00 +00:00
$this -> resolveAnnotations ();
}
2019-12-10 20:27:45 +00:00
public function field ( $name , $fieldKey = self :: KEY_ENTITY_NAME , $throwException = true ) : ? array
2019-08-21 20:13:00 +00:00
{
try {
return $this -> fieldList ( $fieldKey )[ $name ];
}
catch ( \Throwable $e ) {
2019-12-10 20:27:45 +00:00
if ( $throwException ) {
throw new \InvalidArgumentException ( " Can't find entity field's column named ` $name ` from entity { $this -> entityClass } " );
}
2019-08-21 20:13:00 +00:00
}
2019-12-10 20:27:45 +00:00
return null ;
2019-08-21 20:13:00 +00:00
}
public function fieldList ( $fieldKey = self :: KEY_ENTITY_NAME ) : array
{
$fieldList = [];
foreach ( $this -> properties as $item ) {
foreach ( $item [ 'tags' ] ? ? [] as $tag ) {
if ( $tag [ 'object' ] instanceof Field ) {
switch ( $fieldKey ) {
case static :: KEY_ENTITY_NAME :
$key = $item [ 'name' ];
break ;
case static :: KEY_COLUMN_NAME :
$key = $tag [ 'object' ] -> name ? ? $item [ 'name' ];
break ;
default :
throw new \InvalidArgumentException ( " Given `fieldKey` is unknown to the EntityResolver " );
}
$fieldList [ $key ] = $item ;
break ;
}
}
}
return $fieldList ;
}
public function tableName () : string
{
if ( null === $table = $this -> getAnnotationFromClassname ( Table :: class ) ) {
throw new \LogicException ( " Your entity { $this -> entityClass } seems to be missing a @Table() annotation " );
}
if ( $table -> name === " " ) {
throw new \ArgumentCountError ( " Your entity { $this -> entityClass } seems to be missing a `name` argument for your @Table() annotation " );
}
return $table -> name ;
}
public function primaryKeys () : array
{
}
/**
* 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 $item ) {
foreach ( $item [ 'tags' ] as $item ) {
if ( $item [ 'tag' ] === $name ) {
return $this -> instanciateAnnotationObject ( $item );
}
}
}
foreach ( $this -> methods as $item ) {
foreach ( $item [ 'tags' ] as $item ) {
if ( $item [ 'tag' ] === $name ) {
return $this -> instanciateAnnotationObject ( $item );
}
}
}
}
throw new \TypeError ( " Annotation ` $className ` could not be found within your object ` { $this -> entityClass } ` " );
}
else {
throw new \InvalidArgumentException ( " Class ` $className ` was not found within { $this -> entityClass } uses statement (or it's children / traits) " );
}
return null ;
}
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 -> entityClass } 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 & $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 );
}
}
}
}