- 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:
Dave Mc Nicoll committed 2020-05-20 15:34:50 -04:00
1 parent 1839726dc0
commit 4d221859fc
15 files changed
+421 -99

No files matched your search

+172 -77
View File
@@ -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);
}