diff --git a/src/Symfony/Component/Form/CHANGELOG.md b/src/Symfony/Component/Form/CHANGELOG.md index 65ed70a502..7e435063d6 100644 --- a/src/Symfony/Component/Form/CHANGELOG.md +++ b/src/Symfony/Component/Form/CHANGELOG.md @@ -13,6 +13,7 @@ CHANGELOG * Deprecated passing an array as the second argument of the `RadioListMapper::mapDataToForms()` method, pass `\Traversable` instead. * Deprecated passing an array as the first argument of the `RadioListMapper::mapFormsToData()` method, pass `\Traversable` instead. * Added a `choice_translation_parameters` option to `ChoiceType` + * Add `UuidType` and `UlidType` 5.2.0 ----- diff --git a/src/Symfony/Component/Form/Extension/Core/DataTransformer/UlidToStringTransformer.php b/src/Symfony/Component/Form/Extension/Core/DataTransformer/UlidToStringTransformer.php new file mode 100644 index 0000000000..ea3fdec341 --- /dev/null +++ b/src/Symfony/Component/Form/Extension/Core/DataTransformer/UlidToStringTransformer.php @@ -0,0 +1,75 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form\Extension\Core\DataTransformer; + +use Symfony\Component\Form\DataTransformerInterface; +use Symfony\Component\Form\Exception\TransformationFailedException; +use Symfony\Component\Uid\Ulid; + +/** + * Transforms between a ULID string and a Ulid object. + * + * @author Pavel Dyakonov + */ +class UlidToStringTransformer implements DataTransformerInterface +{ + /** + * Transforms a Ulid object into a string. + * + * @param Ulid $value A Ulid object + * + * @return string|null A value as produced by Uid component + * + * @throws TransformationFailedException If the given value is not a Ulid object + */ + public function transform($value) + { + if (null === $value) { + return null; + } + + if (!$value instanceof Ulid) { + throw new TransformationFailedException('Expected a Ulid.'); + } + + return (string) $value; + } + + /** + * Transforms a ULID string into a Ulid object. + * + * @param string $value A ULID string + * + * @return Ulid|null An instance of Ulid + * + * @throws TransformationFailedException If the given value is not a string, + * or could not be transformed + */ + public function reverseTransform($value) + { + if (null === $value || '' === $value) { + return null; + } + + if (!\is_string($value)) { + throw new TransformationFailedException('Expected a string.'); + } + + try { + $ulid = new Ulid($value); + } catch (\InvalidArgumentException $e) { + throw new TransformationFailedException(sprintf('The value "%s" is not a valid ULID.', $value), $e->getCode(), $e); + } + + return $ulid; + } +} diff --git a/src/Symfony/Component/Form/Extension/Core/DataTransformer/UuidToStringTransformer.php b/src/Symfony/Component/Form/Extension/Core/DataTransformer/UuidToStringTransformer.php new file mode 100644 index 0000000000..a019847ae4 --- /dev/null +++ b/src/Symfony/Component/Form/Extension/Core/DataTransformer/UuidToStringTransformer.php @@ -0,0 +1,75 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form\Extension\Core\DataTransformer; + +use Symfony\Component\Form\DataTransformerInterface; +use Symfony\Component\Form\Exception\TransformationFailedException; +use Symfony\Component\Uid\Uuid; + +/** + * Transforms between a UUID string and a Uuid object. + * + * @author Pavel Dyakonov + */ +class UuidToStringTransformer implements DataTransformerInterface +{ + /** + * Transforms a Uuid object into a string. + * + * @param Uuid $value A Uuid object + * + * @return string|null A value as produced by Uid component + * + * @throws TransformationFailedException If the given value is not a Uuid object + */ + public function transform($value) + { + if (null === $value) { + return null; + } + + if (!$value instanceof Uuid) { + throw new TransformationFailedException('Expected a Uuid.'); + } + + return (string) $value; + } + + /** + * Transforms a UUID string into a Uuid object. + * + * @param string $value A UUID string + * + * @return Uuid|null An instance of Uuid + * + * @throws TransformationFailedException If the given value is not a string, + * or could not be transformed + */ + public function reverseTransform($value) + { + if (null === $value || '' === $value) { + return null; + } + + if (!\is_string($value)) { + throw new TransformationFailedException('Expected a string.'); + } + + try { + $uuid = new Uuid($value); + } catch (\InvalidArgumentException $e) { + throw new TransformationFailedException(sprintf('The value "%s" is not a valid UUID.', $value), $e->getCode(), $e); + } + + return $uuid; + } +} diff --git a/src/Symfony/Component/Form/Extension/Core/Type/UlidType.php b/src/Symfony/Component/Form/Extension/Core/Type/UlidType.php new file mode 100644 index 0000000000..640d38ffa9 --- /dev/null +++ b/src/Symfony/Component/Form/Extension/Core/Type/UlidType.php @@ -0,0 +1,49 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form\Extension\Core\Type; + +use Symfony\Component\Form\AbstractType; +use Symfony\Component\Form\Extension\Core\DataTransformer\UlidToStringTransformer; +use Symfony\Component\Form\FormBuilderInterface; +use Symfony\Component\OptionsResolver\Options; +use Symfony\Component\OptionsResolver\OptionsResolver; + +/** + * @author Pavel Dyakonov + */ +class UlidType extends AbstractType +{ + /** + * {@inheritdoc} + */ + public function buildForm(FormBuilderInterface $builder, array $options) + { + $builder + ->addViewTransformer(new UlidToStringTransformer()) + ; + } + + /** + * {@inheritdoc} + */ + public function configureOptions(OptionsResolver $resolver) + { + $resolver->setDefaults([ + 'compound' => false, + 'invalid_message' => function (Options $options, $previousValue) { + return ($options['legacy_error_messages'] ?? true) + ? $previousValue + : 'Please enter a valid ULID.'; + }, + ]); + } +} diff --git a/src/Symfony/Component/Form/Extension/Core/Type/UuidType.php b/src/Symfony/Component/Form/Extension/Core/Type/UuidType.php new file mode 100644 index 0000000000..0c27802b37 --- /dev/null +++ b/src/Symfony/Component/Form/Extension/Core/Type/UuidType.php @@ -0,0 +1,49 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form\Extension\Core\Type; + +use Symfony\Component\Form\AbstractType; +use Symfony\Component\Form\Extension\Core\DataTransformer\UuidToStringTransformer; +use Symfony\Component\Form\FormBuilderInterface; +use Symfony\Component\OptionsResolver\Options; +use Symfony\Component\OptionsResolver\OptionsResolver; + +/** + * @author Pavel Dyakonov + */ +class UuidType extends AbstractType +{ + /** + * {@inheritdoc} + */ + public function buildForm(FormBuilderInterface $builder, array $options) + { + $builder + ->addViewTransformer(new UuidToStringTransformer()) + ; + } + + /** + * {@inheritdoc} + */ + public function configureOptions(OptionsResolver $resolver) + { + $resolver->setDefaults([ + 'compound' => false, + 'invalid_message' => function (Options $options, $previousValue) { + return ($options['legacy_error_messages'] ?? true) + ? $previousValue + : 'Please enter a valid UUID.'; + }, + ]); + } +} diff --git a/src/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/UlidToStringTransformerTest.php b/src/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/UlidToStringTransformerTest.php new file mode 100644 index 0000000000..87a1592e25 --- /dev/null +++ b/src/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/UlidToStringTransformerTest.php @@ -0,0 +1,92 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form\Tests\Extension\Core\DataTransformer; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\Form\Exception\TransformationFailedException; +use Symfony\Component\Form\Extension\Core\DataTransformer\UlidToStringTransformer; +use Symfony\Component\Uid\Ulid; + +class UlidToStringTransformerTest extends TestCase +{ + public function provideValidUlid() + { + return [ + ['01D85PP1982GF6KTVFHQ7W78FB', new Ulid('01d85pp1982gf6ktvfhq7w78fb')], + ]; + } + + /** + * @dataProvider provideValidUlid + */ + public function testTransform($output, $input) + { + $transformer = new UlidToStringTransformer(); + + $input = new Ulid($input); + + $this->assertEquals($output, $transformer->transform($input)); + } + + public function testTransformEmpty() + { + $transformer = new UlidToStringTransformer(); + + $this->assertNull($transformer->transform(null)); + } + + public function testTransformExpectsUlid() + { + $transformer = new UlidToStringTransformer(); + + $this->expectException(TransformationFailedException::class); + + $transformer->transform('1234'); + } + + /** + * @dataProvider provideValidUlid + */ + public function testReverseTransform($input, $output) + { + $reverseTransformer = new UlidToStringTransformer(); + + $output = new Ulid($output); + + $this->assertEquals($output, $reverseTransformer->reverseTransform($input)); + } + + public function testReverseTransformEmpty() + { + $reverseTransformer = new UlidToStringTransformer(); + + $this->assertNull($reverseTransformer->reverseTransform('')); + } + + public function testReverseTransformExpectsString() + { + $reverseTransformer = new UlidToStringTransformer(); + + $this->expectException(TransformationFailedException::class); + + $reverseTransformer->reverseTransform(1234); + } + + public function testReverseTransformExpectsValidUlidString() + { + $reverseTransformer = new UlidToStringTransformer(); + + $this->expectException(TransformationFailedException::class); + + $reverseTransformer->reverseTransform('1234'); + } +} diff --git a/src/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/UuidToStringTransformerTest.php b/src/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/UuidToStringTransformerTest.php new file mode 100644 index 0000000000..f7a93beca8 --- /dev/null +++ b/src/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/UuidToStringTransformerTest.php @@ -0,0 +1,92 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form\Tests\Extension\Core\DataTransformer; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\Form\Exception\TransformationFailedException; +use Symfony\Component\Form\Extension\Core\DataTransformer\UuidToStringTransformer; +use Symfony\Component\Uid\Uuid; + +class UuidToStringTransformerTest extends TestCase +{ + public function provideValidUuid() + { + return [ + ['123e4567-e89b-12d3-a456-426655440000', new Uuid('123e4567-e89b-12d3-a456-426655440000')], + ]; + } + + /** + * @dataProvider provideValidUuid + */ + public function testTransform($output, $input) + { + $transformer = new UuidToStringTransformer(); + + $input = new Uuid($input); + + $this->assertEquals($output, $transformer->transform($input)); + } + + public function testTransformEmpty() + { + $transformer = new UuidToStringTransformer(); + + $this->assertNull($transformer->transform(null)); + } + + public function testTransformExpectsUuid() + { + $transformer = new UuidToStringTransformer(); + + $this->expectException(TransformationFailedException::class); + + $transformer->transform('1234'); + } + + /** + * @dataProvider provideValidUuid + */ + public function testReverseTransform($input, $output) + { + $reverseTransformer = new UuidToStringTransformer(); + + $output = new Uuid($output); + + $this->assertEquals($output, $reverseTransformer->reverseTransform($input)); + } + + public function testReverseTransformEmpty() + { + $reverseTransformer = new UuidToStringTransformer(); + + $this->assertNull($reverseTransformer->reverseTransform('')); + } + + public function testReverseTransformExpectsString() + { + $reverseTransformer = new UuidToStringTransformer(); + + $this->expectException(TransformationFailedException::class); + + $reverseTransformer->reverseTransform(1234); + } + + public function testReverseTransformExpectsValidUuidString() + { + $reverseTransformer = new UuidToStringTransformer(); + + $this->expectException(TransformationFailedException::class); + + $reverseTransformer->reverseTransform('1234'); + } +} diff --git a/src/Symfony/Component/Form/Tests/Extension/Core/Type/UlidTypeTest.php b/src/Symfony/Component/Form/Tests/Extension/Core/Type/UlidTypeTest.php new file mode 100644 index 0000000000..4f61992cb6 --- /dev/null +++ b/src/Symfony/Component/Form/Tests/Extension/Core/Type/UlidTypeTest.php @@ -0,0 +1,42 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form\Tests\Extension\Core\Type; + +use Symfony\Component\Form\Extension\Core\Type\UlidType; +use Symfony\Component\Uid\Ulid; + +final class UlidTypeTest extends BaseTypeTest +{ + public const TESTED_TYPE = UlidType::class; + + public function testPassUlidToView() + { + $ulid = '01D85PP1982GF6KTVFHQ7W78FB'; + + $form = $this->factory->create(static::TESTED_TYPE); + $form->setData(new Ulid($ulid)); + + $this->assertSame($ulid, $form->createView()->vars['value']); + } + + public function testSubmitNullUsesDefaultEmptyData($emptyData = '', $expectedData = null) + { + $form = $this->factory->create(static::TESTED_TYPE, null, [ + 'empty_data' => $emptyData, + ]); + $form->submit(null); + + $this->assertSame($expectedData, $form->getViewData()); + $this->assertSame($expectedData, $form->getNormData()); + $this->assertSame($expectedData, $form->getData()); + } +} diff --git a/src/Symfony/Component/Form/Tests/Extension/Core/Type/UuidTypeTest.php b/src/Symfony/Component/Form/Tests/Extension/Core/Type/UuidTypeTest.php new file mode 100644 index 0000000000..9b9bfb2d2a --- /dev/null +++ b/src/Symfony/Component/Form/Tests/Extension/Core/Type/UuidTypeTest.php @@ -0,0 +1,42 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form\Tests\Extension\Core\Type; + +use Symfony\Component\Form\Extension\Core\Type\UuidType; +use Symfony\Component\Uid\Uuid; + +final class UuidTypeTest extends BaseTypeTest +{ + public const TESTED_TYPE = UuidType::class; + + public function testPassUuidToView() + { + $uuid = '123e4567-e89b-12d3-a456-426655440000'; + + $form = $this->factory->create(static::TESTED_TYPE); + $form->setData(new Uuid($uuid)); + + $this->assertSame($uuid, $form->createView()->vars['value']); + } + + public function testSubmitNullUsesDefaultEmptyData($emptyData = '', $expectedData = null) + { + $form = $this->factory->create(static::TESTED_TYPE, null, [ + 'empty_data' => $emptyData, + ]); + $form->submit(null); + + $this->assertSame($expectedData, $form->getViewData()); + $this->assertSame($expectedData, $form->getNormData()); + $this->assertSame($expectedData, $form->getData()); + } +} diff --git a/src/Symfony/Component/Form/composer.json b/src/Symfony/Component/Form/composer.json index 2112953868..b9800490e9 100644 --- a/src/Symfony/Component/Form/composer.json +++ b/src/Symfony/Component/Form/composer.json @@ -39,7 +39,8 @@ "symfony/http-kernel": "^4.4|^5.0", "symfony/security-csrf": "^4.4|^5.0", "symfony/translation": "^4.4|^5.0", - "symfony/var-dumper": "^4.4|^5.0" + "symfony/var-dumper": "^4.4|^5.0", + "symfony/uid": "^5.1" }, "conflict": { "phpunit/phpunit": "<5.4.3",