- WIP on Notes v2.x
This commit is contained in:
parent
1dd9da6eb6
commit
75231f32b3
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
namespace Ulmus\Adapter;
|
namespace Ulmus\Adapter;
|
||||||
|
|
||||||
use Ulmus\{ConnectionAdapter, Entity\InformationSchema\Table, Migration\FieldDefinition, Repository, QueryBuilder\Sql\MysqlQueryBuilder};
|
use Ulmus\{ConnectionAdapter, Entity\InformationSchema\Table, Migration\FieldDefinition, Repository, QueryBuilder\Sql\MysqlQueryBuilder, Entity};
|
||||||
|
|
||||||
trait DefaultAdapterTrait
|
trait DefaultAdapterTrait
|
||||||
{
|
{
|
||||||
|
|
|
@ -64,7 +64,6 @@ class SQLite implements AdapterInterface, MigrateInterface, SqlAdapterInterface
|
||||||
public function escapeIdentifier(string $segment, int $type) : string
|
public function escapeIdentifier(string $segment, int $type) : string
|
||||||
{
|
{
|
||||||
switch($type) {
|
switch($type) {
|
||||||
default:
|
|
||||||
case static::IDENTIFIER_DATABASE:
|
case static::IDENTIFIER_DATABASE:
|
||||||
case static::IDENTIFIER_TABLE:
|
case static::IDENTIFIER_TABLE:
|
||||||
case static::IDENTIFIER_FIELD:
|
case static::IDENTIFIER_FIELD:
|
||||||
|
|
|
@ -2,6 +2,8 @@
|
||||||
|
|
||||||
namespace Ulmus\Common;
|
namespace Ulmus\Common;
|
||||||
|
|
||||||
|
use Notes\Common\ReflectedClass;
|
||||||
|
use Notes\Common\ReflectedProperty;
|
||||||
use Psr\SimpleCache\CacheInterface;
|
use Psr\SimpleCache\CacheInterface;
|
||||||
use Ulmus\Ulmus,
|
use Ulmus\Ulmus,
|
||||||
Ulmus\Annotation\Classes\Table,
|
Ulmus\Annotation\Classes\Table,
|
||||||
|
@ -24,13 +26,7 @@ class EntityResolver {
|
||||||
|
|
||||||
public string $entityClass;
|
public string $entityClass;
|
||||||
|
|
||||||
public array $uses;
|
public ReflectedClass $reflectedClass;
|
||||||
|
|
||||||
public array $class;
|
|
||||||
|
|
||||||
public array $properties;
|
|
||||||
|
|
||||||
public array $methods;
|
|
||||||
|
|
||||||
protected array $fieldList = [];
|
protected array $fieldList = [];
|
||||||
|
|
||||||
|
@ -38,14 +34,10 @@ class EntityResolver {
|
||||||
{
|
{
|
||||||
$this->entityClass = $entityClass;
|
$this->entityClass = $entityClass;
|
||||||
|
|
||||||
list($this->uses, $this->class, $this->methods, $this->properties) = array_values(
|
$this->reflectedClass = ObjectReflection::fromClass($entityClass, $cache)->reflectClass();
|
||||||
ObjectReflection::fromClass($entityClass, $cache)->read()
|
|
||||||
);
|
|
||||||
|
|
||||||
$this->resolveAnnotations();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function field($name, $fieldKey = self::KEY_ENTITY_NAME, $throwException = true) : ? array
|
public function field($name, $fieldKey = self::KEY_ENTITY_NAME, $throwException = true) : ? ReflectedProperty
|
||||||
{
|
{
|
||||||
try{
|
try{
|
||||||
return $this->fieldList($fieldKey)[$name] ?? null;
|
return $this->fieldList($fieldKey)[$name] ?? null;
|
||||||
|
@ -68,25 +60,25 @@ class EntityResolver {
|
||||||
{
|
{
|
||||||
$fieldList = [];
|
$fieldList = [];
|
||||||
|
|
||||||
foreach($this->properties as $item) {
|
foreach($this->reflectedClass->getProperties(true) as $item) {
|
||||||
foreach($item['tags'] ?? [] as $tag) {
|
foreach($item->getAttributes() as $tag) {
|
||||||
if ( $tag['object'] instanceof Field or $tag['object'] instanceof Attribute\Property\Field ) {
|
if ( $tag->object instanceof Attribute\Property\Field ) {
|
||||||
if ( $skipVirtual && ($tag['object'] instanceof Virtual or $tag['object'] instanceof Attribute\Property\Virtual )) {
|
if ( $skipVirtual && $tag->object instanceof Attribute\Property\Virtual ) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch($fieldKey) {
|
switch($fieldKey) {
|
||||||
case static::KEY_LC_ENTITY_NAME:
|
case static::KEY_LC_ENTITY_NAME:
|
||||||
$key = strtolower($item['name']);
|
$key = strtolower($item->name);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
||||||
case static::KEY_ENTITY_NAME:
|
case static::KEY_ENTITY_NAME:
|
||||||
$key = $item['name'];
|
$key = $item->name;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case static::KEY_COLUMN_NAME:
|
case static::KEY_COLUMN_NAME:
|
||||||
$key = strtolower($tag['object']->name ?? $item['name']);
|
$key = strtolower($tag->object->name ?? $item->name);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -103,26 +95,24 @@ class EntityResolver {
|
||||||
return $fieldList;
|
return $fieldList;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function relation(string $name) : ? array
|
public function relation(string $name) : array
|
||||||
{
|
{
|
||||||
|
$property = $this->reflectedClass->getProperties(true)[$name] ?? false;
|
||||||
|
|
||||||
try{
|
try{
|
||||||
if ( null !== ( $this->properties[$name] ?? null ) ) {
|
if ( $property ) {
|
||||||
foreach($this->properties[$name]['tags'] ?? [] as $tag) {
|
foreach($property->getAttributes() as $tag) {
|
||||||
if ( $tag['object'] instanceof Relation or $tag['object'] instanceof Attribute\Property\Relation ) {
|
if ( $tag->object instanceof Relation or $tag->object instanceof Attribute\Property\Relation ) {
|
||||||
return $this->properties[$name];
|
return $property;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
catch(\Throwable $e) {
|
catch(\Throwable $e) {
|
||||||
# if ( $throwException) {
|
throw new \InvalidArgumentException("Can't find entity relation's column named `$name` from entity {$this->entityClass}");
|
||||||
throw new \InvalidArgumentException("Can't find entity relation's column named `$name` from entity {$this->entityClass}");
|
|
||||||
# }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function searchFieldAnnotation(string $field, array|object|string $annotationType, bool $caseSensitive = true) : ? object
|
public function searchFieldAnnotation(string $field, array|object|string $annotationType, bool $caseSensitive = true) : ? object
|
||||||
|
@ -134,15 +124,17 @@ class EntityResolver {
|
||||||
{
|
{
|
||||||
$list = [];
|
$list = [];
|
||||||
|
|
||||||
$search = $caseSensitive ? $this->properties : array_change_key_case($this->properties, \CASE_LOWER);
|
$properties = $this->reflectedClass->getProperties(true);
|
||||||
|
|
||||||
|
$search = $caseSensitive ? $properties : array_change_key_case($properties, \CASE_LOWER);
|
||||||
|
|
||||||
$annotations = is_array($annotationType) ? $annotationType : [ $annotationType ];
|
$annotations = is_array($annotationType) ? $annotationType : [ $annotationType ];
|
||||||
|
|
||||||
if ( null !== ( $search[$field] ?? null ) ) {
|
if ( null !== ( $search[$field] ?? null ) ) {
|
||||||
foreach($search[$field]['tags'] ?? [] as $tag) {
|
foreach($search[$field]->getAttributes() as $tag) {
|
||||||
foreach($annotations as $annotation) {
|
foreach($annotations as $annotation) {
|
||||||
if ( $tag['object'] instanceof $annotation ) {
|
if ( $tag->object instanceof $annotation ) {
|
||||||
$list[] = $tag['object'];
|
$list[] = $tag->object;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -256,6 +248,7 @@ class EntityResolver {
|
||||||
*/
|
*/
|
||||||
public function getAnnotationFromClassname(string $className, bool $throwError = true) : ? object
|
public function getAnnotationFromClassname(string $className, bool $throwError = true) : ? object
|
||||||
{
|
{
|
||||||
|
exit(__FILE__);
|
||||||
if ( $name = $this->uses[$className] ?? false ) {
|
if ( $name = $this->uses[$className] ?? false ) {
|
||||||
foreach(array_reverse($this->class['tags']) as $item) {
|
foreach(array_reverse($this->class['tags']) as $item) {
|
||||||
if ( $item['tag'] === $name ) {
|
if ( $item['tag'] === $name ) {
|
||||||
|
@ -292,9 +285,9 @@ class EntityResolver {
|
||||||
|
|
||||||
public function getAttributeImplementing(string $interface) : ? object
|
public function getAttributeImplementing(string $interface) : ? object
|
||||||
{
|
{
|
||||||
foreach (array_reverse($this->class['tags']) as $item) {
|
foreach (array_reverse($this->reflectedClass->getAttributes(true)) as $item) {
|
||||||
if ($item['object'] instanceof $interface) {
|
if ($item->object instanceof $interface) {
|
||||||
return $item['object'];
|
return $item->object;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -303,61 +296,11 @@ class EntityResolver {
|
||||||
|
|
||||||
public function instanciateAnnotationObject(array|\ReflectionAttribute $tagDefinition) : object
|
public function instanciateAnnotationObject(array|\ReflectionAttribute $tagDefinition) : object
|
||||||
{
|
{
|
||||||
|
|
||||||
if ($tagDefinition instanceof \ReflectionAttribute) {
|
if ($tagDefinition instanceof \ReflectionAttribute) {
|
||||||
$obj = $tagDefinition->newInstance();
|
$obj = $tagDefinition->newInstance();
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
$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;
|
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,8 +40,10 @@ trait EntityTrait {
|
||||||
$entityResolver = $this->resolveEntity();
|
$entityResolver = $this->resolveEntity();
|
||||||
|
|
||||||
foreach($dataset as $key => $value) {
|
foreach($dataset as $key => $value) {
|
||||||
$field = $entityResolver->field(strtolower($key), EntityResolver::KEY_COLUMN_NAME, false) ?? null;
|
$field = $entityResolver->field(strtolower($key), EntityResolver::KEY_COLUMN_NAME, false) ?? $entityResolver->field(strtolower($key), EntityResolver::KEY_LC_ENTITY_NAME, false);
|
||||||
$field ??= $entityResolver->field(strtolower($key), EntityResolver::KEY_LC_ENTITY_NAME, false);
|
|
||||||
|
# Temp. fix, incoming patch soon
|
||||||
|
$type = $field->getTypes()[0];
|
||||||
|
|
||||||
if ( $field === null ) {
|
if ( $field === null ) {
|
||||||
if ($this->entityStrictFieldsDeclaration ) {
|
if ($this->entityStrictFieldsDeclaration ) {
|
||||||
|
@ -52,12 +54,12 @@ trait EntityTrait {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
elseif ( is_null($value) ) {
|
elseif ( is_null($value) ) {
|
||||||
$this->{$field['name']} = null;
|
$this->{$field->name} = null;
|
||||||
}
|
}
|
||||||
elseif ( $field['type'] === 'array' ) {
|
elseif ( $field->expectType('array') ) {
|
||||||
if ( is_string($value)) {
|
if ( is_string($value)) {
|
||||||
if (substr($value, 0, 1) === "a") {
|
if (substr($value, 0, 1) === "a") {
|
||||||
$this->{$field['name']} = unserialize($value);
|
$this->{$field->name} = unserialize($value);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
$data = json_decode($value, true);
|
$data = json_decode($value, true);
|
||||||
|
@ -66,41 +68,41 @@ trait EntityTrait {
|
||||||
throw new \Exception(sprintf("JSON error while decoding in EntityTrait : '%s' given %s", json_last_error_msg(), $value));
|
throw new \Exception(sprintf("JSON error while decoding in EntityTrait : '%s' given %s", json_last_error_msg(), $value));
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->{$field['name']} = $data;
|
$this->{$field->name} = $data;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
elseif ( is_array($value) ) {
|
elseif ( is_array($value) ) {
|
||||||
$this->{$field['name']} = $value;
|
$this->{$field->name} = $value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
elseif ( EntityField::isScalarType($field['type']) ) {
|
elseif ( EntityField::isScalarType($type->type) ) {
|
||||||
|
|
||||||
if ( $field['type'] === 'string' ) {
|
if ( $type->type === 'string' ) {
|
||||||
$annotation = $entityResolver->searchFieldAnnotation($field['name'], [ Attribute\Property\Field::class, Field::class ] );
|
$annotation = $entityResolver->searchFieldAnnotation($field->name, [ Attribute\Property\Field::class ] );
|
||||||
|
|
||||||
if ( $annotation->length ?? null ) {
|
if ( $annotation->length ?? null ) {
|
||||||
$value = mb_substr($value, 0, $annotation->length);
|
$value = mb_substr($value, 0, $annotation->length);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
elseif ( $field['type'] === 'bool' ) {
|
elseif ( $type->type === 'bool' ) {
|
||||||
$value = (bool) $value;
|
$value = (bool) $value;
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->{$field['name']} = $value;
|
$this->{$field->name} = $value;
|
||||||
}
|
}
|
||||||
elseif ( $value instanceof \UnitEnum ) {
|
elseif ( $value instanceof \UnitEnum ) {
|
||||||
$this->{$field['name']} = $value;
|
$this->{$field->name} = $value;
|
||||||
}
|
}
|
||||||
elseif (enum_exists($field['type'])) {
|
elseif (enum_exists($type->type)) {
|
||||||
$this->{$field['name']} = $field['type']::from($value);
|
$this->{$field->name} = $type->type::from($value);
|
||||||
}
|
}
|
||||||
elseif ( ! $field['builtin'] ) {
|
elseif ( ! $type->builtIn ) {
|
||||||
try {
|
try {
|
||||||
$this->{$field['name']} = Ulmus::instanciateObject($field['type'], [ $value ]);
|
$this->{$field->name} = Ulmus::instanciateObject($type->type, [ $value ]);
|
||||||
}
|
}
|
||||||
catch(\Error $e) {
|
catch(\Error $e) {
|
||||||
$f = $field['type'];
|
$f = $type->type;
|
||||||
throw new \Error(sprintf("%s for class '%s' on field '%s'", $e->getMessage(), get_class($this), $field['name']));
|
throw new \Error(sprintf("%s for class '%s' on field '%s'", $e->getMessage(), get_class($this), $field->name));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -123,9 +125,9 @@ trait EntityTrait {
|
||||||
#[Ignore]
|
#[Ignore]
|
||||||
public function resetVirtualProperties() : self
|
public function resetVirtualProperties() : self
|
||||||
{
|
{
|
||||||
foreach($this->resolveEntity()->properties as $prop => $property) {
|
foreach($this->resolveEntity()->reflectedClass->getProperties(true) as $prop => $property) {
|
||||||
foreach($property['tags'] as $tag) {
|
foreach($property->attributes as $tag) {
|
||||||
if ( in_array(strtolower($tag['tag']), [ 'relation', 'join', 'virtual' ] ) ) {
|
if ( in_array(strtolower($tag->tag), [ 'relation', 'join', 'virtual' ] ) ) {
|
||||||
unset($this->$prop);
|
unset($this->$prop);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -155,7 +157,7 @@ trait EntityTrait {
|
||||||
$entityResolver = $this->resolveEntity();
|
$entityResolver = $this->resolveEntity();
|
||||||
|
|
||||||
foreach($entityResolver->fieldList(Common\EntityResolver::KEY_ENTITY_NAME, true) as $key => $field) {
|
foreach($entityResolver->fieldList(Common\EntityResolver::KEY_ENTITY_NAME, true) as $key => $field) {
|
||||||
$annotation = $entityResolver->searchFieldAnnotation($key, [ Attribute\Property\Field::class, Field::class ]);
|
$annotation = $entityResolver->searchFieldAnnotation($key, [ Attribute\Property\Field::class ]);
|
||||||
|
|
||||||
if ( isset($this->$key) ) {
|
if ( isset($this->$key) ) {
|
||||||
$dataset[$annotation->name ?? $key] = $rewriteValue ?
|
$dataset[$annotation->name ?? $key] = $rewriteValue ?
|
||||||
|
@ -163,13 +165,13 @@ trait EntityTrait {
|
||||||
:
|
:
|
||||||
$this->$key;
|
$this->$key;
|
||||||
}
|
}
|
||||||
elseif ( $field['nullable'] ) {
|
elseif ( $field->allowsNull() ) {
|
||||||
$dataset[$annotation->name ?? $key] = null;
|
$dataset[$annotation->name ?? $key] = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($includeRelations) {
|
if ($includeRelations) {
|
||||||
foreach($entityResolver->properties as $name => $field){
|
foreach($entityResolver->reflectedClass->getProperties(true) as $name => $field){
|
||||||
$relation = $entityResolver->searchFieldAnnotation($name, [ Attribute\Property\Relation::class ] );
|
$relation = $entityResolver->searchFieldAnnotation($name, [ Attribute\Property\Relation::class ] );
|
||||||
|
|
||||||
if ($relation) {
|
if ($relation) {
|
||||||
|
@ -178,7 +180,7 @@ trait EntityTrait {
|
||||||
if ($ignore && $ignore->ignoreExport) {
|
if ($ignore && $ignore->ignoreExport) {
|
||||||
if ( $relation->isOneToOne() ) {
|
if ( $relation->isOneToOne() ) {
|
||||||
# empty object
|
# empty object
|
||||||
$dataset[$name] = ( new \ReflectionClass($field['type']) )->newInstanceWithoutConstructor();
|
$dataset[$name] = ( new \ReflectionClass($field->getTypes()[0]) )->newInstanceWithoutConstructor();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
# empty collection
|
# empty collection
|
||||||
|
@ -326,7 +328,9 @@ trait EntityTrait {
|
||||||
{
|
{
|
||||||
$default = ( $alias === false ? '' : Repository::DEFAULT_ALIAS ); # bw compatibility, to be deprecated
|
$default = ( $alias === false ? '' : Repository::DEFAULT_ALIAS ); # bw compatibility, to be deprecated
|
||||||
|
|
||||||
return new EntityField(static::class, $name, $alias ? Ulmus::repository(static::class)->adapter->adapter()->escapeIdentifier($alias, Adapter\AdapterInterface::IDENTIFIER_FIELD) : $default, Ulmus::resolveEntity(static::class));
|
$alias = $alias ? Ulmus::repository(static::class)->adapter->adapter()->escapeIdentifier($alias, Adapter\AdapterInterface::IDENTIFIER_FIELD) : $default;
|
||||||
|
|
||||||
|
return new EntityField(static::class, $name, $alias, Ulmus::resolveEntity(static::class));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[Ignore]
|
#[Ignore]
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
namespace Ulmus\Migration;
|
namespace Ulmus\Migration;
|
||||||
|
|
||||||
|
use Notes\Common\ReflectedProperty;
|
||||||
use Ulmus\Adapter\AdapterInterface;
|
use Ulmus\Adapter\AdapterInterface;
|
||||||
use Ulmus\Annotation\Property\Field;
|
use Ulmus\Annotation\Property\Field;
|
||||||
use Ulmus\Attribute;
|
use Ulmus\Attribute;
|
||||||
|
@ -29,25 +30,28 @@ class FieldDefinition {
|
||||||
|
|
||||||
public AdapterInterface $adapter;
|
public AdapterInterface $adapter;
|
||||||
|
|
||||||
public function __construct(AdapterInterface $adapter, array $data)
|
public function __construct(AdapterInterface $adapter, ReflectedProperty $data)
|
||||||
{
|
{
|
||||||
$this->adapter = $adapter;
|
$this->adapter = $adapter;
|
||||||
|
|
||||||
$this->name = $data['name'];
|
# Patch coming soon
|
||||||
$this->builtIn = $data['builtin'];
|
$type = $data->getTypes()[0];
|
||||||
$this->tags = $data['tags'];
|
|
||||||
|
|
||||||
if (isset($data['value'])) {
|
$this->name = $data->name;
|
||||||
$this->default = $data['value'];
|
$this->builtIn = $type->builtIn;
|
||||||
|
$this->tags = $data->getAttributes();
|
||||||
|
|
||||||
|
if (isset($data->value)) {
|
||||||
|
$this->default = $data->value;
|
||||||
}
|
}
|
||||||
|
|
||||||
$field = $this->getFieldTag();
|
$field = $this->getFieldTag();
|
||||||
$adapter->whitelistAttributes($field->attributes);
|
$adapter->whitelistAttributes($field->attributes);
|
||||||
|
|
||||||
$this->type = $field->type ?? $data['type'];
|
$this->type = $field->type ?? $type->type;
|
||||||
$this->length = $field->length ?? null;
|
$this->length = $field->length ?? null;
|
||||||
$this->precision = $field->precision ?? null;
|
$this->precision = $field->precision ?? null;
|
||||||
$this->nullable = $data['nullable'] ?: $field->nullable;
|
$this->nullable = $data->allowsNull() ?: $field->nullable;
|
||||||
$this->update = $field->attributes['update'] ?? null;
|
$this->update = $field->attributes['update'] ?? null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -76,11 +80,11 @@ class FieldDefinition {
|
||||||
]));
|
]));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getFieldTag() : Field|Attribute\Property\Field|null
|
public function getFieldTag() : Attribute\Property\Field|null
|
||||||
{
|
{
|
||||||
$field = array_filter($this->tags, fn($item) => $item['object'] instanceof Field || $item['object'] instanceof Attribute\Property\Field);
|
$field = array_filter($this->tags, fn($item) => $item->object instanceof Attribute\Property\Field);
|
||||||
|
|
||||||
return array_pop($field)['object'];
|
return array_pop($field)->object;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getColumnName() : ? string
|
public function getColumnName() : ? string
|
||||||
|
|
|
@ -133,8 +133,6 @@ class Repository
|
||||||
|
|
||||||
return $this->deleteFromPk($entity->$pkField);
|
return $this->deleteFromPk($entity->$pkField);
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function destroyAll(EntityCollection $collection) : void
|
public function destroyAll(EntityCollection $collection) : void
|
||||||
|
@ -397,8 +395,8 @@ class Repository
|
||||||
$prependField and ($prependField .= "$");
|
$prependField and ($prependField .= "$");
|
||||||
|
|
||||||
foreach ($entity::resolveEntity()->fieldList(Common\EntityResolver::KEY_COLUMN_NAME, true) as $key => $field) {
|
foreach ($entity::resolveEntity()->fieldList(Common\EntityResolver::KEY_COLUMN_NAME, true) as $key => $field) {
|
||||||
if (null === $entity::resolveEntity()->searchFieldAnnotation($field['name'], [ Attribute\Property\Relation\Ignore::class, RelationIgnore::class ])) {
|
if (null === $entity::resolveEntity()->searchFieldAnnotation($field->name, [ Attribute\Property\Relation\Ignore::class, RelationIgnore::class ])) {
|
||||||
$this->select(sprintf("%s.$key as {$prependField}{$field['name']}", $this->escapeIdentifier($alias)));
|
$this->select(sprintf("%s.$key as {$prependField}{$field->name}", $this->escapeIdentifier($alias)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -410,9 +408,9 @@ class Repository
|
||||||
$fieldlist = [];
|
$fieldlist = [];
|
||||||
|
|
||||||
foreach ($entity::resolveEntity()->fieldList(Common\EntityResolver::KEY_COLUMN_NAME, true) as $key => $field) {
|
foreach ($entity::resolveEntity()->fieldList(Common\EntityResolver::KEY_COLUMN_NAME, true) as $key => $field) {
|
||||||
if (null === $entity::resolveEntity()->searchFieldAnnotation($field['name'], [ Attribute\Property\Relation\Ignore::class, RelationIgnore::class ])) {
|
if (null === $entity::resolveEntity()->searchFieldAnnotation($field->name, [ Attribute\Property\Relation\Ignore::class, RelationIgnore::class ])) {
|
||||||
$fieldlist[] = $key;
|
$fieldlist[] = $key;
|
||||||
$fieldlist[] = $entity::field($field['name'], $this->escapeIdentifier($alias));
|
$fieldlist[] = $entity::field($field->name, $this->escapeIdentifier($alias));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -625,26 +623,26 @@ class Repository
|
||||||
$this->joined[$item] = true;
|
$this->joined[$item] = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
$annotation = $this->entityResolver->searchFieldAnnotation($item, [ Attribute\Property\Join::class, Join::class ]) ?:
|
$annotation = $this->entityResolver->searchFieldAnnotation($item, [ Attribute\Property\Join::class ]) ?:
|
||||||
$this->entityResolver->searchFieldAnnotation($item, [ Attribute\Property\Relation::class, Relation::class ]);
|
$this->entityResolver->searchFieldAnnotation($item, [ Attribute\Property\Relation::class ]);
|
||||||
|
|
||||||
$isRelation = ( $annotation instanceof Relation ) || ($annotation instanceof Attribute\Property\Relation);
|
$isRelation = ( $annotation instanceof Relation ) || ($annotation instanceof Attribute\Property\Relation);
|
||||||
|
|
||||||
if ($isRelation && ( $annotation->isManyToMany() )) {
|
if ($isRelation && ( $annotation->isManyToMany() )) {
|
||||||
throw new Exception("Many-to-many relation can not be preloaded within joins.");
|
throw new \Exception("Many-to-many relation can not be preloaded within joins.");
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( $annotation ) {
|
if ( $annotation ) {
|
||||||
$alias = $annotation->alias ?? $item;
|
$alias = $annotation->alias ?? $item;
|
||||||
|
|
||||||
$entity = $annotation->entity ?? $this->entityResolver->properties[$item]['type'];
|
$entity = $annotation->entity ?? $this->entityResolver->reflectedClass->getProperties(true)[$item]->getTypes()[0]->type;
|
||||||
|
|
||||||
foreach($entity::resolveEntity()->fieldList(Common\EntityResolver::KEY_COLUMN_NAME, true) as $key => $field) {
|
foreach($entity::resolveEntity()->fieldList(Common\EntityResolver::KEY_COLUMN_NAME, true) as $key => $field) {
|
||||||
if ( null === $entity::resolveEntity()->searchFieldAnnotation($field['name'], [ Attribute\Property\Relation\Ignore::class, RelationIgnore::class ]) ) {
|
if ( null === $entity::resolveEntity()->searchFieldAnnotation($field->name, [ Attribute\Property\Relation\Ignore::class ]) ) {
|
||||||
$escAlias = $this->escapeIdentifier($alias);
|
$escAlias = $this->escapeIdentifier($alias);
|
||||||
$fieldName = $this->escapeIdentifier($key);
|
$fieldName = $this->escapeIdentifier($key);
|
||||||
|
|
||||||
$name = $entity::resolveEntity()->searchFieldAnnotation($field['name'], [ Attribute\Property\Field::class, Field::class ])->name ?? $field['name'];
|
$name = $entity::resolveEntity()->searchFieldAnnotation($field->name, [ Attribute\Property\Field::class ])->name ?? $field->name;
|
||||||
|
|
||||||
|
|
||||||
$this->select("$escAlias.$fieldName as $alias\${$name}");
|
$this->select("$escAlias.$fieldName as $alias\${$name}");
|
||||||
|
@ -654,7 +652,7 @@ class Repository
|
||||||
$this->open();
|
$this->open();
|
||||||
|
|
||||||
if ( ! in_array(WithOptionEnum::SkipWhere, $options)) {
|
if ( ! in_array(WithOptionEnum::SkipWhere, $options)) {
|
||||||
foreach($this->entityResolver->searchFieldAnnotationList($item, [ Attribute\Property\Where::class, Where::class ] ) as $condition) {
|
foreach($this->entityResolver->searchFieldAnnotationList($item, [ Attribute\Property\Where::class ] ) as $condition) {
|
||||||
if ( is_object($condition->field) && ( $condition->field->entityClass !== $entity ) ) {
|
if ( is_object($condition->field) && ( $condition->field->entityClass !== $entity ) ) {
|
||||||
$this->where(is_object($condition->field) ? $condition->field : $entity::field($condition->field), $condition->getValue(), $condition->operator);
|
$this->where(is_object($condition->field) ? $condition->field : $entity::field($condition->field), $condition->getValue(), $condition->operator);
|
||||||
}
|
}
|
||||||
|
@ -662,13 +660,13 @@ class Repository
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( ! in_array(WithOptionEnum::SkipHaving, $options)) {
|
if ( ! in_array(WithOptionEnum::SkipHaving, $options)) {
|
||||||
foreach ($this->entityResolver->searchFieldAnnotationList($item, [Attribute\Property\Having::class, Having::class]) as $condition) {
|
foreach ($this->entityResolver->searchFieldAnnotationList($item, [ Attribute\Property\Having::class ]) as $condition) {
|
||||||
$this->having(is_object($condition->field) ? $condition->field : $entity::field($condition->field), $condition->getValue(), $condition->operator);
|
$this->having(is_object($condition->field) ? $condition->field : $entity::field($condition->field), $condition->getValue(), $condition->operator);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( ! in_array(WithOptionEnum::SkipFilter, $options)) {
|
if ( ! in_array(WithOptionEnum::SkipFilter, $options)) {
|
||||||
foreach ($this->entityResolver->searchFieldAnnotationList($item, [Attribute\Property\Filter::class, Filter::class]) as $filter) {
|
foreach ($this->entityResolver->searchFieldAnnotationList($item, [ Attribute\Property\Filter::class ]) as $filter) {
|
||||||
call_user_func_array([$this->entityClass, $filter->method], [$this, $item, true]);
|
call_user_func_array([$this->entityClass, $filter->method], [$this, $item, true]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -681,7 +679,7 @@ class Repository
|
||||||
|
|
||||||
$this->join("LEFT", $entity::resolveEntity()->tableName(), $key, $foreignKey, $alias, function($join) use ($item, $entity, $alias, $options) {
|
$this->join("LEFT", $entity::resolveEntity()->tableName(), $key, $foreignKey, $alias, function($join) use ($item, $entity, $alias, $options) {
|
||||||
if ( ! in_array(WithOptionEnum::SkipJoinWhere, $options)) {
|
if ( ! in_array(WithOptionEnum::SkipJoinWhere, $options)) {
|
||||||
foreach($this->entityResolver->searchFieldAnnotationList($item, [ Attribute\Property\Where::class, Where::class ]) as $condition) {
|
foreach($this->entityResolver->searchFieldAnnotationList($item, [ Attribute\Property\Where::class ]) as $condition) {
|
||||||
if ( ! is_object($condition->field) ) {
|
if ( ! is_object($condition->field) ) {
|
||||||
$field = $this->entityClass::field($condition->field);
|
$field = $this->entityClass::field($condition->field);
|
||||||
}
|
}
|
||||||
|
@ -699,7 +697,7 @@ class Repository
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( ! in_array(WithOptionEnum::SkipJoinFilter, $options) ) {
|
if ( ! in_array(WithOptionEnum::SkipJoinFilter, $options) ) {
|
||||||
foreach ($this->entityResolver->searchFieldAnnotationList($item, [Attribute\Property\FilterJoin::class, FilterJoin::class]) as $filter) {
|
foreach ($this->entityResolver->searchFieldAnnotationList($item, [ Attribute\Property\FilterJoin::class ]) as $filter) {
|
||||||
call_user_func_array([$this->entityClass, $filter->method], [$join, $item, true]);
|
call_user_func_array([$this->entityClass, $filter->method], [$join, $item, true]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -726,7 +724,7 @@ class Repository
|
||||||
|
|
||||||
# Apply FILTER annotation to this too !
|
# Apply FILTER annotation to this too !
|
||||||
foreach(array_filter((array) $fields) as $item) {
|
foreach(array_filter((array) $fields) as $item) {
|
||||||
if ( $relation = $this->entityResolver->searchFieldAnnotation($item, [ Attribute\Property\Relation::class, Relation::class ]) ) {
|
if ( $relation = $this->entityResolver->searchFieldAnnotation($item, [ Attribute\Property\Relation::class ]) ) {
|
||||||
$alias = $relation->alias ?? $item;
|
$alias = $relation->alias ?? $item;
|
||||||
|
|
||||||
if ( $relation->isManyToMany() ) {
|
if ( $relation->isManyToMany() ) {
|
||||||
|
@ -747,11 +745,11 @@ class Repository
|
||||||
|
|
||||||
# $relation->isManyToMany() and $repository->selectJsonEntity($relation->bridge, $relation->bridgeField, true);
|
# $relation->isManyToMany() and $repository->selectJsonEntity($relation->bridge, $relation->bridgeField, true);
|
||||||
|
|
||||||
foreach($this->entityResolver->searchFieldAnnotationList($item, [ Attribute\Property\Where::class, Where::class ]) as $condition) {
|
foreach($this->entityResolver->searchFieldAnnotationList($item, [ Attribute\Property\Where::class ]) as $condition) {
|
||||||
$repository->where(is_object($condition->field) ? $condition->field : $entity::field($condition->field), $condition->getValue(), $condition->operator);
|
$repository->where(is_object($condition->field) ? $condition->field : $entity::field($condition->field), $condition->getValue(), $condition->operator);
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach($this->entityResolver->searchFieldAnnotationList($item, [ Attribute\Property\Having::class, Having::class ] ) as $condition) {
|
foreach($this->entityResolver->searchFieldAnnotationList($item, [ Attribute\Property\Having::class ] ) as $condition) {
|
||||||
$repository->having(is_object($condition->field) ? $condition->field : $entity::field($condition->field), $condition->getValue(), $condition->operator);
|
$repository->having(is_object($condition->field) ? $condition->field : $entity::field($condition->field), $condition->getValue(), $condition->operator);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -778,9 +776,9 @@ class Repository
|
||||||
public function loadCollectionRelation(EntityCollection $collection, array|string $fields) : void
|
public function loadCollectionRelation(EntityCollection $collection, array|string $fields) : void
|
||||||
{
|
{
|
||||||
foreach ((array)$fields as $name) {
|
foreach ((array)$fields as $name) {
|
||||||
if (null !== ($relation = $this->entityResolver->searchFieldAnnotation($name, [ Attribute\Property\Relation::class, Relation::class ] ))) {
|
if (null !== ($relation = $this->entityResolver->searchFieldAnnotation($name, [ Attribute\Property\Relation::class ] ))) {
|
||||||
$order = $this->entityResolver->searchFieldAnnotationList($name, [ Attribute\Property\OrderBy::class, OrderBy::class ]);
|
$order = $this->entityResolver->searchFieldAnnotationList($name, [ Attribute\Property\OrderBy::class ]);
|
||||||
$where = $this->entityResolver->searchFieldAnnotationList($name, [ Attribute\Property\Where::class, Where::class ]);
|
$where = $this->entityResolver->searchFieldAnnotationList($name, [ Attribute\Property\Where::class ]);
|
||||||
|
|
||||||
$baseEntity = $relation->entity ?? $relation->bridge ?? $this->entityResolver->properties[$name]['type'];
|
$baseEntity = $relation->entity ?? $relation->bridge ?? $this->entityResolver->properties[$name]['type'];
|
||||||
$baseEntityResolver = $baseEntity::resolveEntity();
|
$baseEntityResolver = $baseEntity::resolveEntity();
|
||||||
|
@ -791,7 +789,7 @@ class Repository
|
||||||
$repository = $baseEntity::repository();
|
$repository = $baseEntity::repository();
|
||||||
|
|
||||||
foreach ($baseEntityResolver->fieldList(Common\EntityResolver::KEY_COLUMN_NAME, true) as $key => $field) {
|
foreach ($baseEntityResolver->fieldList(Common\EntityResolver::KEY_COLUMN_NAME, true) as $key => $field) {
|
||||||
if (null === $baseEntityResolver->searchFieldAnnotation($field['name'], [ Attribute\Property\Relation\Ignore::class, RelationIgnore::class ])) {
|
if (null === $baseEntityResolver->searchFieldAnnotation($field->name, [ Attribute\Property\Relation\Ignore::class ])) {
|
||||||
$repository->select($baseEntityResolver->entityClass::field($key));
|
$repository->select($baseEntityResolver->entityClass::field($key));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -953,7 +951,7 @@ class Repository
|
||||||
{
|
{
|
||||||
if ( null === $this->queryBuilder->getFragment(Query\Select::class) ) {
|
if ( null === $this->queryBuilder->getFragment(Query\Select::class) ) {
|
||||||
$fields = $this->entityResolver->fieldList(EntityResolver::KEY_COLUMN_NAME, true);
|
$fields = $this->entityResolver->fieldList(EntityResolver::KEY_COLUMN_NAME, true);
|
||||||
$this->select($this->entityClass::fields(array_map(fn($f) => $f['object']->name ?? $f['name'], $fields)));
|
$this->select($this->entityClass::fields(array_map(fn($f) => $f->object->name ?? $f->name, $fields)));
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( null === $this->queryBuilder->getFragment(Query\From::class) ) {
|
if ( null === $this->queryBuilder->getFragment(Query\From::class) ) {
|
||||||
|
|
|
@ -219,7 +219,7 @@ class RelationBuilder
|
||||||
$entity = $this->relationAnnotations($name, $annotation)['relationRelation']->entity;
|
$entity = $this->relationAnnotations($name, $annotation)['relationRelation']->entity;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
$entity = $annotation->entity ?? $this->resolver->properties[$name]['type'];
|
$entity = $annotation->entity ?? $this->resolver->reflectedClass->getProperties()[$name]->getTypes()[0]->type;
|
||||||
}
|
}
|
||||||
|
|
||||||
$name = strtolower($name);
|
$name = strtolower($name);
|
||||||
|
@ -266,7 +266,7 @@ class RelationBuilder
|
||||||
|
|
||||||
public function oneToMany(string $name, Relation|Attribute\Property\Relation $relation) : Repository
|
public function oneToMany(string $name, Relation|Attribute\Property\Relation $relation) : Repository
|
||||||
{
|
{
|
||||||
$baseEntity = $relation->entity ?? $this->resolver->properties[$name]['type'];
|
$baseEntity = $relation->entity ?? $this->resolver->reflectedClass->getProperties()[$name]->getTypes()[0]->type;
|
||||||
|
|
||||||
$this->repository = $baseEntity::repository();
|
$this->repository = $baseEntity::repository();
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue