diff --git a/library/ContainerRegistry.php b/library/ContainerRegistry.php index d4d8c3b9..9bcc593e 100644 --- a/library/ContainerRegistry.php +++ b/library/ContainerRegistry.php @@ -19,6 +19,13 @@ use Respect\Validation\Message\Formatter\NestedArrayFormatter; use Respect\Validation\Message\Formatter\NestedListStringFormatter; use Respect\Validation\Message\Formatter\TemplateResolver; use Respect\Validation\Message\InterpolationRenderer; +use Respect\Validation\Message\Modifier; +use Respect\Validation\Message\Modifier\ListAndModifier; +use Respect\Validation\Message\Modifier\ListOrModifier; +use Respect\Validation\Message\Modifier\QuoteModifier; +use Respect\Validation\Message\Modifier\RawModifier; +use Respect\Validation\Message\Modifier\StringifyModifier; +use Respect\Validation\Message\Modifier\TransModifier; use Respect\Validation\Message\Renderer; use Respect\Validation\Message\Translator; use Respect\Validation\Message\Translator\DummyTranslator; @@ -49,6 +56,20 @@ final class ContainerRegistry 'respect.validation.formatter.full_message' => autowire(NestedListStringFormatter::class), 'respect.validation.formatter.messages' => autowire(NestedArrayFormatter::class), 'respect.validation.ignored_backtrace_paths' => [__DIR__ . '/Validator.php'], + Modifier::class => factory(static fn(Container $container) => new TransModifier( + $container->get(Translator::class), + new ListOrModifier( + $container->get(Translator::class), + new ListAndModifier( + $container->get(Translator::class), + new QuoteModifier( + new RawModifier( + new StringifyModifier($container->get(Stringifier::class)), + ), + ), + ), + ), + )), Validator::class => factory(static fn(Container $container) => new Validator( $container->get(Factory::class), $container->get(Renderer::class), diff --git a/library/Message/InterpolationRenderer.php b/library/Message/InterpolationRenderer.php index cdfca21c..71e9c015 100644 --- a/library/Message/InterpolationRenderer.php +++ b/library/Message/InterpolationRenderer.php @@ -9,26 +9,21 @@ declare(strict_types=1); namespace Respect\Validation\Message; -use Respect\Stringifier\Stringifier; use Respect\Validation\Message\Formatter\TemplateResolver; -use Respect\Validation\Message\Placeholder\Listed; -use Respect\Validation\Message\Placeholder\Quoted; use Respect\Validation\Name; use Respect\Validation\Result; use function array_key_exists; -use function is_array; -use function is_bool; -use function is_scalar; +use function array_pad; +use function assert; use function is_string; use function preg_replace_callback; -use function print_r; final readonly class InterpolationRenderer implements Renderer { public function __construct( private Translator $translator, - private Stringifier $stringifier = new ValidationStringifier(), + private Modifier $modifier, private TemplateResolver $templateResolver = new TemplateResolver(), ) { } @@ -44,13 +39,7 @@ final readonly class InterpolationRenderer implements Renderer $rendered = (string) preg_replace_callback( '/{{(\w+)(\|([^}]+))?}}/', - function (array $matches) use ($parameters) { - if (!array_key_exists($matches[1], $parameters)) { - return $matches[0]; - } - - return $this->placeholder($matches[1], $parameters[$matches[1]], $matches[3] ?? null); - }, + fn(array $matches) => $this->processPlaceholder($parameters, $matches), $this->translator->translate($givenTemplate ?? $ruleTemplate), ); @@ -61,32 +50,20 @@ final readonly class InterpolationRenderer implements Renderer return $rendered; } - private function placeholder( - string $name, - mixed $value, - string|null $modifier = null, - ): string { - if ($modifier === 'quote' && is_string($value)) { - return $this->placeholder($name, new Quoted($value)); + /** + * @param array $parameters + * @param array $matches + */ + private function processPlaceholder(array $parameters, array $matches): string + { + [$placeholder, $name, , $pipe] = array_pad($matches, 4, null); + assert(is_string($placeholder)); + assert(is_string($name)); + if (!array_key_exists($name, $parameters)) { + return $placeholder; } - if ($modifier === 'listOr' && is_array($value)) { - return $this->placeholder($name, new Listed($value, $this->translator->translate('or'))); - } - - if ($modifier === 'listAnd' && is_array($value)) { - return $this->placeholder($name, new Listed($value, $this->translator->translate('and'))); - } - - if ($modifier === 'raw' && is_scalar($value)) { - return is_bool($value) ? (string) (int) $value : (string) $value; - } - - if ($modifier === 'trans' && is_string($value)) { - return $this->translator->translate($value); - } - - return $this->stringifier->stringify($value, 0) ?? print_r($value, true); + return $this->modifier->modify($parameters[$name], $pipe); } private function getName(Result $result): mixed diff --git a/library/Message/Modifier.php b/library/Message/Modifier.php new file mode 100644 index 00000000..317de48b --- /dev/null +++ b/library/Message/Modifier.php @@ -0,0 +1,15 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Message; + +interface Modifier +{ + public function modify(mixed $value, string|null $pipe): string; +} diff --git a/library/Message/Modifier/ListAndModifier.php b/library/Message/Modifier/ListAndModifier.php new file mode 100644 index 00000000..3a534a30 --- /dev/null +++ b/library/Message/Modifier/ListAndModifier.php @@ -0,0 +1,37 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Message\Modifier; + +use Respect\Validation\Message\Modifier; +use Respect\Validation\Message\Placeholder\Listed; +use Respect\Validation\Message\Translator; + +use function is_array; + +final readonly class ListAndModifier implements Modifier +{ + public function __construct( + private Translator $translator, + private Modifier $nextModifier, + ) { + } + + public function modify(mixed $value, string|null $pipe): string + { + if ($pipe !== 'listAnd' || !is_array($value)) { + return $this->nextModifier->modify($value, $pipe); + } + + return $this->nextModifier->modify( + new Listed($value, $this->translator->translate('and')), + null, + ); + } +} diff --git a/library/Message/Modifier/ListOrModifier.php b/library/Message/Modifier/ListOrModifier.php new file mode 100644 index 00000000..6871f67c --- /dev/null +++ b/library/Message/Modifier/ListOrModifier.php @@ -0,0 +1,37 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Message\Modifier; + +use Respect\Validation\Message\Modifier; +use Respect\Validation\Message\Placeholder\Listed; +use Respect\Validation\Message\Translator; + +use function is_array; + +final readonly class ListOrModifier implements Modifier +{ + public function __construct( + private Translator $translator, + private Modifier $nextModifier, + ) { + } + + public function modify(mixed $value, string|null $pipe): string + { + if ($pipe !== 'listOr' || !is_array($value)) { + return $this->nextModifier->modify($value, $pipe); + } + + return $this->nextModifier->modify( + new Listed($value, $this->translator->translate('or')), + null, + ); + } +} diff --git a/library/Message/Modifier/QuoteModifier.php b/library/Message/Modifier/QuoteModifier.php new file mode 100644 index 00000000..2a056790 --- /dev/null +++ b/library/Message/Modifier/QuoteModifier.php @@ -0,0 +1,32 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Message\Modifier; + +use Respect\Validation\Message\Modifier; +use Respect\Validation\Message\Placeholder\Quoted; + +use function is_string; + +final readonly class QuoteModifier implements Modifier +{ + public function __construct( + private Modifier $nextModifier, + ) { + } + + public function modify(mixed $value, string|null $pipe): string + { + if ($pipe !== 'quote' || !is_string($value)) { + return $this->nextModifier->modify($value, $pipe); + } + + return $this->nextModifier->modify(new Quoted($value), null); + } +} diff --git a/library/Message/Modifier/RawModifier.php b/library/Message/Modifier/RawModifier.php new file mode 100644 index 00000000..170fd23f --- /dev/null +++ b/library/Message/Modifier/RawModifier.php @@ -0,0 +1,36 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Message\Modifier; + +use Respect\Validation\Message\Modifier; + +use function is_bool; +use function is_scalar; + +final readonly class RawModifier implements Modifier +{ + public function __construct( + private Modifier $nextModifier, + ) { + } + + public function modify(mixed $value, string|null $pipe): string + { + if ($pipe !== 'raw') { + return $this->nextModifier->modify($value, $pipe); + } + + if (!is_scalar($value)) { + return $this->nextModifier->modify($value, null); + } + + return is_bool($value) ? (string) (int) $value : (string) $value; + } +} diff --git a/library/Message/Modifier/StringifyModifier.php b/library/Message/Modifier/StringifyModifier.php new file mode 100644 index 00000000..6892776c --- /dev/null +++ b/library/Message/Modifier/StringifyModifier.php @@ -0,0 +1,37 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Message\Modifier; + +use Respect\Stringifier\Stringifier; +use Respect\Validation\Exceptions\ComponentException; +use Respect\Validation\Message\Modifier; + +use function print_r; +use function sprintf; + +final readonly class StringifyModifier implements Modifier +{ + public function __construct( + private Stringifier $stringifier, + ) { + } + + public function modify(mixed $value, string|null $pipe): string + { + if ($pipe !== null) { + throw new ComponentException(sprintf( + 'StringifyModifier only accepts null as pipe but "%s" was given.', + $pipe, + )); + } + + return $this->stringifier->stringify($value, 0) ?? print_r($value, true); + } +} diff --git a/library/Message/Modifier/TransModifier.php b/library/Message/Modifier/TransModifier.php new file mode 100644 index 00000000..e35f1d29 --- /dev/null +++ b/library/Message/Modifier/TransModifier.php @@ -0,0 +1,33 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Message\Modifier; + +use Respect\Validation\Message\Modifier; +use Respect\Validation\Message\Translator; + +use function is_string; + +final readonly class TransModifier implements Modifier +{ + public function __construct( + private Translator $translator, + private Modifier $nextModifier, + ) { + } + + public function modify(mixed $value, string|null $pipe): string + { + if ($pipe !== 'trans' || !is_string($value)) { + return $this->nextModifier->modify($value, $pipe); + } + + return $this->translator->translate($value); + } +} diff --git a/tests/library/Message/NullStringifier.php b/tests/library/Message/NullStringifier.php new file mode 100644 index 00000000..ec675249 --- /dev/null +++ b/tests/library/Message/NullStringifier.php @@ -0,0 +1,20 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Test\Message; + +use Respect\Stringifier\Stringifier; + +final class NullStringifier implements Stringifier +{ + public function stringify(mixed $raw, int $depth): string|null + { + return null; + } +} diff --git a/tests/library/Message/TestingModifier.php b/tests/library/Message/TestingModifier.php new file mode 100644 index 00000000..795924e1 --- /dev/null +++ b/tests/library/Message/TestingModifier.php @@ -0,0 +1,23 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Test\Message; + +use Respect\Validation\Message\Modifier; + +use function print_r; +use function sprintf; + +final readonly class TestingModifier implements Modifier +{ + public function modify(mixed $value, string|null $pipe): string + { + return $pipe ? sprintf('%s(%s)', $pipe, print_r($value, true)) : print_r($value, true); + } +} diff --git a/tests/unit/Message/InterpolationRendererTest.php b/tests/unit/Message/InterpolationRendererTest.php index 8b419650..799d0d83 100644 --- a/tests/unit/Message/InterpolationRendererTest.php +++ b/tests/unit/Message/InterpolationRendererTest.php @@ -15,7 +15,7 @@ use Respect\Validation\Message\Translator\ArrayTranslator; use Respect\Validation\Message\Translator\DummyTranslator; use Respect\Validation\Name; use Respect\Validation\Test\Builders\ResultBuilder; -use Respect\Validation\Test\Message\TestingStringifier; +use Respect\Validation\Test\Message\TestingModifier; use Respect\Validation\Test\TestCase; use function sprintf; @@ -26,7 +26,7 @@ final class InterpolationRendererTest extends TestCase #[Test] public function itShouldRenderResultWithCustomTemplate(): void { - $renderer = new InterpolationRenderer(new DummyTranslator(), new TestingStringifier()); + $renderer = new InterpolationRenderer(new DummyTranslator(), new TestingModifier()); $result = (new ResultBuilder())->template('This is my template')->build(); @@ -36,9 +36,8 @@ final class InterpolationRendererTest extends TestCase #[Test] public function itShouldRenderResultProcessingParametersInTheTemplate(): void { - $stringifier = new TestingStringifier(); - - $renderer = new InterpolationRenderer(new DummyTranslator(), $stringifier); + $modifier = new TestingModifier(); + $renderer = new InterpolationRenderer(new DummyTranslator(), $modifier); $key = 'foo'; $value = true; @@ -49,70 +48,27 @@ final class InterpolationRendererTest extends TestCase ->build(); self::assertSame( - 'Will replace ' . $stringifier->stringify($value, 0), + 'Will replace ' . $modifier->modify($value, null), $renderer->render($result, []), ); } #[Test] - public function itShouldRenderResultProcessingRawParametersInTheTemplate(): void + public function itShouldRenderResultProcessingModifierParametersInTheTemplate(): void { - $stringifier = new TestingStringifier(); - - $renderer = new InterpolationRenderer(new DummyTranslator(), $stringifier); + $modifier = new TestingModifier(); + $renderer = new InterpolationRenderer(new DummyTranslator(), $modifier); $key = 'foo'; $value = 0.1; $result = (new ResultBuilder()) - ->template(sprintf('Will replace {{%1$s}} and {{%1$s|raw}}', $key)) + ->template(sprintf('Will replace {{%1$s}} and {{%1$s|modifier}}', $key)) ->parameters([$key => $value]) ->build(); self::assertSame( - sprintf('Will replace %s and 0.1', $stringifier->stringify($value, 0)), - $renderer->render($result, []), - ); - } - - #[Test] - public function itShouldRenderResultProcessingRawBooleanParametersInTheTemplate(): void - { - $stringifier = new TestingStringifier(); - - $renderer = new InterpolationRenderer(new DummyTranslator(), $stringifier); - - $key = 'foo'; - $value = false; - - $result = (new ResultBuilder()) - ->template(sprintf('Will replace {{%1$s}} and {{%1$s|raw}}', $key)) - ->parameters([$key => $value]) - ->build(); - - self::assertSame( - sprintf('Will replace %s and 0', $stringifier->stringify($value, 0)), - $renderer->render($result, []), - ); - } - - #[Test] - public function itShouldRenderResultProcessingTranslatableParametersInTheTemplate(): void - { - $key = 'foo'; - $value = 'original'; - $translation = 'translated'; - - $stringifier = new TestingStringifier(); - $renderer = new InterpolationRenderer(new ArrayTranslator([$value => $translation]), $stringifier); - - $result = (new ResultBuilder()) - ->template(sprintf('Will replace {{%1$s}} and {{%1$s|trans}}', $key)) - ->parameters([$key => $value]) - ->build(); - - self::assertSame( - sprintf('Will replace %s and %s', $stringifier->stringify($value, 0), $translation), + sprintf('Will replace %s and %s', $modifier->modify($value, null), $modifier->modify($value, 'modifier')), $renderer->render($result, []), ); } @@ -120,9 +76,8 @@ final class InterpolationRendererTest extends TestCase #[Test] public function itShouldRenderResultProcessingNameParameterWhenItIsInTheTemplateAndItIsString(): void { - $stringifier = new TestingStringifier(); - - $renderer = new InterpolationRenderer(new DummyTranslator(), $stringifier); + $modifier = new TestingModifier(); + $renderer = new InterpolationRenderer(new DummyTranslator(), $modifier); $value = 'original'; @@ -132,7 +87,7 @@ final class InterpolationRendererTest extends TestCase ->build(); self::assertSame( - sprintf('Will replace %s', $stringifier->stringify(new Name($value), 0) ?? 'FAILED'), + sprintf('Will replace %s', $modifier->modify(new Name($value), null)), $renderer->render($result, []), ); } @@ -140,9 +95,8 @@ final class InterpolationRendererTest extends TestCase #[Test] public function itShouldRenderResultProcessingNameParameterWhenItIsInTheTemplateAndItIsNotString(): void { - $stringifier = new TestingStringifier(); - - $renderer = new InterpolationRenderer(new DummyTranslator(), $stringifier); + $modifier = new TestingModifier(); + $renderer = new InterpolationRenderer(new DummyTranslator(), $modifier); $value = true; @@ -154,7 +108,7 @@ final class InterpolationRendererTest extends TestCase self::assertSame( sprintf( 'Will replace %s', - $stringifier->stringify($value, 0), + $modifier->modify($value, null), ), $renderer->render($result, []), ); @@ -163,8 +117,8 @@ final class InterpolationRendererTest extends TestCase #[Test] public function itShouldRenderResultProcessingNameAsSomeParameterInTheTemplate(): void { - $stringifier = new TestingStringifier(); - $renderer = new InterpolationRenderer(new DummyTranslator(), $stringifier); + $modifier = new TestingModifier(); + $renderer = new InterpolationRenderer(new DummyTranslator(), $modifier); $name = 'my name'; @@ -174,7 +128,7 @@ final class InterpolationRendererTest extends TestCase ->build(); self::assertSame( - 'Will replace ' . $stringifier->stringify(new Name($name), 0), + 'Will replace ' . $modifier->modify(new Name($name), null), $renderer->render($result, []), ); } @@ -182,9 +136,8 @@ final class InterpolationRendererTest extends TestCase #[Test] public function itShouldRenderResultProcessingInputAsNameWhenResultHasNoName(): void { - $stringifier = new TestingStringifier(); - - $renderer = new InterpolationRenderer(new DummyTranslator(), $stringifier); + $modifier = new TestingModifier(); + $renderer = new InterpolationRenderer(new DummyTranslator(), $modifier); $input = 42; @@ -196,7 +149,7 @@ final class InterpolationRendererTest extends TestCase self::assertSame( sprintf( 'Will replace %s', - $stringifier->stringify($input, 0), + $modifier->modify($input, null), ), $renderer->render($result, []), ); @@ -205,9 +158,8 @@ final class InterpolationRendererTest extends TestCase #[Test] public function itShouldRenderResultProcessingInputAsSomeParameterInTheTemplate(): void { - $stringifier = new TestingStringifier(); - - $renderer = new InterpolationRenderer(new DummyTranslator(), $stringifier); + $modifier = new TestingModifier(); + $renderer = new InterpolationRenderer(new DummyTranslator(), $modifier); $input = 42; @@ -217,7 +169,7 @@ final class InterpolationRendererTest extends TestCase ->build(); self::assertSame( - sprintf('Will replace %s', $stringifier->stringify($input, 0)), + sprintf('Will replace %s', $modifier->modify($input, null)), $renderer->render($result, []), ); } @@ -227,9 +179,8 @@ final class InterpolationRendererTest extends TestCase { $parameterNameValue = 'fake name'; - $stringifier = new TestingStringifier(); - - $renderer = new InterpolationRenderer(new DummyTranslator(), $stringifier); + $modifier = new TestingModifier(); + $renderer = new InterpolationRenderer(new DummyTranslator(), $modifier); $result = (new ResultBuilder()) ->template('Will replace {{subject}}') @@ -238,7 +189,7 @@ final class InterpolationRendererTest extends TestCase ->build(); self::assertSame( - sprintf('Will replace %s', $stringifier->stringify(new Name($parameterNameValue), 0)), + sprintf('Will replace %s', $modifier->modify(new Name($parameterNameValue), null)), $renderer->render($result, []), ); } @@ -246,9 +197,8 @@ final class InterpolationRendererTest extends TestCase #[Test] public function itShouldRenderResultNotOverwritingInputParameterWithRealInput(): void { - $stringifier = new TestingStringifier(); - - $renderer = new InterpolationRenderer(new DummyTranslator(), $stringifier); + $modifier = new TestingModifier(); + $renderer = new InterpolationRenderer(new DummyTranslator(), $modifier); $input = 'real input'; @@ -259,7 +209,7 @@ final class InterpolationRendererTest extends TestCase ->build(); self::assertSame( - sprintf('Will replace %s', $stringifier->stringify($input, 0)), + sprintf('Will replace %s', $modifier->modify($input, null)), $renderer->render($result, []), ); } @@ -267,7 +217,8 @@ final class InterpolationRendererTest extends TestCase #[Test] public function itShouldRenderResultProcessingNonExistingParameters(): void { - $renderer = new InterpolationRenderer(new DummyTranslator(), new TestingStringifier()); + $modifier = new TestingModifier(); + $renderer = new InterpolationRenderer(new DummyTranslator(), $modifier); $result = (new ResultBuilder()) ->template('Will not replace {{unknown}}') @@ -283,7 +234,8 @@ final class InterpolationRendererTest extends TestCase $translations = [$template => 'This is my translated template with {{foo}}']; $translator = new ArrayTranslator($translations); - $renderer = new InterpolationRenderer($translator, new TestingStringifier()); + $modifier = new TestingModifier(); + $renderer = new InterpolationRenderer($translator, $modifier); $result = (new ResultBuilder()) ->template($template) @@ -295,15 +247,16 @@ final class InterpolationRendererTest extends TestCase #[Test] public function itShouldRenderResultWithNonCustomTemplate(): void { - $stringifier = new TestingStringifier(); - $renderer = new InterpolationRenderer(new DummyTranslator(), $stringifier); + $translator = new DummyTranslator(); + $modifier = new TestingModifier(); + $renderer = new InterpolationRenderer($translator, $modifier); $result = (new ResultBuilder())->build(); self::assertSame( sprintf( '%s must be a valid stub', - $stringifier->stringify($result->input, 0), + $modifier->modify($result->input, null), ), $renderer->render($result, []), ); @@ -312,15 +265,16 @@ final class InterpolationRendererTest extends TestCase #[Test] public function itShouldRenderResultWithNonCustomTemplateAndInvertedMode(): void { - $stringifier = new TestingStringifier(); - $renderer = new InterpolationRenderer(new DummyTranslator(), $stringifier); + $translator = new DummyTranslator(); + $modifier = new TestingModifier(); + $renderer = new InterpolationRenderer($translator, $modifier); $result = (new ResultBuilder())->hasInvertedMode()->build(); self::assertSame( sprintf( '%s must not be a valid stub', - $stringifier->stringify($result->input, 0), + $modifier->modify($result->input, null), ), $renderer->render($result, []), ); @@ -329,7 +283,9 @@ final class InterpolationRendererTest extends TestCase #[Test] public function itShouldRenderResultWithNonCustomTemplateWhenCannotFindAttachedTemplate(): void { - $renderer = new InterpolationRenderer(new DummyTranslator(), new TestingStringifier()); + $translator = new DummyTranslator(); + $modifier = new TestingModifier(); + $renderer = new InterpolationRenderer($translator, $modifier); $result = (new ResultBuilder())->template('__not_standard__')->hasInvertedMode()->build(); @@ -342,7 +298,9 @@ final class InterpolationRendererTest extends TestCase #[Test] public function itShouldRenderResultWithItsAdjacentsWhenItHasNoCustomTemplate(): void { - $renderer = new InterpolationRenderer(new DummyTranslator(), new TestingStringifier()); + $translator = new DummyTranslator(); + $modifier = new TestingModifier(); + $renderer = new InterpolationRenderer($translator, $modifier); $result = (new ResultBuilder())->template('__1st__') ->adjacent( @@ -368,7 +326,9 @@ final class InterpolationRendererTest extends TestCase ->adjacent((new ResultBuilder())->template('and this is a adjacent')->build()) ->build(); - $renderer = new InterpolationRenderer(new DummyTranslator(), new TestingStringifier()); + $translator = new DummyTranslator(); + $modifier = new TestingModifier(); + $renderer = new InterpolationRenderer($translator, $modifier); self::assertSame($template, $renderer->render($result, [])); } diff --git a/tests/unit/Message/Modifier/ListAndModifierTest.php b/tests/unit/Message/Modifier/ListAndModifierTest.php new file mode 100644 index 00000000..8a47e7d1 --- /dev/null +++ b/tests/unit/Message/Modifier/ListAndModifierTest.php @@ -0,0 +1,69 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Message\Modifier; + +use PHPUnit\Framework\Attributes\CoversClass; +use PHPUnit\Framework\Attributes\Test; +use Respect\Validation\Message\Placeholder\Listed; +use Respect\Validation\Message\Translator\ArrayTranslator; +use Respect\Validation\Test\Message\TestingModifier; +use Respect\Validation\Test\TestCase; + +#[CoversClass(ListAndModifier::class)] +final class ListAndModifierTest extends TestCase +{ + #[Test] + public function itShouldNotModifyWhenModifierIsNotListAnd(): void + { + $translator = new ArrayTranslator(['and' => 'and']); + $nextModifier = new TestingModifier(); + $modifier = new ListAndModifier($translator, $nextModifier); + + $value = ['item1', 'item2']; + $pipe = 'listOr'; + + $result = $modifier->modify($value, $pipe); + + self::assertSame($nextModifier->modify($value, $pipe), $result); + } + + #[Test] + public function itShouldNotModifyWhenValueIsNotArray(): void + { + $translator = new ArrayTranslator(['and' => 'and']); + $nextModifier = new TestingModifier(); + $modifier = new ListAndModifier($translator, $nextModifier); + + $value = 'not an array'; + $pipe = 'listAnd'; + + $result = $modifier->modify($value, $pipe); + + self::assertSame($nextModifier->modify($value, $pipe), $result); + } + + #[Test] + public function itShouldModifyWhenModifierIsListAndAndValueIsArray(): void + { + $translator = new ArrayTranslator(['and' => 'and']); + $nextModifier = new TestingModifier(); + $modifier = new ListAndModifier($translator, $nextModifier); + + $value = ['item1', 'item2', 'item3']; + $pipe = 'listAnd'; + + $result = $modifier->modify($value, $pipe); + + $expectedValue = new Listed($value, $translator->translate('and')); + $expected = $nextModifier->modify($expectedValue, null); + + self::assertSame($expected, $result); + } +} diff --git a/tests/unit/Message/Modifier/ListOrModifierTest.php b/tests/unit/Message/Modifier/ListOrModifierTest.php new file mode 100644 index 00000000..b7042a84 --- /dev/null +++ b/tests/unit/Message/Modifier/ListOrModifierTest.php @@ -0,0 +1,69 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Message\Modifier; + +use PHPUnit\Framework\Attributes\CoversClass; +use PHPUnit\Framework\Attributes\Test; +use Respect\Validation\Message\Placeholder\Listed; +use Respect\Validation\Message\Translator\ArrayTranslator; +use Respect\Validation\Test\Message\TestingModifier; +use Respect\Validation\Test\TestCase; + +#[CoversClass(ListOrModifier::class)] +final class ListOrModifierTest extends TestCase +{ + #[Test] + public function itShouldNotModifyWhenModifierIsNotListOr(): void + { + $translator = new ArrayTranslator(['or' => 'or']); + $nextModifier = new TestingModifier(); + $modifier = new ListOrModifier($translator, $nextModifier); + + $value = ['item1', 'item2']; + $pipe = 'listAnd'; + + $result = $modifier->modify($value, $pipe); + + self::assertSame($nextModifier->modify($value, $pipe), $result); + } + + #[Test] + public function itShouldNotModifyWhenValueIsNotArray(): void + { + $translator = new ArrayTranslator(['or' => 'or']); + $nextModifier = new TestingModifier(); + $modifier = new ListOrModifier($translator, $nextModifier); + + $value = 'not an array'; + $pipe = 'listOr'; + + $result = $modifier->modify($value, $pipe); + + self::assertSame($nextModifier->modify($value, $pipe), $result); + } + + #[Test] + public function itShouldModifyWhenModifierIsListOrAndValueIsArray(): void + { + $translator = new ArrayTranslator(['or' => 'or']); + $nextModifier = new TestingModifier(); + $modifier = new ListOrModifier($translator, $nextModifier); + + $value = ['item1', 'item2', 'item3']; + $pipe = 'listOr'; + + $result = $modifier->modify($value, $pipe); + + $expectedValue = new Listed($value, $translator->translate('or')); + $expected = $nextModifier->modify($expectedValue, null); + + self::assertSame($expected, $result); + } +} diff --git a/tests/unit/Message/Modifier/QuoteModifierTest.php b/tests/unit/Message/Modifier/QuoteModifierTest.php new file mode 100644 index 00000000..3ebcff8c --- /dev/null +++ b/tests/unit/Message/Modifier/QuoteModifierTest.php @@ -0,0 +1,65 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Message\Modifier; + +use PHPUnit\Framework\Attributes\CoversClass; +use PHPUnit\Framework\Attributes\Test; +use Respect\Validation\Message\Placeholder\Quoted; +use Respect\Validation\Test\Message\TestingModifier; +use Respect\Validation\Test\TestCase; + +#[CoversClass(QuoteModifier::class)] +final class QuoteModifierTest extends TestCase +{ + #[Test] + public function itShouldNotModifyWhenModifierIsNotQuote(): void + { + $nextModifier = new TestingModifier(); + $modifier = new QuoteModifier($nextModifier); + + $value = 'some string'; + $pipe = 'notQuote'; + + $result = $modifier->modify($value, $pipe); + + self::assertSame($nextModifier->modify($value, $pipe), $result); + } + + #[Test] + public function itShouldNotModifyWhenValueIsNotString(): void + { + $nextModifier = new TestingModifier(); + $modifier = new QuoteModifier($nextModifier); + + $value = ['not', 'a', 'string']; + $pipe = 'quote'; + + $result = $modifier->modify($value, $pipe); + + self::assertSame($nextModifier->modify($value, $pipe), $result); + } + + #[Test] + public function itShouldModifyWhenModifierIsQuoteAndValueIsString(): void + { + $nextModifier = new TestingModifier(); + $modifier = new QuoteModifier($nextModifier); + + $value = 'some string'; + $pipe = 'quote'; + + $result = $modifier->modify($value, $pipe); + + $expectedValue = new Quoted($value); + $expected = $nextModifier->modify($expectedValue, null); + + self::assertSame($expected, $result); + } +} diff --git a/tests/unit/Message/Modifier/RawModifierTest.php b/tests/unit/Message/Modifier/RawModifierTest.php new file mode 100644 index 00000000..819bf263 --- /dev/null +++ b/tests/unit/Message/Modifier/RawModifierTest.php @@ -0,0 +1,117 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Message\Modifier; + +use PHPUnit\Framework\Attributes\CoversClass; +use PHPUnit\Framework\Attributes\Test; +use Respect\Validation\Test\Message\TestingModifier; +use Respect\Validation\Test\TestCase; + +#[CoversClass(RawModifier::class)] +final class RawModifierTest extends TestCase +{ + #[Test] + public function itShouldNotModifyWhenModifierIsNotRaw(): void + { + $nextModifier = new TestingModifier(); + $modifier = new RawModifier($nextModifier); + + $value = 'some value'; + $pipe = 'notRaw'; + + $result = $modifier->modify($value, $pipe); + + self::assertSame($nextModifier->modify($value, $pipe), $result); + } + + #[Test] + public function itShouldNotModifyWhenValueIsNotScalar(): void + { + $nextModifier = new TestingModifier(); + $modifier = new RawModifier($nextModifier); + + $value = ['not', 'scalar']; + $pipe = 'raw'; + + $result = $modifier->modify($value, $pipe); + + self::assertSame($nextModifier->modify($value, null), $result); + } + + #[Test] + public function itShouldModifyWhenModifierIsRawAndValueIsScalarString(): void + { + $nextModifier = new TestingModifier(); + $modifier = new RawModifier($nextModifier); + + $value = 'some string'; + $pipe = 'raw'; + + $result = $modifier->modify($value, $pipe); + + self::assertSame($value, $result); + } + + #[Test] + public function itShouldModifyWhenModifierIsRawAndValueIsScalarInt(): void + { + $nextModifier = new TestingModifier(); + $modifier = new RawModifier($nextModifier); + + $value = 123; + $pipe = 'raw'; + + $result = $modifier->modify($value, $pipe); + + self::assertSame('123', $result); + } + + #[Test] + public function itShouldModifyWhenModifierIsRawAndValueIsScalarFloat(): void + { + $nextModifier = new TestingModifier(); + $modifier = new RawModifier($nextModifier); + + $value = 123.456; + $pipe = 'raw'; + + $result = $modifier->modify($value, $pipe); + + self::assertSame('123.456', $result); + } + + #[Test] + public function itShouldModifyWhenModifierIsRawAndValueIsScalarBoolTrue(): void + { + $nextModifier = new TestingModifier(); + $modifier = new RawModifier($nextModifier); + + $value = true; + $pipe = 'raw'; + + $result = $modifier->modify($value, $pipe); + + self::assertSame('1', $result); + } + + #[Test] + public function itShouldModifyWhenModifierIsRawAndValueIsScalarBoolFalse(): void + { + $nextModifier = new TestingModifier(); + $modifier = new RawModifier($nextModifier); + + $value = false; + $pipe = 'raw'; + + $result = $modifier->modify($value, $pipe); + + self::assertSame('0', $result); + } +} diff --git a/tests/unit/Message/Modifier/StringifyModifierTest.php b/tests/unit/Message/Modifier/StringifyModifierTest.php new file mode 100644 index 00000000..b60858e0 --- /dev/null +++ b/tests/unit/Message/Modifier/StringifyModifierTest.php @@ -0,0 +1,63 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Message\Modifier; + +use PHPUnit\Framework\Attributes\CoversClass; +use PHPUnit\Framework\Attributes\Test; +use Respect\Validation\Exceptions\ComponentException; +use Respect\Validation\Test\Message\NullStringifier; +use Respect\Validation\Test\Message\TestingStringifier; +use Respect\Validation\Test\TestCase; + +use function print_r; +use function sprintf; + +#[CoversClass(StringifyModifier::class)] +final class StringifyModifierTest extends TestCase +{ + #[Test] + public function itShouldUseStringifierWhenAvailable(): void + { + $value = ['some', 'array']; + + $stringifier = new TestingStringifier(); + $modifier = new StringifyModifier($stringifier); + + $expected = $stringifier->stringify($value, 0); + + self::assertSame($expected, $modifier->modify($value, null)); + } + + #[Test] + public function itShouldUseFallbackWhenStringifierIsNull(): void + { + $value = ['some', 'array']; + $expected = print_r($value, true); + + $modifier = new StringifyModifier(new NullStringifier()); + + self::assertSame($expected, $modifier->modify($value, null)); + } + + #[Test] + public function itShouldFailWhenPipeParameterIsGiven(): void + { + $pipe = 'someModifier'; + + $modifier = new StringifyModifier(new TestingStringifier()); + + $this->expectExceptionObject(new ComponentException(sprintf( + 'StringifyModifier only accepts null as pipe but "%s" was given.', + $pipe, + ))); + + $modifier->modify(['some', 'array'], $pipe); + } +} diff --git a/tests/unit/Message/Modifier/TransModifierTest.php b/tests/unit/Message/Modifier/TransModifierTest.php new file mode 100644 index 00000000..8f4de03d --- /dev/null +++ b/tests/unit/Message/Modifier/TransModifierTest.php @@ -0,0 +1,83 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +namespace Respect\Validation\Message\Modifier; + +use PHPUnit\Framework\Attributes\CoversClass; +use PHPUnit\Framework\Attributes\Test; +use Respect\Validation\Message\Translator\ArrayTranslator; +use Respect\Validation\Test\Message\TestingModifier; +use Respect\Validation\Test\TestCase; + +#[CoversClass(TransModifier::class)] +final class TransModifierTest extends TestCase +{ + #[Test] + public function itShouldNotModifyWhenModifierIsNotTrans(): void + { + $translator = new ArrayTranslator(['message' => 'translated message']); + $nextModifier = new TestingModifier(); + $modifier = new TransModifier($translator, $nextModifier); + + $value = 'message'; + $pipe = 'notTrans'; + + $result = $modifier->modify($value, $pipe); + + self::assertSame($nextModifier->modify($value, $pipe), $result); + } + + #[Test] + public function itShouldNotModifyWhenValueIsNotString(): void + { + $translator = new ArrayTranslator(['message' => 'translated message']); + $nextModifier = new TestingModifier(); + $modifier = new TransModifier($translator, $nextModifier); + + $value = ['not', 'a', 'string']; + $pipe = 'trans'; + + $result = $modifier->modify($value, $pipe); + + self::assertSame($nextModifier->modify($value, $pipe), $result); + } + + #[Test] + public function itShouldModifyWhenModifierIsTransAndValueIsString(): void + { + $key = 'message'; + $translatedMessage = 'translated message'; + $translator = new ArrayTranslator([$key => $translatedMessage]); + $nextModifier = new TestingModifier(); + $modifier = new TransModifier($translator, $nextModifier); + + $value = $key; + $pipe = 'trans'; + + $result = $modifier->modify($value, $pipe); + + self::assertSame($translatedMessage, $result); + } + + #[Test] + public function itShouldReturnKeyWhenTranslationNotFound(): void + { + $key = 'nonexistent'; + $translator = new ArrayTranslator(['message' => 'translated message']); + $nextModifier = new TestingModifier(); + $modifier = new TransModifier($translator, $nextModifier); + + $value = $key; + $pipe = 'trans'; + + $result = $modifier->modify($value, $pipe); + + self::assertSame($key, $result); + } +}