diff --git a/composer.json b/composer.json index ad91758..8620c9d 100644 --- a/composer.json +++ b/composer.json @@ -37,7 +37,8 @@ }, "autoload-dev": { "psr-4": { - "Respect\\Relational\\": "tests/" + "Respect\\Relational\\": ["tests/", "tests/Stubs/"], + "Respect\\Relational\\OtherEntity\\": "tests/Stubs/OtherEntity/" } }, "scripts": { diff --git a/phpcs.xml.dist b/phpcs.xml.dist index aecc899..d0a519e 100644 --- a/phpcs.xml.dist +++ b/phpcs.xml.dist @@ -14,14 +14,9 @@ src/ tests/ - - - - - - + - + tests/ diff --git a/phpstan.neon.dist b/phpstan.neon.dist index a79c04a..334cef8 100644 --- a/phpstan.neon.dist +++ b/phpstan.neon.dist @@ -9,7 +9,6 @@ parameters: - message: '/Access to an undefined property Respect\\Relational\\Mapper::\$\w+\./' - message: '/Unsafe usage of new static\(\)\./' - message: '/Cannot unset property .+ because it might have hooks in a subclass\./' - - message: '/Array has \d+ duplicate keys/' - message: '/Parameter #1 .+ of class Respect\\Relational\\Mapper constructor expects .+, string given\./' path: tests/MapperTest.php diff --git a/src/Mapper.php b/src/Mapper.php index 62e611d..e64cb05 100644 --- a/src/Mapper.php +++ b/src/Mapper.php @@ -61,6 +61,30 @@ public function getDb(): Db return $this->db; } + public function fetch(Collection $collection, mixed $extra = null): mixed + { + $statement = $this->createStatement($collection, $extra); + $hydrated = $this->fetchHydrated($collection, $statement); + if (!$hydrated) { + return false; + } + + return $this->parseHydrated($hydrated); + } + + /** @return array */ + public function fetchAll(Collection $collection, mixed $extra = null): array + { + $statement = $this->createStatement($collection, $extra); + $entities = []; + + while ($hydrated = $this->fetchHydrated($collection, $statement)) { + $entities[] = $this->parseHydrated($hydrated); + } + + return $entities; + } + public function persist(object $object, Collection $onCollection): bool { $next = $onCollection->getNext(); @@ -268,22 +292,6 @@ protected function checkNewIdentity(object $entity, Collection $collection): boo return true; } - protected function createStatement( - Collection $collection, - mixed $withExtra = null, - ): PDOStatement { - $query = $this->generateQuery($collection); - - if ($withExtra instanceof Sql) { - $query->appendQuery($withExtra); - } - - $statement = $this->db->prepare((string) $query, PDO::FETCH_NUM); - $statement->execute($query->getParams()); - - return $statement; - } - protected function generateQuery(Collection $collection): Sql { $collections = iterator_to_array( @@ -499,28 +507,6 @@ protected function hasComposition(string $entity, string|null $next, string|null || $entity === $s->composed($next, $parent); } - protected function fetchSingle( - Collection $collection, - PDOStatement $statement, - ): SplObjectStorage|false { - $name = $collection->getName(); - $entityName = $name; - $row = $statement->fetch(PDO::FETCH_OBJ); - - if (!$row) { - return false; - } - - if ($this->typable($collection)) { - $entityName = $this->inferGet($row, $this->getType($collection)); - } - - $entities = new SplObjectStorage(); - $entities[$this->transformSingleRow($row, $entityName)] = $collection; - - return $entities; - } - protected function getNewEntityByName(string $entityName): object { $entityName = $this->getStyle()->styledName($entityName); @@ -571,24 +557,6 @@ protected function inferGet(object &$object, string $prop): mixed } } - protected function fetchMulti( - Collection $collection, - PDOStatement $statement, - ): SplObjectStorage|false { - $entities = []; - $row = $statement->fetch(PDO::FETCH_NUM); - - if (!$row) { - return false; - } - - $this->postHydrate( - $entities = $this->createEntities($row, $statement, $collection), - ); - - return $entities; - } - /** @param array $row */ protected function createEntities( array $row, @@ -709,4 +677,77 @@ protected function getAllProperties(object $object): array return $cols; } + + private function parseHydrated(SplObjectStorage $hydrated): mixed + { + $this->tracked->addAll($hydrated); + $hydrated->rewind(); + + return $hydrated->current(); + } + + private function fetchHydrated(Collection $collection, PDOStatement $statement): SplObjectStorage|false + { + if (!$collection->hasMore()) { + return $this->fetchSingle($collection, $statement); + } + + return $this->fetchMulti($collection, $statement); + } + + private function createStatement( + Collection $collection, + mixed $withExtra = null, + ): PDOStatement { + $query = $this->generateQuery($collection); + + if ($withExtra instanceof Sql) { + $query->appendQuery($withExtra); + } + + $statement = $this->db->prepare((string) $query, PDO::FETCH_NUM); + $statement->execute($query->getParams()); + + return $statement; + } + + private function fetchSingle( + Collection $collection, + PDOStatement $statement, + ): SplObjectStorage|false { + $name = $collection->getName(); + $entityName = $name; + $row = $statement->fetch(PDO::FETCH_OBJ); + + if (!$row) { + return false; + } + + if ($this->typable($collection)) { + $entityName = $this->inferGet($row, $this->getType($collection)); + } + + $entities = new SplObjectStorage(); + $entities[$this->transformSingleRow($row, $entityName)] = $collection; + + return $entities; + } + + private function fetchMulti( + Collection $collection, + PDOStatement $statement, + ): SplObjectStorage|false { + $entities = []; + $row = $statement->fetch(PDO::FETCH_NUM); + + if (!$row) { + return false; + } + + $this->postHydrate( + $entities = $this->createEntities($row, $statement, $collection), + ); + + return $entities; + } } diff --git a/tests/DbTest.php b/tests/DbTest.php index 53c0581..4e3133f 100644 --- a/tests/DbTest.php +++ b/tests/DbTest.php @@ -123,28 +123,3 @@ protected function tearDown(): void unset($this->object); } } - -class TestFetchingClass -{ - public int|null $testa = null; - - public string|null $testb = null; - - public int|null $testez = null; -} - -class TestFetchingInto -{ - public int|null $testa = null; - - public string|null $testb = null; - - public int|null $testez = null; -} - -class TestFetchingClassArgs -{ - public function __construct(public string|null $testd = null) - { - } -} diff --git a/tests/MapperTest.php b/tests/MapperTest.php index 5512b15..d0f29f0 100644 --- a/tests/MapperTest.php +++ b/tests/MapperTest.php @@ -1145,170 +1145,3 @@ public function testShouldNotExecuteEntityConstructorWhenDisabled(): void ); } } - -class Postcomment -{ - public int|null $id = null; -} - -class Bug -{ - public int|null $id = null; - - public string|null $title = null; - - public string|null $type = null; -} - -class Improvement -{ - public int|null $id = null; - - public string|null $title = null; - - public string|null $type = null; -} - -class Comment -{ - public mixed $id = null; - - public mixed $post_id = null; - - public string|null $text = null; - - private string|null $datetime = null; - - public function setDatetime(Datetime $datetime): void - { - $this->datetime = $datetime->format('Y-m-d H:i:s'); - } - - public function getDatetime(): Datetime - { - return new Datetime($this->datetime); - } -} - -class Post -{ - public mixed $id = null; - - public mixed $author_id = null; - - public string|null $text = null; - - public string|null $title = null; - - /** @Relational\isNotColumn -> annotation because generate a sql error case column not exists in db. */ - private string $datetime = ''; - - public function setDatetime(Datetime $datetime): void - { - $this->datetime = $datetime->format('Y-m-d H:i:s'); - } - - public function getDatetime(): Datetime - { - return new Datetime($this->datetime); - } -} - -namespace Respect\Relational\OtherEntity; - -use DomainException; - -class Post -{ - private mixed $id = null; - - private mixed $author_id = null; - - private mixed $title = null; - - private mixed $text = null; - - public function getTitle(): mixed - { - return $this->title; - } - - public function setTitle(mixed $title): void - { - $this->title = $title; - } - - public function getId(): mixed - { - return $this->id; - } - - public function getAuthor(): mixed - { - return $this->author_id; - } - - public function getText(): mixed - { - return $this->text; - } - - public function setId(mixed $id): void - { - $this->id = $id; - } - - public function setAuthor(Author $author): void - { - $this->author_id = $author; - } - - public function setText(mixed $text): void - { - $this->text = $text; - } -} - -class Author -{ - private mixed $id = null; - - private mixed $name = null; - - public function getId(): mixed - { - return $this->id; - } - - public function getName(): mixed - { - return $this->name; - } - - public function setId(mixed $id): void - { - $this->id = $id; - } - - public function setName(mixed $name): void - { - $this->name = $name; - } -} - - -class Comment -{ - public int|null $id = null; - - public int|null $post_id = null; - - public string|null $text = null; - - public string|null $datetime = null; - - public function __construct() - { - throw new DomainException('Exception from __construct'); - } -} diff --git a/tests/Stubs/Bug.php b/tests/Stubs/Bug.php new file mode 100644 index 0000000..a9d6f3c --- /dev/null +++ b/tests/Stubs/Bug.php @@ -0,0 +1,14 @@ +datetime = $datetime->format('Y-m-d H:i:s'); + } + + public function getDatetime(): Datetime + { + return new Datetime($this->datetime); + } +} diff --git a/tests/Stubs/Improvement.php b/tests/Stubs/Improvement.php new file mode 100644 index 0000000..10f5978 --- /dev/null +++ b/tests/Stubs/Improvement.php @@ -0,0 +1,14 @@ +id; + } + + public function getName(): mixed + { + return $this->name; + } + + public function setId(mixed $id): void + { + $this->id = $id; + } + + public function setName(mixed $name): void + { + $this->name = $name; + } +} diff --git a/tests/Stubs/OtherEntity/Comment.php b/tests/Stubs/OtherEntity/Comment.php new file mode 100644 index 0000000..5d96334 --- /dev/null +++ b/tests/Stubs/OtherEntity/Comment.php @@ -0,0 +1,23 @@ +title; + } + + public function setTitle(mixed $title): void + { + $this->title = $title; + } + + public function getId(): mixed + { + return $this->id; + } + + public function getAuthor(): mixed + { + return $this->author_id; + } + + public function getText(): mixed + { + return $this->text; + } + + public function setId(mixed $id): void + { + $this->id = $id; + } + + public function setAuthor(Author $author): void + { + $this->author_id = $author; + } + + public function setText(mixed $text): void + { + $this->text = $text; + } +} diff --git a/tests/Stubs/Post.php b/tests/Stubs/Post.php new file mode 100644 index 0000000..9039092 --- /dev/null +++ b/tests/Stubs/Post.php @@ -0,0 +1,31 @@ + annotation because generate a sql error case column not exists in db. */ + private string $datetime = ''; + + public function setDatetime(Datetime $datetime): void + { + $this->datetime = $datetime->format('Y-m-d H:i:s'); + } + + public function getDatetime(): Datetime + { + return new Datetime($this->datetime); + } +} diff --git a/tests/Stubs/Postcomment.php b/tests/Stubs/Postcomment.php new file mode 100644 index 0000000..812825f --- /dev/null +++ b/tests/Stubs/Postcomment.php @@ -0,0 +1,10 @@ +style = new class extends AbstractStyle { - public function styledProperty(string $name): string - { - return $name; - } - - public function realName(string $name): string - { - return $name; - } - - public function realProperty(string $name): string - { - return $name; - } - - public function styledName(string $name): string - { - return $name; - } - - public function identifier(string $name): string - { - return 'id'; - } - - public function remoteIdentifier(string $name): string - { - return $name . '_id'; - } - - public function composed(string $left, string $right): string - { - return $left . '_' . $right; - } - - public function isRemoteIdentifier(string $name): bool - { - return false; - } - - public function remoteFromIdentifier(string $name): string|null - { - return null; - } - }; - } - - /** @return array */ - public static function singularPluralProvider(): array - { - return [ - ['post', 'posts'], - ['comment', 'comments'], - ['category', 'categories'], - ['tag', 'tags'], - ['entity', 'entities'], - ]; - } - - /** @return array */ - public static function camelCaseToSeparatorProvider(): array - { - return [ - ['-', 'HenriqueMoody', 'Henrique-Moody'], - [' ', 'AlexandreGaigalas', 'Alexandre Gaigalas'], - ['_', 'AugustoPascutti', 'Augusto_Pascutti'], - ]; - } - - #[DataProvider('singularPluralProvider')] - public function testPluralToSingularAndViceVersa(string $singular, string $plural): void - { - $pluralToSingular = new ReflectionMethod($this->style, 'pluralToSingular'); - $this->assertEquals($singular, $pluralToSingular->invoke($this->style, $plural)); - - $singularToPlural = new ReflectionMethod($this->style, 'singularToPlural'); - $this->assertEquals($plural, $singularToPlural->invoke($this->style, $singular)); - } - - #[DataProvider('camelCaseToSeparatorProvider')] - public function testCamelCaseToSeparatorAndViceVersa( - string $separator, - string $camelCase, - string $separated, - ): void { - $camelCaseToSeparatorMethod = new ReflectionMethod($this->style, 'camelCaseToSeparator'); - $this->assertEquals( - $separated, - $camelCaseToSeparatorMethod->invoke($this->style, $camelCase, $separator), - ); - - $separatorToCamelCaseMethod = new ReflectionMethod($this->style, 'separatorToCamelCase'); - $this->assertEquals( - $camelCase, - $separatorToCamelCaseMethod->invoke($this->style, $separated, $separator), - ); - } -} diff --git a/tests/Styles/CakePHPTest.php b/tests/Styles/CakePHPTest.php deleted file mode 100644 index 4b20acf..0000000 --- a/tests/Styles/CakePHPTest.php +++ /dev/null @@ -1,346 +0,0 @@ - */ - private array $posts; - - /** @var list */ - private array $authors; - - /** @var list */ - private array $comments; - - /** @var list */ - private array $categories; - - /** @var list */ - private array $postsCategories; - - protected function setUp(): void - { - $conn = new PDO('sqlite::memory:'); - $db = new Db($conn); - $conn->exec( - (string) Sql::createTable( - 'posts', - [ - 'id INTEGER PRIMARY KEY', - 'title VARCHAR(255)', - 'text TEXT', - 'author_id INTEGER', - ], - ), - ); - $conn->exec( - (string) Sql::createTable( - 'authors', - [ - 'id INTEGER PRIMARY KEY', - 'name VARCHAR(255)', - ], - ), - ); - $conn->exec( - (string) Sql::createTable( - 'comments', - [ - 'id INTEGER PRIMARY KEY', - 'post_id INTEGER', - 'text TEXT', - ], - ), - ); - - $conn->exec( - (string) Sql::createTable( - // id, name, category_id - 'categories', - [ - 'id INTEGER PRIMARY KEY', - 'name VARCHAR(255)', - 'category_id INTEGER', - ], - ), - ); - $conn->exec( - (string) Sql::createTable( - 'post_categories', - [ - 'id INTEGER PRIMARY KEY', - 'post_id INTEGER', - 'category_id INTEGER', - ], - ), - ); - $this->posts = [ - (object) [ - 'id' => 5, - 'title' => 'Post Title', - 'text' => 'Post Text', - 'author_id' => 1, - ], - ]; - $this->authors = [ - (object) [ - 'id' => 1, - 'name' => 'Author 1', - ], - ]; - $this->comments = [ - (object) [ - 'id' => 7, - 'post_id' => 5, - 'text' => 'Comment Text', - ], - (object) [ - 'id' => 8, - 'post_id' => 4, - 'text' => 'Comment Text 2', - ], - ]; - $this->categories = [ - (object) [ - 'id' => 2, - 'name' => 'Sample Category', - 'category_id' => null, - ], - (object) [ - 'id' => 3, - 'name' => 'NONON', - 'category_id' => null, - ], - ]; - $this->postsCategories = [ - (object) [ - 'id' => 66, - 'post_id' => 5, - 'category_id' => 2, - ], - ]; - - foreach ($this->authors as $author) { - $db->insertInto('authors', (array) $author)->values((array) $author)->exec(); - } - - foreach ($this->posts as $post) { - $db->insertInto('posts', (array) $post)->values((array) $post)->exec(); - } - - foreach ($this->comments as $comment) { - $db->insertInto('comments', (array) $comment)->values((array) $comment)->exec(); - } - - foreach ($this->categories as $category) { - $db->insertInto('categories', (array) $category)->values((array) $category)->exec(); - } - - foreach ($this->postsCategories as $postCategory) { - $db->insertInto('post_categories', (array) $postCategory)->values((array) $postCategory)->exec(); - } - - $this->conn = $conn; - $this->style = new CakePHP(); - $this->mapper = new Mapper($conn); - $this->mapper->setStyle($this->style); - $this->mapper->entityNamespace = __NAMESPACE__ . '\\'; - } - - #[DataProvider('tableEntityProvider')] - public function testTableAndEntitiesMethods(string $table, string $entity): void - { - $this->assertEquals($entity, $this->style->styledName($table)); - $this->assertEquals($table, $this->style->realName($entity)); - $this->assertEquals('id', $this->style->identifier($table)); - } - - #[DataProvider('columnsPropertyProvider')] - public function testColumnsAndPropertiesMethods(string $column): void - { - $this->assertEquals($column, $this->style->styledProperty($column)); - $this->assertEquals($column, $this->style->realProperty($column)); - $this->assertFalse($this->style->isRemoteIdentifier($column)); - $this->assertNull($this->style->remoteFromIdentifier($column)); - } - - #[DataProvider('manyToMantTableProvider')] - public function testTableFromLeftRightTable(string $left, string $right, string $table): void - { - $this->assertEquals($table, $this->style->composed($left, $right)); - } - - #[DataProvider('foreignProvider')] - public function testForeign(string $table, string $foreign): void - { - $this->assertTrue($this->style->isRemoteIdentifier($foreign)); - $this->assertEquals($table, $this->style->remoteFromIdentifier($foreign)); - $this->assertEquals($foreign, $this->style->remoteIdentifier($table)); - } - - public function testFetchingEntityTyped(): void - { - $mapper = $this->mapper; - $comment = $mapper->comments[8]->fetch(); - $this->assertInstanceOf(__NAMESPACE__ . '\Comment', $comment); - } - - public function testFetchingAllEntityTyped(): void - { - $mapper = $this->mapper; - $comment = $mapper->comments->fetchAll(); - $this->assertInstanceOf(__NAMESPACE__ . '\Comment', $comment[1]); - - $categories = $mapper->post_categories->categories->fetch(); - $this->assertInstanceOf(__NAMESPACE__ . '\PostCategory', $categories); - $this->assertInstanceOf(__NAMESPACE__ . '\Category', $categories->category_id); - } - - public function testFetchingAllEntityTypedNested(): void - { - $mapper = $this->mapper; - $comment = $mapper->comments->posts->authors->fetchAll(); - $this->assertInstanceOf(__NAMESPACE__ . '\Comment', $comment[0]); - $this->assertInstanceOf(__NAMESPACE__ . '\Post', $comment[0]->post_id); - $this->assertInstanceOf( - __NAMESPACE__ . '\Author', - $comment[0]->post_id->author_id, - ); - } - - public function testPersistingEntityTyped(): void - { - $mapper = $this->mapper; - $comment = $mapper->comments[8]->fetch(); - $this->assertInstanceOf(__NAMESPACE__ . '\Comment', $comment); - $comment->text = 'HeyHey'; - $mapper->comments->persist($comment); - $mapper->flush(); - $result = $this->conn->query( - 'select text from comments where id=8', - )->fetchColumn(0); - $this->assertEquals('HeyHey', $result); - } - - public function testPersistingNewEntityTyped(): void - { - $mapper = $this->mapper; - $comment = new Comment(); - $comment->text = 'HeyHey'; - $mapper->comments->persist($comment); - $mapper->flush(); - $result = $this->conn->query( - 'select text from comments where id=9', - )->fetchColumn(0); - $this->assertEquals('HeyHey', $result); - } - - /** @return array> */ - public static function tableEntityProvider(): array - { - return [ - ['posts', 'Post'], - ['comments', 'Comment'], - ['categories', 'Category'], - ['post_categories', 'PostCategory'], - ['post_tags', 'PostTag'], - ]; - } - - /** @return array> */ - public static function manyToMantTableProvider(): array - { - return [ - ['post', 'category', 'post_categories'], - ['user', 'group', 'user_groups'], - ['group', 'profile', 'group_profiles'], - ]; - } - - /** @return array> */ - public static function columnsPropertyProvider(): array - { - return [ - ['id'], - ['text'], - ['name'], - ['content'], - ['created'], - ]; - } - - /** @return array> */ - public static function foreignProvider(): array - { - return [ - ['posts', 'post_id'], - ['authors', 'author_id'], - ['tags', 'tag_id'], - ['users', 'user_id'], - ]; - } -} - -class Post -{ - public mixed $id = null; - - public string|null $title = null; - - public string|null $text = null; - - public mixed $author_id = null; -} - -class Author -{ - public mixed $id = null; - - public string|null $name = null; -} - -class Comment -{ - public mixed $id = null; - - public mixed $post_id = null; - - public string|null $text = null; -} - -class Category -{ - public mixed $id = null; - - public string|null $name = null; - - public mixed $category_id = null; -} - -class PostCategory -{ - public mixed $id = null; - - public mixed $post_id = null; - - public mixed $category_id = null; -} diff --git a/tests/Styles/NorthWindTest.php b/tests/Styles/NorthWindTest.php deleted file mode 100644 index f26f26b..0000000 --- a/tests/Styles/NorthWindTest.php +++ /dev/null @@ -1,348 +0,0 @@ - */ - private array $posts; - - /** @var list */ - private array $authors; - - /** @var list */ - private array $comments; - - /** @var list */ - private array $categories; - - /** @var list */ - private array $postsCategories; - - protected function setUp(): void - { - $conn = new PDO('sqlite::memory:'); - $db = new Db($conn); - $conn->exec( - (string) Sql::createTable( - 'Posts', - [ - 'PostID INTEGER PRIMARY KEY', - 'Title VARCHAR(255)', - 'Text TEXT', - 'AuthorID INTEGER', - ], - ), - ); - $conn->exec( - (string) Sql::createTable( - 'Authors', - [ - 'AuthorID INTEGER PRIMARY KEY', - 'Name VARCHAR(255)', - ], - ), - ); - $conn->exec( - (string) Sql::createTable( - 'Comments', - [ - 'CommentID INTEGER PRIMARY KEY', - 'PostID INTEGER', - 'Text TEXT', - ], - ), - ); - - $conn->exec( - (string) Sql::createTable( - 'Categories', - [ - 'CategoryID INTEGER PRIMARY KEY', - 'Name VARCHAR(255)', - 'Description TEXT', - ], - ), - ); - $conn->exec( - (string) Sql::createTable( - 'PostCategories', - [ - 'PostCategoryID INTEGER PRIMARY KEY', - 'PostID INTEGER', - 'CategoryID INTEGER', - ], - ), - ); - $this->posts = [ - (object) [ - 'PostID' => 5, - 'Title' => 'Post Title', - 'Text' => 'Post Text', - 'AuthorID' => 1, - ], - ]; - $this->authors = [ - (object) [ - 'AuthorID' => 1, - 'Name' => 'Author 1', - ], - ]; - $this->comments = [ - (object) [ - 'CommentID' => 7, - 'PostID' => 5, - 'Text' => 'Comment Text', - ], - (object) [ - 'CommentID' => 8, - 'PostID' => 4, - 'Text' => 'Comment Text 2', - ], - ]; - $this->categories = [ - (object) [ - 'CategoryID' => 2, - 'Name' => 'Sample Category', - 'Description' => 'Category description', - ], - (object) [ - 'CategoryID' => 3, - 'Name' => 'NONON', - 'CategoryID' => null, - ], - ]; - $this->postsCategories = [ - (object) [ - 'PostCategoryID' => 66, - 'PostID' => 5, - 'CategoryID' => 2, - ], - ]; - - foreach ($this->authors as $author) { - $db->insertInto('Authors', (array) $author)->values((array) $author)->exec(); - } - - foreach ($this->posts as $post) { - $db->insertInto('Posts', (array) $post)->values((array) $post)->exec(); - } - - foreach ($this->comments as $comment) { - $db->insertInto('Comments', (array) $comment)->values((array) $comment)->exec(); - } - - foreach ($this->categories as $category) { - $db->insertInto('Categories', (array) $category)->values((array) $category)->exec(); - } - - foreach ($this->postsCategories as $postCategory) { - $db->insertInto('PostCategories', (array) $postCategory)->values((array) $postCategory)->exec(); - } - - $this->conn = $conn; - $this->style = new NorthWind(); - $this->mapper = new Mapper($conn); - $this->mapper->setStyle($this->style); - $this->mapper->entityNamespace = __NAMESPACE__ . '\\'; - } - - /** @return array> */ - public static function tableEntityProvider(): array - { - return [ - ['Posts', 'Posts'], - ['Comments', 'Comments'], - ['Categories', 'Categories'], - ['PostCategories', 'PostCategories'], - ['PostTags', 'PostTags'], - ]; - } - - /** @return array> */ - public static function manyToMantTableProvider(): array - { - return [ - ['Posts', 'Categories', 'PostCategories'], - ['Users', 'Groups', 'UserGroups'], - ['Groups', 'Profiles', 'GroupProfiles'], - ]; - } - - /** @return array> */ - public static function columnsPropertyProvider(): array - { - return [ - ['Text'], - ['Name'], - ['Content'], - ['Created'], - ['Udated'], - ]; - } - - /** @return array> */ - public static function keyProvider(): array - { - return [ - ['Posts', 'PostID'], - ['Authors', 'AuthorID'], - ['Tags', 'TagID'], - ['Users', 'UserID'], - ]; - } - - #[DataProvider('tableEntityProvider')] - public function testTableAndEntitiesMethods(string $table, string $entity): void - { - $this->assertEquals($entity, $this->style->styledName($table)); - $this->assertEquals($table, $this->style->realName($entity)); - } - - #[DataProvider('columnsPropertyProvider')] - public function testColumnsAndPropertiesMethods(string $column): void - { - $this->assertEquals($column, $this->style->styledProperty($column)); - $this->assertEquals($column, $this->style->realProperty($column)); - $this->assertFalse($this->style->isRemoteIdentifier($column)); - $this->assertNull($this->style->remoteFromIdentifier($column)); - } - - #[DataProvider('manyToMantTableProvider')] - public function testTableFromLeftRightTable(string $left, string $right, string $table): void - { - $this->assertEquals($table, $this->style->composed($left, $right)); - } - - #[DataProvider('keyProvider')] - public function testKeys(string $table, string $foreign): void - { - $this->assertTrue($this->style->isRemoteIdentifier($foreign)); - $this->assertEquals($table, $this->style->remoteFromIdentifier($foreign)); - $this->assertEquals($foreign, $this->style->identifier($table)); - $this->assertEquals($foreign, $this->style->remoteIdentifier($table)); - } - - public function testFetchingEntityTyped(): void - { - $mapper = $this->mapper; - $comment = $mapper->Comments[8]->fetch(); - $this->assertInstanceOf(__NAMESPACE__ . '\Comments', $comment); - } - - public function testFetchingAllEntityTyped(): void - { - $mapper = $this->mapper; - $comment = $mapper->Comments->fetchAll(); - $this->assertInstanceOf(__NAMESPACE__ . '\Comments', $comment[1]); - - $categories = $mapper->PostCategories->Categories->fetch(); - $this->assertInstanceOf(__NAMESPACE__ . '\PostCategories', $categories); - $this->assertInstanceOf( - __NAMESPACE__ . '\Categories', - $categories->CategoryID, - ); - } - - public function testFetchingAllEntityTypedNested(): void - { - $mapper = $this->mapper; - $comment = $mapper->Comments->Posts->Authors->fetchAll(); - $this->assertInstanceOf(__NAMESPACE__ . '\Comments', $comment[0]); - $this->assertInstanceOf(__NAMESPACE__ . '\Posts', $comment[0]->PostID); - $this->assertInstanceOf( - __NAMESPACE__ . '\Authors', - $comment[0]->PostID->AuthorID, - ); - } - - public function testPersistingEntityTyped(): void - { - $mapper = $this->mapper; - $comment = $mapper->Comments[8]->fetch(); - $this->assertInstanceOf(__NAMESPACE__ . '\Comments', $comment); - $comment->Text = 'HeyHey'; - $mapper->Comments->persist($comment); - $mapper->flush(); - $result = $this->conn->query( - 'select Text from Comments where CommentID=8', - )->fetchColumn(0); - $this->assertEquals('HeyHey', $result); - } - - public function testPersistingNewEntityTyped(): void - { - $mapper = $this->mapper; - $comment = new Comments(); - $comment->Text = 'HeyHey'; - $mapper->Comments->persist($comment); - $mapper->flush(); - $result = $this->conn->query( - 'select Text from Comments where CommentID=9', - )->fetchColumn(0); - $this->assertEquals('HeyHey', $result); - } -} - -class Posts -{ - public mixed $PostID = null; - - public string|null $Title = null; - - public string|null $Text = null; - - public mixed $AuthorID = null; -} - -class Authors -{ - public mixed $AuthorID = null; - - public string|null $Name = null; -} - -class Comments -{ - public mixed $CommentID = null; - - public mixed $PostID = null; - - public string|null $Text = null; -} - -class Categories -{ - public mixed $CategoryID = null; - - public string|null $Name = null; - - public string|null $Description = null; -} - -class PostCategories -{ - public mixed $PostCategoryID = null; - - public mixed $PostID = null; - - public mixed $CategoryID = null; -} diff --git a/tests/Styles/PluralTest.php b/tests/Styles/PluralTest.php deleted file mode 100644 index 3787fcd..0000000 --- a/tests/Styles/PluralTest.php +++ /dev/null @@ -1,342 +0,0 @@ - */ - private array $posts; - - /** @var list */ - private array $authors; - - /** @var list */ - private array $comments; - - /** @var list */ - private array $categories; - - /** @var list */ - private array $postsCategories; - - protected function setUp(): void - { - $conn = new PDO('sqlite::memory:'); - $db = new Db($conn); - $conn->exec( - (string) Sql::createTable( - 'posts', - [ - 'id INTEGER PRIMARY KEY', - 'title VARCHAR(255)', - 'text TEXT', - 'author_id INTEGER', - ], - ), - ); - $conn->exec( - (string) Sql::createTable( - 'authors', - [ - 'id INTEGER PRIMARY KEY', - 'name VARCHAR(255)', - ], - ), - ); - $conn->exec( - (string) Sql::createTable( - 'comments', - [ - 'id INTEGER PRIMARY KEY', - 'post_id INTEGER', - 'text TEXT', - ], - ), - ); - $conn->exec( - (string) Sql::createTable( - 'categories', - [ - 'id INTEGER PRIMARY KEY', - 'name VARCHAR(255)', - ], - ), - ); - $conn->exec( - (string) Sql::createTable( - 'posts_categories', - [ - 'id INTEGER PRIMARY KEY', - 'post_id INTEGER', - 'category_id INTEGER', - ], - ), - ); - $this->posts = [ - (object) [ - 'id' => 5, - 'title' => 'Post Title', - 'text' => 'Post Text', - 'author_id' => 1, - ], - ]; - $this->authors = [ - (object) [ - 'id' => 1, - 'name' => 'Author 1', - ], - ]; - $this->comments = [ - (object) [ - 'id' => 7, - 'post_id' => 5, - 'text' => 'Comment Text', - ], - (object) [ - 'id' => 8, - 'post_id' => 4, - 'text' => 'Comment Text 2', - ], - ]; - $this->categories = [ - (object) [ - 'id' => 2, - 'name' => 'Sample Category', - ], - (object) [ - 'id' => 3, - 'name' => 'NONON', - ], - ]; - $this->postsCategories = [ - (object) [ - 'id' => 66, - 'post_id' => 5, - 'category_id' => 2, - ], - ]; - - foreach ($this->authors as $author) { - $db->insertInto('authors', (array) $author)->values((array) $author)->exec(); - } - - foreach ($this->posts as $post) { - $db->insertInto('posts', (array) $post)->values((array) $post)->exec(); - } - - foreach ($this->comments as $comment) { - $db->insertInto('comments', (array) $comment)->values((array) $comment)->exec(); - } - - foreach ($this->categories as $category) { - $db->insertInto('categories', (array) $category)->values((array) $category)->exec(); - } - - foreach ($this->postsCategories as $postCategory) { - $db->insertInto('posts_categories', (array) $postCategory)->values((array) $postCategory)->exec(); - } - - $this->conn = $conn; - $this->style = new Plural(); - $this->mapper = new Mapper($conn); - $this->mapper->setStyle($this->style); - $this->mapper->entityNamespace = __NAMESPACE__ . '\\'; - } - - #[DataProvider('tableEntityProvider')] - public function testTableAndEntitiesMethods(string $table, string $entity): void - { - $this->assertEquals($entity, $this->style->styledName($table)); - $this->assertEquals($table, $this->style->realName($entity)); - $this->assertEquals('id', $this->style->identifier($table)); - } - - #[DataProvider('columnsPropertyProvider')] - public function testColumnsAndPropertiesMethods(string $column): void - { - $this->assertEquals($column, $this->style->styledProperty($column)); - $this->assertEquals($column, $this->style->realProperty($column)); - $this->assertFalse($this->style->isRemoteIdentifier($column)); - $this->assertNull($this->style->remoteFromIdentifier($column)); - } - - #[DataProvider('manyToMantTableProvider')] - public function testTableFromLeftRightTable(string $left, string $right, string $table): void - { - $this->assertEquals($table, $this->style->composed($left, $right)); - } - - #[DataProvider('foreignProvider')] - public function testForeign(string $table, string $foreign): void - { - $this->assertTrue($this->style->isRemoteIdentifier($foreign)); - $this->assertEquals($table, $this->style->remoteFromIdentifier($foreign)); - $this->assertEquals($foreign, $this->style->remoteIdentifier($table)); - } - - public function testFetchingEntityTyped(): void - { - $mapper = $this->mapper; - $comment = $mapper->comments[8]->fetch(); - $this->assertInstanceOf(__NAMESPACE__ . '\Comment', $comment); - } - - public function testFetchingAllEntityTyped(): void - { - $mapper = $this->mapper; - $comment = $mapper->comments->fetchAll(); - $this->assertInstanceOf(__NAMESPACE__ . '\Comment', $comment[1]); - - $categories = $mapper->posts_categories->categories->fetch(); - $this->assertInstanceOf(__NAMESPACE__ . '\PostCategory', $categories); - $this->assertInstanceOf( - __NAMESPACE__ . '\Category', - $categories->category_id, - ); - } - - public function testFetchingAllEntityTypedNested(): void - { - $mapper = $this->mapper; - $comment = $mapper->comments->posts->authors->fetchAll(); - $this->assertInstanceOf(__NAMESPACE__ . '\Comment', $comment[0]); - $this->assertInstanceOf(__NAMESPACE__ . '\Post', $comment[0]->post_id); - $this->assertInstanceOf( - __NAMESPACE__ . '\Author', - $comment[0]->post_id->author_id, - ); - } - - public function testPersistingEntityTyped(): void - { - $mapper = $this->mapper; - $comment = $mapper->comments[8]->fetch(); - $this->assertInstanceOf(__NAMESPACE__ . '\Comment', $comment); - $comment->text = 'HeyHey'; - $mapper->comments->persist($comment); - $mapper->flush(); - $result = $this->conn->query( - 'select text from comments where id=8', - )->fetchColumn(0); - $this->assertEquals('HeyHey', $result); - } - - public function testPersistingNewEntityTyped(): void - { - $mapper = $this->mapper; - $comment = new Comment(); - $comment->text = 'HeyHey'; - $mapper->comments->persist($comment); - $mapper->flush(); - $result = $this->conn->query( - 'select text from comments where id=9', - )->fetchColumn(0); - $this->assertEquals('HeyHey', $result); - } - - /** @return array> */ - public static function tableEntityProvider(): array - { - return [ - ['posts', 'Post'], - ['comments', 'Comment'], - ['categories', 'Category'], - ['posts_categories', 'PostCategory'], - ['posts_tags', 'PostTag'], - ]; - } - - /** @return array> */ - public static function manyToMantTableProvider(): array - { - return [ - ['post', 'category', 'posts_categories'], - ['user', 'group', 'users_groups'], - ['group', 'profile', 'groups_profiles'], - ]; - } - - /** @return array> */ - public static function columnsPropertyProvider(): array - { - return [ - ['id'], - ['text'], - ['name'], - ['content'], - ['created'], - ]; - } - - /** @return array> */ - public static function foreignProvider(): array - { - return [ - ['posts', 'post_id'], - ['authors', 'author_id'], - ['tags', 'tag_id'], - ['users', 'user_id'], - ]; - } -} - -class Post -{ - public mixed $id = null; - - public string|null $title = null; - - public string|null $text = null; - - public mixed $author_id = null; -} - -class Author -{ - public mixed $id = null; - - public string|null $name = null; -} - -class Comment -{ - public mixed $id = null; - - public mixed $post_id = null; - - public string|null $text = null; -} - -class Category -{ - public mixed $id = null; - - public string|null $name = null; -} - -class PostCategory -{ - public mixed $id = null; - - public mixed $post_id = null; - - public mixed $category_id = null; -} diff --git a/tests/Styles/SakilaTest.php b/tests/Styles/SakilaTest.php deleted file mode 100644 index 8297805..0000000 --- a/tests/Styles/SakilaTest.php +++ /dev/null @@ -1,351 +0,0 @@ - */ - private array $posts; - - /** @var list */ - private array $authors; - - /** @var list */ - private array $comments; - - /** @var list */ - private array $categories; - - /** @var list */ - private array $postsCategories; - - protected function setUp(): void - { - $conn = new PDO('sqlite::memory:'); - $db = new Db($conn); - $conn->exec( - (string) Sql::createTable( - 'post', - [ - 'post_id INTEGER PRIMARY KEY', - 'title VARCHAR(255)', - 'text TEXT', - 'author_id INTEGER', - ], - ), - ); - $conn->exec( - (string) Sql::createTable( - 'author', - [ - 'author_id INTEGER PRIMARY KEY', - 'name VARCHAR(255)', - ], - ), - ); - $conn->exec( - (string) Sql::createTable( - 'comment', - [ - 'comment_id INTEGER PRIMARY KEY', - 'post_id INTEGER', - 'text TEXT', - ], - ), - ); - - $conn->exec( - (string) Sql::createTable( - 'category', - [ - 'category_id INTEGER PRIMARY KEY', - 'name VARCHAR(255)', - 'content VARCHAR(255)', - 'description TEXT', - ], - ), - ); - $conn->exec( - (string) Sql::createTable( - 'post_category', - [ - 'post_category_id INTEGER PRIMARY KEY', - 'post_id INTEGER', - 'category_id INTEGER', - ], - ), - ); - $this->posts = [ - (object) [ - 'post_id' => 5, - 'title' => 'Post Title', - 'text' => 'Post Text', - 'author_id' => 1, - ], - ]; - $this->authors = [ - (object) [ - 'author_id' => 1, - 'name' => 'Author 1', - ], - ]; - $this->comments = [ - (object) [ - 'comment_id' => 7, - 'post_id' => 5, - 'text' => 'Comment Text', - ], - (object) [ - 'comment_id' => 8, - 'post_id' => 4, - 'text' => 'Comment Text 2', - ], - ]; - $this->categories = [ - (object) [ - 'category_id' => 2, - 'name' => 'Sample Category', - 'content' => null, - ], - (object) [ - 'category_id' => 3, - 'name' => 'NONON', - 'content' => null, - ], - ]; - $this->postsCategories = [ - (object) [ - 'post_category_id' => 66, - 'post_id' => 5, - 'category_id' => 2, - ], - ]; - - foreach ($this->authors as $author) { - $db->insertInto('author', (array) $author)->values((array) $author)->exec(); - } - - foreach ($this->posts as $post) { - $db->insertInto('post', (array) $post)->values((array) $post)->exec(); - } - - foreach ($this->comments as $comment) { - $db->insertInto('comment', (array) $comment)->values((array) $comment)->exec(); - } - - foreach ($this->categories as $category) { - $db->insertInto('category', (array) $category)->values((array) $category)->exec(); - } - - foreach ($this->postsCategories as $postCategory) { - $db->insertInto('post_category', (array) $postCategory)->values((array) $postCategory)->exec(); - } - - $this->conn = $conn; - $this->style = new Sakila(); - $this->mapper = new Mapper($conn); - $this->mapper->setStyle($this->style); - $this->mapper->entityNamespace = __NAMESPACE__ . '\\'; - } - - /** @return array> */ - public static function tableEntityProvider(): array - { - return [ - ['post', 'Post'], - ['comment', 'Comment'], - ['category', 'Category'], - ['post_category', 'PostCategory'], - ['post_tag', 'PostTag'], - ]; - } - - /** @return array> */ - public static function manyToMantTableProvider(): array - { - return [ - ['post', 'category', 'post_category'], - ['user', 'group', 'user_group'], - ['group', 'profile', 'group_profile'], - ]; - } - - /** @return array> */ - public static function columnsPropertyProvider(): array - { - return [ - ['id'], - ['text'], - ['name'], - ['content'], - ['created'], - ]; - } - - /** @return array> */ - public static function keyProvider(): array - { - return [ - ['post', 'post_id'], - ['author', 'author_id'], - ['tag', 'tag_id'], - ['user', 'user_id'], - ]; - } - - #[DataProvider('tableEntityProvider')] - public function testTableAndEntitiesMethods(string $table, string $entity): void - { - $this->assertEquals($entity, $this->style->styledName($table)); - $this->assertEquals($table, $this->style->realName($entity)); - } - - #[DataProvider('columnsPropertyProvider')] - public function testColumnsAndPropertiesMethods(string $column): void - { - $this->assertEquals($column, $this->style->styledProperty($column)); - $this->assertEquals($column, $this->style->realProperty($column)); - $this->assertFalse($this->style->isRemoteIdentifier($column)); - $this->assertNull($this->style->remoteFromIdentifier($column)); - } - - #[DataProvider('manyToMantTableProvider')] - public function testTableFromLeftRightTable(string $left, string $right, string $table): void - { - $this->assertEquals($table, $this->style->composed($left, $right)); - } - - #[DataProvider('keyProvider')] - public function testForeign(string $table, string $key): void - { - $this->assertTrue($this->style->isRemoteIdentifier($key)); - $this->assertEquals($table, $this->style->remoteFromIdentifier($key)); - $this->assertEquals($key, $this->style->identifier($table)); - $this->assertEquals($key, $this->style->remoteIdentifier($table)); - } - - public function testFetchingEntityTyped(): void - { - $mapper = $this->mapper; - $comment = $mapper->comment[8]->fetch(); - $this->assertInstanceOf(__NAMESPACE__ . '\Comment', $comment); - } - - public function testFetchingAllEntityTyped(): void - { - $mapper = $this->mapper; - $comment = $mapper->comment->fetchAll(); - $this->assertInstanceOf(__NAMESPACE__ . '\Comment', $comment[1]); - - $categories = $mapper->post_category->category->fetch(); - $this->assertInstanceOf(__NAMESPACE__ . '\PostCategory', $categories); - $this->assertInstanceOf( - __NAMESPACE__ . '\Category', - $categories->category_id, - ); - } - - public function testFetchingAllEntityTypedNested(): void - { - $mapper = $this->mapper; - $comment = $mapper->comment->post->author->fetchAll(); - $this->assertInstanceOf(__NAMESPACE__ . '\Comment', $comment[0]); - $this->assertInstanceOf(__NAMESPACE__ . '\Post', $comment[0]->post_id); - $this->assertInstanceOf( - __NAMESPACE__ . '\Author', - $comment[0]->post_id->author_id, - ); - } - - public function testPersistingEntityTyped(): void - { - $mapper = $this->mapper; - $comment = $mapper->comment[8]->fetch(); - $this->assertInstanceOf(__NAMESPACE__ . '\Comment', $comment); - $comment->text = 'HeyHey'; - $mapper->comment->persist($comment); - $mapper->flush(); - $result = $this->conn->query( - 'select text from comment where comment_id=8', - )->fetchColumn(0); - $this->assertEquals('HeyHey', $result); - } - - public function testPersistingNewEntityTyped(): void - { - $mapper = $this->mapper; - $comment = new Comment(); - $comment->text = 'HeyHey'; - $mapper->comment->persist($comment); - $mapper->flush(); - $result = $this->conn->query( - 'select text from comment where comment_id=9', - )->fetchColumn(0); - $this->assertEquals('HeyHey', $result); - } -} - -class Post -{ - public mixed $post_id = null; - - public string|null $title = null; - - public string|null $text = null; - - public mixed $author_id = null; -} - -class Author -{ - public mixed $author_id = null; - - public string|null $name = null; -} - -class Comment -{ - public mixed $comment_id = null; - - public mixed $post_id = null; - - public string|null $text = null; -} - -class Category -{ - public mixed $category_id = null; - - public string|null $name = null; - - public string|null $content = null; - - public string|null $description = null; -} - -class PostCategory -{ - public mixed $post_category_id = null; - - public mixed $post_id = null; - - public mixed $category_id = null; -} diff --git a/tests/Styles/StandardTest.php b/tests/Styles/StandardTest.php deleted file mode 100644 index 68c6b56..0000000 --- a/tests/Styles/StandardTest.php +++ /dev/null @@ -1,96 +0,0 @@ -style = new Standard(); - } - - /** @return array> */ - public static function tableEntityProvider(): array - { - return [ - ['post', 'Post'], - ['comment', 'Comment'], - ['category', 'Category'], - ['post_category', 'PostCategory'], - ['post_tag', 'PostTag'], - ]; - } - - /** @return array> */ - public static function manyToMantTableProvider(): array - { - return [ - ['post', 'category', 'post_category'], - ['user', 'group', 'user_group'], - ['group', 'profile', 'group_profile'], - ]; - } - - /** @return array> */ - public static function columnsPropertyProvider(): array - { - return [ - ['id'], - ['text'], - ['name'], - ['content'], - ['created'], - ]; - } - - /** @return array> */ - public static function foreignProvider(): array - { - return [ - ['post', 'post_id'], - ['author', 'author_id'], - ['tag', 'tag_id'], - ['user', 'user_id'], - ]; - } - - #[DataProvider('tableEntityProvider')] - public function testTableAndEntitiesMethods(string $table, string $entity): void - { - $this->assertEquals($entity, $this->style->styledName($table)); - $this->assertEquals($table, $this->style->realName($entity)); - $this->assertEquals('id', $this->style->identifier($table)); - } - - #[DataProvider('columnsPropertyProvider')] - public function testColumnsAndPropertiesMethods(string $name): void - { - $this->assertEquals($name, $this->style->styledProperty($name)); - $this->assertEquals($name, $this->style->realProperty($name)); - $this->assertFalse($this->style->isRemoteIdentifier($name)); - $this->assertNull($this->style->remoteFromIdentifier($name)); - } - - #[DataProvider('manyToMantTableProvider')] - public function testTableFromLeftRightTable(string $left, string $right, string $table): void - { - $this->assertEquals($table, $this->style->composed($left, $right)); - } - - #[DataProvider('foreignProvider')] - public function testForeign(string $table, string $foreign): void - { - $this->assertTrue($this->style->isRemoteIdentifier($foreign)); - $this->assertEquals($table, $this->style->remoteFromIdentifier($foreign)); - $this->assertEquals($foreign, $this->style->remoteIdentifier($table)); - } -}