From d90b4735a272b23779037cd93e50f00ebb4d1c6d Mon Sep 17 00:00:00 2001 From: Priyadi Iman Nurcahyo <1102197+priyadi@users.noreply.github.com> Date: Fri, 3 May 2024 19:53:26 +0700 Subject: [PATCH] feat: `ramsey/uuid` support (#62) --- CHANGELOG.md | 3 + composer.json | 1 + config/services.php | 5 + src/MapperFactory.php | 17 +++ .../Implementation/RamseyUuidTransformer.php | 104 ++++++++++++++++++ tests/Fixtures/Uid/ObjectWithStringUids.php | 1 + tests/Fixtures/Uid/ObjectWithUids.php | 4 + .../UidDto/ObjectWithStringUidsDto.php | 1 + tests/Fixtures/UidDto/ObjectWithUidsDto.php | 2 + tests/IntegrationTest/UidTest.php | 4 +- 10 files changed, 141 insertions(+), 1 deletion(-) create mode 100644 src/Transformer/Implementation/RamseyUuidTransformer.php diff --git a/CHANGELOG.md b/CHANGELOG.md index ec30e03..586ed68 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,8 @@ # CHANGELOG +## 1.4.0 + +* feat: `ramsey/uuid` support ## 1.3.0 diff --git a/composer.json b/composer.json index 9c7123b..5b47c54 100644 --- a/composer.json +++ b/composer.json @@ -53,6 +53,7 @@ "phpstan/phpstan-phpunit": "^1.3", "phpunit/phpunit": "^10.5", "psalm/plugin-phpunit": "^0.19.0", + "ramsey/uuid": "^3.0", "symfony/framework-bundle": "^6.4 || ^7.0", "symfony/http-kernel": "^6.4 || ^7.0", "symfony/runtime": "^6.4 || ^7.0", diff --git a/config/services.php b/config/services.php index c7c6a39..d5c3831 100644 --- a/config/services.php +++ b/config/services.php @@ -51,6 +51,7 @@ use Rekalogika\Mapper\Transformer\Implementation\ObjectToObjectTransformer; use Rekalogika\Mapper\Transformer\Implementation\ObjectToStringTransformer; use Rekalogika\Mapper\Transformer\Implementation\PresetTransformer; +use Rekalogika\Mapper\Transformer\Implementation\RamseyUuidTransformer; use Rekalogika\Mapper\Transformer\Implementation\ScalarToScalarTransformer; use Rekalogika\Mapper\Transformer\Implementation\StringToBackedEnumTransformer; use Rekalogika\Mapper\Transformer\Implementation\SymfonyUidTransformer; @@ -130,6 +131,10 @@ ->set(SymfonyUidTransformer::class) ->tag('rekalogika.mapper.transformer', ['priority' => -550]); + $services + ->set(RamseyUuidTransformer::class) + ->tag('rekalogika.mapper.transformer', ['priority' => -550]); + $services ->set(ObjectToStringTransformer::class) ->tag('rekalogika.mapper.transformer', ['priority' => -600]); diff --git a/src/MapperFactory.php b/src/MapperFactory.php index 152a8fc..8fd8e7b 100644 --- a/src/MapperFactory.php +++ b/src/MapperFactory.php @@ -15,6 +15,7 @@ use Psr\Cache\CacheItemPoolInterface; use Psr\Container\ContainerInterface; +use Ramsey\Uuid\UuidInterface; use Rekalogika\Mapper\Command\MappingCommand; use Rekalogika\Mapper\Command\TryCommand; use Rekalogika\Mapper\Command\TryPropertyCommand; @@ -57,6 +58,7 @@ use Rekalogika\Mapper\Transformer\Implementation\ObjectToObjectTransformer; use Rekalogika\Mapper\Transformer\Implementation\ObjectToStringTransformer; use Rekalogika\Mapper\Transformer\Implementation\PresetTransformer; +use Rekalogika\Mapper\Transformer\Implementation\RamseyUuidTransformer; use Rekalogika\Mapper\Transformer\Implementation\ScalarToScalarTransformer; use Rekalogika\Mapper\Transformer\Implementation\StringToBackedEnumTransformer; use Rekalogika\Mapper\Transformer\Implementation\SymfonyUidTransformer; @@ -130,6 +132,7 @@ class MapperFactory private ?CopyTransformer $copyTransformer = null; private ?ClassMethodTransformer $classMethodTransformer = null; private ?SymfonyUidTransformer $symfonyUidTransformer = null; + private ?RamseyUuidTransformer $ramseyUuidTransformer = null; private ?PresetTransformer $presetTransformer = null; private CacheItemPoolInterface $propertyInfoExtractorCache; @@ -518,6 +521,15 @@ protected function getSymfonyUidTransformer(): SymfonyUidTransformer return $this->symfonyUidTransformer; } + protected function getRamseyUuidTransformer(): RamseyUuidTransformer + { + if (null === $this->ramseyUuidTransformer) { + $this->ramseyUuidTransformer = new RamseyUuidTransformer(); + } + + return $this->ramseyUuidTransformer; + } + protected function getPresetTransformer(): PresetTransformer { if (null === $this->presetTransformer) { @@ -597,6 +609,11 @@ protected function getTransformersIterator(): iterable => $this->getSymfonyUidTransformer(); } + if (interface_exists(UuidInterface::class)) { + yield 'RamseyUuidTransformer' + => $this->getRamseyUuidTransformer(); + } + yield 'ObjectToStringTransformer' => $this->getObjectToStringTransformer(); diff --git a/src/Transformer/Implementation/RamseyUuidTransformer.php b/src/Transformer/Implementation/RamseyUuidTransformer.php new file mode 100644 index 0000000..184433b --- /dev/null +++ b/src/Transformer/Implementation/RamseyUuidTransformer.php @@ -0,0 +1,104 @@ + + * + * For the full copyright and license information, please view the LICENSE file + * that was distributed with this source code. + */ + +namespace Rekalogika\Mapper\Transformer\Implementation; + +use Ramsey\Uuid\Uuid; +use Ramsey\Uuid\UuidInterface; +use Rekalogika\Mapper\Context\Context; +use Rekalogika\Mapper\Exception\InvalidArgumentException; +use Rekalogika\Mapper\Transformer\TransformerInterface; +use Rekalogika\Mapper\Transformer\TypeMapping; +use Rekalogika\Mapper\Util\TypeFactory; +use Rekalogika\Mapper\Util\TypeUtil; +use Symfony\Component\PropertyInfo\Type; + +final readonly class RamseyUuidTransformer implements TransformerInterface +{ + public function transform( + mixed $source, + mixed $target, + ?Type $sourceType, + ?Type $targetType, + Context $context + ): mixed { + if ($targetType === null) { + throw new InvalidArgumentException( + sprintf( + 'Target type is null when trying to transform type "%s" to "%s", using source "%s".', + TypeUtil::getDebugType($sourceType), + TypeUtil::getDebugType($targetType), + \get_debug_type($source) + ) + ); + } + + // wants to convert string to uuid + + if (is_string($source)) { + $targetClass = $targetType->getClassName(); + + if ($targetClass === null) { + throw new InvalidArgumentException( + sprintf( + 'Target class is null when trying to transform type "%s" to "%s", using source "%s".', + TypeUtil::getDebugType($sourceType), + TypeUtil::getDebugType($targetType), + \get_debug_type($source) + ) + ); + } + + return Uuid::fromString($source); + } + + // wants to convert uuid to string + + if ($source instanceof UuidInterface) { + if ($targetType->getBuiltinType() === Type::BUILTIN_TYPE_STRING) { + return $source->toString(); + } elseif ($targetType->getClassName() === UuidInterface::class) { + return $source; + } + + return $source->toString(); + } + + throw new InvalidArgumentException( + sprintf( + 'Trying to transform type "%s" to "%s", using source "%s".', + TypeUtil::getDebugType($sourceType), + TypeUtil::getDebugType($targetType), + \get_debug_type($source) + ) + ); + } + + public function getSupportedTransformation(): iterable + { + yield new TypeMapping( + TypeFactory::objectOfClass(UuidInterface::class), + TypeFactory::string(), + ); + + yield new TypeMapping( + TypeFactory::string(), + TypeFactory::objectOfClass(UuidInterface::class), + ); + + yield new TypeMapping( + TypeFactory::objectOfClass(UuidInterface::class), + TypeFactory::objectOfClass(UuidInterface::class), + ); + } +} diff --git a/tests/Fixtures/Uid/ObjectWithStringUids.php b/tests/Fixtures/Uid/ObjectWithStringUids.php index 88c1da0..03d10ef 100644 --- a/tests/Fixtures/Uid/ObjectWithStringUids.php +++ b/tests/Fixtures/Uid/ObjectWithStringUids.php @@ -17,4 +17,5 @@ class ObjectWithStringUids { public string $uuid = '6ba7b810-9dad-11d1-80b4-00c04fd430c8'; public string $ulid = '01F9Z3ZQZJQJZJZJZJZJZJZJZJ'; + public string $ramseyUuid = '6ba7b810-9dad-11d1-80b4-00c04fd430c8'; } diff --git a/tests/Fixtures/Uid/ObjectWithUids.php b/tests/Fixtures/Uid/ObjectWithUids.php index 68cddb5..1a057a5 100644 --- a/tests/Fixtures/Uid/ObjectWithUids.php +++ b/tests/Fixtures/Uid/ObjectWithUids.php @@ -13,6 +13,8 @@ namespace Rekalogika\Mapper\Tests\Fixtures\Uid; +use Ramsey\Uuid\Uuid as RamseyUuid; +use Ramsey\Uuid\UuidInterface; use Symfony\Component\Uid\Ulid; use Symfony\Component\Uid\Uuid; @@ -20,10 +22,12 @@ class ObjectWithUids { public Uuid $uuid; public Ulid $ulid; + public UuidInterface $ramseyUuid; public function __construct() { $this->uuid = Uuid::fromString('c4e0d7e0-7f1a-4b1e-8e3c-2b4b1b9a0b5a'); $this->ulid = Ulid::fromString('01F9Z3ZJZ1QJXZJXZJXZJXZJXZ'); + $this->ramseyUuid = RamseyUuid::fromString('c4e0d7e0-7f1a-4b1e-8e3c-2b4b1b9a0b5a'); } } diff --git a/tests/Fixtures/UidDto/ObjectWithStringUidsDto.php b/tests/Fixtures/UidDto/ObjectWithStringUidsDto.php index 0d30100..1769818 100644 --- a/tests/Fixtures/UidDto/ObjectWithStringUidsDto.php +++ b/tests/Fixtures/UidDto/ObjectWithStringUidsDto.php @@ -17,4 +17,5 @@ class ObjectWithStringUidsDto { public ?string $uuid = null; public ?string $ulid = null; + public ?string $ramseyUuid = null; } diff --git a/tests/Fixtures/UidDto/ObjectWithUidsDto.php b/tests/Fixtures/UidDto/ObjectWithUidsDto.php index 6f87fe1..12f1d5b 100644 --- a/tests/Fixtures/UidDto/ObjectWithUidsDto.php +++ b/tests/Fixtures/UidDto/ObjectWithUidsDto.php @@ -13,6 +13,7 @@ namespace Rekalogika\Mapper\Tests\Fixtures\UidDto; +use Ramsey\Uuid\UuidInterface; use Symfony\Component\Uid\Ulid; use Symfony\Component\Uid\Uuid; @@ -20,4 +21,5 @@ class ObjectWithUidsDto { public ?Uuid $uuid = null; public ?Ulid $ulid = null; + public ?UuidInterface $ramseyUuid = null; } diff --git a/tests/IntegrationTest/UidTest.php b/tests/IntegrationTest/UidTest.php index c9d6ee2..eb60aaa 100644 --- a/tests/IntegrationTest/UidTest.php +++ b/tests/IntegrationTest/UidTest.php @@ -30,6 +30,7 @@ public function testUuidToString(): void $this->assertEquals('c4e0d7e0-7f1a-4b1e-8e3c-2b4b1b9a0b5a', $dto->uuid); $this->assertEquals('01F9Z3ZJZ1QJXZJXZJXZJXZJXZ', $dto->ulid); + $this->assertEquals('c4e0d7e0-7f1a-4b1e-8e3c-2b4b1b9a0b5a', $dto->ramseyUuid); } public function testStringToUuid(): void @@ -40,7 +41,7 @@ public function testStringToUuid(): void $this->assertInstanceOf(ObjectWithUidsDto::class, $dto); $this->assertEquals(Uuid::fromString('6ba7b810-9dad-11d1-80b4-00c04fd430c8'), $dto->uuid); $this->assertEquals(Ulid::fromString('01F9Z3ZQZJQJZJZJZJZJZJZJZJ'), $dto->ulid); - + $this->assertEquals('6ba7b810-9dad-11d1-80b4-00c04fd430c8', $dto->ramseyUuid?->toString()); } public function testUuidToUuid(): void @@ -51,6 +52,7 @@ public function testUuidToUuid(): void $this->assertInstanceOf(ObjectWithUidsDto::class, $dto); $this->assertEquals(Uuid::fromString('c4e0d7e0-7f1a-4b1e-8e3c-2b4b1b9a0b5a'), $dto->uuid); $this->assertEquals(Ulid::fromString('01F9Z3ZJZ1QJXZJXZJXZJXZJXZ'), $dto->ulid); + $this->assertEquals('c4e0d7e0-7f1a-4b1e-8e3c-2b4b1b9a0b5a', $dto->ramseyUuid?->toString()); } }