diff --git a/src/Attribute/Property/ArrayOf.php b/src/Attribute/Property/ArrayOf.php index 3e4446f..56cf861 100644 --- a/src/Attribute/Property/ArrayOf.php +++ b/src/Attribute/Property/ArrayOf.php @@ -25,22 +25,26 @@ class ArrayOf implements \Ulmus\Entity\EntityValueModifier sprintf("Given item '%s' is not a valid enum for type %s ; try one of theses instead : %s", $item, $this->type, implode("', '", array_map(fn($e) => $e->value, $this->type::cases()))) ); } else { - $value = $this->type::from($item); + $obj = $this->type::from($item); } } elseif (class_exists($this->type)) { if (is_subclass_of($this->type, JsonUnserializable::class)) { - $value = (new \ReflectionClass($this->type))->newInstanceWithoutConstructor(); - $value->jsonUnserialize($item); + $obj = (new \ReflectionClass($this->type))->newInstanceWithoutConstructor(); + $obj->jsonUnserialize($item); } else { - $value = new $this->type($item); + $obj = new $this->type($item); } } + else { + throw new \InvalidArgumentException("Given type for ArrayOf is incompatible with it's use. An object should be provided"); + } - $return[$index] = $value; + $return[$index] = $obj; } } + if (! $property->type->builtIn) { $cls = $property->type->type; diff --git a/src/Entity/ArrayCollection.php b/src/Entity/ArrayCollection.php index b2ee592..c57e19b 100644 --- a/src/Entity/ArrayCollection.php +++ b/src/Entity/ArrayCollection.php @@ -6,7 +6,6 @@ use Ulmus\EntityCollection; class ArrayCollection extends EntityCollection implements JsonUnserializable { - public function jsonUnserialize(array $json): void { $this->fromArray($json); diff --git a/src/Entity/DatasetHandler.php b/src/Entity/DatasetHandler.php index 0faba5f..b7a5639 100644 --- a/src/Entity/DatasetHandler.php +++ b/src/Entity/DatasetHandler.php @@ -17,7 +17,7 @@ class DatasetHandler protected bool $entityStrictFieldsDeclaration = false, ) {} - public function pull(object $entity) : Generator + public function pull(object $entity, bool $nullable = true) : Generator { foreach($this->entityResolver->fieldList(EntityResolver::KEY_ENTITY_NAME, true) as $key => $field) { $attribute = $this->entityResolver->searchFieldAnnotation($key,[ Field::class ]); @@ -25,7 +25,7 @@ class DatasetHandler if ( $entity->__isset($key) ) { yield $attribute->name ?? $key => $entity->$key; } - elseif ( $field->allowsNull() ) { + elseif ( $nullable && $field->allowsNull() ) { yield $attribute->name ?? $key => null; } } diff --git a/src/Entity/EntityInterface.php b/src/Entity/EntityInterface.php index 3835a0e..9134a5b 100644 --- a/src/Entity/EntityInterface.php +++ b/src/Entity/EntityInterface.php @@ -18,7 +18,7 @@ interface EntityInterface extends SearchableInterface /* extends \JsonSerializab public function isLoaded() : bool; public function jsonSerialize() : mixed; public static function resolveEntity() : EntityResolver; - public static function repository(string $alias = Repository::DEFAULT_ALIAS, ConnectionAdapter $adapter = null) : Repository; + public static function repository(string $alias = Repository::DEFAULT_ALIAS, ?ConnectionAdapter $adapter = null) : Repository; public static function entityCollection(...$arguments) : EntityCollection; public static function queryBuilder() : QueryBuilderInterface; public static function field($name, null|string|false $alias = Repository::DEFAULT_ALIAS) : EntityField; diff --git a/src/Entity/Field/Datetime.php b/src/Entity/Field/Datetime.php index 3cf5662..37d31f4 100644 --- a/src/Entity/Field/Datetime.php +++ b/src/Entity/Field/Datetime.php @@ -28,7 +28,7 @@ class Datetime extends \DateTime implements EntityObjectInterface, \JsonSerializ return $obj; } - public function setTime($hour, $minute, $second = 0, $microsecond = 0) : \DateTimeInterface + public function setTime($hour, $minute, $second = 0, $microsecond = 0) : \DateTime { $fromParent = parent::setTime($hour, $minute, $second, $microsecond); @@ -45,14 +45,15 @@ class Datetime extends \DateTime implements EntityObjectInterface, \JsonSerializ return $this->format($this->format); } + #[\Deprecated] public function formatLocale(string $format) : string { return strftime($format, $this->getTimestamp()); } - public function formatLocaleIntl(int $dateFormatter = \IntlDateFormatter::LONG, int $timeFormatter = \IntlDateFormatter::NONE) : string + public function formatLocaleIntl(int $dateFormatter = \IntlDateFormatter::LONG, int $timeFormatter = \IntlDateFormatter::NONE, ? string $pattern = null) : string { - $formatter = new \IntlDateFormatter(\Locale::getDefault(), $dateFormatter, $timeFormatter, \Locale::getRegion("")); + $formatter = new \IntlDateFormatter(\Locale::getDefault(), $dateFormatter, $timeFormatter, \date_default_timezone_get(), \IntlDateFormatter::GREGORIAN, $pattern); return $formatter->format($this->getTimestamp()); } diff --git a/src/EntityTrait.php b/src/EntityTrait.php index 491c46e..bbd2c5b 100644 --- a/src/EntityTrait.php +++ b/src/EntityTrait.php @@ -4,20 +4,15 @@ namespace Ulmus; use Notes\Attribute\Ignore; -use Psr\Http\Message\ServerRequestInterface; - use Ulmus\{Attribute\Obj\JsonSerialize, - Attribute\Property\Join, - Attribute\Property\Relation, Attribute\Property\ResettablePropertyInterface, - Attribute\Property\Virtual, Common\EntityResolver, Common\EntityField, Entity\DatasetHandler, Entity\EntityInterface, QueryBuilder\QueryBuilderInterface}; -use Ulmus\{Attribute\RegisterEntityEventInterface, Entity\EntityValueModifier, SearchRequest, Event}; +use Ulmus\{Attribute\RegisterEntityEventInterface, Entity\EntityValueModifier, }; #[JsonSerialize(includeRelations: true)] trait EntityTrait { @@ -33,7 +28,7 @@ trait EntityTrait { protected array $entityDatasetUnmatchedFields = []; #[Ignore] - protected DatasetHandler $datasetHandler; + public DatasetHandler $datasetHandler; #[Ignore] public string $loadedFromAdapter; @@ -82,7 +77,16 @@ trait EntityTrait { foreach($generator as $field => $value) { foreach($properties[$field]->attributes as $tag) { if ( $tag->object instanceof EntityValueModifier ) { - $value = $tag->object->push($value, $properties[$field]); + try { + $value = $tag->object->push($value, $properties[$field]); + } + catch(\Throwable $ex) { + throw new \LogicException( + message: sprintf("An error occured trying to push an EntityValueModifier results : %s", $ex->getMessage()), + code: $ex->getCode(), + previous: $ex, + ); + } } } @@ -128,6 +132,18 @@ trait EntityTrait { } } + #[Ignore] + public function entityGetDiffDataset() : array + { + $return = []; + + foreach($this->datasetHandler->pull($this, false) as $field => $value) { + $return[$field] = static::repository()->adapter->adapter()->writableValue($value); + } + + return $return; + } + #[Ignore] public function resetVirtualProperties() : self { @@ -217,7 +233,12 @@ trait EntityTrait { return true; } - return isset($this->$name); + if (isset($this->$name)) { + return true; + } + + # Handling undefined 'nullable' + return new \ReflectionProperty($this, $name)->isInitialized($this); } #[Ignore] @@ -289,7 +310,7 @@ trait EntityTrait { } #[Ignore] - public static function repository(string $alias = Repository::DEFAULT_ALIAS, ConnectionAdapter $adapter = null) : Repository + public static function repository(string $alias = Repository::DEFAULT_ALIAS, ?ConnectionAdapter $adapter = null) : Repository { return Ulmus::repository(static::class, $alias, $adapter); } diff --git a/src/QueryBuilder/Sql/MysqlQueryBuilder.php b/src/QueryBuilder/Sql/MysqlQueryBuilder.php index 658a2d1..a1c1043 100644 --- a/src/QueryBuilder/Sql/MysqlQueryBuilder.php +++ b/src/QueryBuilder/Sql/MysqlQueryBuilder.php @@ -491,7 +491,7 @@ class MysqlQueryBuilder extends SqlQueryBuilder } } - public function getFragments(QueryFragmentInterface|array|\Stringable|string $fragment = null) : array + public function getFragments(QueryFragmentInterface|array|\Stringable|string|null $fragment = null) : array { return $fragment !== null ? array_filter($this->queryStack, fn($e) => is_a($e, $fragment, true) ) : $this->queryStack; } @@ -501,7 +501,7 @@ class MysqlQueryBuilder extends SqlQueryBuilder return $this->render(); } - public function addParameter(mixed $value, string $key = null) : string + public function addParameter(mixed $value, ?string $key = null) : string { if ( $this->parent ?? false ) { return $this->parent->addParameter($value, $key); @@ -540,4 +540,5 @@ class MysqlQueryBuilder extends SqlQueryBuilder return $next + 1; } + } diff --git a/src/Repository.php b/src/Repository.php index 420de9e..4d20fc7 100644 --- a/src/Repository.php +++ b/src/Repository.php @@ -337,7 +337,7 @@ class Repository implements RepositoryInterface public function generateDatasetDiff(object $entity, bool $oldValues = false) : array { - $array = array_change_key_case($entity->toArray()); + $array = array_change_key_case($entity->entityGetDiffDataset()); $dataset = array_change_key_case($entity->entityGetDataset(false, true)); diff --git a/src/Ulmus.php b/src/Ulmus.php index 675c101..09d8848 100644 --- a/src/Ulmus.php +++ b/src/Ulmus.php @@ -108,7 +108,7 @@ abstract class Ulmus return static::$resolved[$entityClass] ?? static::$resolved[$entityClass] = new Common\EntityResolver($entityClass, static::$cache); } - public static function repository(string $entityClass, string $alias = Repository::DEFAULT_ALIAS, ConnectionAdapter $adapter = null) : Repository + public static function repository(string $entityClass, string $alias = Repository::DEFAULT_ALIAS, ?ConnectionAdapter $adapter = null) : Repository { $adapter ??= $entityClass::resolveEntity()->sqlAdapter(); $cls = $adapter->adapter()->repositoryClass();