Skip to content

Commit 3023390

Browse files
authored
Merge pull request #39 from rekalogika:feat/null-array-source
feat: null to `Traversable` or `ArrayAccess` is now handled & returns empty.
2 parents b74e2ad + f43f5e1 commit 3023390

9 files changed

+115
-0
lines changed

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
* feat(`PresetMappingFactory`): Add `fromObjectCache()` and `fromObjectCacheReversed()`.
2525
* chore: Simplify remembering mapper.
2626
* refactor: Deprecate serializer context.
27+
* feat: null to `Traversable` or `ArrayAccess` is now handled & returns empty.
2728

2829
## 1.0.0
2930

psalm.xml

+2
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,8 @@
5252
<file name="tests/Fixtures/UninitializedProperty/ObjectWithUninitializedProperty.php" />
5353
<file name="tests/Fixtures/UninitializedPropertyDto/FinalObjectWithUninitializedPropertyDto.php" />
5454
<file name="tests/Fixtures/UninitializedPropertyDto/ObjectWithUninitializedPropertyDto.php" />
55+
<file name="tests/Fixtures/ArrayLikeDto/ObjectWithNotNullArrayAccessPropertyDto.php" />
56+
<file name="tests/Fixtures/ArrayLikeDto/ObjectWithNotNullTraversablePropertyDto.php" />
5557
</errorLevel>
5658
</MissingConstructor>
5759
<ArgumentTypeCoercion>

src/Transformer/Implementation/TraversableToArrayAccessTransformer.php

