From 7798c3517a7da1416f58850048899e393f93ae9c Mon Sep 17 00:00:00 2001 From: Priyadi Iman Nurcahyo <1102197+priyadi@users.noreply.github.com> Date: Thu, 10 Oct 2024 22:08:56 +0700 Subject: [PATCH] feat: transformation from `Stringable` to int, float, and bool by casting (#218) --- CHANGELOG.md | 1 + .../ObjectToStringTransformer.php | 31 ++++++++++++++++++- .../StringToBackedEnumTransformer.php | 3 ++ .../rekalogika-mapper/generated-mappings.php | 20 +++++++++--- .../ObjectImplementingNumericStringable.php | 23 ++++++++++++++ .../ObjectWithNumericStringableProperty.php | 24 ++++++++++++++ .../ObjectWithStringableProperty.php | 4 +-- ...Dto.php => ObjectWithFloatPropertyDto.php} | 4 +-- .../ObjectWithIntegerPropertyDto.php | 19 ++++++++++++ .../ObjectWithStringPropertyDto.php | 19 ++++++++++++ .../ObjectEnumStringMappingTest.php | 25 +++++++++++++-- 11 files changed, 161 insertions(+), 12 deletions(-) create mode 100644 tests/src/Fixtures/EnumAndStringable/ObjectImplementingNumericStringable.php create mode 100644 tests/src/Fixtures/EnumAndStringable/ObjectWithNumericStringableProperty.php rename tests/src/Fixtures/EnumAndStringableDto/{ObjectWithStringablePropertyDto.php => ObjectWithFloatPropertyDto.php} (81%) create mode 100644 tests/src/Fixtures/EnumAndStringableDto/ObjectWithIntegerPropertyDto.php create mode 100644 tests/src/Fixtures/EnumAndStringableDto/ObjectWithStringPropertyDto.php diff --git a/CHANGELOG.md b/CHANGELOG.md index d08f1841..d9f7f8d1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ * chore: rector run * perf: object mapper resolver cache prewarming * fix: terms +* feat: transformation from `Stringable` to int, float, and bool by casting ## 1.9.4 diff --git a/src/Transformer/Implementation/ObjectToStringTransformer.php b/src/Transformer/Implementation/ObjectToStringTransformer.php index 3f05f5aa..8e62cefd 100644 --- a/src/Transformer/Implementation/ObjectToStringTransformer.php +++ b/src/Transformer/Implementation/ObjectToStringTransformer.php @@ -17,9 +17,13 @@ use Rekalogika\Mapper\Exception\InvalidArgumentException; use Rekalogika\Mapper\Transformer\TransformerInterface; use Rekalogika\Mapper\Transformer\TypeMapping; +use Rekalogika\Mapper\Util\TypeCheck; use Rekalogika\Mapper\Util\TypeFactory; use Symfony\Component\PropertyInfo\Type; +/** + * @todo rename class to ObjectToScalarTransformer + */ final readonly class ObjectToStringTransformer implements TransformerInterface { #[\Override] @@ -31,7 +35,17 @@ public function transform( Context $context, ): mixed { if ($source instanceof \Stringable) { - return (string) $source; + if (TypeCheck::isString($targetType)) { + return (string) $source; + } elseif (TypeCheck::isInt($targetType)) { + return (int) (string) $source; + } elseif (TypeCheck::isFloat($targetType)) { + return (float) (string) $source; + } elseif (TypeCheck::isBool($targetType)) { + return (bool) (string) $source; + } else { + return (string) $source; + } } elseif ($source instanceof \BackedEnum) { return $source->value; } elseif ($source instanceof \UnitEnum) { @@ -49,6 +63,21 @@ public function getSupportedTransformation(): iterable TypeFactory::string(), ); + yield new TypeMapping( + TypeFactory::objectOfClass(\Stringable::class), + TypeFactory::int(), + ); + + yield new TypeMapping( + TypeFactory::objectOfClass(\Stringable::class), + TypeFactory::float(), + ); + + yield new TypeMapping( + TypeFactory::objectOfClass(\Stringable::class), + TypeFactory::bool(), + ); + yield new TypeMapping( TypeFactory::objectOfClass(\UnitEnum::class), TypeFactory::string(), diff --git a/src/Transformer/Implementation/StringToBackedEnumTransformer.php b/src/Transformer/Implementation/StringToBackedEnumTransformer.php index 9f0b7f13..1e91bae0 100644 --- a/src/Transformer/Implementation/StringToBackedEnumTransformer.php +++ b/src/Transformer/Implementation/StringToBackedEnumTransformer.php @@ -21,6 +21,9 @@ use Rekalogika\Mapper\Util\TypeFactory; use Symfony\Component\PropertyInfo\Type; +/** + * @todo rename class to StringToEnumTransformer + */ final readonly class StringToBackedEnumTransformer implements TransformerInterface { #[\Override] diff --git a/tests/config/rekalogika-mapper/generated-mappings.php b/tests/config/rekalogika-mapper/generated-mappings.php index 3145bc65..95c2839b 100644 --- a/tests/config/rekalogika-mapper/generated-mappings.php +++ b/tests/config/rekalogika-mapper/generated-mappings.php @@ -358,21 +358,33 @@ ); $mappingCollection->addObjectMapping( - // tests/src/IntegrationTest/ObjectEnumStringMappingTest.php on line 38 + // tests/src/IntegrationTest/ObjectEnumStringMappingTest.php on line 57 source: \Rekalogika\Mapper\Tests\Fixtures\EnumAndStringable\ObjectWithEnumProperty::class, target: \Rekalogika\Mapper\Tests\Fixtures\EnumAndStringable\ObjectWithStringProperty::class ); $mappingCollection->addObjectMapping( - // tests/src/IntegrationTest/ObjectEnumStringMappingTest.php on lines 47, 58, 67 + // tests/src/IntegrationTest/ObjectEnumStringMappingTest.php on line 49 + source: \Rekalogika\Mapper\Tests\Fixtures\EnumAndStringable\ObjectWithNumericStringableProperty::class, + target: \Rekalogika\Mapper\Tests\Fixtures\EnumAndStringableDto\ObjectWithFloatPropertyDto::class + ); + + $mappingCollection->addObjectMapping( + // tests/src/IntegrationTest/ObjectEnumStringMappingTest.php on line 41 + source: \Rekalogika\Mapper\Tests\Fixtures\EnumAndStringable\ObjectWithNumericStringableProperty::class, + target: \Rekalogika\Mapper\Tests\Fixtures\EnumAndStringableDto\ObjectWithIntegerPropertyDto::class + ); + + $mappingCollection->addObjectMapping( + // tests/src/IntegrationTest/ObjectEnumStringMappingTest.php on lines 66, 77, 86 source: \Rekalogika\Mapper\Tests\Fixtures\EnumAndStringable\ObjectWithStringProperty::class, target: \Rekalogika\Mapper\Tests\Fixtures\EnumAndStringable\ObjectWithEnumProperty::class ); $mappingCollection->addObjectMapping( - // tests/src/IntegrationTest/ObjectEnumStringMappingTest.php on line 30 + // tests/src/IntegrationTest/ObjectEnumStringMappingTest.php on line 33 source: \Rekalogika\Mapper\Tests\Fixtures\EnumAndStringable\ObjectWithStringableProperty::class, - target: \Rekalogika\Mapper\Tests\Fixtures\EnumAndStringableDto\ObjectWithStringablePropertyDto::class + target: \Rekalogika\Mapper\Tests\Fixtures\EnumAndStringableDto\ObjectWithStringPropertyDto::class ); $mappingCollection->addObjectMapping( diff --git a/tests/src/Fixtures/EnumAndStringable/ObjectImplementingNumericStringable.php b/tests/src/Fixtures/EnumAndStringable/ObjectImplementingNumericStringable.php new file mode 100644 index 00000000..fe393c27 --- /dev/null +++ b/tests/src/Fixtures/EnumAndStringable/ObjectImplementingNumericStringable.php @@ -0,0 +1,23 @@ + + * + * For the full copyright and license information, please view the LICENSE file + * that was distributed with this source code. + */ + +namespace Rekalogika\Mapper\Tests\Fixtures\EnumAndStringable; + +class ObjectImplementingNumericStringable implements \Stringable +{ + #[\Override] + public function __toString(): string + { + return '123456.789'; + } +} diff --git a/tests/src/Fixtures/EnumAndStringable/ObjectWithNumericStringableProperty.php b/tests/src/Fixtures/EnumAndStringable/ObjectWithNumericStringableProperty.php new file mode 100644 index 00000000..b99a1e7a --- /dev/null +++ b/tests/src/Fixtures/EnumAndStringable/ObjectWithNumericStringableProperty.php @@ -0,0 +1,24 @@ + + * + * For the full copyright and license information, please view the LICENSE file + * that was distributed with this source code. + */ + +namespace Rekalogika\Mapper\Tests\Fixtures\EnumAndStringable; + +class ObjectWithNumericStringableProperty +{ + public ObjectImplementingNumericStringable $property; + + public function __construct() + { + $this->property = new ObjectImplementingNumericStringable(); + } +} diff --git a/tests/src/Fixtures/EnumAndStringable/ObjectWithStringableProperty.php b/tests/src/Fixtures/EnumAndStringable/ObjectWithStringableProperty.php index 8d9e9ccc..0ae557f1 100644 --- a/tests/src/Fixtures/EnumAndStringable/ObjectWithStringableProperty.php +++ b/tests/src/Fixtures/EnumAndStringable/ObjectWithStringableProperty.php @@ -15,10 +15,10 @@ class ObjectWithStringableProperty { - public ObjectImplementingStringable $stringable; + public ObjectImplementingStringable $property; public function __construct() { - $this->stringable = new ObjectImplementingStringable(); + $this->property = new ObjectImplementingStringable(); } } diff --git a/tests/src/Fixtures/EnumAndStringableDto/ObjectWithStringablePropertyDto.php b/tests/src/Fixtures/EnumAndStringableDto/ObjectWithFloatPropertyDto.php similarity index 81% rename from tests/src/Fixtures/EnumAndStringableDto/ObjectWithStringablePropertyDto.php rename to tests/src/Fixtures/EnumAndStringableDto/ObjectWithFloatPropertyDto.php index f308139d..ed395d27 100644 --- a/tests/src/Fixtures/EnumAndStringableDto/ObjectWithStringablePropertyDto.php +++ b/tests/src/Fixtures/EnumAndStringableDto/ObjectWithFloatPropertyDto.php @@ -13,7 +13,7 @@ namespace Rekalogika\Mapper\Tests\Fixtures\EnumAndStringableDto; -class ObjectWithStringablePropertyDto +class ObjectWithFloatPropertyDto { - public ?string $stringable = null; + public ?float $property = null; } diff --git a/tests/src/Fixtures/EnumAndStringableDto/ObjectWithIntegerPropertyDto.php b/tests/src/Fixtures/EnumAndStringableDto/ObjectWithIntegerPropertyDto.php new file mode 100644 index 00000000..406b7967 --- /dev/null +++ b/tests/src/Fixtures/EnumAndStringableDto/ObjectWithIntegerPropertyDto.php @@ -0,0 +1,19 @@ + + * + * For the full copyright and license information, please view the LICENSE file + * that was distributed with this source code. + */ + +namespace Rekalogika\Mapper\Tests\Fixtures\EnumAndStringableDto; + +class ObjectWithIntegerPropertyDto +{ + public ?int $property = null; +} diff --git a/tests/src/Fixtures/EnumAndStringableDto/ObjectWithStringPropertyDto.php b/tests/src/Fixtures/EnumAndStringableDto/ObjectWithStringPropertyDto.php new file mode 100644 index 00000000..c51618f3 --- /dev/null +++ b/tests/src/Fixtures/EnumAndStringableDto/ObjectWithStringPropertyDto.php @@ -0,0 +1,19 @@ + + * + * For the full copyright and license information, please view the LICENSE file + * that was distributed with this source code. + */ + +namespace Rekalogika\Mapper\Tests\Fixtures\EnumAndStringableDto; + +class ObjectWithStringPropertyDto +{ + public ?string $property = null; +} diff --git a/tests/src/IntegrationTest/ObjectEnumStringMappingTest.php b/tests/src/IntegrationTest/ObjectEnumStringMappingTest.php index 5b161eae..c073c78e 100644 --- a/tests/src/IntegrationTest/ObjectEnumStringMappingTest.php +++ b/tests/src/IntegrationTest/ObjectEnumStringMappingTest.php @@ -16,20 +16,39 @@ use Rekalogika\Mapper\Exception\InvalidArgumentException; use Rekalogika\Mapper\Tests\Common\FrameworkTestCase; use Rekalogika\Mapper\Tests\Fixtures\EnumAndStringable\ObjectWithEnumProperty; +use Rekalogika\Mapper\Tests\Fixtures\EnumAndStringable\ObjectWithNumericStringableProperty; use Rekalogika\Mapper\Tests\Fixtures\EnumAndStringable\ObjectWithStringableProperty; use Rekalogika\Mapper\Tests\Fixtures\EnumAndStringable\ObjectWithStringProperty; use Rekalogika\Mapper\Tests\Fixtures\EnumAndStringable\SomeBackedEnum; use Rekalogika\Mapper\Tests\Fixtures\EnumAndStringable\SomeEnum; -use Rekalogika\Mapper\Tests\Fixtures\EnumAndStringableDto\ObjectWithStringablePropertyDto; +use Rekalogika\Mapper\Tests\Fixtures\EnumAndStringableDto\ObjectWithFloatPropertyDto; +use Rekalogika\Mapper\Tests\Fixtures\EnumAndStringableDto\ObjectWithIntegerPropertyDto; +use Rekalogika\Mapper\Tests\Fixtures\EnumAndStringableDto\ObjectWithStringPropertyDto; class ObjectEnumStringMappingTest extends FrameworkTestCase { public function testStringableToString(): void { $object = new ObjectWithStringableProperty(); - $result = $this->mapper->map($object, ObjectWithStringablePropertyDto::class); + $result = $this->mapper->map($object, ObjectWithStringPropertyDto::class); - $this->assertEquals('foo', $result->stringable); + $this->assertEquals('foo', $result->property); + } + + public function testStringableToInteger(): void + { + $object = new ObjectWithNumericStringableProperty(); + $result = $this->mapper->map($object, ObjectWithIntegerPropertyDto::class); + + $this->assertEquals(123456, $result->property); + } + + public function testStringableToFloat(): void + { + $object = new ObjectWithNumericStringableProperty(); + $result = $this->mapper->map($object, ObjectWithFloatPropertyDto::class); + + $this->assertEquals(123456.789, $result->property); } public function testEnumToString(): void