- Added Events to repository and entitytrait objects. Some more work to be done on this.
- Diverses bug fixes linked to join and relations - Field date and datetime are now outputed using given locale.
This commit is contained in:
1 parent
1839726dc0
commit
4d221859fc
15 files changed
+421
-99
No files matched your search
+172
-77
@@ -8,25 +8,26 @@ use Ulmus\Repository,
|
||||
Ulmus\Common\EntityField;
|
||||
|
||||
use Ulmus\Annotation\Classes\{ Method, Table, Collation, };
|
||||
use Ulmus\Annotation\Property\{ Field, Relation, OrderBy, Where, };
|
||||
use Ulmus\Annotation\Property\{ Field, Relation, OrderBy, Where, Join };
|
||||
use Ulmus\Annotation\Property\Field\{ Id, ForeignKey, CreatedAt, UpdatedAt, };
|
||||
|
||||
trait EntityTrait {
|
||||
use EventTrait;
|
||||
|
||||
/**
|
||||
* @Ignore
|
||||
*/
|
||||
protected bool $strictEntityFieldsDeclaration = false;
|
||||
protected bool $entityStrictFieldsDeclaration = false;
|
||||
|
||||
/**
|
||||
* @Ignore
|
||||
*/
|
||||
protected array $unmatchedEntityDatasetFields = [];
|
||||
protected array $entityDatasetUnmatchedFields = [];
|
||||
|
||||
/**
|
||||
* @Ignore
|
||||
*/
|
||||
public array $datasetSource = [];
|
||||
public array $entityLoadedDataset = [];
|
||||
|
||||
/**
|
||||
* @Ignore
|
||||
@@ -37,94 +38,144 @@ trait EntityTrait {
|
||||
|
||||
# Resolve relations here if one is called
|
||||
|
||||
# @TODO REFACTOR THIS CODE URGENTLY !
|
||||
if ( null !== ( $relation = $entityResolver->searchFieldAnnotation($name, new Relation() ) ) ) {
|
||||
$relationType = strtolower(str_replace(['-', '_'], '', $relation->type));
|
||||
|
||||
$order = $entityResolver->searchFieldAnnotationList($name, new OrderBy() );
|
||||
$where = $entityResolver->searchFieldAnnotationList($name, new Where() );
|
||||
# @TODO REFACTOR THIS CODE ASAP !
|
||||
if ( $this->isLoaded() ) {
|
||||
|
||||
if ( $relation->entity ?? false ) {
|
||||
$baseEntity = $relation->entity();
|
||||
|
||||
$repository = $baseEntity->repository();
|
||||
if ( null !== ( $join= $entityResolver->searchFieldAnnotation($name, new Join() ) ) ) {
|
||||
$vars = [];
|
||||
|
||||
foreach($where as $condition) {
|
||||
$repository->where($condition->field, $condition->value, $condition->operator);
|
||||
$entity = $join->entity ?? $entityResolver->properties[$name]['type'];
|
||||
|
||||
foreach($this->entityDatasetUnmatchedFields as $key => $value) {
|
||||
$len = strlen( $name ) + 1;
|
||||
|
||||
if ( substr($key, 0, $len ) === "{$name}$" ) {
|
||||
$vars[substr($key, $len)] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
foreach($order as $item) {
|
||||
$repository->orderBy($item->field, $item->order);
|
||||
}
|
||||
|
||||
$field = $relation->key;
|
||||
|
||||
if ( method_exists($this, $filterMethod = "filterRelation$name") ) {
|
||||
$this->$filterMethod($repository);
|
||||
if ( [] !== $data = (array_values(array_unique($vars)) !== [ null ] ? $vars : []) ) {
|
||||
return ( new $entity() )->fromArray($data);
|
||||
}
|
||||
}
|
||||
|
||||
switch( $relationType ) {
|
||||
case 'onetoone':
|
||||
$repository->where( $baseEntity->field($relation->foreignKey), $this->$field );
|
||||
$result = call_user_func([$repository, $relation->function]);
|
||||
|
||||
if ( count($result) === 0 ) {
|
||||
return $baseEntity;
|
||||
if ( null !== ( $relation = $entityResolver->searchFieldAnnotation($name, new Relation() ) ) ) {
|
||||
$relationType = strtolower(str_replace(['-', '_'], '', $relation->type));
|
||||
|
||||
$order = $entityResolver->searchFieldAnnotationList($name, new OrderBy() );
|
||||
$where = $entityResolver->searchFieldAnnotationList($name, new Where() );
|
||||
|
||||
if ( $relation->entity ?? false ) {
|
||||
$baseEntity = $relation->entity();
|
||||
|
||||
$repository = $baseEntity->repository();
|
||||
|
||||
foreach($where as $condition) {
|
||||
$repository->where($condition->field, $condition->value, $condition->operator);
|
||||
}
|
||||
|
||||
return $this->$name = $result[0];
|
||||
|
||||
case 'onetomany':
|
||||
$repository->where( $baseEntity->field($relation->foreignKey), $this->$field); # <<<<<<<<< CHANGE $THIS->ID WITH PROPER NOMENCLATURE
|
||||
|
||||
return $this->$name = call_user_func([$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.");
|
||||
|
||||
foreach($order as $item) {
|
||||
$repository->orderBy($item->field, $item->order);
|
||||
}
|
||||
|
||||
$bridgeEntity = Ulmus::resolveEntity($relation->bridge);
|
||||
$bridgeRelation = $bridgeEntity->searchFieldAnnotation($relation->field, new Relation() );
|
||||
$relationRelation = $bridgeEntity->searchFieldAnnotation($relation->foreignField, new Relation() );
|
||||
|
||||
$repository = $relationRelation->entity()->repository();
|
||||
|
||||
$bridgeAlias = uniqid("bridge_");
|
||||
$relationAlias = uniqid("relation_");
|
||||
$field = $relation->key;
|
||||
}
|
||||
|
||||
$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} );
|
||||
switch( $relationType ) {
|
||||
case 'onetoone':
|
||||
$repository->where( $baseEntity->field($relation->foreignKey), $this->$field );
|
||||
|
||||
$this->$name = call_user_func([ $repository, $relationRelation->function ]);
|
||||
|
||||
if ($relation->bridgeField ?? false) {
|
||||
$repository = $relationRelation->entity::repository();
|
||||
$this->eventExecute(Event\EntityRelationLoadInterface::class, $name, $repository);
|
||||
|
||||
$repository->select("$bridgeAlias.*")
|
||||
$result = call_user_func([$repository, $relation->function]);
|
||||
|
||||
if ( count($result) === 0 ) {
|
||||
return $baseEntity;
|
||||
}
|
||||
|
||||
return $this->$name = $result[0];
|
||||
|
||||
case 'onetomany':
|
||||
$repository->where( $baseEntity->field($relation->foreignKey), $this->$field);
|
||||
$this->eventExecute(Event\EntityRelationLoadInterface::class, $name, $repository);
|
||||
|
||||
return $this->$name = call_user_func([$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() );
|
||||
|
||||
$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} );
|
||||
|
||||
$bridgeName = $relation->bridgeField;
|
||||
foreach($where as $condition) {
|
||||
$repository->where($condition->field, $condition->value, $condition->operator);
|
||||
}
|
||||
|
||||
foreach($order as $item) {
|
||||
$repository->orderBy($item->field, $item->order);
|
||||
}
|
||||
|
||||
$this->eventExecute(Event\EntityRelationLoadInterface::class, $name, $repository);
|
||||
|
||||
$this->$bridgeName = $repository->collectionFromQuery($relation->bridge);
|
||||
}
|
||||
|
||||
return $this->$name;
|
||||
}
|
||||
$this->$name = call_user_func([ $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} );
|
||||
|
||||
foreach($where as $condition) {
|
||||
$repository->where($condition->field, $condition->value, $condition->operator);
|
||||
}
|
||||
|
||||
foreach($order as $item) {
|
||||
$repository->orderBy($item->field, $item->order);
|
||||
}
|
||||
|
||||
$bridgeName = $relation->bridgeField;
|
||||
|
||||
$this->$bridgeName = $repository->collectionFromQuery($relation->bridge);
|
||||
}
|
||||
|
||||
return $this->$name;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
throw new \Exception(sprintf("[%s] - Undefined variable: %s", static::class, $name));
|
||||
}
|
||||
|
||||
/**
|
||||
* @Ignore
|
||||
*/
|
||||
public function __isset(string $name) : bool
|
||||
{
|
||||
if ( $this->isLoaded() && static::resolveEntity()->searchFieldAnnotation($name, new Relation() ) ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return isset($this->$name);
|
||||
}
|
||||
|
||||
@@ -145,11 +196,11 @@ trait EntityTrait {
|
||||
}
|
||||
|
||||
if ( $field === null ) {
|
||||
if ($this->strictEntityFieldsDeclaration ) {
|
||||
if ($this->entityStrictFieldsDeclaration ) {
|
||||
throw new \Exception("Field `$key` can not be found within your entity ".static::class);
|
||||
}
|
||||
else {
|
||||
$this->unmatchedEntityDatasetFields[$key] = $value;
|
||||
$this->entityDatasetUnmatchedFields[$key] = $value;
|
||||
}
|
||||
}
|
||||
elseif ( is_null($value) ) {
|
||||
@@ -178,24 +229,30 @@ trait EntityTrait {
|
||||
if ( ! $loaded ) {
|
||||
#if ( $field !== null ) {
|
||||
# $annotation = $entityResolver->searchFieldAnnotation($field['name'], new Field() );
|
||||
# $this->datasetSource[$annotation ? $annotation->name : $field['name']] = $dataset; # <--------- THIS TO FIX !!!!!!
|
||||
# $this->entityLoadedDataset[$annotation ? $annotation->name : $field['name']] = $dataset; # <--------- THIS TO FIX !!!!!!
|
||||
#}
|
||||
$this->datasetSource = array_change_key_case($dataset, \CASE_LOWER);
|
||||
$this->entityLoadedDataset = array_change_key_case($dataset, \CASE_LOWER);
|
||||
}
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @Ignore
|
||||
*/
|
||||
public function fromArray(iterable $dataset) : self
|
||||
{
|
||||
return $this->entityFillFromDataset($dataset);
|
||||
}
|
||||
|
||||
public function entityGetDataset(bool $returnSource = false) : array
|
||||
{
|
||||
/**
|
||||
* @Ignore
|
||||
*/
|
||||
public function entityGetDataset(bool $includeRelations = false, bool $returnSource = false) : array
|
||||
{
|
||||
if ( $returnSource ) {
|
||||
return $this->datasetSource;
|
||||
return $this->entityLoadedDataset;
|
||||
}
|
||||
|
||||
$dataset = [];
|
||||
@@ -226,19 +283,52 @@ trait EntityTrait {
|
||||
}
|
||||
}
|
||||
|
||||
# @TODO Must fix recursive bug !
|
||||
if ($includeRelations) {
|
||||
foreach($entityResolver->properties as $name => $field){
|
||||
$relation = $entityResolver->searchFieldAnnotation($name, new Relation() );
|
||||
|
||||
if ( $relation && isset($this->$name) && ($relation->entity ?? $relation->bridge) !== static::class ) {
|
||||
if ( null !== $value = $this->$name ?? null ) {
|
||||
if ( is_iterable($value) ) {
|
||||
$list = [];
|
||||
|
||||
foreach($value as $entity) {
|
||||
$list[] = $entity->entityGetDataset(true);
|
||||
}
|
||||
|
||||
$dataset[$name] = $list;
|
||||
}
|
||||
elseif ( is_object($value) ) {
|
||||
$dataset[$name] = $value->entityGetDataset(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $dataset;
|
||||
}
|
||||
|
||||
public function toArray() : array
|
||||
/**
|
||||
* @Ignore
|
||||
*/
|
||||
public function toArray($includeRelations = false) : array
|
||||
{
|
||||
return $this->entityGetDataset();
|
||||
return $this->entityGetDataset($includeRelations);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Ignore
|
||||
*/
|
||||
public function toCollection() : array
|
||||
{
|
||||
return new EntityCollection($this->toArray());
|
||||
}
|
||||
|
||||
/**
|
||||
* @Ignore
|
||||
*/
|
||||
public function isLoaded() : bool
|
||||
{
|
||||
if ( null === $pkField = $this->resolveEntity()->getPrimaryKeyField($this) ) {
|
||||
@@ -250,12 +340,17 @@ trait EntityTrait {
|
||||
return isset($this->$key);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @Ignore
|
||||
*/
|
||||
public function __sleep()
|
||||
{
|
||||
return array_keys($this->resolveEntity()->fieldList());
|
||||
}
|
||||
|
||||
/**
|
||||
* @Ignore
|
||||
*/
|
||||
public function jsonSerialize()
|
||||
{
|
||||
return $this->entityGetDataset();
|
||||
@@ -264,7 +359,7 @@ trait EntityTrait {
|
||||
/**
|
||||
* @Ignore
|
||||
*/
|
||||
public function resolveEntity() : EntityResolver
|
||||
public static function resolveEntity() : EntityResolver
|
||||
{
|
||||
return Ulmus::resolveEntity(static::class);
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user