fix: handle correctly iterable source during mapping

This commit is contained in:
Romain Canon 2021-11-30 12:59:50 +01:00
parent a77b28c5c2
commit dd4624c5e0
7 changed files with 69 additions and 3 deletions

View File

@ -19,7 +19,7 @@ final class InvalidSourceForObject extends RuntimeException implements Message
$type = get_debug_type($source);
parent::__construct(
"Invalid source type `$type`, it must be an array.",
"Invalid source type `$type`, it must be an iterable.",
1632903281
);
}

View File

@ -23,6 +23,7 @@ use function array_values;
use function count;
use function is_a;
use function is_array;
use function is_iterable;
use function iterator_to_array;
final class MethodObjectBuilder implements ObjectBuilder
@ -115,6 +116,10 @@ final class MethodObjectBuilder implements ObjectBuilder
return [];
}
if (is_iterable($source) && ! is_array($source)) {
$source = iterator_to_array($source);
}
$parameters = $this->method->parameters();
if (count($parameters) === 1) {

View File

@ -68,6 +68,10 @@ final class ReflectionObjectBuilder implements ObjectBuilder
return [];
}
if (is_iterable($source) && ! is_array($source)) {
$source = iterator_to_array($source);
}
$properties = $this->class->properties();
if (count($properties) === 1) {

View File

@ -0,0 +1,27 @@
<?php
declare(strict_types=1);
namespace CuyZ\Valinor\Tests\Integration\Mapping\Source;
use CuyZ\Valinor\Mapper\MappingError;
use CuyZ\Valinor\Mapper\Source\JsonSource;
use CuyZ\Valinor\Tests\Integration\IntegrationTest;
use CuyZ\Valinor\Tests\Integration\Mapping\Fixture\SimpleObject;
final class JsonSourceMappingTest extends IntegrationTest
{
public function test_json_source_is_mapped_correctly(): void
{
try {
$object = $this->mapperBuilder->mapper()->map(
SimpleObject::class,
new JsonSource('{"value": "foo"}')
);
} catch (MappingError $error) {
$this->mappingFail($error);
}
self::assertSame('foo', $object->value);
}
}

View File

@ -0,0 +1,30 @@
<?php
declare(strict_types=1);
namespace CuyZ\Valinor\Tests\Integration\Mapping\Source;
use CuyZ\Valinor\Mapper\MappingError;
use CuyZ\Valinor\Mapper\Source\YamlSource;
use CuyZ\Valinor\Tests\Integration\IntegrationTest;
use CuyZ\Valinor\Tests\Integration\Mapping\Fixture\SimpleObject;
/**
* @requires extension yaml
*/
final class YamlSourceMappingTest extends IntegrationTest
{
public function test_yaml_source_is_mapped_correctly(): void
{
try {
$object = $this->mapperBuilder->mapper()->map(
SimpleObject::class,
new YamlSource('value: foo')
);
} catch (MappingError $error) {
$this->mappingFail($error);
}
self::assertSame('foo', $object->value);
}
}

View File

@ -131,7 +131,7 @@ final class MethodObjectBuilderTest extends TestCase
$this->expectException(InvalidSourceForObject::class);
$this->expectExceptionCode(1632903281);
$this->expectExceptionMessage('Invalid source type `string`, it must be an array.');
$this->expectExceptionMessage('Invalid source type `string`, it must be an iterable.');
/** @var Generator<Argument> $arguments */
$arguments = $objectBuilder->describeArguments('foo');

View File

@ -66,7 +66,7 @@ final class ReflectionObjectBuilderTest extends TestCase
$this->expectException(InvalidSourceForObject::class);
$this->expectExceptionCode(1632903281);
$this->expectExceptionMessage('Invalid source type `string`, it must be an array.');
$this->expectExceptionMessage('Invalid source type `string`, it must be an iterable.');
/** @var Generator<Argument> $arguments */
$arguments = $objectBuilder->describeArguments('foo');