From 3725e5d3222a8708e606c8a3989963e6df98f21a Mon Sep 17 00:00:00 2001 From: Dev Date: Wed, 25 Feb 2026 21:15:32 +0000 Subject: [PATCH] Fix bugs in validators, transformers, views and improve CS Fixer config MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Fix bitwise & vs | in UniqueFieldValidator::formatValue() flags (was always 0) - Fix ArrayToStringTransformer stripping non-digit chars — use trim() instead - Fix TelExtension stripping + country-code prefix from phone numbers - Fix FailureView defaulting to "Validation Failed" for non-validation errors - Remove unused `input` option from TimestampType (always uses DatePoint) - Improve CS Fixer config: add @Symfony:risky, @PHP85Migration, @PHP8x5Migration:risky, remove redundant rules, fix trailing_comma_in_multiline silent override - Apply CS Fixer: add license headers, static closures, get_class() to ::class Co-Authored-By: Claude Opus 4.6 --- .claude/settings.json | 12 +++++++ .php-cs-fixer.dist.php | 33 ++++++++++--------- .../TransformationFailedException.php | 4 +-- src/Extension/TelExtension.php | 8 ++--- src/Transformer/ArrayToStringTransformer.php | 2 +- .../JsonStringToArrayTransformer.php | 8 ++--- src/Type/HiddenEntityType.php | 8 ++--- src/Type/TimestampType.php | 6 ---- .../Constraints/UniqueFieldValidator.php | 2 +- src/View/FailureView.php | 5 +-- src/View/ValidationFailedView.php | 2 +- tests/Integrational/Entity/TestUser.php | 7 ++++ .../FormTypesIntegrationTest.php | 7 ++++ .../HiddenEntityTypeIntegrationTest.php | 7 ++++ ...nEntityTypeQueryBuilderIntegrationTest.php | 11 +++++-- .../ProblemNormalizerIntegrationTest.php | 7 ++++ tests/Integrational/ServiceWiringTest.php | 7 ++++ .../TelExtensionIntegrationTest.php | 7 ++++ .../UniqueFieldValidatorIntegrationTest.php | 7 ++++ tests/Unit/ApiFormTraitTest.php | 11 +++++-- tests/Unit/ChamberOrchestraFormBundleTest.php | 7 ++++ .../ChamberOrchestraFormExtensionTest.php | 7 ++++ .../Unit/Exception/ExceptionInterfaceTest.php | 7 ++++ .../InvalidArgumentExceptionTest.php | 7 ++++ tests/Unit/Exception/LogicExceptionTest.php | 7 ++++ .../SubmittedFormRequiredExceptionTest.php | 7 ++++ .../TransformationFailedExceptionTest.php | 7 ++++ .../TranslatableExceptionInterfaceTest.php | 7 ++++ .../XmlHttpRequestRequiredExceptionTest.php | 7 ++++ tests/Unit/Extension/TelExtensionTest.php | 8 +++++ tests/Unit/FormTraitTest.php | 21 ++++++++---- .../Normalizer/ProblemNormalizerTest.php | 7 ++++ .../ArrayToStringTransformerTest.php | 14 ++++++++ .../DateTimeToNumberTransformerTest.php | 7 ++++ .../JsonStringToArrayTransformerTest.php | 7 ++++ .../Transformer/TextToBoolTransformerTest.php | 7 ++++ tests/Unit/Type/Api/GetFormTest.php | 7 ++++ tests/Unit/Type/Api/MutationFormTest.php | 7 ++++ tests/Unit/Type/Api/PostFormTest.php | 7 ++++ tests/Unit/Type/Api/QueryFormTest.php | 7 ++++ tests/Unit/Type/BooleanTypeTest.php | 7 ++++ .../Type/HiddenEntityTypeEndToEndTest.php | 7 ++++ tests/Unit/Type/HiddenEntityTypeTest.php | 7 ++++ tests/Unit/Type/TimestampTypeTest.php | 23 ++++++++++--- tests/Unit/Utils/CollectionUtilsTest.php | 7 ++++ .../Validator/Constraints/UniqueFieldTest.php | 7 ++++ .../Constraints/UniqueFieldValidatorTest.php | 7 ++++ tests/Unit/View/FailureViewTest.php | 19 +++++++++++ tests/Unit/View/RedirectViewTest.php | 7 ++++ tests/Unit/View/SuccessHtmlViewTest.php | 7 ++++ tests/Unit/View/SuccessViewTest.php | 7 ++++ tests/Unit/View/ValidationFailedViewTest.php | 7 ++++ tests/Unit/View/ViolationViewTest.php | 7 ++++ 53 files changed, 385 insertions(+), 57 deletions(-) create mode 100644 .claude/settings.json diff --git a/.claude/settings.json b/.claude/settings.json new file mode 100644 index 0000000..432db3f --- /dev/null +++ b/.claude/settings.json @@ -0,0 +1,12 @@ +{ + "enabledPlugins": { + "code-review@claude-plugins-official": true, + "github@claude-plugins-official": true, + "feature-dev@claude-plugins-official": true, + "code-simplifier@claude-plugins-official": true, + "ralph-loop@claude-plugins-official": true, + "pr-review-toolkit@claude-plugins-official": true, + "claude-md-management@claude-plugins-official": true, + "php-lsp@claude-plugins-official": true + } +} diff --git a/.php-cs-fixer.dist.php b/.php-cs-fixer.dist.php index efe746d..9613a54 100644 --- a/.php-cs-fixer.dist.php +++ b/.php-cs-fixer.dist.php @@ -1,32 +1,35 @@ in(__DIR__ . '/src') - ->in(__DIR__ . '/tests') + ->in(__DIR__.'/src') + ->in(__DIR__.'/tests') + ->notPath('Resources/config/') ; return (new PhpCsFixer\Config()) ->setRules([ '@PER-CS' => true, '@Symfony' => true, - 'declare_strict_types' => true, - 'strict_param' => true, - 'array_syntax' => ['syntax' => 'short'], - 'ordered_imports' => ['sort_algorithm' => 'alpha'], - 'no_unused_imports' => true, - 'trailing_comma_in_multiline' => true, - 'single_quote' => true, - 'global_namespace_import' => [ - 'import_classes' => false, - 'import_constants' => false, - 'import_functions' => false, + '@Symfony:risky' => true, + '@PHP85Migration' => true, + '@PHP8x5Migration:risky' => true, + 'header_comment' => [ + 'header' => <<<'EOF' +This file is part of the ChamberOrchestra package. + +For the full copyright and license information, please view the LICENSE +file that was distributed with this source code. +EOF, + 'location' => 'after_declare_strict', + 'separate' => 'both', ], + 'strict_param' => true, 'native_function_invocation' => [ 'include' => ['@all'], - 'scope' => 'all', + 'scope' => 'namespaced', 'strict' => true, ], ]) ->setFinder($finder) ->setRiskyAllowed(true) -; + ; diff --git a/src/Exception/TransformationFailedException.php b/src/Exception/TransformationFailedException.php index 48f43fb..d81a45a 100644 --- a/src/Exception/TransformationFailedException.php +++ b/src/Exception/TransformationFailedException.php @@ -14,13 +14,13 @@ class TransformationFailedException extends \Symfony\Component\Form\Exception\TransformationFailedException implements ExceptionInterface { /** @param list $allowedTypes */ - public static function notAllowedType(mixed $id, array $allowedTypes): TransformationFailedException + public static function notAllowedType(mixed $id, array $allowedTypes): self { return new self( \sprintf( "Passed value is not one of allowed types, allowed types '%s', passed '%s'.", \implode(',', $allowedTypes), - \is_object($id) ? \get_class($id) : \gettype($id) + \is_object($id) ? $id::class : \gettype($id) ) ); } diff --git a/src/Extension/TelExtension.php b/src/Extension/TelExtension.php index 3f3f0b7..24258fc 100644 --- a/src/Extension/TelExtension.php +++ b/src/Extension/TelExtension.php @@ -28,15 +28,13 @@ public function buildForm(FormBuilderInterface $builder, array $options): void { $builder->addViewTransformer( new CallbackTransformer( - function (?string $value): ?string { - return $value; - }, - function (?string $value): ?string { + static fn (?string $value): ?string => $value, + static function (?string $value): ?string { if (null === $value || '' === $value) { return null; } - return \preg_replace('/[^\d]/', '', $value) ?? ''; + return \preg_replace('/[^\d+]/', '', $value) ?? ''; } ) ); diff --git a/src/Transformer/ArrayToStringTransformer.php b/src/Transformer/ArrayToStringTransformer.php index a3a752c..b4ce11b 100644 --- a/src/Transformer/ArrayToStringTransformer.php +++ b/src/Transformer/ArrayToStringTransformer.php @@ -38,7 +38,7 @@ public function reverseTransform(mixed $value): array } return \array_map( - static fn (string $value): string => \preg_replace('/[^\d]/', '', $value) ?? '', + static fn (string $value): string => \trim($value), \explode(',', $value) ); } diff --git a/src/Transformer/JsonStringToArrayTransformer.php b/src/Transformer/JsonStringToArrayTransformer.php index 7bd5050..2e8332e 100644 --- a/src/Transformer/JsonStringToArrayTransformer.php +++ b/src/Transformer/JsonStringToArrayTransformer.php @@ -24,9 +24,9 @@ public function transform(mixed $value): ?string } try { - $value = \json_encode($value, JSON_THROW_ON_ERROR); + $value = \json_encode($value, \JSON_THROW_ON_ERROR); } catch (\JsonException $e) { - throw new TransformationFailedException(\sprintf('Could not encode array into json.'), $e->getCode(), $e); + throw new TransformationFailedException('Could not encode array into json.', $e->getCode(), $e); } return $value; @@ -41,9 +41,9 @@ public function reverseTransform(mixed $value): ?array try { /** @var array $decoded */ - $decoded = \json_decode($value, true, 512, JSON_BIGINT_AS_STRING | JSON_THROW_ON_ERROR); + $decoded = \json_decode($value, true, 512, \JSON_BIGINT_AS_STRING | \JSON_THROW_ON_ERROR); } catch (\JsonException $e) { - throw new TransformationFailedException(\sprintf('Could not parse JSON into array.'), $e->getCode(), $e); + throw new TransformationFailedException('Could not parse JSON into array.', $e->getCode(), $e); } return $decoded; diff --git a/src/Type/HiddenEntityType.php b/src/Type/HiddenEntityType.php index 093f88b..4d439f9 100644 --- a/src/Type/HiddenEntityType.php +++ b/src/Type/HiddenEntityType.php @@ -43,7 +43,7 @@ public function buildForm(FormBuilderInterface $builder, array $options): void $builder->addViewTransformer( new CallbackTransformer( - function (?object $value) use ($entityClass, $choiceValue, $em): string|null { + static function (?object $value) use ($entityClass, $choiceValue, $em): string|null { if (null === $value) { return null; } @@ -99,7 +99,7 @@ public function configureOptions(OptionsResolver $resolver): void $resolver ->setRequired('class') ->setAllowedTypes('class', 'string') - ->setAllowedValues('class', function (string $value) use ($em): bool { + ->setAllowedValues('class', static function (string $value) use ($em): bool { if (!\class_exists($value)) { return false; } @@ -115,7 +115,7 @@ public function configureOptions(OptionsResolver $resolver): void $resolver ->setAllowedTypes('query_builder', ['null', 'callable', QueryBuilder::class]) - ->setNormalizer('query_builder', function (Options $options, mixed $value) use ($em): ?QueryBuilder { + ->setNormalizer('query_builder', static function (Options $options, mixed $value) use ($em): ?QueryBuilder { if (null === $value || $value instanceof QueryBuilder) { return $value; } @@ -139,7 +139,7 @@ public function configureOptions(OptionsResolver $resolver): void $resolver ->setAllowedTypes('choice_value', ['null', 'string']) - ->setNormalizer('choice_value', function (Options $options, mixed $value) use ($em): string { + ->setNormalizer('choice_value', static function (Options $options, mixed $value) use ($em): string { /** @var class-string $entityClass */ $entityClass = $options['class']; $class = $em->getClassMetadata($entityClass); diff --git a/src/Type/TimestampType.php b/src/Type/TimestampType.php index a0ce1c0..d167fd4 100644 --- a/src/Type/TimestampType.php +++ b/src/Type/TimestampType.php @@ -24,15 +24,9 @@ class TimestampType extends AbstractType public function configureOptions(OptionsResolver $resolver): void { $resolver->setDefaults([ - 'input' => 'datetime_immutable', 'grouping' => false, 'scale' => 0, ]); - - $resolver->setAllowedValues('input', [ - 'datetime', - 'datetime_immutable', - ]); } /** @param array $options */ diff --git a/src/Validator/Constraints/UniqueFieldValidator.php b/src/Validator/Constraints/UniqueFieldValidator.php index c8594c2..0e39d27 100644 --- a/src/Validator/Constraints/UniqueFieldValidator.php +++ b/src/Validator/Constraints/UniqueFieldValidator.php @@ -73,7 +73,7 @@ private function addViolation(UniqueField $constraint, mixed $value): void && (!\is_object($value) || $value instanceof \DateTimeInterface || \method_exists($value, '__toString'))) { $builder->setParameter( '{{ value }}', - $this->formatValue($value, self::PRETTY_DATE & self::OBJECT_TO_STRING) + $this->formatValue($value, self::PRETTY_DATE | self::OBJECT_TO_STRING) ); } $builder diff --git a/src/View/FailureView.php b/src/View/FailureView.php index 60d2f97..7e7fe05 100644 --- a/src/View/FailureView.php +++ b/src/View/FailureView.php @@ -13,6 +13,7 @@ use ChamberOrchestra\ViewBundle\View\ResponseView; use Symfony\Component\HttpFoundation\JsonResponse; +use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Serializer\Normalizer\NormalizerInterface; class FailureView extends ResponseView @@ -20,9 +21,9 @@ class FailureView extends ResponseView protected string $type = 'https://datatracker.ietf.org/doc/html/rfc9110#section-15'; protected readonly string $title; - public function __construct(int $status = JsonResponse::HTTP_BAD_REQUEST, string $message = 'Validation Failed') + public function __construct(int $status = JsonResponse::HTTP_BAD_REQUEST, ?string $message = null) { - $this->title = $message; + $this->title = $message ?? Response::$statusTexts[$status] ?? 'Error'; parent::__construct($status, ['Content-Type' => 'application/problem+json']); } diff --git a/src/View/ValidationFailedView.php b/src/View/ValidationFailedView.php index 5524c8c..0558db3 100644 --- a/src/View/ValidationFailedView.php +++ b/src/View/ValidationFailedView.php @@ -24,7 +24,7 @@ class ValidationFailedView extends FailureView /** @param list $violations */ public function __construct(array $violations = [], string $message = 'Validation Failed') { - $this->detail = \implode("\n", \array_map(fn (ViolationView $error): string => $error->title, $violations)); + $this->detail = \implode("\n", \array_map(static fn (ViolationView $error): string => $error->title, $violations)); $this->violations = $violations; parent::__construct(JsonResponse::HTTP_UNPROCESSABLE_ENTITY, $message); diff --git a/tests/Integrational/Entity/TestUser.php b/tests/Integrational/Entity/TestUser.php index e3cc35f..618a52a 100644 --- a/tests/Integrational/Entity/TestUser.php +++ b/tests/Integrational/Entity/TestUser.php @@ -2,6 +2,13 @@ declare(strict_types=1); +/* + * This file is part of the ChamberOrchestra package. + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Tests\Integrational\Entity; use Doctrine\ORM\Mapping as ORM; diff --git a/tests/Integrational/FormTypesIntegrationTest.php b/tests/Integrational/FormTypesIntegrationTest.php index a000218..d31219e 100644 --- a/tests/Integrational/FormTypesIntegrationTest.php +++ b/tests/Integrational/FormTypesIntegrationTest.php @@ -2,6 +2,13 @@ declare(strict_types=1); +/* + * This file is part of the ChamberOrchestra package. + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Tests\Integrational; use ChamberOrchestra\FormBundle\Type\BooleanType; diff --git a/tests/Integrational/HiddenEntityTypeIntegrationTest.php b/tests/Integrational/HiddenEntityTypeIntegrationTest.php index b6e7ca1..014301b 100644 --- a/tests/Integrational/HiddenEntityTypeIntegrationTest.php +++ b/tests/Integrational/HiddenEntityTypeIntegrationTest.php @@ -2,6 +2,13 @@ declare(strict_types=1); +/* + * This file is part of the ChamberOrchestra package. + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Tests\Integrational; use ChamberOrchestra\FormBundle\Type\HiddenEntityType; diff --git a/tests/Integrational/HiddenEntityTypeQueryBuilderIntegrationTest.php b/tests/Integrational/HiddenEntityTypeQueryBuilderIntegrationTest.php index c5593bd..7b52898 100644 --- a/tests/Integrational/HiddenEntityTypeQueryBuilderIntegrationTest.php +++ b/tests/Integrational/HiddenEntityTypeQueryBuilderIntegrationTest.php @@ -2,6 +2,13 @@ declare(strict_types=1); +/* + * This file is part of the ChamberOrchestra package. + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Tests\Integrational; use ChamberOrchestra\FormBundle\Type\HiddenEntityType; @@ -40,9 +47,7 @@ public function testQueryBuilderAndChoiceValueAreUsed(): void 'class' => TestUser::class, 'choice_value' => 'email', 'data_class' => null, - 'query_builder' => static function (EntityRepository $repository) { - return $repository->createQueryBuilder('u'); - }, + 'query_builder' => static fn (EntityRepository $repository) => $repository->createQueryBuilder('u'), ]); $form->submit('user@example.com'); diff --git a/tests/Integrational/ProblemNormalizerIntegrationTest.php b/tests/Integrational/ProblemNormalizerIntegrationTest.php index 71b4fc7..bc5463a 100644 --- a/tests/Integrational/ProblemNormalizerIntegrationTest.php +++ b/tests/Integrational/ProblemNormalizerIntegrationTest.php @@ -2,6 +2,13 @@ declare(strict_types=1); +/* + * This file is part of the ChamberOrchestra package. + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Tests\Integrational; use ChamberOrchestra\FormBundle\Exception\TranslatableExceptionInterface; diff --git a/tests/Integrational/ServiceWiringTest.php b/tests/Integrational/ServiceWiringTest.php index 6afa9b7..a43a404 100644 --- a/tests/Integrational/ServiceWiringTest.php +++ b/tests/Integrational/ServiceWiringTest.php @@ -2,6 +2,13 @@ declare(strict_types=1); +/* + * This file is part of the ChamberOrchestra package. + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Tests\Integrational; use ChamberOrchestra\FormBundle\Extension\TelExtension; diff --git a/tests/Integrational/TelExtensionIntegrationTest.php b/tests/Integrational/TelExtensionIntegrationTest.php index 8e16d44..9269947 100644 --- a/tests/Integrational/TelExtensionIntegrationTest.php +++ b/tests/Integrational/TelExtensionIntegrationTest.php @@ -2,6 +2,13 @@ declare(strict_types=1); +/* + * This file is part of the ChamberOrchestra package. + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Tests\Integrational; use PHPUnit\Framework\TestCase; diff --git a/tests/Integrational/UniqueFieldValidatorIntegrationTest.php b/tests/Integrational/UniqueFieldValidatorIntegrationTest.php index 9bfd4bc..16281f1 100644 --- a/tests/Integrational/UniqueFieldValidatorIntegrationTest.php +++ b/tests/Integrational/UniqueFieldValidatorIntegrationTest.php @@ -2,6 +2,13 @@ declare(strict_types=1); +/* + * This file is part of the ChamberOrchestra package. + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Tests\Integrational; use ChamberOrchestra\FormBundle\Validator\Constraints\UniqueField; diff --git a/tests/Unit/ApiFormTraitTest.php b/tests/Unit/ApiFormTraitTest.php index ff81e88..774d10e 100644 --- a/tests/Unit/ApiFormTraitTest.php +++ b/tests/Unit/ApiFormTraitTest.php @@ -2,6 +2,13 @@ declare(strict_types=1); +/* + * This file is part of the ChamberOrchestra package. + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Tests\Unit; use ChamberOrchestra\FormBundle\ApiFormTrait; @@ -32,7 +39,7 @@ public function exposeConvertRequestToArray(Request $request): array [], [], ['CONTENT_TYPE' => 'application/json'], - \json_encode(['payload' => ['id' => 1]], JSON_THROW_ON_ERROR) + \json_encode(['payload' => ['id' => 1]], \JSON_THROW_ON_ERROR) ); $request->files->set('file', ['name' => 'upload.txt']); @@ -91,7 +98,7 @@ public function testHandleApiCallThrowsOnNullRequest(): void $stack = new RequestStack(); $container = $this->createStub(ContainerInterface::class); - $container->method('get')->willReturnCallback(fn (string $id) => match ($id) { + $container->method('get')->willReturnCallback(static fn (string $id) => match ($id) { 'request_stack' => $stack, }); diff --git a/tests/Unit/ChamberOrchestraFormBundleTest.php b/tests/Unit/ChamberOrchestraFormBundleTest.php index 0def4b4..918e8e8 100644 --- a/tests/Unit/ChamberOrchestraFormBundleTest.php +++ b/tests/Unit/ChamberOrchestraFormBundleTest.php @@ -2,6 +2,13 @@ declare(strict_types=1); +/* + * This file is part of the ChamberOrchestra package. + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Tests\Unit; use ChamberOrchestra\FormBundle\ChamberOrchestraFormBundle; diff --git a/tests/Unit/DependencyInjection/ChamberOrchestraFormExtensionTest.php b/tests/Unit/DependencyInjection/ChamberOrchestraFormExtensionTest.php index 127098e..d5f7347 100644 --- a/tests/Unit/DependencyInjection/ChamberOrchestraFormExtensionTest.php +++ b/tests/Unit/DependencyInjection/ChamberOrchestraFormExtensionTest.php @@ -2,6 +2,13 @@ declare(strict_types=1); +/* + * This file is part of the ChamberOrchestra package. + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Tests\Unit\DependencyInjection; use ChamberOrchestra\FormBundle\DependencyInjection\ChamberOrchestraFormExtension; diff --git a/tests/Unit/Exception/ExceptionInterfaceTest.php b/tests/Unit/Exception/ExceptionInterfaceTest.php index e06e3df..4d4bce5 100644 --- a/tests/Unit/Exception/ExceptionInterfaceTest.php +++ b/tests/Unit/Exception/ExceptionInterfaceTest.php @@ -2,6 +2,13 @@ declare(strict_types=1); +/* + * This file is part of the ChamberOrchestra package. + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Tests\Unit\Exception; use ChamberOrchestra\FormBundle\Exception\ExceptionInterface; diff --git a/tests/Unit/Exception/InvalidArgumentExceptionTest.php b/tests/Unit/Exception/InvalidArgumentExceptionTest.php index e2d46a8..7ea228d 100644 --- a/tests/Unit/Exception/InvalidArgumentExceptionTest.php +++ b/tests/Unit/Exception/InvalidArgumentExceptionTest.php @@ -2,6 +2,13 @@ declare(strict_types=1); +/* + * This file is part of the ChamberOrchestra package. + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Tests\Unit\Exception; use ChamberOrchestra\FormBundle\Exception\ExceptionInterface; diff --git a/tests/Unit/Exception/LogicExceptionTest.php b/tests/Unit/Exception/LogicExceptionTest.php index 0095e6c..cc32ecf 100644 --- a/tests/Unit/Exception/LogicExceptionTest.php +++ b/tests/Unit/Exception/LogicExceptionTest.php @@ -2,6 +2,13 @@ declare(strict_types=1); +/* + * This file is part of the ChamberOrchestra package. + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Tests\Unit\Exception; use ChamberOrchestra\FormBundle\Exception\ExceptionInterface; diff --git a/tests/Unit/Exception/SubmittedFormRequiredExceptionTest.php b/tests/Unit/Exception/SubmittedFormRequiredExceptionTest.php index a011c97..832c09a 100644 --- a/tests/Unit/Exception/SubmittedFormRequiredExceptionTest.php +++ b/tests/Unit/Exception/SubmittedFormRequiredExceptionTest.php @@ -2,6 +2,13 @@ declare(strict_types=1); +/* + * This file is part of the ChamberOrchestra package. + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Tests\Unit\Exception; use ChamberOrchestra\FormBundle\Exception\ExceptionInterface; diff --git a/tests/Unit/Exception/TransformationFailedExceptionTest.php b/tests/Unit/Exception/TransformationFailedExceptionTest.php index d81bfd9..03f6449 100644 --- a/tests/Unit/Exception/TransformationFailedExceptionTest.php +++ b/tests/Unit/Exception/TransformationFailedExceptionTest.php @@ -2,6 +2,13 @@ declare(strict_types=1); +/* + * This file is part of the ChamberOrchestra package. + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Tests\Unit\Exception; use ChamberOrchestra\FormBundle\Exception\TransformationFailedException; diff --git a/tests/Unit/Exception/TranslatableExceptionInterfaceTest.php b/tests/Unit/Exception/TranslatableExceptionInterfaceTest.php index 631ee11..0ec069c 100644 --- a/tests/Unit/Exception/TranslatableExceptionInterfaceTest.php +++ b/tests/Unit/Exception/TranslatableExceptionInterfaceTest.php @@ -2,6 +2,13 @@ declare(strict_types=1); +/* + * This file is part of the ChamberOrchestra package. + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Tests\Unit\Exception; use ChamberOrchestra\FormBundle\Exception\TranslatableExceptionInterface; diff --git a/tests/Unit/Exception/XmlHttpRequestRequiredExceptionTest.php b/tests/Unit/Exception/XmlHttpRequestRequiredExceptionTest.php index eff34be..2f6f94b 100644 --- a/tests/Unit/Exception/XmlHttpRequestRequiredExceptionTest.php +++ b/tests/Unit/Exception/XmlHttpRequestRequiredExceptionTest.php @@ -2,6 +2,13 @@ declare(strict_types=1); +/* + * This file is part of the ChamberOrchestra package. + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Tests\Unit\Exception; use ChamberOrchestra\FormBundle\Exception\ExceptionInterface; diff --git a/tests/Unit/Extension/TelExtensionTest.php b/tests/Unit/Extension/TelExtensionTest.php index 30ab6ac..c7a8463 100644 --- a/tests/Unit/Extension/TelExtensionTest.php +++ b/tests/Unit/Extension/TelExtensionTest.php @@ -2,6 +2,13 @@ declare(strict_types=1); +/* + * This file is part of the ChamberOrchestra package. + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Tests\Unit\Extension; use ChamberOrchestra\FormBundle\Extension\TelExtension; @@ -35,6 +42,7 @@ public function testBuildFormAddsTransformer(): void $extension->buildForm($builder, []); self::assertSame('123', $captured->reverseTransform('1 (2)3')); + self::assertSame('+15551234567', $captured->reverseTransform('+1 (555) 123-4567')); self::assertNull($captured->reverseTransform('')); } } diff --git a/tests/Unit/FormTraitTest.php b/tests/Unit/FormTraitTest.php index 4f98417..9c88d57 100644 --- a/tests/Unit/FormTraitTest.php +++ b/tests/Unit/FormTraitTest.php @@ -2,6 +2,13 @@ declare(strict_types=1); +/* + * This file is part of the ChamberOrchestra package. + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Tests\Unit; use ChamberOrchestra\FormBundle\FormTrait; @@ -94,7 +101,7 @@ public function exposeOnFormSubmitted(FormInterface $form, ?callable $callable = $form->method('isValid')->willReturn(true); $form->method('getData')->willReturn(['id' => 1]); - $response = $host->exposeOnFormSubmitted($form, fn () => ['ok' => true]); + $response = $host->exposeOnFormSubmitted($form, static fn () => ['ok' => true]); self::assertInstanceOf(DataView::class, $response); } @@ -195,7 +202,7 @@ public function testCreateRedirectResponseReturnsViewForXmlHttpRequest(): void $stack->push($request); $container = $this->createStub(ContainerInterface::class); - $container->method('get')->willReturnCallback(fn (string $id) => match ($id) { + $container->method('get')->willReturnCallback(static fn (string $id) => match ($id) { 'request_stack' => $stack, }); @@ -236,7 +243,7 @@ public function testCreateRedirectResponseReturnsResponseForNonXmlHttpRequest(): $stack->push($request); $container = $this->createStub(ContainerInterface::class); - $container->method('get')->willReturnCallback(fn (string $id) => match ($id) { + $container->method('get')->willReturnCallback(static fn (string $id) => match ($id) { 'request_stack' => $stack, }); @@ -277,7 +284,7 @@ public function testCreateSuccessHtmlResponseHandlesXmlHttpRequest(): void $stack->push($request); $container = $this->createStub(ContainerInterface::class); - $container->method('get')->willReturnCallback(fn (string $id) => match ($id) { + $container->method('get')->willReturnCallback(static fn (string $id) => match ($id) { 'request_stack' => $stack, }); @@ -322,7 +329,7 @@ public function testCreateSuccessHtmlResponseHandlesNonXmlHttpRequest(): void $stack->push($request); $container = $this->createStub(ContainerInterface::class); - $container->method('get')->willReturnCallback(fn (string $id) => match ($id) { + $container->method('get')->willReturnCallback(static fn (string $id) => match ($id) { 'request_stack' => $stack, }); @@ -363,7 +370,7 @@ public function testHandleFormCallThrowsOnNullRequest(): void $stack = new RequestStack(); $container = $this->createStub(ContainerInterface::class); - $container->method('get')->willReturnCallback(function (string $id) use ($stack) { + $container->method('get')->willReturnCallback(static function (string $id) use ($stack) { return match ($id) { 'request_stack' => $stack, 'form.factory' => Forms::createFormFactory(), @@ -398,7 +405,7 @@ public function testCreateRedirectResponseFallsBackWhenNoRequest(): void $stack = new RequestStack(); $container = $this->createStub(ContainerInterface::class); - $container->method('get')->willReturnCallback(fn (string $id) => match ($id) { + $container->method('get')->willReturnCallback(static fn (string $id) => match ($id) { 'request_stack' => $stack, }); diff --git a/tests/Unit/Serializer/Normalizer/ProblemNormalizerTest.php b/tests/Unit/Serializer/Normalizer/ProblemNormalizerTest.php index 6e749bb..2acdd0c 100644 --- a/tests/Unit/Serializer/Normalizer/ProblemNormalizerTest.php +++ b/tests/Unit/Serializer/Normalizer/ProblemNormalizerTest.php @@ -2,6 +2,13 @@ declare(strict_types=1); +/* + * This file is part of the ChamberOrchestra package. + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Tests\Unit\Serializer\Normalizer; use ChamberOrchestra\FormBundle\Exception\TranslatableExceptionInterface; diff --git a/tests/Unit/Transformer/ArrayToStringTransformerTest.php b/tests/Unit/Transformer/ArrayToStringTransformerTest.php index 55d2cb9..8b365d9 100644 --- a/tests/Unit/Transformer/ArrayToStringTransformerTest.php +++ b/tests/Unit/Transformer/ArrayToStringTransformerTest.php @@ -2,6 +2,13 @@ declare(strict_types=1); +/* + * This file is part of the ChamberOrchestra package. + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Tests\Unit\Transformer; use ChamberOrchestra\FormBundle\Exception\TransformationFailedException; @@ -19,6 +26,13 @@ public function testTransformAndReverseTransform(): void self::assertSame(['123', '456'], $transformer->reverseTransform('123, 456')); } + public function testReverseTransformTrimsWhitespace(): void + { + $transformer = new ArrayToStringTransformer(); + + self::assertSame(['foo', 'bar', 'baz'], $transformer->reverseTransform('foo, bar, baz')); + } + public function testTransformRejectsInvalidType(): void { $transformer = new ArrayToStringTransformer(); diff --git a/tests/Unit/Transformer/DateTimeToNumberTransformerTest.php b/tests/Unit/Transformer/DateTimeToNumberTransformerTest.php index 4adf2d2..a1be2e0 100644 --- a/tests/Unit/Transformer/DateTimeToNumberTransformerTest.php +++ b/tests/Unit/Transformer/DateTimeToNumberTransformerTest.php @@ -2,6 +2,13 @@ declare(strict_types=1); +/* + * This file is part of the ChamberOrchestra package. + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Tests\Unit\Transformer; use ChamberOrchestra\FormBundle\Transformer\DateTimeToNumberTransformer; diff --git a/tests/Unit/Transformer/JsonStringToArrayTransformerTest.php b/tests/Unit/Transformer/JsonStringToArrayTransformerTest.php index 62e7b8d..ddf4912 100644 --- a/tests/Unit/Transformer/JsonStringToArrayTransformerTest.php +++ b/tests/Unit/Transformer/JsonStringToArrayTransformerTest.php @@ -2,6 +2,13 @@ declare(strict_types=1); +/* + * This file is part of the ChamberOrchestra package. + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Tests\Unit\Transformer; use ChamberOrchestra\FormBundle\Exception\TransformationFailedException; diff --git a/tests/Unit/Transformer/TextToBoolTransformerTest.php b/tests/Unit/Transformer/TextToBoolTransformerTest.php index 6ed4092..7e05f8a 100644 --- a/tests/Unit/Transformer/TextToBoolTransformerTest.php +++ b/tests/Unit/Transformer/TextToBoolTransformerTest.php @@ -2,6 +2,13 @@ declare(strict_types=1); +/* + * This file is part of the ChamberOrchestra package. + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Tests\Unit\Transformer; use ChamberOrchestra\FormBundle\Exception\TransformationFailedException; diff --git a/tests/Unit/Type/Api/GetFormTest.php b/tests/Unit/Type/Api/GetFormTest.php index 6fe1d8e..bb5fbd7 100644 --- a/tests/Unit/Type/Api/GetFormTest.php +++ b/tests/Unit/Type/Api/GetFormTest.php @@ -2,6 +2,13 @@ declare(strict_types=1); +/* + * This file is part of the ChamberOrchestra package. + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Tests\Unit\Type\Api; use ChamberOrchestra\FormBundle\Type\Api\GetForm; diff --git a/tests/Unit/Type/Api/MutationFormTest.php b/tests/Unit/Type/Api/MutationFormTest.php index 8de1502..c991900 100644 --- a/tests/Unit/Type/Api/MutationFormTest.php +++ b/tests/Unit/Type/Api/MutationFormTest.php @@ -2,6 +2,13 @@ declare(strict_types=1); +/* + * This file is part of the ChamberOrchestra package. + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Tests\Unit\Type\Api; use ChamberOrchestra\FormBundle\Type\Api\MutationForm; diff --git a/tests/Unit/Type/Api/PostFormTest.php b/tests/Unit/Type/Api/PostFormTest.php index 6316c02..3e0b196 100644 --- a/tests/Unit/Type/Api/PostFormTest.php +++ b/tests/Unit/Type/Api/PostFormTest.php @@ -2,6 +2,13 @@ declare(strict_types=1); +/* + * This file is part of the ChamberOrchestra package. + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Tests\Unit\Type\Api; use ChamberOrchestra\FormBundle\Type\Api\PostForm; diff --git a/tests/Unit/Type/Api/QueryFormTest.php b/tests/Unit/Type/Api/QueryFormTest.php index d6c7841..00938dc 100644 --- a/tests/Unit/Type/Api/QueryFormTest.php +++ b/tests/Unit/Type/Api/QueryFormTest.php @@ -2,6 +2,13 @@ declare(strict_types=1); +/* + * This file is part of the ChamberOrchestra package. + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Tests\Unit\Type\Api; use ChamberOrchestra\FormBundle\Type\Api\GetForm; diff --git a/tests/Unit/Type/BooleanTypeTest.php b/tests/Unit/Type/BooleanTypeTest.php index 562d26e..897d477 100644 --- a/tests/Unit/Type/BooleanTypeTest.php +++ b/tests/Unit/Type/BooleanTypeTest.php @@ -2,6 +2,13 @@ declare(strict_types=1); +/* + * This file is part of the ChamberOrchestra package. + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Tests\Unit\Type; use ChamberOrchestra\FormBundle\Transformer\TextToBoolTransformer; diff --git a/tests/Unit/Type/HiddenEntityTypeEndToEndTest.php b/tests/Unit/Type/HiddenEntityTypeEndToEndTest.php index e666bc2..36a9604 100644 --- a/tests/Unit/Type/HiddenEntityTypeEndToEndTest.php +++ b/tests/Unit/Type/HiddenEntityTypeEndToEndTest.php @@ -2,6 +2,13 @@ declare(strict_types=1); +/* + * This file is part of the ChamberOrchestra package. + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Tests\Unit\Type; use ChamberOrchestra\FormBundle\Type\HiddenEntityType; diff --git a/tests/Unit/Type/HiddenEntityTypeTest.php b/tests/Unit/Type/HiddenEntityTypeTest.php index 406b45c..59ea049 100644 --- a/tests/Unit/Type/HiddenEntityTypeTest.php +++ b/tests/Unit/Type/HiddenEntityTypeTest.php @@ -2,6 +2,13 @@ declare(strict_types=1); +/* + * This file is part of the ChamberOrchestra package. + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Tests\Unit\Type; use ChamberOrchestra\FormBundle\Exception\InvalidArgumentException; diff --git a/tests/Unit/Type/TimestampTypeTest.php b/tests/Unit/Type/TimestampTypeTest.php index 4867765..73409f7 100644 --- a/tests/Unit/Type/TimestampTypeTest.php +++ b/tests/Unit/Type/TimestampTypeTest.php @@ -2,11 +2,19 @@ declare(strict_types=1); +/* + * This file is part of the ChamberOrchestra package. + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Tests\Unit\Type; use ChamberOrchestra\FormBundle\Transformer\DateTimeToNumberTransformer; use ChamberOrchestra\FormBundle\Type\TimestampType; use PHPUnit\Framework\TestCase; +use Symfony\Component\Clock\DatePoint; use Symfony\Component\Form\Extension\Core\Type\NumberType; use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\OptionsResolver\OptionsResolver; @@ -21,12 +29,11 @@ public function testConfigureOptionsSetsDefaults(): void $type->configureOptions($resolver); $options = $resolver->resolve(); - self::assertSame('datetime_immutable', $options['input']); self::assertFalse($options['grouping']); self::assertSame(0, $options['scale']); } - public function testBuildFormAddsTransformer(): void + public function testBuildFormAddsDatePointTransformer(): void { $type = new TimestampType(); $builder = $this->createMock(FormBuilderInterface::class); @@ -34,9 +41,17 @@ public function testBuildFormAddsTransformer(): void $builder ->expects($this->once()) ->method('addModelTransformer') - ->with($this->callback(static fn ($transformer) => $transformer instanceof DateTimeToNumberTransformer)); + ->with($this->callback(static function ($transformer): bool { + if (!$transformer instanceof DateTimeToNumberTransformer) { + return false; + } + + $result = $transformer->reverseTransform(0); + + return $result instanceof DatePoint; + })); - $type->buildForm($builder, ['input' => 'datetime_immutable']); + $type->buildForm($builder, []); } public function testParentIsNumberType(): void diff --git a/tests/Unit/Utils/CollectionUtilsTest.php b/tests/Unit/Utils/CollectionUtilsTest.php index d2ce2a1..51cc140 100644 --- a/tests/Unit/Utils/CollectionUtilsTest.php +++ b/tests/Unit/Utils/CollectionUtilsTest.php @@ -2,6 +2,13 @@ declare(strict_types=1); +/* + * This file is part of the ChamberOrchestra package. + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Tests\Unit\Utils; use ChamberOrchestra\FormBundle\Utils\CollectionUtils; diff --git a/tests/Unit/Validator/Constraints/UniqueFieldTest.php b/tests/Unit/Validator/Constraints/UniqueFieldTest.php index 4f11359..043ae98 100644 --- a/tests/Unit/Validator/Constraints/UniqueFieldTest.php +++ b/tests/Unit/Validator/Constraints/UniqueFieldTest.php @@ -2,6 +2,13 @@ declare(strict_types=1); +/* + * This file is part of the ChamberOrchestra package. + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Tests\Unit\Validator\Constraints; use ChamberOrchestra\FormBundle\Validator\Constraints\UniqueField; diff --git a/tests/Unit/Validator/Constraints/UniqueFieldValidatorTest.php b/tests/Unit/Validator/Constraints/UniqueFieldValidatorTest.php index ce84a27..ed29d34 100644 --- a/tests/Unit/Validator/Constraints/UniqueFieldValidatorTest.php +++ b/tests/Unit/Validator/Constraints/UniqueFieldValidatorTest.php @@ -2,6 +2,13 @@ declare(strict_types=1); +/* + * This file is part of the ChamberOrchestra package. + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Tests\Unit\Validator\Constraints; use ChamberOrchestra\FormBundle\Exception\LogicException; diff --git a/tests/Unit/View/FailureViewTest.php b/tests/Unit/View/FailureViewTest.php index 6c522bd..7a2cb14 100644 --- a/tests/Unit/View/FailureViewTest.php +++ b/tests/Unit/View/FailureViewTest.php @@ -2,6 +2,13 @@ declare(strict_types=1); +/* + * This file is part of the ChamberOrchestra package. + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Tests\Unit\View; use ChamberOrchestra\FormBundle\View\FailureView; @@ -34,4 +41,16 @@ public function testNormalizeUsesNormalizer(): void self::assertSame('Bad', $data['title']); self::assertSame('https://datatracker.ietf.org/doc/html/rfc9110#section-15', $data['type']); } + + public function testDefaultTitleDerivedFromStatusCode(): void + { + $normalizer = $this->createMock(NormalizerInterface::class); + $normalizer->method('normalize')->willReturnCallback(static fn (array $data) => $data); + + $badRequest = new FailureView(JsonResponse::HTTP_BAD_REQUEST); + self::assertSame('Bad Request', $badRequest->normalize($normalizer)['title']); + + $serverError = new FailureView(JsonResponse::HTTP_INTERNAL_SERVER_ERROR); + self::assertSame('Internal Server Error', $serverError->normalize($normalizer)['title']); + } } diff --git a/tests/Unit/View/RedirectViewTest.php b/tests/Unit/View/RedirectViewTest.php index d4f6b13..58c34b1 100644 --- a/tests/Unit/View/RedirectViewTest.php +++ b/tests/Unit/View/RedirectViewTest.php @@ -2,6 +2,13 @@ declare(strict_types=1); +/* + * This file is part of the ChamberOrchestra package. + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Tests\Unit\View; use ChamberOrchestra\FormBundle\View\RedirectView; diff --git a/tests/Unit/View/SuccessHtmlViewTest.php b/tests/Unit/View/SuccessHtmlViewTest.php index 621a274..ea853e0 100644 --- a/tests/Unit/View/SuccessHtmlViewTest.php +++ b/tests/Unit/View/SuccessHtmlViewTest.php @@ -2,6 +2,13 @@ declare(strict_types=1); +/* + * This file is part of the ChamberOrchestra package. + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Tests\Unit\View; use ChamberOrchestra\FormBundle\View\SuccessHtmlView; diff --git a/tests/Unit/View/SuccessViewTest.php b/tests/Unit/View/SuccessViewTest.php index 403fec5..aebf2f9 100644 --- a/tests/Unit/View/SuccessViewTest.php +++ b/tests/Unit/View/SuccessViewTest.php @@ -2,6 +2,13 @@ declare(strict_types=1); +/* + * This file is part of the ChamberOrchestra package. + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Tests\Unit\View; use ChamberOrchestra\FormBundle\View\SuccessView; diff --git a/tests/Unit/View/ValidationFailedViewTest.php b/tests/Unit/View/ValidationFailedViewTest.php index 25d09d2..5ebe8d3 100644 --- a/tests/Unit/View/ValidationFailedViewTest.php +++ b/tests/Unit/View/ValidationFailedViewTest.php @@ -2,6 +2,13 @@ declare(strict_types=1); +/* + * This file is part of the ChamberOrchestra package. + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Tests\Unit\View; use ChamberOrchestra\FormBundle\View\ValidationFailedView; diff --git a/tests/Unit/View/ViolationViewTest.php b/tests/Unit/View/ViolationViewTest.php index aae15dd..aaa92fd 100644 --- a/tests/Unit/View/ViolationViewTest.php +++ b/tests/Unit/View/ViolationViewTest.php @@ -2,6 +2,13 @@ declare(strict_types=1); +/* + * This file is part of the ChamberOrchestra package. + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Tests\Unit\View; use ChamberOrchestra\FormBundle\View\ViolationView;