+5
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,10 @@ public function transform(
5151
?Type $targetType,
5252
Context $context
5353
): mixed {
54+
if ($source === null) {
55+
$source = [];
56+
}
57+
5458
if ($targetType === null) {
5559
throw new InvalidArgumentException('Target type must not be null.', context: $context);
5660
}
@@ -221,6 +225,7 @@ public function getSupportedTransformation(): iterable
221225
$sourceTypes = [
222226
TypeFactory::objectOfClass(\Traversable::class),
223227
TypeFactory::array(),
228+
TypeFactory::null(),
224229
];
225230

226231
$targetTypes = [

src/Transformer/Implementation/TraversableToTraversableTransformer.php

+5
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,10 @@ public function transform(
4444
?Type $targetType,
4545
Context $context
4646
): mixed {
47+
if ($source === null) {
48+
$source = [];
49+
}
50+
4751
if ($targetType === null) {
4852
throw new InvalidArgumentException('Target type must not be null.', context: $context);
4953
}
@@ -103,6 +107,7 @@ public function getSupportedTransformation(): iterable
103107
$sourceTypes = [
104108
TypeFactory::objectOfClass(\Traversable::class),
105109
TypeFactory::array(),
110+
TypeFactory::null(),
106111
];
107112

108113
$targetTypes = [
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
/*
6+
* This file is part of rekalogika/mapper package.
7+
*
8+
* (c) Priyadi Iman Nurcahyo <https://rekalogika.dev>
9+
*
10+
* For the full copyright and license information, please view the LICENSE file
11+
* that was distributed with this source code.
12+
*/
13+
14+
namespace Rekalogika\Mapper\Tests\Fixtures\ArrayLike;
15+
16+
use Doctrine\Common\Collections\Collection;
17+
use Rekalogika\Mapper\Tests\Fixtures\Scalar\ObjectWithScalarProperties;
18+
19+
class ObjectWithNullCollectionProperty
20+
{
21+
/**
22+
* @var null|Collection<int,ObjectWithScalarProperties>
23+
*/
24+
public ?Collection $property = null;
25+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
/*
6+
* This file is part of rekalogika/mapper package.
7+
*
8+
* (c) Priyadi Iman Nurcahyo <https://rekalogika.dev>
9+
*
10+
* For the full copyright and license information, please view the LICENSE file
11+
* that was distributed with this source code.
12+
*/
13+
14+
namespace Rekalogika\Mapper\Tests\Fixtures\ArrayLikeDto;
15+
16+
use Rekalogika\Mapper\Tests\Fixtures\ScalarDto\ObjectWithScalarPropertiesDto;
17+
18+
class ObjectWithNotNullArrayAccessPropertyDto
19+
{
20+
/**
21+
* @var \ArrayAccess<int,ObjectWithScalarPropertiesDto>
22+
*/
23+
public \ArrayAccess $property;
24+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
/*
6+
* This file is part of rekalogika/mapper package.
7+
*
8+
* (c) Priyadi Iman Nurcahyo <https://rekalogika.dev>
9+
*
10+
* For the full copyright and license information, please view the LICENSE file
11+
* that was distributed with this source code.
12+
*/
13+
14+
namespace Rekalogika\Mapper\Tests\Fixtures\ArrayLikeDto;
15+
16+
use Rekalogika\Mapper\Tests\Fixtures\ScalarDto\ObjectWithScalarPropertiesDto;
17+
18+
class ObjectWithNotNullTraversablePropertyDto
19+
{
20+
/**
21+
* @var \Traversable<int,ObjectWithScalarPropertiesDto>
22+
*/
23+
public \Traversable $property;
24+
}

tests/IntegrationTest/TraversableToArrayAccessMappingTest.php

+16
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
use Rekalogika\Mapper\Tests\Fixtures\ArrayLike\ObjectWithArrayProperty;
2121
use Rekalogika\Mapper\Tests\Fixtures\ArrayLike\ObjectWithArrayPropertyWithStringKey;
2222
use Rekalogika\Mapper\Tests\Fixtures\ArrayLike\ObjectWithCollectionProperty;
23+
use Rekalogika\Mapper\Tests\Fixtures\ArrayLike\ObjectWithNullCollectionProperty;
2324
use Rekalogika\Mapper\Tests\Fixtures\ArrayLike\ObjectWithSplObjectStorageProperty;
2425
use Rekalogika\Mapper\Tests\Fixtures\ArrayLike\ObjectWithTraversableProperties;
2526
use Rekalogika\Mapper\Tests\Fixtures\ArrayLikeDto\ObjectWithArrayAccessPropertyDto;
@@ -30,6 +31,7 @@
3031
use Rekalogika\Mapper\Tests\Fixtures\ArrayLikeDto\ObjectWithArrayPropertyWithCompatibleHintDto;
3132
use Rekalogika\Mapper\Tests\Fixtures\ArrayLikeDto\ObjectWithArrayPropertyWithoutTypeHintDto;
3233
use Rekalogika\Mapper\Tests\Fixtures\ArrayLikeDto\ObjectWithCollectionPropertyDto;
34+
use Rekalogika\Mapper\Tests\Fixtures\ArrayLikeDto\ObjectWithNotNullArrayAccessPropertyDto;
3335
use Rekalogika\Mapper\Tests\Fixtures\Scalar\ObjectWithScalarProperties;
3436
use Rekalogika\Mapper\Tests\Fixtures\ScalarDto\ObjectWithScalarPropertiesDto;
3537
use Rekalogika\Mapper\Transformer\Model\HashTable;
@@ -177,6 +179,20 @@ public function testCollectionToArrayAccessDto(): void
177179
$this->assertEquals(1.1, $result->property[1]?->d);
178180
}
179181

182+
public function testNullToNotNullArrayAccessDto(): void
183+
{
184+
$source = new ObjectWithNullCollectionProperty();
185+
186+
$result = $this->mapper->map($source, ObjectWithNotNullArrayAccessPropertyDto::class);
187+
188+
$this->assertInstanceOf(ObjectWithNotNullArrayAccessPropertyDto::class, $result);
189+
190+
$property = $result->property;
191+
$this->assertInstanceOf(LazyArray::class, $property);
192+
// @phpstan-ignore-next-line
193+
$this->assertInstanceOf(\ArrayAccess::class, $property);
194+
}
195+
180196
public function testArrayToArrayInterfaceDto(): void
181197
{
182198
$source = new ObjectWithArrayProperty();

tests/IntegrationTest/TraversableToTraversableMappingTest.php

+13
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,9 @@
1717
use Rekalogika\Mapper\Tests\Fixtures\ArrayLike\ObjectWithArrayProperty;
1818
use Rekalogika\Mapper\Tests\Fixtures\ArrayLike\ObjectWithLazyDoctrineCollectionProperty;
1919
use Rekalogika\Mapper\Tests\Fixtures\ArrayLike\ObjectWithLazyDoctrineCollectionWithPresetCountableProperty;
20+
use Rekalogika\Mapper\Tests\Fixtures\ArrayLike\ObjectWithNullCollectionProperty;
2021
use Rekalogika\Mapper\Tests\Fixtures\ArrayLike\ObjectWithTraversableProperties;
22+
use Rekalogika\Mapper\Tests\Fixtures\ArrayLikeDto\ObjectWithNotNullTraversablePropertyDto;
2123
use Rekalogika\Mapper\Tests\Fixtures\ArrayLikeDto\ObjectWithTraversablePropertyDto;
2224
use Rekalogika\Mapper\Tests\Fixtures\ArrayLikeDto\ObjectWithTraversablePropertyWithoutTypeHintDto;
2325
use Rekalogika\Mapper\Tests\Fixtures\Scalar\ObjectWithScalarProperties;
@@ -121,4 +123,15 @@ public function testArrayToTraversableWithoutTypehint(): void
121123
$this->assertEquals(1.1, $item->d);
122124
}
123125
}
126+
127+
public function testNullToNotNullTraversableDto(): void
128+
{
129+
$source = new ObjectWithNullCollectionProperty();
130+
$result = $this->mapper->map($source, ObjectWithNotNullTraversablePropertyDto::class);
131+
132+
$this->assertInstanceOf(\Traversable::class, $result->property);
133+
134+
$arrayResult = iterator_to_array($result->property);
135+
$this->assertEmpty($arrayResult);
136+
}
124137
}

0 commit comments

Comments
 (0)