Skip to content

Commit 60c3d33

Browse files
l-xusox
authored andcommitted
Add strictness about keys in hydration
1 parent b1f65e0 commit 60c3d33

File tree

6 files changed

+79
-10
lines changed

6 files changed

+79
-10
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
/vendor/
22
/build/
33
composer.lock
4+
clover.xml

.travis.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,6 @@ script:
88

99
install:
1010
- travis_retry composer install --no-interaction --prefer-source
11+
12+
after_success:
13+
- bash <(curl -s https://codecov.io/bash)

phpunit.xml.dist

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,4 +18,8 @@
1818
<directory suffix=".php">src/</directory>
1919
</whitelist>
2020
</filter>
21+
22+
<logging>
23+
<log type="coverage-clover" target="clover.xml"/>
24+
</logging>
2125
</phpunit>

src/Scn/Hydrator/Hydrator.php

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010
final class Hydrator implements HydratorInterface
1111
{
1212

13+
public const NO_STRICT_KEYS = 1;
14+
1315
private function invoke(callable $callback, object $entity, ...$args)
1416
{
1517
if ($callback instanceof \Closure) {
@@ -19,8 +21,22 @@ private function invoke(callable $callback, object $entity, ...$args)
1921
return $callback(...$args);
2022
}
2123

22-
public function hydrate(HydratorConfigInterface $config, object $entity, array $data): void
23-
{
24+
public function hydrate(
25+
HydratorConfigInterface $config,
26+
object $entity,
27+
array $data,
28+
int $flags = 0
29+
): void {
30+
$hydratorProperties = $config->getHydratorProperties();
31+
32+
if (~$flags & static::NO_STRICT_KEYS) {
33+
$diff = array_keys(array_diff_key($data, $hydratorProperties));
34+
35+
if ($diff !== []) {
36+
throw new \InvalidArgumentException(sprintf('Unexpected data: %s', join(', ', $diff)));
37+
}
38+
}
39+
2440
foreach ($config->getHydratorProperties() as $propertyName => $set) {
2541
$this->invoke($set, $entity, $data[$propertyName] ?? null, $propertyName);
2642
}

src/Scn/Hydrator/HydratorInterface.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
interface HydratorInterface
1111
{
1212

13-
public function hydrate(HydratorConfigInterface $config, object $entity, array $data): void;
13+
public function hydrate(HydratorConfigInterface $config, object $entity, array $data, int $flags = 0): void;
1414

1515
public function extract(ExtractorConfigInterface $config, object $entity): array;
1616
}

tests/Scn/Hydrator/HydratorTest.php

Lines changed: 52 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,58 @@ public function testHydrate(): void
5656
$this->assertSame($testData, $this->testValueStorage);
5757
}
5858

59+
public function testHydrateIsStrictByDefault()
60+
{
61+
62+
$testPropertySetter = function (
63+
$value,
64+
string $name
65+
): void {
66+
$this->testValueStorage[$name] = $value;
67+
};
68+
69+
$hydratorConfig = new GenericHydratorConfig([
70+
'prop1' => $testPropertySetter,
71+
]);
72+
73+
74+
$testData = [
75+
'unexpected' => true,
76+
'prop1' => 'fu',
77+
'another_unexpected' => true,
78+
];
79+
80+
$expectedResult = [
81+
'prop1' => 'fu',
82+
];
83+
84+
$this->expectException(\InvalidArgumentException::class);
85+
$this->expectExceptionMessage('Unexpected data: unexpected, another_unexpected');
86+
87+
$this->subject->hydrate($hydratorConfig, $this, $testData, 0);
88+
89+
$this->assertSame($expectedResult, $this->testValueStorage);
90+
}
91+
92+
public function testHydrateOnNonStrict()
93+
{
94+
$hydratorConfig = new GenericHydratorConfig([
95+
'prop1' => 'strval',
96+
]);
97+
98+
99+
$testData = [
100+
'unexpected' => true,
101+
'prop1' => 'fu',
102+
'another_unexpected' => true,
103+
];
104+
105+
$this->expectException(\InvalidArgumentException::class);
106+
$this->expectExceptionMessage('Unexpected data: unexpected, another_unexpected');
107+
108+
$this->subject->hydrate($hydratorConfig, $this, $testData, 0);
109+
}
110+
59111
public function testExtract(): void
60112
{
61113
$testPropertyGetter = function (
@@ -73,13 +125,6 @@ public function testExtract(): void
73125

74126
$randomInt = random_int(0, PHP_INT_MAX);
75127

76-
77-
$testData = [
78-
'prop1' => 'fu',
79-
'prop2' => $randomInt,
80-
'prop3' => null,
81-
];
82-
83128
$this->testValueStorage = [
84129
'prop1' => ['fu', $this],
85130
'prop2' => [$randomInt, $this],

0 commit comments

Comments
 (0)