Skip to content

Commit f831a85

Browse files
authored
Merge pull request #5 from emulgeator/null-value-handling
Handling case when a class typed property receives a null value
2 parents 05ca5bf + 4a6d854 commit f831a85

File tree

7 files changed

+106
-5
lines changed

7 files changed

+106
-5
lines changed

.phpunit.result.cache

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
C:37:"PHPUnit\Runner\DefaultTestResultCache":1847:{a:2:{s:7:"defects";a:1:{s:117:"Emul\ArrayToClassMapper\Test\Unit\MapperTest::testMapWhenClassDocBlockTypedPropertyGivenWithNullValue_shouldSetToNull";i:4;}s:5:"times";a:13:{s:117:"Emul\ArrayToClassMapper\Test\Unit\MapperTest::testMapWhenClassDocBlockTypedPropertyGivenWithNullValue_shouldSetToNull";d:0.006;s:76:"Emul\ArrayToClassMapper\Test\Unit\MapperTest::testMapWhenNullGiven_shouldSet";d:0.028;s:93:"Emul\ArrayToClassMapper\Test\Unit\MapperTest::testMapWhenBuiltInTypedPropertyGiven_shouldCast";d:0.005;s:114:"Emul\ArrayToClassMapper\Test\Unit\MapperTest::testMapWhenArrayTypedPropertyGivenWithoutDocBlock_shouldCastElements";d:0.006;s:123:"Emul\ArrayToClassMapper\Test\Unit\MapperTest::testMapWhenArrayTypedPropertyGivenWithBuiltInDockBlockType_shouldCastElements";d:0.006;s:133:"Emul\ArrayToClassMapper\Test\Unit\MapperTest::testMapWhenArrayTypedPropertyGivenWithCustomDockBlockType_shouldMapElementsToCustomType";d:0.01;s:109:"Emul\ArrayToClassMapper\Test\Unit\MapperTest::testMapWhenClassTypedPropertyGivenWithNullValue_shouldSetToNull";d:0.006;s:90:"Emul\ArrayToClassMapper\Test\Unit\MapperTest::testMapWhenClassTypedPropertyGiven_shouldMap";d:0.006;s:159:"Emul\ArrayToClassMapper\Test\Unit\MapperTest::testMapWhenArrayTypedPropertyGivenWithCustomDockBlockTypeAndCustomMapperProvided_shouldMapElementsWithGivenMapper";d:0.022;s:94:"Emul\ArrayToClassMapper\Test\Unit\MapperTest::testMapWhenTypelessPropertyGiven_shouldJustStore";d:0.005;s:115:"Emul\ArrayToClassMapper\Test\Unit\MapperTest::testMapWhenScalarDocBlockTypePropertyGiven_shouldCastToDocumentedType";d:0.005;s:114:"Emul\ArrayToClassMapper\Test\Unit\MapperTest::testMapWhenCustomDocBlockTypedPropertyGiven_shouldMapWithGivenMapper";d:0.006;s:119:"Emul\ArrayToClassMapper\Test\Unit\MapperTest::testMapWhenCustomDocBlockTypedArrayPropertyGiven_shouldMapWithGivenMapper";d:0.008;}}}

src/Mapper.php

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ public function map(array $input, string $className)
6666
$property->setValue($object, $value);
6767
}
6868
} else {
69-
$property->setValue($object, $this->castCustom($value, $type->getName()));
69+
$this->setCustomValue($object, $property, $type->getName(), $value);
7070
}
7171
} else {
7272
if (empty($docBlockType)) {
@@ -80,7 +80,7 @@ public function map(array $input, string $className)
8080
$property->setValue($object, $value);
8181
}
8282
} else {
83-
$property->setValue($object, $this->castCustom($value, $docBlockType->getName()));
83+
$this->setCustomValue($object, $property, $docBlockType->getName(), $value);
8484
}
8585
}
8686
}
@@ -90,6 +90,19 @@ public function map(array $input, string $className)
9090
return $object;
9191
}
9292

93+
private function setCustomValue($object, \ReflectionProperty $property, string $typeName, $value): void
94+
{
95+
if (
96+
$value === null
97+
&& empty($this->getCustomMapper($typeName))
98+
) {
99+
$property->setValue($object, null);
100+
}
101+
else {
102+
$property->setValue($object, $this->castCustom($value, $typeName));
103+
}
104+
}
105+
93106
private function castArray(array $array, DocBlockType $docblockType): array
94107
{
95108
$castedArray = [];

test/Unit/MapperTest.php

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88
use Emul\ArrayToClassMapper\DocBlock\DocBlockParser;
99
use Emul\ArrayToClassMapper\DocBlock\Entity\DocBlockType;
1010
use Emul\ArrayToClassMapper\Test\Unit\Stub\ClassDocBlockTypedArrayStub;
11+
use Emul\ArrayToClassMapper\Test\Unit\Stub\ClassDocBlockTypedStub;
12+
use Emul\ArrayToClassMapper\Test\Unit\Stub\ClassTypedStub;
1113
use Emul\ArrayToClassMapper\Test\Unit\Stub\CustomDocBlockTypedArrayStub;
1214
use Emul\ArrayToClassMapper\Test\Unit\Stub\CustomDocBlockTypedStub;
1315
use Emul\ArrayToClassMapper\Test\Unit\Stub\CustomStub;
@@ -29,6 +31,20 @@ protected function setUp(): void
2931
$this->docBlockParser = \Mockery::mock(DocBlockParser::class);
3032
}
3133

