- Added a MssqlRepository
- Adapter some code to allow more flexibility for the new LDAP adapter from ulmus-ldap. - Insert's fields are now escaped by default. - A new RelationBuilder was added, a lot of code from the EntityTrait was moved into this. Some code from the Repository class will need to be moved there too.
This commit is contained in:
1 parent
8f9332fbad
commit
16c6eb57fb
32 files changed
+641
-243
No files matched your search
+12
-175
@@ -8,8 +8,9 @@ use Ulmus\Repository,
|
||||
Ulmus\Common\EntityField;
|
||||
|
||||
use Ulmus\Annotation\Classes\{ Method, Table, Collation, };
|
||||
use Ulmus\Annotation\Property\{ Field, Filter, Relation, OrderBy, Where, Join, Virtual, On, };
|
||||
use Ulmus\Annotation\Property\Field\{ Id, ForeignKey, CreatedAt, UpdatedAt, Datetime as DateTime, Date, Time, };
|
||||
use Ulmus\Annotation\Property\{ Field, Filter, Relation, OrderBy, Where, Join, Virtual, On, WithJoin, };
|
||||
use Ulmus\Annotation\Property\Field\{ Id, ForeignKey, CreatedAt, UpdatedAt, Datetime as DateTime, Date, Time, Bigint, Tinyint, Text, Mediumtext, Longtext, };
|
||||
use Ulmus\Annotation\Property\Relation\{ Ignore as RelationIgnore };
|
||||
|
||||
trait EntityTrait {
|
||||
use EventTrait;
|
||||
@@ -28,174 +29,18 @@ trait EntityTrait {
|
||||
* @Ignore
|
||||
*/
|
||||
public array $entityLoadedDataset = [];
|
||||
|
||||
|
||||
/**
|
||||
* @Ignore
|
||||
*/
|
||||
public function __get(string $name)
|
||||
{
|
||||
$entityResolver = $this->resolveEntity();
|
||||
|
||||
# Resolve relations here if one is called
|
||||
|
||||
# @TODO REFACTOR THIS CODE ASAP !
|
||||
if ( $this->isLoaded() ) {
|
||||
$annotation = $entityResolver->searchFieldAnnotation($name, new Annotation\Property\Join) ?:
|
||||
$entityResolver->searchFieldAnnotation($name, new Annotation\Property\Relation);
|
||||
|
||||
if ( $annotation ) {
|
||||
$vars = [];
|
||||
|
||||
$len = strlen( $name ) + 1;
|
||||
|
||||
foreach($this->entityDatasetUnmatchedFields as $key => $value) {
|
||||
if ( substr($key, 0, $len ) === "{$name}$" ) {
|
||||
$vars[substr($key, $len)] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
if ( [] !== $data = (array_values(array_unique($vars)) !== [ null ] ? $vars : []) ) {
|
||||
$entity = $annotation->entity ?? $entityResolver->properties[$name]['type'];
|
||||
|
||||
return $this->$name = ( new $entity() )->fromArray($data)->resetVirtualProperties();
|
||||
}
|
||||
}
|
||||
|
||||
if ( null !== ( $relation = $entityResolver->searchFieldAnnotation($name, new Relation() ) ) ) {
|
||||
$order = $entityResolver->searchFieldAnnotationList($name, new OrderBy() );
|
||||
$where = $entityResolver->searchFieldAnnotationList($name, new Where() );
|
||||
$filters = $entityResolver->searchFieldAnnotationList($name, new Filter() );
|
||||
|
||||
$baseEntity = $relation->entity ?? $relation->bridge ?? $entityResolver->properties[$name]['type'];
|
||||
$repository = $baseEntity::repository()->open();
|
||||
|
||||
foreach($where as $condition) {
|
||||
$repository->where($condition->field, is_callable($condition->value) ? call_user_func_array($condition->value, [ $this ]) : $condition->value, $condition->operator, $condition->condition);
|
||||
}
|
||||
|
||||
$repository->close();
|
||||
|
||||
foreach ($order as $item) {
|
||||
$repository->orderBy($item->field, $item->order);
|
||||
}
|
||||
|
||||
$applyFilter = function($repository) use ($filters, $name) {
|
||||
foreach($filters as $filter) {
|
||||
$repository = call_user_func_array([ $this, $filter->method ], [ $repository, $name ]);
|
||||
}
|
||||
|
||||
return $repository;
|
||||
};
|
||||
|
||||
$field = $relation->key;
|
||||
|
||||
$applyFilter = function($repository) use ($filters, $name) {
|
||||
foreach($filters as $filter) {
|
||||
$repository = call_user_func_array([ $this, $filter->method ], [ $repository, $name ]);
|
||||
}
|
||||
|
||||
return $repository;
|
||||
};
|
||||
|
||||
switch( $relation->normalizeType() ) {
|
||||
case 'onetoone':
|
||||
$repository->limit(1);
|
||||
|
||||
if ($relation->foreignKey) {
|
||||
$repository->where( is_object($relation->foreignKey) ? $relation->foreignKey : $baseEntity::field($relation->foreignKey), is_callable($field) ? $field($this) : $this->$field );
|
||||
}
|
||||
|
||||
$this->eventExecute(Event\EntityRelationLoadInterface::class, $name, $repository);
|
||||
|
||||
$result = call_user_func([$repository, $relation->function]);
|
||||
|
||||
if ( count($result) === 0 ) {
|
||||
return new $baseEntity();
|
||||
}
|
||||
|
||||
return $this->$name = $result[0];
|
||||
|
||||
case 'onetomany':
|
||||
if ($relation->foreignKey) {
|
||||
$repository->where( is_object($relation->foreignKey) ? $relation->foreignKey : $baseEntity::field($relation->foreignKey), is_callable($field) ? $field($this) : $this->$field );
|
||||
}
|
||||
|
||||
$this->eventExecute(Event\EntityRelationLoadInterface::class, $name, $repository);
|
||||
|
||||
return $this->$name = call_user_func([$applyFilter($repository), $relation->function]);
|
||||
|
||||
case 'manytomany':
|
||||
if ( false === $relation->bridge ?? false ) {
|
||||
throw new \Exception("Your many-to-many @Relation() from variable `$name` is missing a 'bridge' value.");
|
||||
}
|
||||
|
||||
$bridgeEntity = Ulmus::resolveEntity($relation->bridge);
|
||||
$bridgeRelation = $bridgeEntity->searchFieldAnnotation($relation->field, new Relation() );
|
||||
$relationRelation = $bridgeEntity->searchFieldAnnotation($relation->foreignField, new Relation() );
|
||||
|
||||
if ($relationRelation === null) {
|
||||
throw new \Exception("@Relation annotation not found for field `{$relation->foreignField}` in entity {$relation->bridge}");
|
||||
}
|
||||
|
||||
$repository = $relationRelation->entity()->repository();
|
||||
|
||||
$bridgeAlias = uniqid("bridge_");
|
||||
$relationAlias = uniqid("relation_");
|
||||
|
||||
# @TODO Rewrite to be done here, this code must move somewhere else...
|
||||
$repository->select("{$repository->alias}.*")
|
||||
->join(Query\Join::TYPE_INNER, $bridgeEntity->tableName(), $relation->bridge::field($relationRelation->key, $bridgeAlias), $relationRelation->entity::field($relationRelation->foreignKey), $bridgeAlias)
|
||||
->join(Query\Join::TYPE_INNER, $this->resolveEntity()->tableName(), $relation->bridge::field($bridgeRelation->key, $bridgeAlias), static::field($bridgeRelation->foreignKey, $relationAlias), $relationAlias)
|
||||
->where( static::field($bridgeRelation->foreignKey, $relationAlias), $this->{$bridgeRelation->foreignKey} );
|
||||
|
||||
$repository->open();
|
||||
|
||||
foreach($where as $condition) {
|
||||
$repository->where($condition->field, $condition->value, $condition->operator);
|
||||
}
|
||||
|
||||
$repository->close();
|
||||
|
||||
foreach($order as $item) {
|
||||
$repository->orderBy($item->field, $item->order);
|
||||
}
|
||||
|
||||
$this->eventExecute(Event\EntityRelationLoadInterface::class, $name, $repository);
|
||||
|
||||
$this->$name = call_user_func([ $applyFilter($repository), $relationRelation->function ]);
|
||||
|
||||
if ($relation->bridgeField ?? false) {
|
||||
$repository = $relationRelation->entity::repository();
|
||||
|
||||
$repository->select("$bridgeAlias.*")
|
||||
->join(Query\Join::TYPE_INNER, $bridgeEntity->tableName(), $relation->bridge::field($relationRelation->key, $bridgeAlias), $relationRelation->entity::field($relationRelation->foreignKey), $bridgeAlias)
|
||||
->join(Query\Join::TYPE_INNER, $this->resolveEntity()->tableName(), $relation->bridge::field($bridgeRelation->key, $bridgeAlias), static::field($bridgeRelation->foreignKey, $relationAlias), $relationAlias)
|
||||
->where( static::field($bridgeRelation->foreignKey, $relationAlias), $this->{$bridgeRelation->foreignKey} );
|
||||
|
||||
$repository->open();
|
||||
|
||||
foreach($where as $condition) {
|
||||
$repository->where($condition->field, $condition->value, $condition->operator);
|
||||
}
|
||||
|
||||
$repository->close();
|
||||
|
||||
foreach($order as $item) {
|
||||
$repository->orderBy($item->field, $item->order);
|
||||
}
|
||||
|
||||
$bridgeName = $relation->bridgeField;
|
||||
|
||||
$this->$bridgeName = $repository->collectionFromQuery($relation->bridge);
|
||||
}
|
||||
|
||||
return $this->$name;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
$relation = new Repository\RelationBuilder($this);
|
||||
|
||||
if ( false !== $data = $relation->searchRelation($name) ) {
|
||||
return $this->$name = $data;
|
||||
}
|
||||
|
||||
|
||||
throw new \Exception(sprintf("[%s] - Undefined variable: %s", static::class, $name));
|
||||
}
|
||||
|
||||
@@ -227,7 +72,7 @@ trait EntityTrait {
|
||||
$field = $entityResolver->field(strtolower($key), EntityResolver::KEY_COLUMN_NAME, false) ?? null;
|
||||
|
||||
if ( $field === null ) {
|
||||
$field = $entityResolver->field($key, EntityResolver::KEY_ENTITY_NAME, false);
|
||||
$field = $entityResolver->field(strtolower($key), EntityResolver::KEY_LC_ENTITY_NAME, false);
|
||||
}
|
||||
|
||||
if ( $field === null ) {
|
||||
@@ -261,7 +106,7 @@ trait EntityTrait {
|
||||
elseif ( $field['type'] === 'bool' ) {
|
||||
$this->{$field['name']} = (bool) $value;
|
||||
}
|
||||
|
||||
|
||||
$this->{$field['name']} = $value;
|
||||
}
|
||||
elseif ( ! $field['builtin'] ) {
|
||||
@@ -385,7 +230,7 @@ trait EntityTrait {
|
||||
*/
|
||||
public function toCollection() : EntityCollection
|
||||
{
|
||||
return static::entityCollection([ $this->toArray() ]);
|
||||
return static::entityCollection([ $this ]);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -445,14 +290,6 @@ trait EntityTrait {
|
||||
return $collection;
|
||||
}
|
||||
|
||||
/**
|
||||
* @Ignore
|
||||
*/
|
||||
public static function queryBuilder() : QueryBuilder
|
||||
{
|
||||
return Ulmus::queryBuilder(static::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Ignore
|
||||
*/
|
||||
|
||||
Reference in new issue
Block a user