From da508491dfc18f43f6763917588e5fb1b1ae128a Mon Sep 17 00:00:00 2001 From: Alexandre Gomes Gaigalas Date: Fri, 3 Apr 2026 03:30:47 -0300 Subject: [PATCH] Remove STI and MTI implementations These features reached blocker limitations for future designs and will be re-planned from scratch later. --- phpstan.neon.dist | 2 +- src/Collections/Collection.php | 26 +------ src/Collections/Composite.php | 46 ------------ src/Collections/Typed.php | 60 ---------------- src/EntityFactory.php | 4 +- src/Hydrators/Base.php | 17 ----- src/Hydrators/Nested.php | 2 +- src/Hydrators/PrestyledAssoc.php | 44 ++---------- tests/AbstractMapperTest.php | 25 +++---- tests/Collections/CompositeTest.php | 53 -------------- tests/Collections/TypedTest.php | 70 ------------------- tests/EntityFactoryTest.php | 13 ++++ tests/Hydrators/NestedTest.php | 32 +++++---- tests/Hydrators/PrestyledAssocTest.php | 44 ------------ tests/InMemoryMapper.php | 30 +++++++- tests/Stubs/Bug.php | 14 ---- tests/Stubs/Issue.php | 14 ---- .../Styles/CakePHP/CakePHPIntegrationTest.php | 57 ++------------- .../NorthWind/NorthWindIntegrationTest.php | 57 ++------------- tests/Styles/Plural/PluralIntegrationTest.php | 57 ++------------- tests/Styles/Sakila/SakilaIntegrationTest.php | 57 ++------------- 21 files changed, 106 insertions(+), 618 deletions(-) delete mode 100644 src/Collections/Composite.php delete mode 100644 src/Collections/Typed.php delete mode 100644 tests/Collections/CompositeTest.php delete mode 100644 tests/Collections/TypedTest.php delete mode 100644 tests/Stubs/Bug.php delete mode 100644 tests/Stubs/Issue.php diff --git a/phpstan.neon.dist b/phpstan.neon.dist index f881cee..45378a9 100644 --- a/phpstan.neon.dist +++ b/phpstan.neon.dist @@ -4,7 +4,7 @@ parameters: - src/ - tests/ ignoreErrors: - - message: '/Call to an undefined (static )?method Respect\\Data\\(AbstractMapper|InMemoryMapper|Collections\\(Collection|Composite|Typed))::\w+\(\)\./' + - message: '/Call to an undefined (static )?method Respect\\Data\\(AbstractMapper|InMemoryMapper|Collections\\Collection)::\w+\(\)\./' - message: '/Unsafe usage of new static\(\)\./' - message: '/Property .+ is never read, only written\./' diff --git a/src/Collections/Collection.php b/src/Collections/Collection.php index b5a6788..d8da3dc 100644 --- a/src/Collections/Collection.php +++ b/src/Collections/Collection.php @@ -37,32 +37,12 @@ public function derive( ): static { return new static( $this->name, - ...$this->deriveArgs( - with: $with, - filter: $filter, - required: $required, - ), + with: [...$this->with, ...$with], + filter: $filter ?? $this->filter, + required: $required ?? $this->required, ); } - /** - * @param list $with - * @param array|scalar|null $filter - * - * @return array{with: list, filter: array|int|float|string|bool|null, required: bool} - */ - protected function deriveArgs( // @phpstan-ignore missingType.iterableValue - array $with = [], - array|int|float|string|bool|null $filter = null, - bool|null $required = null, - ): array { - return [ - 'with' => [...$this->with, ...$with], - 'filter' => $filter ?? $this->filter, - 'required' => $required ?? $this->required, - ]; - } - /** * @param list $children * diff --git a/src/Collections/Composite.php b/src/Collections/Composite.php deleted file mode 100644 index 4663244..0000000 --- a/src/Collections/Composite.php +++ /dev/null @@ -1,46 +0,0 @@ -> $compositions - * @param list $with - * @param array|scalar|null $filter - */ - public function __construct( - string $name, - public private(set) readonly array $compositions = [], - array $with = [], - array|int|float|string|bool|null $filter = null, - bool $required = false, - ) { - parent::__construct($name, $with, $filter, $required); - } - - /** - * @param list $with - * - * @return array - */ - protected function deriveArgs( - array $with = [], - array|int|float|string|bool|null $filter = null, - bool|null $required = null, - ): array { - $base = parent::deriveArgs($with, $filter, $required); - - return ['compositions' => $this->compositions] + $base; - } - - /** @param array>> $arguments */ - public static function __callStatic(string $name, array $arguments): static - { - return new static($name, ...$arguments); - } -} diff --git a/src/Collections/Typed.php b/src/Collections/Typed.php deleted file mode 100644 index c92886c..0000000 --- a/src/Collections/Typed.php +++ /dev/null @@ -1,60 +0,0 @@ - $with - * @param array|scalar|null $filter - */ - public function __construct( - string $name, - public private(set) readonly string $type = '', - array $with = [], - array|int|float|string|bool|null $filter = null, - bool $required = false, - ) { - parent::__construct($name, $with, $filter, $required); - } - - /** - * @param object|array $row - * - * @return class-string - */ - public function resolveEntityClass(EntityFactory $factory, object|array $row): string - { - $name = is_array($row) ? ($row[$this->type] ?? null) : $factory->get($row, $this->type); - - return $factory->resolveClass(is_string($name) ? $name : (string) $this->name); - } - - /** - * @param list $with - * - * @return array - */ - protected function deriveArgs( - array $with = [], - array|int|float|string|bool|null $filter = null, - bool|null $required = null, - ): array { - $base = parent::deriveArgs($with, $filter, $required); - - return ['type' => $this->type] + $base; - } - - /** @param array $arguments */ - public static function __callStatic(string $name, array $arguments): static - { - return new static($name, ...$arguments); - } -} diff --git a/src/EntityFactory.php b/src/EntityFactory.php index 7683a63..5f77a10 100644 --- a/src/EntityFactory.php +++ b/src/EntityFactory.php @@ -192,7 +192,7 @@ public function extractProperties(object $entity): array $props = []; foreach ($this->reflectProperties($entity::class) as $name => $prop) { - if (!$prop->isInitialized($entity) || $prop->getAttributes(NotPersistable::class)) { + if ($prop->isVirtual() || !$prop->isInitialized($entity) || $prop->getAttributes(NotPersistable::class)) { continue; } @@ -218,7 +218,7 @@ public function enumerateFields(string $collectionName): array $fields = []; foreach ($this->reflectProperties($class) as $name => $prop) { - if ($prop->getAttributes(NotPersistable::class) || isset($relations[$name])) { + if ($prop->isVirtual() || $prop->getAttributes(NotPersistable::class) || isset($relations[$name])) { continue; } diff --git a/src/Hydrators/Base.php b/src/Hydrators/Base.php index dbf09aa..9ccff1f 100644 --- a/src/Hydrators/Base.php +++ b/src/Hydrators/Base.php @@ -6,7 +6,6 @@ use DomainException; use Respect\Data\Collections\Collection; -use Respect\Data\Collections\Typed; use Respect\Data\EntityFactory; use Respect\Data\Hydrator; use SplObjectStorage; @@ -75,20 +74,4 @@ protected function wireRelationships(SplObjectStorage $entities): void } } } - - /** - * @param object|array $row - * - * @return class-string - */ - protected function resolveEntityClass( - Collection $collection, - object|array $row, - ): string { - if ($collection instanceof Typed) { - return $collection->resolveEntityClass($this->entityFactory, $row); - } - - return $this->entityFactory->resolveClass((string) $collection->name); - } } diff --git a/src/Hydrators/Nested.php b/src/Hydrators/Nested.php index 3ff2d0c..175aeb1 100644 --- a/src/Hydrators/Nested.php +++ b/src/Hydrators/Nested.php @@ -43,7 +43,7 @@ private function hydrateNode( SplObjectStorage $entities, ): void { $entity = $this->entityFactory->create( - $this->resolveEntityClass($collection, $data), + $this->entityFactory->resolveClass((string) $collection->name), ); foreach ($data as $key => $value) { diff --git a/src/Hydrators/PrestyledAssoc.php b/src/Hydrators/PrestyledAssoc.php index 5d9d8c0..983c097 100644 --- a/src/Hydrators/PrestyledAssoc.php +++ b/src/Hydrators/PrestyledAssoc.php @@ -7,10 +7,8 @@ use DomainException; use Respect\Data\CollectionIterator; use Respect\Data\Collections\Collection; -use Respect\Data\Collections\Composite; use SplObjectStorage; -use function array_keys; use function explode; use function is_array; @@ -52,11 +50,15 @@ public function hydrateAll( $instances = []; foreach ($grouped as $prefix => $props) { - $basePrefix = $this->resolveCompositionBase($prefix, $collMap); + if (!isset($collMap[$prefix])) { + throw new DomainException('Unknown column prefix "' . $prefix . '" in hydration row'); + } + + $basePrefix = $prefix; if (!isset($instances[$basePrefix])) { $coll = $collMap[$basePrefix]; - $class = $this->resolveEntityClass($coll, $props); + $class = $this->entityFactory->resolveClass((string) $coll->name); $instances[$basePrefix] = $this->entityFactory->create($class); $entities[$instances[$basePrefix]] = $coll; } @@ -83,10 +85,6 @@ private function buildCollMap(Collection $collection): array $this->collMap = []; foreach (CollectionIterator::recursive($collection) as $spec => $c) { - if ($c->name === null) { - continue; - } - $this->collMap[$spec] = $c; } @@ -94,34 +92,4 @@ private function buildCollMap(Collection $collection): array return $this->collMap; } - - /** - * Resolve a composition prefix back to its base entity specifier. - * - * Composition columns use prefixes like "post_WITH_comment" (see Composite::COMPOSITION_MARKER). - * This returns "post" so properties are merged into the parent entity. - * - * @param array $collMap - */ - private function resolveCompositionBase(string $prefix, array $collMap): string - { - if (isset($collMap[$prefix])) { - return $prefix; - } - - // Look for a base specifier where this prefix is a composition alias - foreach ($collMap as $spec => $coll) { - if (!$coll instanceof Composite) { - continue; - } - - foreach (array_keys($coll->compositions) as $compName) { - if ($prefix === $spec . Composite::COMPOSITION_MARKER . $compName) { - return $spec; - } - } - } - - throw new DomainException('Unknown column prefix "' . $prefix . '" in hydration row'); - } } diff --git a/tests/AbstractMapperTest.php b/tests/AbstractMapperTest.php index 9d57234..9802c47 100644 --- a/tests/AbstractMapperTest.php +++ b/tests/AbstractMapperTest.php @@ -9,7 +9,6 @@ use PHPUnit\Framework\TestCase; use ReflectionObject; use Respect\Data\Collections\Collection; -use Respect\Data\Collections\Composite; use Respect\Data\Hydrators\Nested; use Respect\Data\Styles\CakePHP; use Respect\Data\Styles\Standard; @@ -52,20 +51,6 @@ public function registerCollectionShouldAddCollectionToPool(): void $this->assertEquals($coll->name, $clone->name); } - #[Test] - public function callingRegisteredCollectionWithArgsDerives(): void - { - $coll = Composite::post(['comment' => ['text']]); - $this->mapper->registerCollection('postComment', $coll); - - $derived = $this->mapper->postComment(filter: 5); - - $this->assertInstanceOf(Composite::class, $derived); - $this->assertEquals('post', $derived->name); - $this->assertEquals(['comment' => ['text']], $derived->compositions); - $this->assertEquals(5, $derived->filter); - } - #[Test] public function callingRegisteredCollectionWithoutArgsClones(): void { @@ -1305,4 +1290,14 @@ public function mergeWithIdentityMapNormalizesConditionFallback(): void $this->assertTrue($mapper->isTracked($merged)); $this->assertFalse($mapper->isTracked($fetched)); } + + #[Test] + public function callingRegisteredCollectionWithArgsDerives(): void + { + $coll = Collection::post(); + $this->mapper->registerCollection('post', $coll); + $derived = $this->mapper->post(filter: 5); + $this->assertEquals('post', $derived->name); + $this->assertEquals(5, $derived->filter); + } } diff --git a/tests/Collections/CompositeTest.php b/tests/Collections/CompositeTest.php deleted file mode 100644 index 503daef..0000000 --- a/tests/Collections/CompositeTest.php +++ /dev/null @@ -1,53 +0,0 @@ - ['bar']]); - $children2 = Composite::baz(['bat' => ['bar']]); - $coll = Collection::foo([$children1, $children2]); - $this->assertInstanceOf(Collection::class, $coll); - $this->assertInstanceOf(Composite::class, $children1); - $this->assertInstanceOf(Composite::class, $children2); - $this->assertTrue($coll->hasChildren); - $this->assertEquals(2, count($coll->with)); - $this->assertEquals(['foo' => ['bar']], $children1->compositions); - $this->assertEquals(['bat' => ['bar']], $children2->compositions); - } - - #[Test] - public function derivePreservesCompositions(): void - { - $original = Composite::post(['comment' => ['text']]); - $derived = $original->derive(with: [Collection::author()], filter: 5); - - $this->assertInstanceOf(Composite::class, $derived); - $this->assertEquals('post', $derived->name); - $this->assertEquals(['comment' => ['text']], $derived->compositions); - $this->assertCount(1, $derived->with); - $this->assertEquals('author', $derived->with[0]->name); - $this->assertEquals(5, $derived->filter); - } - - #[Test] - public function callStaticShouldCreateCompositeCollectionWithName(): void - { - $coll = Composite::items(); - $this->assertInstanceOf(Composite::class, $coll); - $this->assertEquals('items', $coll->name); - $this->assertEquals([], $coll->compositions); - } -} diff --git a/tests/Collections/TypedTest.php b/tests/Collections/TypedTest.php deleted file mode 100644 index b10271e..0000000 --- a/tests/Collections/TypedTest.php +++ /dev/null @@ -1,70 +0,0 @@ -assertInstanceOf(Collection::class, $coll); - $this->assertInstanceOf(Typed::class, $children1); - $this->assertInstanceOf(Typed::class, $children2); - $this->assertTrue($coll->hasChildren); - $this->assertEquals(2, count($coll->with)); - $this->assertEquals('a', $children1->type); - $this->assertEquals('b', $children2->type); - } - - #[Test] - public function derivePreservesType(): void - { - $original = Typed::issues('type'); - $derived = $original->derive(with: [Collection::author()], filter: 1); - - $this->assertInstanceOf(Typed::class, $derived); - $this->assertEquals('issues', $derived->name); - $this->assertEquals('type', $derived->type); - $this->assertCount(1, $derived->with); - $this->assertEquals('author', $derived->with[0]->name); - $this->assertEquals(1, $derived->filter); - } - - #[Test] - public function callStaticShouldCreateTypedCollectionWithName(): void - { - $coll = Typed::items(); - $this->assertInstanceOf(Typed::class, $coll); - $this->assertEquals('items', $coll->name); - $this->assertEquals('', $coll->type); - } - - #[Test] - public function resolveEntityClassReturnsDiscriminatorClass(): void - { - $factory = new EntityFactory(entityNamespace: 'Respect\\Data\\Stubs\\'); - $coll = Typed::issues('type'); - $this->assertEquals('Respect\\Data\\Stubs\\Bug', $coll->resolveEntityClass($factory, ['type' => 'Bug'])); - } - - #[Test] - public function resolveEntityClassFallsBackToCollectionName(): void - { - $factory = new EntityFactory(entityNamespace: 'Respect\\Data\\Stubs\\'); - $coll = Typed::issue('type'); - $this->assertEquals('Respect\\Data\\Stubs\\Issue', $coll->resolveEntityClass($factory, [])); - } -} diff --git a/tests/EntityFactoryTest.php b/tests/EntityFactoryTest.php index c605ee3..1ae02f6 100644 --- a/tests/EntityFactoryTest.php +++ b/tests/EntityFactoryTest.php @@ -503,4 +503,17 @@ public function setWithStyledFlagSkipsConversion(): void $factory->set($entity, 'name', 'Alice', styled: true); $this->assertSame('Alice', $factory->get($entity, 'name')); } + + #[Test] + public function setThrowsOnUntypedProperty(): void + { + $factory = new EntityFactory(entityNamespace: __NAMESPACE__ . '\\Stubs\\'); + $entity = new class { + // @phpstan-ignore missingType.property + public $untyped; // phpcs:ignore SlevomatCodingStandard.TypeHints.PropertyTypeHint + }; + $this->expectException(DomainException::class); + $this->expectExceptionMessage('must have a type declaration'); + $factory->set($entity, 'untyped', 'value'); + } } diff --git a/tests/Hydrators/NestedTest.php b/tests/Hydrators/NestedTest.php index ab9e22f..2cb3fa4 100644 --- a/tests/Hydrators/NestedTest.php +++ b/tests/Hydrators/NestedTest.php @@ -8,7 +8,6 @@ use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\TestCase; use Respect\Data\Collections\Collection; -use Respect\Data\Collections\Typed; use Respect\Data\EntityFactory; #[CoversClass(Nested::class)] @@ -121,18 +120,6 @@ public function hydrateWithChildren(): void $this->assertCount(3, $result); } - #[Test] - public function hydrateWithTypedCollection(): void - { - $raw = ['id' => 1, 'title' => 'Issue', 'type' => 'Bug']; - $collection = Typed::issue('type'); - - $result = $this->hydrator->hydrateAll($raw, $collection); - - $this->assertNotFalse($result); - $this->assertCount(1, $result); - } - #[Test] public function hydrateChildWithNullNameIsSkipped(): void { @@ -175,6 +162,25 @@ public function hydrateReturnsRootEntity(): void $this->assertEquals('Alice', $this->factory->get($result, 'name')); } + #[Test] + public function wireRelationshipsSkipsChildWithNullId(): void + { + $raw = [ + 'id' => 1, + 'title' => 'Post', + 'author' => ['name' => 'No ID'], + ]; + $collection = Collection::post([Collection::author()]); + + $result = $this->hydrator->hydrateAll($raw, $collection); + + $this->assertNotFalse($result); + $result->rewind(); + $post = $result->current(); + // Author has no id → wiring is skipped + $this->assertNull($this->factory->get($post, 'author')); + } + #[Test] public function hydrateReturnsRootWithWiredRelation(): void { diff --git a/tests/Hydrators/PrestyledAssocTest.php b/tests/Hydrators/PrestyledAssocTest.php index f6dc913..a904860 100644 --- a/tests/Hydrators/PrestyledAssocTest.php +++ b/tests/Hydrators/PrestyledAssocTest.php @@ -9,11 +9,8 @@ use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\TestCase; use Respect\Data\Collections\Collection; -use Respect\Data\Collections\Composite; -use Respect\Data\Collections\Typed; use Respect\Data\EntityFactory; use Respect\Data\Stubs\Author; -use Respect\Data\Stubs\Bug; #[CoversClass(PrestyledAssoc::class)] #[CoversClass(Base::class)] @@ -135,47 +132,6 @@ public function hydrateReturnsRootRegardlessOfColumnOrder(): void $this->assertEquals('Hello', $this->factory->get($result, 'title')); } - #[Test] - public function hydrateResolvesTypedEntities(): void - { - $hydrator = new PrestyledAssoc($this->factory); - $collection = Typed::issue('type'); - - $result = $hydrator->hydrateAll( - ['issue__id' => 1, 'issue__type' => 'Bug', 'issue__title' => 'Bug Report'], - $collection, - ); - - $this->assertNotFalse($result); - $result->rewind(); - $this->assertInstanceOf(Bug::class, $result->current()); - } - - #[Test] - public function hydrateCompositeEntity(): void - { - $hydrator = new PrestyledAssoc($this->factory); - $composite = Composite::author(['profile' => ['bio']], [Collection::post()]); - - $result = $hydrator->hydrateAll( - [ - 'author__id' => 1, - 'author__name' => 'Alice', - 'author_WITH_profile__bio' => 'A bio', - 'post__id' => 10, - 'post__title' => 'Hello', - ], - $composite, - ); - - $this->assertNotFalse($result); - $this->assertCount(2, $result); - $result->rewind(); - $entity = $result->current(); - $this->assertEquals(1, $this->factory->get($entity, 'id')); - $this->assertEquals('A bio', $this->factory->get($entity, 'bio')); - } - #[Test] public function hydrateCachesCollMapAcrossRows(): void { diff --git a/tests/InMemoryMapper.php b/tests/InMemoryMapper.php index 8737ca9..878e952 100644 --- a/tests/InMemoryMapper.php +++ b/tests/InMemoryMapper.php @@ -10,7 +10,6 @@ use function array_merge; use function array_values; use function is_array; -use function reset; final class InMemoryMapper extends AbstractMapper { @@ -111,6 +110,10 @@ private function updateEntity(object $entity, Collection $collection, string $ta private function deleteEntity(object $entity, string $tableName, string $id): void { + if (!isset($this->tables[$tableName])) { + return; + } + $idValue = $this->entityFactory->get($entity, $id); $rows = $this->tables[$tableName]; @@ -193,15 +196,36 @@ private function findRows(string $table, mixed $condition): array return $rows; } + if (is_array($condition)) { + return array_values(array_filter( + $rows, + static fn(array $row): bool => self::matchesCondition($row, $condition), + )); + } + $id = $this->style->identifier($table); - $idValue = is_array($condition) ? reset($condition) : $condition; return array_values(array_filter( $rows, - static fn(array $row): bool => isset($row[$id]) && $row[$id] == $idValue, + static fn(array $row): bool => isset($row[$id]) && $row[$id] == $condition, )); } + /** + * @param array $row + * @param array $condition + */ + private static function matchesCondition(array $row, array $condition): bool + { + foreach ($condition as $column => $value) { + if (!isset($row[$column]) || $row[$column] != $value) { + return false; + } + } + + return true; + } + /** @return array|null */ private function findRowById(string $table, string $id, mixed $idValue): array|null { diff --git a/tests/Stubs/Bug.php b/tests/Stubs/Bug.php deleted file mode 100644 index 41afbfa..0000000 --- a/tests/Stubs/Bug.php +++ /dev/null @@ -1,14 +0,0 @@ -mapper; - $comment = $mapper->fetch($mapper->comments(filter: 8)); - $this->assertInstanceOf(Comment::class, $comment); - } - - public function testFetchingAllEntityTyped(): void - { - $mapper = $this->mapper; - $comment = $mapper->fetchAll($mapper->comments()); - $this->assertInstanceOf(Comment::class, $comment[1]); - - $categories = $mapper->fetch($mapper->post_categories([$mapper->categories()])); - $this->assertInstanceOf(PostCategory::class, $categories); - $this->assertInstanceOf(Category::class, $categories->category); - } - - public function testFetchingAllEntityTypedNested(): void - { - $mapper = $this->mapper; - $comment = $mapper->fetchAll($mapper->comments([$mapper->posts([$mapper->authors()])])); - $this->assertInstanceOf(Comment::class, $comment[0]); - $this->assertInstanceOf(Post::class, $comment[0]->post); - $this->assertInstanceOf(Author::class, $comment[0]->post->author); - } - - public function testPersistingEntityTyped(): void - { - $mapper = $this->mapper; - $comment = $mapper->fetch($mapper->comments(filter: 8)); - $this->assertInstanceOf(Comment::class, $comment); - $comment->text = 'HeyHey'; - $mapper->persist($comment, $mapper->comments()); - $mapper->flush(); - - $updated = $mapper->fetch($mapper->comments(filter: 8)); - $this->assertInstanceOf(Comment::class, $updated); - $this->assertEquals('HeyHey', $updated->text); - } - - public function testPersistingNewEntityTyped(): void - { - $mapper = $this->mapper; - $comment = new Comment(); - $comment->text = 'HeyHey'; - $mapper->persist($comment, $mapper->comments()); - $mapper->flush(); - - $this->assertGreaterThan(0, $comment->id); - $allComments = $mapper->fetchAll($mapper->comments()); - $this->assertCount(3, $allComments); + $entity = $this->mapper->fetch($this->mapper->posts()); + $this->assertIsObject($entity); + $this->assertEquals('Post Title', $this->mapper->entityFactory->get($entity, 'title')); } } diff --git a/tests/Styles/NorthWind/NorthWindIntegrationTest.php b/tests/Styles/NorthWind/NorthWindIntegrationTest.php index ab29d72..25eae04 100644 --- a/tests/Styles/NorthWind/NorthWindIntegrationTest.php +++ b/tests/Styles/NorthWind/NorthWindIntegrationTest.php @@ -5,6 +5,7 @@ namespace Respect\Data\Styles\NorthWind; use PHPUnit\Framework\Attributes\CoversClass; +use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\TestCase; use Respect\Data\EntityFactory; use Respect\Data\Hydrators\Nested; @@ -45,57 +46,11 @@ protected function setUp(): void ]); } - public function testFetchingEntityTyped(): void + #[Test] + public function fetchAndPersistRoundTrip(): void { - $mapper = $this->mapper; - $comment = $mapper->fetch($mapper->Comments(filter: 8)); - $this->assertInstanceOf(Comments::class, $comment); - } - - public function testFetchingAllEntityTyped(): void - { - $mapper = $this->mapper; - $comment = $mapper->fetchAll($mapper->Comments()); - $this->assertInstanceOf(Comments::class, $comment[1]); - - $categories = $mapper->fetch($mapper->PostCategories([$mapper->Categories()])); - $this->assertInstanceOf(PostCategories::class, $categories); - $this->assertInstanceOf(Categories::class, $categories->Category); - } - - public function testFetchingAllEntityTypedNested(): void - { - $mapper = $this->mapper; - $comment = $mapper->fetchAll($mapper->Comments([$mapper->Posts([$mapper->Authors()])])); - $this->assertInstanceOf(Comments::class, $comment[0]); - $this->assertInstanceOf(Posts::class, $comment[0]->Post); - $this->assertInstanceOf(Authors::class, $comment[0]->Post->Author); - } - - public function testPersistingEntityTyped(): void - { - $mapper = $this->mapper; - $comment = $mapper->fetch($mapper->Comments(filter: 8)); - $this->assertInstanceOf(Comments::class, $comment); - $comment->Text = 'HeyHey'; - $mapper->persist($comment, $mapper->Comments()); - $mapper->flush(); - - $updated = $mapper->fetch($mapper->Comments(filter: 8)); - $this->assertInstanceOf(Comments::class, $updated); - $this->assertEquals('HeyHey', $updated->Text); - } - - public function testPersistingNewEntityTyped(): void - { - $mapper = $this->mapper; - $comment = new Comments(); - $comment->Text = 'HeyHey'; - $mapper->persist($comment, $mapper->Comments()); - $mapper->flush(); - - $this->assertGreaterThan(0, $comment->CommentID); - $allComments = $mapper->fetchAll($mapper->Comments()); - $this->assertCount(3, $allComments); + $entity = $this->mapper->fetch($this->mapper->Posts()); + $this->assertIsObject($entity); + $this->assertEquals('Post Title', $this->mapper->entityFactory->get($entity, 'Title')); } } diff --git a/tests/Styles/Plural/PluralIntegrationTest.php b/tests/Styles/Plural/PluralIntegrationTest.php index 1e656d5..e434164 100644 --- a/tests/Styles/Plural/PluralIntegrationTest.php +++ b/tests/Styles/Plural/PluralIntegrationTest.php @@ -5,6 +5,7 @@ namespace Respect\Data\Styles\Plural; use PHPUnit\Framework\Attributes\CoversClass; +use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\TestCase; use Respect\Data\EntityFactory; use Respect\Data\Hydrators\Nested; @@ -45,57 +46,11 @@ protected function setUp(): void ]); } - public function testFetchingEntityTyped(): void + #[Test] + public function fetchAndPersistRoundTrip(): void { - $mapper = $this->mapper; - $comment = $mapper->fetch($mapper->comments(filter: 8)); - $this->assertInstanceOf(Comment::class, $comment); - } - - public function testFetchingAllEntityTyped(): void - { - $mapper = $this->mapper; - $comment = $mapper->fetchAll($mapper->comments()); - $this->assertInstanceOf(Comment::class, $comment[1]); - - $categories = $mapper->fetch($mapper->posts_categories([$mapper->categories()])); - $this->assertInstanceOf(PostCategory::class, $categories); - $this->assertInstanceOf(Category::class, $categories->category); - } - - public function testFetchingAllEntityTypedNested(): void - { - $mapper = $this->mapper; - $comment = $mapper->fetchAll($mapper->comments([$mapper->posts([$mapper->authors()])])); - $this->assertInstanceOf(Comment::class, $comment[0]); - $this->assertInstanceOf(Post::class, $comment[0]->post); - $this->assertInstanceOf(Author::class, $comment[0]->post->author); - } - - public function testPersistingEntityTyped(): void - { - $mapper = $this->mapper; - $comment = $mapper->fetch($mapper->comments(filter: 8)); - $this->assertInstanceOf(Comment::class, $comment); - $comment->text = 'HeyHey'; - $mapper->persist($comment, $mapper->comments()); - $mapper->flush(); - - $updated = $mapper->fetch($mapper->comments(filter: 8)); - $this->assertInstanceOf(Comment::class, $updated); - $this->assertEquals('HeyHey', $updated->text); - } - - public function testPersistingNewEntityTyped(): void - { - $mapper = $this->mapper; - $comment = new Comment(); - $comment->text = 'HeyHey'; - $mapper->persist($comment, $mapper->comments()); - $mapper->flush(); - - $this->assertGreaterThan(0, $comment->id); - $allComments = $mapper->fetchAll($mapper->comments()); - $this->assertCount(3, $allComments); + $entity = $this->mapper->fetch($this->mapper->posts()); + $this->assertIsObject($entity); + $this->assertEquals('Post Title', $this->mapper->entityFactory->get($entity, 'title')); } } diff --git a/tests/Styles/Sakila/SakilaIntegrationTest.php b/tests/Styles/Sakila/SakilaIntegrationTest.php index 37ae49f..ab99e61 100644 --- a/tests/Styles/Sakila/SakilaIntegrationTest.php +++ b/tests/Styles/Sakila/SakilaIntegrationTest.php @@ -5,6 +5,7 @@ namespace Respect\Data\Styles\Sakila; use PHPUnit\Framework\Attributes\CoversClass; +use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\TestCase; use Respect\Data\EntityFactory; use Respect\Data\Hydrators\Nested; @@ -45,57 +46,11 @@ protected function setUp(): void ]); } - public function testFetchingEntityTyped(): void + #[Test] + public function fetchAndPersistRoundTrip(): void { - $mapper = $this->mapper; - $comment = $mapper->fetch($mapper->comment(filter: 8)); - $this->assertInstanceOf(Comment::class, $comment); - } - - public function testFetchingAllEntityTyped(): void - { - $mapper = $this->mapper; - $comment = $mapper->fetchAll($mapper->comment()); - $this->assertInstanceOf(Comment::class, $comment[1]); - - $categories = $mapper->fetch($mapper->post_category([$mapper->category()])); - $this->assertInstanceOf(PostCategory::class, $categories); - $this->assertInstanceOf(Category::class, $categories->category); - } - - public function testFetchingAllEntityTypedNested(): void - { - $mapper = $this->mapper; - $comment = $mapper->fetchAll($mapper->comment([$mapper->post([$mapper->author()])])); - $this->assertInstanceOf(Comment::class, $comment[0]); - $this->assertInstanceOf(Post::class, $comment[0]->post); - $this->assertInstanceOf(Author::class, $comment[0]->post->author); - } - - public function testPersistingEntityTyped(): void - { - $mapper = $this->mapper; - $comment = $mapper->fetch($mapper->comment(filter: 8)); - $this->assertInstanceOf(Comment::class, $comment); - $comment->text = 'HeyHey'; - $mapper->persist($comment, $mapper->comment()); - $mapper->flush(); - - $updated = $mapper->fetch($mapper->comment(filter: 8)); - $this->assertInstanceOf(Comment::class, $updated); - $this->assertEquals('HeyHey', $updated->text); - } - - public function testPersistingNewEntityTyped(): void - { - $mapper = $this->mapper; - $comment = new Comment(); - $comment->text = 'HeyHey'; - $mapper->persist($comment, $mapper->comment()); - $mapper->flush(); - - $this->assertGreaterThan(0, $comment->commentId); - $allComments = $mapper->fetchAll($mapper->comment()); - $this->assertCount(3, $allComments); + $entity = $this->mapper->fetch($this->mapper->post()); + $this->assertIsObject($entity); + $this->assertEquals('Post Title', $this->mapper->entityFactory->get($entity, 'title')); } }