34+
public function testMapWhenNullGiven_shouldSet()
35+
{
36+
$mapper = $this->getMapper();
37+
38+
$this->expectTypeRetrievedFromDocBlock('', null);
39+
40+
$input = ['int' => null];
41+
42+
/** @var ScalarTypedStub $result */
43+
$result = $mapper->map($input, ScalarTypedStub::class);
44+
45+
$this->assertNull($result->getInt());
46+
}
47+
3248
public function testMapWhenBuiltInTypedPropertyGiven_shouldCast()
3349
{
3450
$mapper = $this->getMapper();
@@ -101,6 +117,48 @@ public function testMapWhenArrayTypedPropertyGivenWithCustomDockBlockType_should
101117
$this->assertSame(2, $mappedArray[1]->getInt());
102118
}
103119

120+
public function testMapWhenClassTypedPropertyGivenWithNullValue_shouldSetToNull()
121+
{
122+
$mapper = $this->getMapper();
123+
124+
$this->expectTypeRetrievedFromDocBlock('', null);
125+
126+
$input = ['object' => null];
127+
128+
/** @var ClassTypedStub $result */
129+
$result = $mapper->map($input, ClassTypedStub::class);
130+
131+
$this->assertNull($result->getObject());
132+
}
133+
134+
public function testMapWhenClassDocBlockTypedPropertyGivenWithNullValue_shouldSetToNull()
135+
{
136+
$mapper = $this->getMapper();
137+
138+
$this->expectTypeRetrievedFromDocBlock('/** @var ScalarTypedStub|null */', new DocBlockType('ScalarTypedStub', true, false, true));
139+
140+
$input = ['object' => null];
141+
142+
/** @var ClassDocBlockTypedStub $result */
143+
$result = $mapper->map($input, ClassDocBlockTypedStub::class);
144+
145+
$this->assertNull($result->getObject());
146+
}
147+
148+
public function testMapWhenClassTypedPropertyGiven_shouldMap()
149+
{
150+
$mapper = $this->getMapper();
151+
152+
$this->expectTypeRetrievedFromDocBlock('', null);
153+
154+
$input = ['object' => ['int' => 1]];
155+
156+
/** @var ClassTypedStub $result */
157+
$result = $mapper->map($input, ClassTypedStub::class);
158+
159+
$this->assertSame(1, $result->getObject()->getInt());
160+
}
161+
104162
public function testMapWhenArrayTypedPropertyGivenWithCustomDockBlockTypeAndCustomMapperProvided_shouldMapElementsWithGivenMapper()
105163
{
106164
$currentTime = '2020-01-01 01:01:01';
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<?php
2+
declare(strict_types=1);
3+
4+
namespace Emul\ArrayToClassMapper\Test\Unit\Stub;
5+
6+
class ClassDocBlockTypedStub
7+
{
8+
/** @var ScalarTypedStub|null */
9+
private $object;
10+
11+
public function getObject(): ?ScalarTypedStub
12+
{
13+
return $this->object;
14+
}
15+
}

test/Unit/Stub/ClassTypedStub.php

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<?php
2+
declare(strict_types=1);
3+
4+
namespace Emul\ArrayToClassMapper\Test\Unit\Stub;
5+
6+
class ClassTypedStub
7+
{
8+
private ?ScalarTypedStub $object;
9+
10+
public function getObject(): ?ScalarTypedStub
11+
{
12+
return $this->object;
13+
}
14+
}

test/Unit/Stub/CustomTypedStub.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,9 @@
77

88
class CustomTypedStub
99
{
10-
private Carbon $currentTime;
10+
private ?Carbon $currentTime;
1111

12-
public function getCurrentTime(): Carbon
12+
public function getCurrentTime(): ?Carbon
1313
{
1414
return $this->currentTime;
1515
}

test/Unit/Stub/ScalarTypedStub.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ public function __construct()
1212
throw new \Exception('Constructor called');
1313
}
1414

15-
public function getInt(): int
15+
public function getInt(): ?int
1616
{
1717
return $this->int;
1818
}

0 commit comments

Comments
 (0)