Skip to content

Commit 839fc90

Browse files
committed
Enhance with method to support multiple input formats.
Added support for cloning `Data` instances using JSON, `stdClass`, and other normalized formats. Updated tests and documentation to reflect the changes, and ensured the method throws an exception when no parameters are passed.
1 parent 7ff39e6 commit 839fc90

File tree

4 files changed

+79
-3
lines changed

4 files changed

+79
-3
lines changed

docs/CloneableData.md

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,3 +89,31 @@ $janeDoe = $johnDoe->with(firstName: 'Jane');
8989

9090
$janeDoe->fullName; // 'Jane Doe'
9191
```
92+
93+
Normalizers
94+
-
95+
96+
When cloning a `Data` object, normalizers that are typically used when hydrating a `Data` object
97+
using `from` method are also used.
98+
99+
This will allow the ability to pass `json` data, `ArrayAccess` or `stdClass` objects for example to the `with` method.
100+
If a custom normalizer is implemented for the `Data` class, it can be used as well.
101+
102+
```php
103+
$johnDoe = new PersonDaa('John', 'Doe');
104+
105+
$janeDoe = $johnDoe->with('{"firstName": "Jane"}');
106+
107+
$janeDoe->fullName; // 'Jane Doe'
108+
```
109+
110+
Using an `stdClass` object:
111+
112+
```php
113+
$object = new stdClass();
114+
$object->firstName = 'Jake';
115+
116+
$jakeDoe = $janeDoe->with($object);
117+
118+
$jakeDoe->fullName; // 'Jake Doe'
119+
```

src/Concerns/CloneableData.php

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,12 @@ trait CloneableData
1818
public function with(mixed ...$args): static
1919
{
2020
try {
21-
$value = static::normalizeValue($args, static::class);
21+
if (empty($args)) {
22+
throw DataCreationException::invalidParamsPassed(static::class);
23+
}
24+
25+
$value = static::normalizeValue($args, static::class)
26+
?: static::normalizeValue($args[0], static::class);
2227

2328
if ($value === false) {
2429
throw DataCreationException::invalidParamsPassed(static::class);

tests/Unit/Concerns/CloneableDataTest.php

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,19 @@ public function __construct(
7777
$object->with(lastName: 'Doe');
7878
}
7979

80+
/**
81+
* @throws Throwable
82+
*/
83+
#[Test]
84+
public function will_throw_an_exception_if_no_param_is_passed(): void
85+
{
86+
$person = new PersonData(firstName: 'John', lastName: 'Doe');
87+
88+
self::expectException(DataCreationException::class);
89+
90+
$person->with();
91+
}
92+
8093
/**
8194
* @param array<string, mixed> $args
8295
* @param array<string, mixed> $expectedProperties

tests/Unit/Documentation/CloneableDataExampleTest.php

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
use PHPUnit\Framework\Attributes\UsesClass;
99
use PHPUnit\Framework\Attributes\Test;
1010
use Nuxtifyts\PhpDto\Tests\Dummies\Enums\Todo\Status;
11+
use stdClass;
1112
use DateTimeImmutable;
1213
use Throwable;
1314

@@ -19,7 +20,7 @@ final class CloneableDataExampleTest extends UnitCase
1920
* @throws Throwable
2021
*/
2122
#[Test]
22-
public function test_it_can_clone_data_as_example_in_documentation(): void
23+
public function it_can_clone_data_as_example_in_documentation(): void
2324
{
2425
$emptyTodo = TodoData::empty();
2526

@@ -56,7 +57,7 @@ public function test_it_can_clone_data_as_example_in_documentation(): void
5657
* @throws Throwable
5758
*/
5859
#[Test]
59-
public function test_is_can_clone_dts_with_computed_properties(): void
60+
public function it_can_clone_data_instances_with_computed_properties(): void
6061
{
6162
$person = new PersonData(firstName: 'John', lastName: 'Doe');
6263

@@ -66,4 +67,33 @@ public function test_is_can_clone_dts_with_computed_properties(): void
6667

6768
self::assertEquals('Jane Doe', $personWithFirstName->fullName);
6869
}
70+
71+
/**
72+
* @throws Throwable
73+
*/
74+
#[Test]
75+
public function it_can_clone_data_instances_by_passing_json(): void
76+
{
77+
$person = new PersonData(firstName: 'John', lastName: 'Doe');
78+
79+
$personWithFirstName = $person->with('{"firstName": "Jane"}');
80+
81+
self::assertEquals('Jane Doe', $personWithFirstName->fullName);
82+
}
83+
84+
/**
85+
* @throws Throwable
86+
*/
87+
#[Test]
88+
public function it_can_clone_data_instances_by_passing_std_object(): void
89+
{
90+
$person = new PersonData(firstName: 'John', lastName: 'Doe');
91+
92+
$object = new stdClass();
93+
$object->firstName = 'Jane';
94+
95+
$personWithFirstName = $person->with($object);
96+
97+
self::assertEquals('Jane Doe', $personWithFirstName->fullName);
98+
}
6999
}

0 commit comments

Comments
 (0)