Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Changed converting enum from and to raw values + added support for Ba… #638

Merged
merged 6 commits into from
Feb 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions src/Entity/AbstractEntity.php
Original file line number Diff line number Diff line change
Expand Up @@ -490,6 +490,10 @@ protected function initProperty(PropertyMetadata $metadata, string $name, bool $
{
$this->validated[$name] = true;

if (!isset($this->data[$name]) && !array_key_exists($name, $this->data)) {
$this->data[$name] = $this->persistedId === null ? $metadata->defaultValue : null;
}

if ($metadata->wrapper !== null) {
$wrapper = $this->createPropertyWrapper($metadata);
if ($initValue || isset($this->data[$metadata->name])) {
Expand All @@ -499,9 +503,6 @@ protected function initProperty(PropertyMetadata $metadata, string $name, bool $
return;
}

if (!isset($this->data[$name]) && !array_key_exists($name, $this->data)) {
$this->data[$name] = $this->persistedId === null ? $metadata->defaultValue : null;
}

if ($this->data[$name] !== null) {
// data type coercion
Expand Down
23 changes: 18 additions & 5 deletions src/Entity/PropertyWrapper/BackedEnumWrapper.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

use BackedEnum;
use Nextras\Orm\Entity\ImmutableValuePropertyWrapper;
use Nextras\Orm\Exception\InvalidArgumentException;
use Nextras\Orm\Exception\NullValueException;
use function array_key_first;
use function assert;
Expand All @@ -29,8 +30,13 @@ public function convertToRawValue(mixed $value): mixed
{
if ($value === null) return null;
$type = array_key_first($this->propertyMetadata->types);
assert($value instanceof $type);
assert($value instanceof BackedEnum);
if ($value instanceof BackedEnum === false) {
throw new InvalidArgumentException('Value must be of type BackedEnum.');
}
if ($value instanceof $type === false) {
throw new InvalidArgumentException('Value must be of type ' . $type . '.');
}

return $value->value;
}

Expand All @@ -42,9 +48,16 @@ public function convertFromRawValue(mixed $value): ?BackedEnum
throw new NullValueException($this->propertyMetadata);
}

assert(is_int($value) || is_string($value));
$type = array_key_first($this->propertyMetadata->types);
assert(is_subclass_of($type, BackedEnum::class));
return $type::from($value);
if (is_int($value) || is_string($value)) {
if (is_subclass_of($type, BackedEnum::class)) {
return $type::from($value);
}
}
if ($value instanceof BackedEnum && $value instanceof $type) {
return $value;
}

throw new InvalidArgumentException('Invalid value for enum.');
}
}
5 changes: 5 additions & 0 deletions src/Entity/Reflection/ModifierParser.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,14 @@
namespace Nextras\Orm\Entity\Reflection;


use BackedEnum;
use Nette\Utils\Reflection;
use Nextras\Orm\Entity\Reflection\Parser\Token;
use Nextras\Orm\Entity\Reflection\Parser\TokenLexer;
use Nextras\Orm\Entity\Reflection\Parser\TokenStream;
use Nextras\Orm\Exception\InvalidStateException;
use ReflectionClass;
use ReflectionEnum;


class ModifierParser
Expand Down Expand Up @@ -189,6 +191,9 @@ private function processKeyword(string $value, ReflectionClass $reflectionClass)
$reflection = new ReflectionClass($className);
}

if ($reflection->isEnum() && is_subclass_of($className, BackedEnum::class)) {
return (new ReflectionEnum($className))->getCase($const)->getValue();
}
$enum = [];
$constants = $reflection->getConstants();
if (str_contains($const, '*')) {
Expand Down
43 changes: 43 additions & 0 deletions tests/cases/integration/Collection/collection.enumOnEntities.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
<?php declare(strict_types = 1);

/**
* @testCase
* @dataProvider ../../../databases.ini
*/

namespace NextrasTests\Orm\Integration\Collection;


use inc\model\book\GenreEnum;
use NextrasTests\Orm\DataTestCase;
use Tester\Assert;


require_once __DIR__ . '/../../../bootstrap.php';


class CollectionEnumOnEntitiesTest extends DataTestCase
{
public function testEntityEnumType(): void
{
$collection = $this->orm->books->findBy([
'genre' => [
GenreEnum::HORROR,
GenreEnum::THRILLER,
GenreEnum::SCIFI,
GenreEnum::FANTASY,
],
]);
$collection = $collection->orderBy('id');
Assert::same(3, $collection->countStored());

foreach ($collection as $book) {
Assert::type(GenreEnum::class, $book->genre);
}
}

}


$test = new CollectionEnumOnEntitiesTest();
$test->run();
130 changes: 130 additions & 0 deletions tests/cases/integration/Entity/entity.enumProps.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
<?php declare(strict_types = 1);

/**
* @testCase
* @dataProvider ../../../databases.ini
*/

namespace NextrasTests\Orm\Integration\Entity;


use DateTimeImmutable;
use inc\model\book\GenreEnum;
use Nextras\Orm\Exception\InvalidArgumentException;
use NextrasTests\Orm\Author;
use NextrasTests\Orm\Book;
use NextrasTests\Orm\Currency;
use NextrasTests\Orm\DataTestCase;
use NextrasTests\Orm\Money;
use NextrasTests\Orm\Publisher;
use Tester\Assert;


require_once __DIR__ . '/../../../bootstrap.php';


class EntityEnumPropTest extends DataTestCase
{

public function testEnumOnEntity(): void
{
/** @var Book $book */
$book = $this->orm->books->findAll()->fetch();

Assert::notNull($book);

Assert::same(GenreEnum::SCIFI, $book->genre);
}


public function testAddEntityWithEnum(): void
{
$bookName = 'Book 5';

$book = $this->createBookEntity($bookName);
$book->genre = GenreEnum::ROMANCE;
$this->orm->books->persistAndFlush($book);

Assert::same(GenreEnum::ROMANCE, $book->genre);

$entity = $this->orm->books->getBy(['title' => $bookName]);
Assert::notNull($entity);

Assert::type(GenreEnum::class, $entity->genre);

Assert::same(GenreEnum::ROMANCE, $entity->genre);
}


private function createBookEntity(string $title): Book
{
$book = new Book();
$book->title = $title;
$book->publishedAt = new DateTimeImmutable('2021-12-14 21:10:02');
$book->price = new Money(150, Currency::CZK);
$this->createAuthorToBook($book);
$this->createPublisherToBook($book);
$this->orm->books->persist($book);

return $book;
}


private function createAuthorToBook(Book $book): void
{
$author1 = new Author();
$author1->name = 'Writer 1';
$author1->web = 'http://example.com/1';
$this->orm->authors->persist($author1);

$book->author = $author1;
}


private function createPublisherToBook(Book $book): void
{
$publisher1 = new Publisher();
$publisher1->name = 'Nextras publisher A';
$this->orm->publishers->persist($publisher1);

$book->publisher = $publisher1;
}


public function testAddEntityWithDefaultEnum(): void
{
$bookName = 'Book 6';

$book = $this->createBookEntity($bookName);
$this->orm->books->persistAndFlush($book);

Assert::same(GenreEnum::FANTASY, $book->genre);

$entity = $this->orm->books->getBy(['title' => $bookName]);
Assert::notNull($entity);

Assert::type(GenreEnum::class, $entity->genre);

Assert::same(GenreEnum::FANTASY, $entity->genre);
}


public function testAddEntityWithUnknownEnum(): void
{
$bookName = 'Book 7';

$book = $this->createBookEntity($bookName);
// @phpstan-ignore-next-line
$book->genre = 'documentary';

Assert::exception(function () use ($book) {
$this->orm->books->persistAndFlush($book);
}, InvalidArgumentException::class);

}

}


$test = new EntityEnumPropTest();
$test->run();
5 changes: 5 additions & 0 deletions tests/db/array-data.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
namespace NextrasTests\Orm;


use inc\model\book\GenreEnum;
use Nextras\Dbal\Utils\DateTimeImmutable;


Expand Down Expand Up @@ -43,6 +44,7 @@
$book1->author = $author1;
$book1->translator = $author1;
$book1->publisher = $publisher1;
$book1->genre = GenreEnum::SCIFI;
$book1->publishedAt = new \DateTimeImmutable('2021-12-14 21:10:04');
$book1->price = new Money(50, Currency::CZK);
$book1->tags->set([$tag1, $tag2]);
Expand All @@ -52,6 +54,7 @@
$book2->title = 'Book 2';
$book2->author = $author1;
$book2->publisher = $publisher2;
$book2->genre = GenreEnum::HORROR;
$book2->publishedAt = new \DateTimeImmutable('2021-12-14 21:10:02');
$book2->price = new Money(150, Currency::CZK);
$book2->tags->set([$tag2, $tag3]);
Expand All @@ -62,6 +65,7 @@
$book3->author = $author2;
$book3->translator = $author2;
$book3->publisher = $publisher3;
$book3->genre = GenreEnum::THRILLER;
$book3->publishedAt = new \DateTimeImmutable('2021-12-14 21:10:03');
$book3->price = new Money(20, Currency::CZK);
$book3->tags->set([$tag3]);
Expand All @@ -72,6 +76,7 @@
$book4->author = $author2;
$book4->translator = $author2;
$book4->publisher = $publisher1;
$book4->genre = GenreEnum::ROMANCE;
$book4->nextPart = $book3;
$book4->publishedAt = new \DateTimeImmutable('2021-12-14 21:10:01');
$book4->price = new Money(220, Currency::CZK);
Expand Down
8 changes: 4 additions & 4 deletions tests/db/mssql-data.sql
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,10 @@ SET IDENTITY_INSERT tags OFF;
DBCC checkident ('tags', reseed, 3) WITH NO_INFOMSGS;

SET IDENTITY_INSERT books ON;
INSERT INTO books (id, author_id, translator_id, title, next_part, publisher_id, published_at, price, price_currency) VALUES (1, 1, 1, 'Book 1', NULL, 1, '2021-12-14 21:10:04', 50, 'CZK');
INSERT INTO books (id, author_id, translator_id, title, next_part, publisher_id, published_at, price, price_currency) VALUES (2, 1, NULL, 'Book 2', NULL, 2, '2021-12-14 21:10:02', 150, 'CZK');
INSERT INTO books (id, author_id, translator_id, title, next_part, publisher_id, published_at, price, price_currency) VALUES (3, 2, 2, 'Book 3', NULL, 3, '2021-12-14 21:10:03', 20, 'CZK');
INSERT INTO books (id, author_id, translator_id, title, next_part, publisher_id, published_at, price, price_currency) VALUES (4, 2, 2, 'Book 4', 3, 1, '2021-12-14 21:10:01', 220, 'CZK');
INSERT INTO books (id, author_id, translator_id, title, next_part, publisher_id, published_at, genre, price, price_currency) VALUES (1, 1, 1, 'Book 1', NULL, 1, '2021-12-14 21:10:04', 'sciFi', 50, 'CZK');
INSERT INTO books (id, author_id, translator_id, title, next_part, publisher_id, published_at, genre, price, price_currency) VALUES (2, 1, NULL, 'Book 2', NULL, 2, '2021-12-14 21:10:02', 'horror', 150, 'CZK');
INSERT INTO books (id, author_id, translator_id, title, next_part, publisher_id, published_at, genre, price, price_currency) VALUES (3, 2, 2, 'Book 3', NULL, 3, '2021-12-14 21:10:03', 'thriller', 20, 'CZK');
INSERT INTO books (id, author_id, translator_id, title, next_part, publisher_id, published_at, genre, price, price_currency) VALUES (4, 2, 2, 'Book 4', 3, 1, '2021-12-14 21:10:01', 'romance', 220, 'CZK');
SET IDENTITY_INSERT books OFF;

DBCC checkident ('books', reseed, 4) WITH NO_INFOMSGS;
Expand Down
1 change: 1 addition & 0 deletions tests/db/mssql-init.sql
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ CREATE TABLE books
next_part int,
publisher_id int NOT NULL,
published_at datetimeoffset NOT NULL,
genre varchar(20) NOT NULL,
printed_at datetimeoffset,
ean_id int,
price int,
Expand Down
8 changes: 4 additions & 4 deletions tests/db/mysql-data.sql
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,10 @@ INSERT INTO tags (id, name, is_global) VALUES (1, 'Tag 1', 'y');
INSERT INTO tags (id, name, is_global) VALUES (2, 'Tag 2', 'y');
INSERT INTO tags (id, name, is_global) VALUES (3, 'Tag 3', 'n');

INSERT INTO books (id, author_id, translator_id, title, next_part, publisher_id, published_at, price, price_currency) VALUES (1, 1, 1, 'Book 1', NULL, 1, '2021-12-14 21:10:04', 50, 'CZK');
INSERT INTO books (id, author_id, translator_id, title, next_part, publisher_id, published_at, price, price_currency) VALUES (2, 1, NULL, 'Book 2', NULL, 2, '2021-12-14 21:10:02', 150, 'CZK');
INSERT INTO books (id, author_id, translator_id, title, next_part, publisher_id, published_at, price, price_currency) VALUES (3, 2, 2, 'Book 3', NULL, 3, '2021-12-14 21:10:03', 20, 'CZK');
INSERT INTO books (id, author_id, translator_id, title, next_part, publisher_id, published_at, price, price_currency) VALUES (4, 2, 2, 'Book 4', 3, 1, '2021-12-14 21:10:01', 220, 'CZK');
INSERT INTO books (id, author_id, translator_id, title, next_part, publisher_id, genre, published_at, price, price_currency) VALUES (1, 1, 1, 'Book 1', NULL, 1, 'sciFi', '2021-12-14 21:10:04', 50, 'CZK');
INSERT INTO books (id, author_id, translator_id, title, next_part, publisher_id, genre, published_at, price, price_currency) VALUES (2, 1, NULL, 'Book 2', NULL, 2, 'horror', '2021-12-14 21:10:02', 150, 'CZK');
INSERT INTO books (id, author_id, translator_id, title, next_part, publisher_id, genre, published_at, price, price_currency) VALUES (3, 2, 2, 'Book 3', NULL, 3, 'thriller', '2021-12-14 21:10:03', 20, 'CZK');
INSERT INTO books (id, author_id, translator_id, title, next_part, publisher_id, genre, published_at, price, price_currency) VALUES (4, 2, 2, 'Book 4', 3, 1, 'romance', '2021-12-14 21:10:01', 220, 'CZK');

INSERT INTO books_x_tags (book_id, tag_id) VALUES (1, 1);
INSERT INTO books_x_tags (book_id, tag_id) VALUES (1, 2);
Expand Down
1 change: 1 addition & 0 deletions tests/db/mysql-init.sql
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ CREATE TABLE books
title varchar(50) NOT NULL,
next_part int,
publisher_id int NOT NULL,
genre varchar(20) NOT NULL,
published_at DATETIME NOT NULL,
printed_at DATETIME,
ean_id int,
Expand Down
8 changes: 4 additions & 4 deletions tests/db/pgsql-data.sql
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,10 @@ INSERT INTO "tags" ("id", "name", "is_global") VALUES (3, 'Tag 3', 'n');
SELECT setval('tags_id_seq', 3, true);


INSERT INTO "books" ("id", "author_id", "translator_id", "title", "next_part", "publisher_id", "published_at", "price", "price_currency") VALUES (1, 1, 1, 'Book 1', NULL, 1, '2021-12-14 21:10:04', 50, 'CZK');
INSERT INTO "books" ("id", "author_id", "translator_id", "title", "next_part", "publisher_id", "published_at", "price", "price_currency") VALUES (2, 1, NULL, 'Book 2', NULL, 2, '2021-12-14 21:10:02', 150, 'CZK');
INSERT INTO "books" ("id", "author_id", "translator_id", "title", "next_part", "publisher_id", "published_at", "price", "price_currency") VALUES (3, 2, 2, 'Book 3', NULL, 3, '2021-12-14 21:10:03', 20, 'CZK');
INSERT INTO "books" ("id", "author_id", "translator_id", "title", "next_part", "publisher_id", "published_at", "price", "price_currency") VALUES (4, 2, 2, 'Book 4', 3, 1, '2021-12-14 21:10:01', 220, 'CZK');
INSERT INTO "books" ("id", "author_id", "translator_id", "title", "next_part", "publisher_id", "published_at", "genre", "price", "price_currency") VALUES (1, 1, 1, 'Book 1', NULL, 1, '2021-12-14 21:10:04', 'sciFi', 50, 'CZK');
INSERT INTO "books" ("id", "author_id", "translator_id", "title", "next_part", "publisher_id", "published_at", "genre", "price", "price_currency") VALUES (2, 1, NULL, 'Book 2', NULL, 2, '2021-12-14 21:10:02', 'horror', 150, 'CZK');
INSERT INTO "books" ("id", "author_id", "translator_id", "title", "next_part", "publisher_id", "published_at", "genre", "price", "price_currency") VALUES (3, 2, 2, 'Book 3', NULL, 3, '2021-12-14 21:10:03', 'thriller', 20, 'CZK');
INSERT INTO "books" ("id", "author_id", "translator_id", "title", "next_part", "publisher_id", "published_at", "genre", "price", "price_currency") VALUES (4, 2, 2, 'Book 4', 3, 1, '2021-12-14 21:10:01', 'romance', 220, 'CZK');

SELECT setval('books_id_seq', 4, true);

Expand Down
1 change: 1 addition & 0 deletions tests/db/pgsql-init.sql
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ CREATE TABLE "books"
"next_part" int,
"publisher_id" int NOT NULL,
"published_at" TIMESTAMP NOT NULL,
"genre" varchar(20) NOT NULL,
"printed_at" TIMESTAMP,
"ean_id" int,
"price" int,
Expand Down
2 changes: 2 additions & 0 deletions tests/inc/model/book/Book.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@


use DateTimeImmutable;
use inc\model\book\GenreEnum;
use Nextras\Orm\Entity\Entity;
use Nextras\Orm\Relationships\ManyHasMany;

Expand All @@ -18,6 +19,7 @@
* @property Book|null $previousPart {1:1 Book::$nextPart}
* @property Ean|null $ean {1:1 Ean::$book, isMain=true, cascade=[persist, remove]}
* @property Publisher $publisher {m:1 Publisher::$books}
* @property GenreEnum $genre {default GenreEnum::FANTASY}
* @property DateTimeImmutable $publishedAt {default "2021-12-31 23:59:59"}
* @property DateTimeImmutable|null $printedAt
* @property Money|null $price {embeddable}
Expand Down
Loading
Loading