Skip to content

Commit

Permalink
fix: properly handle list type when input contains superfluous keys
Browse files Browse the repository at this point in the history
Co-authored-by: Romain Canon <[email protected]>
  • Loading branch information
Ocramius and romm committed Mar 12, 2024
1 parent 4b68835 commit 1b8efa1
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 3 deletions.
9 changes: 6 additions & 3 deletions src/Mapper/Object/ArgumentsValues.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

use CuyZ\Valinor\Mapper\Object\Exception\InvalidSource;
use CuyZ\Valinor\Type\CompositeTraversableType;
use CuyZ\Valinor\Type\Types\ArrayKeyType;
use IteratorAggregate;
use Traversable;

Expand Down Expand Up @@ -116,15 +117,17 @@ private function transformValueForSingleArgument(mixed $value): mixed

$argument = $this->arguments->at(0);
$name = $argument->name();
$isTraversable = $argument-> type() instanceof CompositeTraversableType;
$type = $argument->type();
$isTraversableAndAllowsStringKeys = $type instanceof CompositeTraversableType
&& $type->keyType() !== ArrayKeyType::integer();

if (is_array($value) && array_key_exists($name, $value)) {
if ($this->forInterface || ! $isTraversable || count($value) === 1) {
if ($this->forInterface || ! $isTraversableAndAllowsStringKeys || count($value) === 1) {
return $value;
}
}

if ($value === [] && ! $isTraversable) {
if ($value === [] && ! $isTraversableAndAllowsStringKeys) {
return $value;
}

Expand Down
44 changes: 44 additions & 0 deletions tests/Integration/Mapping/Other/SuperfluousKeysMappingTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,44 @@ public function test_single_property_node_can_be_mapped_with_superfluous_key():
}
self::assertSame('foo', $result->foo);
}

public function test_single_list_property_node_can_be_mapped_with_superfluous_key(): void
{
try {
$result = $this->mapper->map(ObjectWithSingleListProperty::class, [
'unrelated_key' => 'this-should-be-ignored-and-have-no-effect',
'values' => [7, 8, 9],
]);
} catch (MappingError $error) {
$this->mappingFail($error);
}

self::assertSame([7, 8, 9], $result->values);
}

public function test_single_list_property_node_can_be_mapped_with_matching_key_and_without_superfluous_key(): void
{
try {
$result = $this->mapper->map(ObjectWithSingleListProperty::class, [
'values' => [7, 8, 9],
]);
} catch (MappingError $error) {
$this->mappingFail($error);
}

self::assertSame([7, 8, 9], $result->values);
}

public function test_single_list_property_node_can_be_mapped_(): void
{
try {
$result = $this->mapper->map(ObjectWithSingleListProperty::class, [7, 8, 9]);
} catch (MappingError $error) {
$this->mappingFail($error);
}

self::assertSame([7, 8, 9], $result->values);
}
}

final class UnionOfBarAndFizAndFoo
Expand All @@ -86,3 +124,9 @@ final class SomeBarAndFizObject

public string $fiz;
}

final class ObjectWithSingleListProperty
{
/** @var list<int> */
public array $values;
}

0 comments on commit 1b8efa1

Please sign in to comment.