initializeEntity($dataset); } #[Ignore] public function initializeEntity(iterable|null $dataset = null) : void { $this->datasetHandler = new DatasetHandler(static::resolveEntity(), $this->entityStrictFieldsDeclaration); if ($dataset) { $this->fromArray($dataset); } $this->resetVirtualProperties(); } #[Ignore] public function entityFillFromDataset(iterable $dataset, bool $overwriteDataset = false) : self { $loaded = $this->isLoaded(); $handler = $this->datasetHandler->push($dataset); foreach($handler as $field => $value) { $this->$field = $value; } $this->entityDatasetUnmatchedFields = $handler->getReturn(); # Keeping original data to diff on UPDATE query if ( ! $loaded ) { $this->entityLoadedDataset = array_change_key_case(is_array($dataset) ? $dataset : iterator_to_array($dataset), \CASE_LOWER); } elseif ($overwriteDataset) { $this->entityLoadedDataset = array_change_key_case(is_array($dataset) ? $dataset : iterator_to_array($dataset), \CASE_LOWER) + $this->entityLoadedDataset; } return $this; } #[Ignore] public function entityGetDataset(bool $includeRelations = false, bool $returnSource = false, bool $rewriteValue = true) : array { if ( $returnSource ) { return $this->entityLoadedDataset; } $dataset = []; foreach($this->datasetHandler->pull($this) as $field => $value) { $dataset[$field] = $rewriteValue ? static::repository()->adapter->adapter()->writableValue($value) : $value; } if ($includeRelations) { foreach($this->datasetHandler->pullRelation($this) as $field => $object) { $dataset[$field] = $object; } } return $dataset; } #[Ignore] public function resetVirtualProperties() : self { foreach($this->resolveEntity()->reflectedClass->getProperties(true) as $field => $property) { foreach($property->attributes as $tag) { if ( $tag->object instanceof ResettablePropertyInterface ) { unset($this->$field); } } } return $this; } #[Ignore] public function fromArray(iterable|EntityInterface $dataset) : static { if ($dataset instanceof EntityInterface) { $dataset = $dataset->toArray(); } return $this->entityFillFromDataset($dataset); } #[Ignore] public function toArray($includeRelations = false, array $filterFields = null, bool $rewriteValue = true) : array { $dataset = $this->entityGetDataset($includeRelations, false, $rewriteValue); return $filterFields ? array_intersect_key($dataset, array_flip($filterFields)) : $dataset; } #[Ignore] public function toCollection() : EntityCollection { return static::entityCollection([ $this ]); } #[Ignore] public function isLoaded() : bool { if (empty($this->entityLoadedDataset)) { return false; } if ( null === $pkField = $this->resolveEntity()->getPrimaryKeyField() ) { if ( null !== $compoundKeyFields = $this->resolveEntity()->getCompoundKeyFields() ) { $loaded = false; foreach ($compoundKeyFields->column as $column) { $field = $this->resolveEntity()->field($column); if (! $field->allowsNull() ) { $loaded |= isset($this->{$field->name}); } } return $loaded; }; } else { $key = key($pkField); return isset($this->$key); } throw new Exception\EntityPrimaryKeyUnknown(sprintf("Entity %s has no field containing attributes 'primary_key'", static::class)); } #[Ignore] public function __get(string $name) { $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)); } #[Ignore] public function __isset(string $name) : bool { $rel = static::resolveEntity()->searchFieldAnnotation($name, [ Attribute\Property\Relation::class ]); if ( $this->isLoaded() && $rel ) { return true; } return isset($this->$name); } #[Ignore] public function __sleep() { return array_merge(array_keys($this->resolveEntity()->fieldList()), [ 'entityLoadedDataset' ] ); } #[Ignore] public function __wakeup() { $this->resetVirtualProperties(); } #[Ignore] public function __clone() { if ( null !== $pkField = $this->resolveEntity()->getPrimaryKeyField($this) ) { $key = key($pkField); unset($this->$key); } } #[Ignore] public function jsonSerialize() : mixed { return $this->entityGetDataset(true, false, false); } #[Ignore] public static function resolveEntity() : EntityResolver { return Ulmus::resolveEntity(static::class); } #[Ignore] public static function repository(string $alias = Repository::DEFAULT_ALIAS, ConnectionAdapter $adapter = null) : Repository { return Ulmus::repository(static::class, $alias, $adapter); } #[Ignore] public static function entityCollection(...$arguments) : EntityCollection { $collection = new EntityCollection(...$arguments); $collection->entityClass = static::class; return $collection; } #[Ignore] public static function queryBuilder() : QueryBuilderInterface { return Ulmus::queryBuilder(static::class); } #[Ignore] public static function field($name, null|string|false $alias = Repository::DEFAULT_ALIAS) : EntityField { $default = ( $alias === false ? '' : static::repository()::DEFAULT_ALIAS ); # bw compatibility, to be deprecated $alias = $alias ? Ulmus::repository(static::class)->adapter->adapter()->escapeIdentifier($alias, Adapter\AdapterInterface::IDENTIFIER_FIELD) : $default; return new EntityField(static::class, $name, $alias, Ulmus::resolveEntity(static::class)); } #[Ignore] public static function fields(array $fields, null|string|false $alias = Repository::DEFAULT_ALIAS, string $separator = ', ') : string { return implode($separator, array_map(function($item) use ($alias){ return static::field($item, $alias); }, $fields)); } #[Ignore] public static function searchRequest(...$arguments) : SearchRequest\SearchRequestInterface { return new /* #[SearchRequest\Attribute\SearchRequestParameter(YourEntityClass::class)] */ class(... $arguments) extends SearchRequest\SearchRequest { # Define searchable properties here, some ex: # #[SearchParameter(method: SearchMethodEnum::Where)] # public ? string $username = null; # #[SearchParameter(method: SearchMethodEnum::Where, toggle: true)] # public ? bool $hidden = null; # #[SearchParameter(method: SearchMethodEnum::Like)] # public ? string $word = null; }; } }