resolveEntity(); # 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() ); if ( $relation->entity ?? false ) { $baseEntity = $relation->entity(); $repository = $baseEntity->repository(); foreach($where as $condition) { $repository->where($condition->field, $condition->value, $condition->operator); } foreach($order as $item) { $repository->orderBy($item->field, $item->order); } $field = $relation->key; if ( method_exists($this, $filterMethod = "filterRelation$name") ) { $this->$filterMethod($repository); } } 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; } 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."); } $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_"); $repository->select("{$repository->alias}.*") ->join(Query\Join::TYPE_INNER, $bridgeEntity->tableName() . " $bridgeAlias", $relation->bridge::field($relationRelation->key, $bridgeAlias), $relationRelation->entity::field($relationRelation->foreignKey)) ->join(Query\Join::TYPE_INNER, $this->resolveEntity()->tableName() . " $relationAlias", $relation->bridge::field($bridgeRelation->key, $bridgeAlias), static::field($bridgeRelation->foreignKey, $relationAlias)) ->where( static::field($bridgeRelation->foreignKey, $relationAlias), $this->{$bridgeRelation->foreignKey} ); $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() . " $bridgeAlias", $relation->bridge::field($relationRelation->key, $bridgeAlias), $relationRelation->entity::field($relationRelation->foreignKey)) ->join(Query\Join::TYPE_INNER, $this->resolveEntity()->tableName() . " $relationAlias", $relation->bridge::field($bridgeRelation->key, $bridgeAlias), static::field($bridgeRelation->foreignKey, $relationAlias)) ->where( static::field($bridgeRelation->foreignKey, $relationAlias), $this->{$bridgeRelation->foreignKey} ); $bridgeName = $relation->bridgeField; $this->$bridgeName = $repository->collectionFromQuery($relation->bridge); } return $this->$name; } return; } throw new \Exception(sprintf("[%s] - Undefined variable: %s", static::class, $name)); } public function __isset(string $name) : bool { return isset($this->$name); } /** * @Ignore */ public function entityFillFromDataset(iterable $dataset) : self { $loaded = $this->isLoaded(); $entityResolver = $this->resolveEntity(); foreach($dataset as $key => $value) { $field = $entityResolver->field(strtolower($key), EntityResolver::KEY_COLUMN_NAME, false) ?? null; if ( $field === null ) { $field = $entityResolver->field($key, EntityResolver::KEY_ENTITY_NAME, false); } if ( $field === null ) { if ($this->strictEntityFieldsDeclaration ) { throw new \Exception("Field `$key` can not be found within your entity ".static::class); } else { $this->unmatchedEntityDatasetFields[$key] = $value; } } elseif ( is_null($value) ) { $this->{$field['name']} = null; } elseif ( $field['type'] === 'array' ) { $this->{$field['name']} = substr($value, 0, 1) === "a" ? unserialize($value) : json_decode($value, true); } elseif ( EntityField::isScalarType($field['type']) ) { $this->{$field['name']} = $value; } elseif ( ! $field['builtin'] ) { $this->{$field['name']} = Ulmus::instanciateObject($field['type'], [ $value ]); } # Keeping original data to diff on UPDATE query if ( ! $loaded ) { #if ( $field !== null ) { # $annotation = $entityResolver->searchFieldAnnotation($field['name'], new Field() ); # $this->datasetSource[$annotation ? $annotation->name : $field['name']] = $dataset; # <--------- THIS TO FIX !!!!!! #} $this->datasetSource = array_change_key_case($dataset, \CASE_LOWER); } } return $this; } public function fromArray(iterable $dataset) : self { return $this->entityFillFromDataset($dataset); } public function entityGetDataset(bool $returnSource = false) : array { if ( $returnSource ) { return $this->datasetSource; } $dataset = []; $entityResolver = $this->resolveEntity(); foreach($entityResolver->fieldList() as $key => $field) { $annotation = $entityResolver->searchFieldAnnotation($key, new Field() ); if ( isset($this->$key) ) { $realKey = $annotation->name ?? $key; switch (true) { case is_object($this->$key): $dataset[$realKey] = Ulmus::convertObject($this->$key); break; case is_array($this->$key): $dataset[$realKey] = Ulmus::encodeArray($this->$key); break; default: $dataset[$realKey] = $this->$key; } } elseif ( $field['nullable'] ) { $dataset[ $annotation->name ?? $key ] = null; } } return $dataset; } public function toArray() : array { return $this->entityGetDataset(); } public function toCollection() : array { return new EntityCollection($this->toArray()); } public function isLoaded() : bool { if ( null === $pkField = $this->resolveEntity()->getPrimaryKeyField($this) ) { throw new Exception\EntityPrimaryKeyUnknown("Entity has no field containing attributes 'primary_key'"); } $key = key($pkField); return isset($this->$key); } public function __sleep() { return array_keys($this->resolveEntity()->fieldList()); } public function jsonSerialize() { return $this->entityGetDataset(); } /** * @Ignore */ public function resolveEntity() : EntityResolver { return Ulmus::resolveEntity(static::class); } /** * @Ignore */ public static function repository(string $alias = Repository::DEFAULT_ALIAS) : Repository { return Ulmus::repository(static::class, $alias); } /** * @Ignore */ public static function queryBuilder() : QueryBuilder { return Ulmus::queryBuilder(static::class); } /** * @Ignore */ public static function field($name, ? string $alias = null) : EntityField { return new EntityField(static::class, $name, $alias ?: Repository::DEFAULT_ALIAS, Ulmus::resolveEntity(static::class)); } /** * @Ignore */ public static function fields(array $fields, ? string $alias = null) : string { return implode(', ', array_map(function($item) use ($alias){ return static::field($item, $alias); }, $fields)); } }