From 6a1863283b47afe20bb43f942544a8a7fd615460 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20Vo=C5=99=C3=AD=C5=A1ek?= Date: Sun, 29 May 2022 20:13:04 +0200 Subject: [PATCH] Return null when traversing entity 1:1 not found --- src/Data/HintableModelTrait.php | 11 ++++++ tests/Data/HintableModelArrayTest.php | 50 +++++++++++++++++++++++---- 2 files changed, 55 insertions(+), 6 deletions(-) diff --git a/src/Data/HintableModelTrait.php b/src/Data/HintableModelTrait.php index a80ec61..f2f5c41 100644 --- a/src/Data/HintableModelTrait.php +++ b/src/Data/HintableModelTrait.php @@ -136,6 +136,17 @@ public function &__get(string $name) /** @var Model */ $model = $this->ref($hProp->fieldName); + // HasOne/ContainsOne::ref() method returns an unloaded entity when traversing entity not found + if ($model->isEntity()) { + $this->assertIsEntity(); + + if (!$model->isLoaded()) { + $res = null; + + return $res; + } + } + if ($hProp->refType === HintablePropertyDef::REF_TYPE_ONE) { // TODO this requires checking all parents! // // ensure no more than one record can load diff --git a/tests/Data/HintableModelArrayTest.php b/tests/Data/HintableModelArrayTest.php index afe97fa..baaf26c 100644 --- a/tests/Data/HintableModelArrayTest.php +++ b/tests/Data/HintableModelArrayTest.php @@ -7,6 +7,7 @@ use Atk4\Core\Phpunit\TestCase; use Atk4\Data\Exception; use Atk4\Data\Persistence; +use Mvorisek\Atk4\Hintable\Phpstan\PhpstanUtil; /** * @coversDefaultClass \Mvorisek\Atk4\Hintable\Data\HintableModelTrait @@ -33,7 +34,9 @@ public function testFieldName(): void public function testFieldNameUndeclaredException(): void { $model = new Model\Simple(); + $this->expectException(Exception::class); + $this->expectExceptionMessage('Hintable property is not defined'); $model->fieldName()->undeclared; // @phpstan-ignore-line } @@ -73,6 +76,11 @@ protected function createDatabaseForRefTest(): Persistence $standard12 = (clone $standardTemplate) ->set(Model\Standard::hinting()->fieldName()->simpleOneId, $simple3->id) ->save(); + /* 13 - null simpleOneId */ (clone $standardTemplate) + ->save(); + /* 14 - invalid simpleOneId */ (clone $standardTemplate) + ->set(Model\Standard::hinting()->fieldName()->simpleOneId, 999) + ->save(); $simple1 ->set(Model\Simple::hinting()->fieldName()->refId, $standard11->id) @@ -135,27 +143,57 @@ public function testRefMany(): void }, iterator_to_array($model->load(12)->simpleMany))); } - public function testRefManyIsNotEntity(): void + public function testRefOneLoadOneException(): void { $db = $this->createDatabaseForRefTest(); $model = new Model\Standard($db); - $this->assertFalse($model->load(12)->simpleMany->isEntity()); + $modelSimple = $model->simpleOne; + + $this->expectException(Exception::class); + $this->expectExceptionMessage('more than one record can be loaded'); + $modelSimple->loadOne(); } - public function testRefOneLoadOneException(): void + public function testRefManyLoadOneException(): void { $db = $this->createDatabaseForRefTest(); $model = new Model\Standard($db); + $modelSimple = $model->simpleMany; + $this->expectException(Exception::class); - $model->simpleOne->loadOne(); + $this->expectExceptionMessage('more than one record can be loaded'); + $modelSimple->loadOne(); } - public function testRefManyLoadOneException(): void + public function testRefOneTraverseNullException(): void + { + $db = $this->createDatabaseForRefTest(); + $model = new Model\Standard($db); + $entity13 = $model->load(13); + + $this->expectException(Exception::class); + $this->expectExceptionMessage('Unable to traverse on null value'); + PhpstanUtil::ignoreUnusedVariable($entity13->simpleOne); + } + + public function testRefOneTraverseInvalidException(): void + { + $db = $this->createDatabaseForRefTest(); + $model = new Model\Standard($db); + $entity14 = $model->load(14); + + $this->assertNull($entity14->simpleOne); // TODO should throw + } + + public function testRefManyTraverseNullException(): void { $db = $this->createDatabaseForRefTest(); $model = new Model\Standard($db); + $entityNull = $model->createEntity(); + $this->expectException(Exception::class); - $model->simpleMany->loadOne(); + $this->expectExceptionMessage('Unable to traverse on null value'); + PhpstanUtil::ignoreUnusedVariable($entityNull->simpleMany); } public function testPhpstanModelIteratorAggregate(): void