ulmus/src/EntityTrait.php

215 lines
6.3 KiB
PHP
Raw Normal View History

2019-08-21 20:13:00 +00:00
<?php
namespace Ulmus;
use Ulmus\Repository,
Ulmus\Common\EntityResolver,
Ulmus\Common\EntityField;
2020-02-05 21:19:57 +00:00
use Ulmus\Annotation\Classes\{ Method, Table, Collation, };
2019-08-21 20:13:00 +00:00
use Ulmus\Annotation\Property\{ Field, Relation, OrderBy, Where, };
use Ulmus\Annotation\Property\Field\{ Id, ForeignKey, CreatedAt, UpdatedAt, };
trait EntityTrait {
/**
* @Ignore
*/
protected bool $strictEntityFieldsDeclaration = true;
/**
* @Ignore
*/
protected array $unmatchedEntityDatasetFields = [];
/**
* @Ignore
*/
public function __get(string $name)
{
$entityResolver= $this->resolveEntity();
# Resolve relations here if one is called
if ( null !== ( $relation = $entityResolver->searchFieldAnnotation($name, new Relation() ) ) ) {
$order = $entityResolver->searchFieldAnnotationList($name, new OrderBy() );
$where = $entityResolver->searchFieldAnnotationList($name, new Where() );
$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($relation->type) {
case 'oneToMany':
2020-02-05 21:19:57 +00:00
$repository->where( $baseEntity->field($relation->foreignKey), $this->$field); # <<<<<<<<< CHANGE $THIS->ID WITH PROPER NOMENCLATURE
return $this->$name = $repository->loadAll();
case 'oneToOne':
$repository->where( $baseEntity->field($relation->foreignKey), $this->$field );
2019-08-21 20:13:00 +00:00
$result = $repository->loadAll();
if ( count($result) === 0 ) {
return $baseEntity;
}
return $this->$name = $result[0];
}
return;
}
2020-02-05 21:19:57 +00:00
throw new \Exception(sprintf("[%s] - Undefined variable: %s", static::class, $name));
}
/**
* @Ignore
*/
2020-02-05 21:19:57 +00:00
public function entityFillFromDataset(iterable $dataset) : self
2019-08-21 20:13:00 +00:00
{
$fields = $this->resolveEntity();
2019-08-21 20:13:00 +00:00
foreach($dataset as $key => $value) {
2020-02-05 21:19:57 +00:00
$field = $fields->field(strtolower($key), EntityResolver::KEY_COLUMN_NAME, false) ?? null;
if ( $field === null ) {
$field = $fields->field($key, EntityResolver::KEY_ENTITY_NAME, false);
}
2020-02-05 21:19:57 +00:00
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;
}
2019-08-21 20:13:00 +00:00
}
elseif ( is_null($value) ) {
2019-08-21 20:13:00 +00:00
$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 ]);
2019-08-21 20:13:00 +00:00
}
}
2019-08-21 20:13:00 +00:00
return $this;
}
2020-02-05 21:19:57 +00:00
public function fromArray(iterable $dataset) : self
{
return $this->entityFillFromDataset($dataset);
}
public function entityGetDataset() : array
{
$dataset = [];
$entityResolver = $this->resolveEntity();
foreach($entityResolver->fieldList() as $key => $field) {
$annotation = $entityResolver->searchFieldAnnotation($key, new Field() );
if ( isset($this->$key) ) {
$dataset[ $annotation->name ?? $key ] = $this->$key;
}
elseif ( $field['nullable'] ) {
$dataset[ $annotation->name ?? $key ] = null;
}
}
return $dataset;
}
2020-02-05 21:19:57 +00:00
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);
}
2019-08-21 20:13:00 +00:00
/**
* @Ignore
*/
public static function repository(string $alias = Repository::DEFAULT_ALIAS) : Repository
2019-08-21 20:13:00 +00:00
{
return Ulmus::repository(static::class, $alias, Ulmus::$defaultAdapter);
2019-08-21 20:13:00 +00:00
}
/**
* @Ignore
*/
public static function queryBuilder() : QueryBuilder
{
return Ulmus::queryBuilder(static::class);
}
/**
* @Ignore
*/
public static function field($name, ? string $alias = null) : EntityField
2019-08-21 20:13:00 +00:00
{
return new EntityField(static::class, $name, $alias ?: Repository::DEFAULT_ALIAS);
}
/**
* @Ignore
*/
public static function fields(...$fields) : string
2019-08-21 20:13:00 +00:00
{
return implode(', ', array_map(function($name) {
return static::field($name);
}, $fields));
}
}