- WIP on attributes ; on testing phase
This commit is contained in:
1 parent
5295a335b3
commit
e6d0279c1a
44 files changed
+763
-142
No files matched your search
@@ -2,11 +2,13 @@
|
||||
|
||||
namespace Ulmus\Common;
|
||||
|
||||
use Psr\SimpleCache\CacheInterface;
|
||||
use Ulmus\Ulmus,
|
||||
Ulmus\Annotation\Classes\Table,
|
||||
Ulmus\Annotation\Property\Field,
|
||||
Ulmus\Annotation\Property\Virtual,
|
||||
Ulmus\Annotation\Property\Relation;
|
||||
Ulmus\Annotation\Property\Relation,
|
||||
Ulmus\Attribute;
|
||||
|
||||
use Notes\Annotation;
|
||||
|
||||
@@ -32,12 +34,12 @@ class EntityResolver {
|
||||
|
||||
protected array $fieldList = [];
|
||||
|
||||
public function __construct(string $entityClass)
|
||||
public function __construct(string $entityClass, ? CacheInterface $cache = null)
|
||||
{
|
||||
$this->entityClass = $entityClass;
|
||||
|
||||
list($this->uses, $this->class, $this->methods, $this->properties) = array_values(
|
||||
ObjectReflection::fromClass($entityClass)->read()
|
||||
ObjectReflection::fromClass($entityClass, $cache)->read()
|
||||
);
|
||||
|
||||
$this->resolveAnnotations();
|
||||
@@ -57,17 +59,31 @@ class EntityResolver {
|
||||
return null;
|
||||
}
|
||||
|
||||
public function searchField($name) : null|array
|
||||
{
|
||||
try{
|
||||
return $this->field($name, self::KEY_ENTITY_NAME, false) ?: $this->field($name, self::KEY_COLUMN_NAME, false);
|
||||
}
|
||||
catch(\Throwable $e) {
|
||||
if ( $throwException) {
|
||||
throw new \InvalidArgumentException("Can't find entity field's column named `$name` from entity {$this->entityClass}");
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public function fieldList($fieldKey = self::KEY_ENTITY_NAME, bool $skipVirtual = false) : array
|
||||
{
|
||||
$fieldList = [];
|
||||
|
||||
foreach($this->properties as $item) {
|
||||
foreach($item['tags'] ?? [] as $tag) {
|
||||
if ( $tag['object'] instanceof Field ) {
|
||||
if ( $skipVirtual && ($tag['object'] instanceof Virtual )) {
|
||||
if ( $tag['object'] instanceof Field or $tag['object'] instanceof Attribute\Property\Field ) {
|
||||
if ( $skipVirtual && ($tag['object'] instanceof Virtual or $tag['object'] instanceof Attribute\Property\Virtual )) {
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
switch($fieldKey) {
|
||||
case static::KEY_LC_ENTITY_NAME:
|
||||
$key = strtolower($item['name']);
|
||||
@@ -101,7 +117,7 @@ class EntityResolver {
|
||||
try{
|
||||
if ( null !== ( $this->properties[$name] ?? null ) ) {
|
||||
foreach($this->properties[$name]['tags'] ?? [] as $tag) {
|
||||
if ( $tag['object'] instanceof Relation ) {
|
||||
if ( $tag['object'] instanceof Relation or $tag['object'] instanceof Attribute\Property\Relation ) {
|
||||
return $this->properties[$name];
|
||||
}
|
||||
}
|
||||
@@ -118,22 +134,25 @@ class EntityResolver {
|
||||
return null;
|
||||
}
|
||||
|
||||
public function searchFieldAnnotation(string $field, Annotation $annotationType, bool $caseSensitive = true) : ? Annotation
|
||||
public function searchFieldAnnotation(string $field, array|object|string $annotationType, bool $caseSensitive = true) : ? object
|
||||
{
|
||||
$found = $this->searchFieldAnnotationList($field, $annotationType, $caseSensitive);
|
||||
return $found ? $found[0] : null;
|
||||
return $this->searchFieldAnnotationList($field, $annotationType, $caseSensitive)[0] ?? null;
|
||||
}
|
||||
|
||||
public function searchFieldAnnotationList(string $field, Annotation $annotationType, bool $caseSensitive = true) : array
|
||||
public function searchFieldAnnotationList(string $field, array|object|string $annotationType, bool $caseSensitive = true) : array
|
||||
{
|
||||
$list = [];
|
||||
|
||||
$search = $caseSensitive ? $this->properties : array_change_key_case($this->properties, \CASE_LOWER);
|
||||
|
||||
$annotations = is_array($annotationType) ? $annotationType : [ $annotationType ];
|
||||
|
||||
if ( null !== ( $search[$field] ?? null ) ) {
|
||||
foreach($search[$field]['tags'] ?? [] as $tag) {
|
||||
if ( $tag['object'] instanceof $annotationType ) {
|
||||
$list[] = $tag['object'];
|
||||
foreach($annotations as $annotation) {
|
||||
if ( $tag['object'] instanceof $annotation ) {
|
||||
$list[] = $tag['object'];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -154,9 +173,9 @@ class EntityResolver {
|
||||
return $table->name ?? "";
|
||||
}
|
||||
|
||||
public function tableAnnotation($required = false) : Table
|
||||
public function tableAnnotation($required = false) : Table|Attribute\Obj\Table
|
||||
{
|
||||
if ( null === $table = $this->getAnnotationFromClassname( Table::class ) ) {
|
||||
if ( null === $table = $this->getTableAttribute() ) {
|
||||
if ($required) {
|
||||
throw new \LogicException("Your entity {$this->entityClass} seems to be missing a @Table() annotation");
|
||||
}
|
||||
@@ -172,7 +191,7 @@ class EntityResolver {
|
||||
|
||||
public function sqlAdapter() : \Ulmus\ConnectionAdapter
|
||||
{
|
||||
if ( null !== $table = $this->getAnnotationFromClassname( Table::class ) ) {
|
||||
if ( null !== $table = $this->getTableAttribute() ) {
|
||||
if ( $table->adapter ?? null ) {
|
||||
if ( null === ( $adapter = \Ulmus\Ulmus::$registeredAdapters[$table->adapter] ?? null ) ) {
|
||||
throw new \Exception("Requested database adapter `{$table->adapter}` is not registered.");
|
||||
@@ -196,7 +215,7 @@ class EntityResolver {
|
||||
|
||||
public function schemaName(bool $required = false) : ? string
|
||||
{
|
||||
if ( null === $table = $this->getAnnotationFromClassname( Table::class ) ) {
|
||||
if ( null === $table = $this->getTableAttribute() ) {
|
||||
throw new \LogicException("Your entity {$this->entityClass} seems to be missing a @Table() annotation");
|
||||
}
|
||||
|
||||
@@ -210,7 +229,8 @@ class EntityResolver {
|
||||
public function getPrimaryKeyField() : ? array
|
||||
{
|
||||
foreach($this->fieldList() as $key => $value) {
|
||||
if ( null !== ( $field = $this->searchFieldAnnotation($key, new Field() ) ) ) {
|
||||
$field = $this->searchFieldAnnotation($key, [ Attribute\Property\Field::class, Field::class ]);
|
||||
if ( null !== $field ) {
|
||||
if ( false !== ( $field->attributes['primary_key'] ?? false ) ) {
|
||||
return [ $key => $field ];
|
||||
}
|
||||
@@ -230,13 +250,17 @@ class EntityResolver {
|
||||
return null;
|
||||
}
|
||||
|
||||
protected function getTableAttribute()
|
||||
{
|
||||
return $this->getAnnotationFromClassname(Attribute\Obj\Table::class, false) ?: $this->getAnnotationFromClassname( Table::class );
|
||||
}
|
||||
|
||||
/**
|
||||
* Transform an annotation into it's object's counterpart
|
||||
*/
|
||||
public function getAnnotationFromClassname(string $className, bool $throwError = true) : ? object
|
||||
{
|
||||
if ( $name = $this->uses[$className] ?? false ) {
|
||||
|
||||
foreach(array_reverse($this->class['tags']) as $item) {
|
||||
if ( $item['tag'] === $name ) {
|
||||
return $this->instanciateAnnotationObject($item);
|
||||
@@ -270,18 +294,23 @@ class EntityResolver {
|
||||
return null;
|
||||
}
|
||||
|
||||
public function instanciateAnnotationObject(array $tagDefinition) : Annotation
|
||||
public function instanciateAnnotationObject(array|\ReflectionAttribute $tagDefinition) : object
|
||||
{
|
||||
$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)");
|
||||
if ($tagDefinition instanceof \ReflectionAttribute) {
|
||||
$obj = $tagDefinition->newInstance();
|
||||
}
|
||||
else {
|
||||
$arguments = $this->extractArguments($tagDefinition['arguments']);
|
||||
|
||||
$obj = new $class(... $arguments['constructor']);
|
||||
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)");
|
||||
}
|
||||
|
||||
foreach($arguments['setter'] as $key => $value) {
|
||||
$obj->$key = $value;
|
||||
$obj = new $class(... $arguments['constructor']);
|
||||
|
||||
foreach ($arguments['setter'] as $key => $value) {
|
||||
$obj->$key = $value;
|
||||
}
|
||||
}
|
||||
|
||||
return $obj;
|
||||
@@ -309,18 +338,18 @@ class EntityResolver {
|
||||
protected function resolveAnnotations()
|
||||
{
|
||||
foreach($this->class['tags'] as &$tag) {
|
||||
$tag['object'] = $this->instanciateAnnotationObject($tag);
|
||||
$tag['object'] ??= $this->instanciateAnnotationObject($tag);
|
||||
}
|
||||
|
||||
foreach($this->properties as &$property) {
|
||||
foreach($property['tags'] as &$tag){
|
||||
$tag['object'] = $this->instanciateAnnotationObject($tag);
|
||||
$tag['object'] ??= $this->instanciateAnnotationObject($tag);
|
||||
}
|
||||
}
|
||||
|
||||
foreach($this->methods as &$method) {
|
||||
foreach($method['tags'] as &$tag){
|
||||
$tag['object'] = $this->instanciateAnnotationObject($tag);
|
||||
$tag['object'] ??= $this->instanciateAnnotationObject($tag);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user