From 415eff5db42b6aa951eba543e6f215e560b65ff1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rub=C3=A9n=20Robles?= Date: Fri, 17 Mar 2023 12:32:07 +0100 Subject: [PATCH] fix filled & tests --- src/DataTransferObject.php | 19 ++++++++++++++++--- tests/Fixtures/CreatePostData.php | 8 ++++++-- tests/Unit/DataTransferObjectTest.php | 5 ++++- 3 files changed, 26 insertions(+), 6 deletions(-) diff --git a/src/DataTransferObject.php b/src/DataTransferObject.php index 4359cff..fe7acfe 100644 --- a/src/DataTransferObject.php +++ b/src/DataTransferObject.php @@ -2,6 +2,7 @@ namespace OpenSoutheners\LaravelDto; +use Exception; use Illuminate\Foundation\Http\FormRequest; use Illuminate\Http\Request; use Illuminate\Support\Str; @@ -100,8 +101,12 @@ public function filled(string $property): bool $reflection = new \ReflectionClass($this); - $reflectionProperty = $reflection->getProperty($classProperty); - + $reflectionProperty = match (true) { + $reflection->hasProperty($property) => $reflection->getProperty($property), + $reflection->hasProperty($classProperty) => $reflection->getProperty($classProperty), + default => throw new Exception("Properties '{$property}' or '{$classProperty}' doesn't exists on class instance."), + }; + $defaultValue = $reflectionProperty->getDefaultValue(); $propertyValue = $reflectionProperty->getValue($this); @@ -111,11 +116,19 @@ public function filled(string $property): bool return function_exists('filled') && filled($propertyValue); } + /** + * Not filled when DTO property's default value is set to null while none is passed through + */ if (! $propertyValue && $reflectionPropertyType->allowsNull() && $defaultValue === null) { return false; } - if ($reflectionProperty->getValue($this) === $defaultValue) { + /** + * Not filled when property isn't promoted and does have a default value matching value sent + * + * @see problem with promoted properties and hasDefaultValue/getDefaultValue https://bugs.php.net/bug.php?id=81386 + */ + if (! $reflectionProperty->isPromoted() && $reflectionProperty->hasDefaultValue() && $propertyValue === $defaultValue) { return false; } diff --git a/tests/Fixtures/CreatePostData.php b/tests/Fixtures/CreatePostData.php index bffe578..8c9ecf3 100644 --- a/tests/Fixtures/CreatePostData.php +++ b/tests/Fixtures/CreatePostData.php @@ -6,14 +6,18 @@ class CreatePostData extends DataTransferObject { + public mixed $authorEmail = 'me@d8vjork.com'; + public function __construct( public string $title, public array|null $tags, public PostStatus $postStatus, public Post|null $post = null, - public array|string|null $country = null + public array|string|null $country = null, + public $description = '', + $authorEmail = null ) { - // + $this->authorEmail = $authorEmail; } /** diff --git a/tests/Unit/DataTransferObjectTest.php b/tests/Unit/DataTransferObjectTest.php index 36b8179..d3a4dca 100644 --- a/tests/Unit/DataTransferObjectTest.php +++ b/tests/Unit/DataTransferObjectTest.php @@ -36,17 +36,20 @@ public function testDataTransferObjectFromArrayDelimitedLists() $this->assertIsString($data->country); } - public function testDataTransferObjectFilled() + public function testDataTransferObjectFilledViaClassProperties() { $data = CreatePostData::fromArray([ 'title' => 'Hello world', 'tags' => '', 'post_status' => PostStatus::Published->value, + 'author_email' => 'me@d8vjork.com', ]); $this->assertTrue($data->filled('tags')); $this->assertTrue($data->filled('postStatus')); $this->assertFalse($data->filled('post')); + $this->assertFalse($data->filled('description')); + $this->assertFalse($data->filled('author_email')); } public function testDataTransferObjectWithDefaults()