- 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:
mcndave committed 2021-03-01 16:26:06 +00:00
1 parent 8f9332fbad
commit 16c6eb57fb
32 files changed
+641 -243

No files matched your search

+12 -175
View File
@@ -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
*/