Skip to content

Commit 80d92bf

Browse files
committed
Use "respect/string-formatter"
1 parent 9862963 commit 80d92bf

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

48 files changed

+249
-1477
lines changed

composer.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,8 @@
2323
"php": ">=8.5",
2424
"php-di/php-di": "^7.1",
2525
"psr/container": "^2.0",
26-
"respect/stringifier": "^2.0.0",
26+
"respect/string-formatter": "^0.1.0",
27+
"respect/stringifier": "^3.0",
2728
"symfony/polyfill-mbstring": "^1.33"
2829
},
2930
"require-dev": {
@@ -46,6 +47,7 @@
4647
"sokil/php-isocodes-db-only": "^4.0",
4748
"squizlabs/php_codesniffer": "^4.0",
4849
"symfony/console": "^7.4",
50+
"symfony/translation": "^8.0",
4951
"symfony/var-exporter": "^6.4 || ^7.0"
5052
},
5153
"suggest": {

docs/messages/placeholder-pipes.md

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -62,25 +62,25 @@ v::templated(
6262
// → Le champ "adresse e-mail" est invalide
6363
```
6464

65-
### listOr
65+
### list:or
6666

67-
The `listOr` modifier formats arrays as readable lists using "or":
67+
The `list:or` modifier formats arrays as readable lists using "or":
6868

6969
```php
7070
v::templated(
71-
'Status must be {{haystack|listOr}}',
71+
'Status must be {{haystack|list:or}}',
7272
v::in(['active', 'pending', 'archived']),
7373
)->assert('deleted');
7474
// → Status must be "active", "pending", or "archived"
7575
```
7676

77-
### listAnd
77+
### list:and
7878

79-
The `listAnd` modifier formats arrays as readable lists using "and":
79+
The `list:and` modifier formats arrays as readable lists using "and":
8080

8181
```php
8282
v::templated(
83-
'User must have {{roles|listAnd}} roles to perform this action',
83+
'User must have {{roles|list:and}} roles to perform this action',
8484
v::callback(fn(User $user) => $user->hasRoles(['admin', 'editor'])),
8585
['roles' => ['admin', 'editor']],
8686
)->assert($user);

library/ContainerRegistry.php

Lines changed: 41 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -12,27 +12,33 @@
1212

1313
use DI\Container;
1414
use Psr\Container\ContainerInterface;
15+
use Respect\StringFormatter\BypassTranslator;
16+
use Respect\StringFormatter\Modifier;
17+
use Respect\StringFormatter\Modifiers\ListModifier;
18+
use Respect\StringFormatter\Modifiers\QuoteModifier;
19+
use Respect\StringFormatter\Modifiers\RawModifier;
20+
use Respect\StringFormatter\Modifiers\StringifyModifier;
21+
use Respect\StringFormatter\Modifiers\TransModifier;
22+
use Respect\StringFormatter\PlaceholderFormatter;
23+
use Respect\Stringifier\DumpStringifier;
24+
use Respect\Stringifier\Handler;
25+
use Respect\Stringifier\Handlers\CompositeHandler;
26+
use Respect\Stringifier\HandlerStringifier;
1527
use Respect\Stringifier\Quoter;
16-
use Respect\Stringifier\Quoters\StandardQuoter;
28+
use Respect\Stringifier\Quoters\CodeQuoter;
1729
use Respect\Stringifier\Stringifier;
1830
use Respect\Validation\Message\Formatter\FirstResultStringFormatter;
1931
use Respect\Validation\Message\Formatter\NestedArrayFormatter;
2032
use Respect\Validation\Message\Formatter\NestedListStringFormatter;
2133
use Respect\Validation\Message\Formatter\TemplateResolver;
34+
use Respect\Validation\Message\Handler\NameHandler;
35+
use Respect\Validation\Message\Handler\PathHandler;
36+
use Respect\Validation\Message\Handler\ResultHandler;
2237
use Respect\Validation\Message\InterpolationRenderer;
23-
use Respect\Validation\Message\Modifier;
24-
use Respect\Validation\Message\Modifier\ListAndModifier;
25-
use Respect\Validation\Message\Modifier\ListOrModifier;
26-
use Respect\Validation\Message\Modifier\QuoteModifier;
27-
use Respect\Validation\Message\Modifier\RawModifier;
28-
use Respect\Validation\Message\Modifier\StringifyModifier;
29-
use Respect\Validation\Message\Modifier\TransModifier;
3038
use Respect\Validation\Message\Renderer;
31-
use Respect\Validation\Message\Translator;
32-
use Respect\Validation\Message\Translator\DummyTranslator;
33-
use Respect\Validation\Message\ValidationStringifier;
3439
use Respect\Validation\Transformers\Prefix;
3540
use Respect\Validation\Transformers\Transformer;
41+
use Symfony\Contracts\Translation\TranslatorInterface;
3642

3743
use function DI\autowire;
3844
use function DI\create;
@@ -47,9 +53,7 @@ public static function createContainer(): Container
4753
return new Container([
4854
Transformer::class => create(Prefix::class),
4955
TemplateResolver::class => create(TemplateResolver::class),
50-
Quoter::class => create(StandardQuoter::class)->constructor(ValidationStringifier::MAXIMUM_LENGTH),
51-
Stringifier::class => autowire(ValidationStringifier::class),
52-
Translator::class => autowire(DummyTranslator::class),
56+
TranslatorInterface::class => autowire(BypassTranslator::class),
5357
Renderer::class => autowire(InterpolationRenderer::class),
5458
ResultFilter::class => create(OnlyFailedChildrenResultFilter::class),
5559
'respect.validation.formatter.message' => autowire(FirstResultStringFormatter::class),
@@ -61,19 +65,33 @@ public static function createContainer(): Container
6165
$container->get(Transformer::class),
6266
$container->get('respect.validation.rule_factory.namespaces'),
6367
)),
68+
Quoter::class => create(CodeQuoter::class)->constructor(120),
69+
Handler::class => factory(static function (Container $container) {
70+
$handler = CompositeHandler::create();
71+
$handler->prependHandler(new PathHandler($container->get(Quoter::class)));
72+
$handler->prependHandler(new NameHandler());
73+
$handler->prependHandler(new ResultHandler($handler));
74+
75+
return $handler;
76+
}),
77+
PlaceholderFormatter::class => factory(static fn(Container $container) => new PlaceholderFormatter(
78+
[],
79+
$container->get(Modifier::class),
80+
)),
81+
Stringifier::class => factory(static fn(Container $container) => new HandlerStringifier(
82+
$container->get(Handler::class),
83+
new DumpStringifier(),
84+
)),
6485
Modifier::class => factory(static fn(Container $container) => new TransModifier(
65-
$container->get(Translator::class),
66-
new ListOrModifier(
67-
$container->get(Translator::class),
68-
new ListAndModifier(
69-
$container->get(Translator::class),
70-
new QuoteModifier(
71-
new RawModifier(
72-
new StringifyModifier($container->get(Stringifier::class)),
73-
),
86+
new ListModifier(
87+
new QuoteModifier(
88+
new RawModifier(
89+
new StringifyModifier($container->get(Stringifier::class)),
7490
),
7591
),
92+
$container->get(TranslatorInterface::class),
7693
),
94+
$container->get(TranslatorInterface::class),
7795
)),
7896
ValidatorBuilder::class => factory(static fn(Container $container) => new ValidatorBuilder(
7997
$container->get(ValidatorFactory::class),

library/Exceptions/ValidationException.php

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -18,22 +18,19 @@
1818
namespace Respect\Validation\Exceptions;
1919

2020
use InvalidArgumentException;
21+
use Respect\Validation\ResultQuery;
2122

2223
use function array_shift;
2324
use function in_array;
2425
use function realpath;
2526

2627
final class ValidationException extends InvalidArgumentException implements Exception
2728
{
28-
/**
29-
* @param array<string|int, mixed> $messages
30-
* @param array<string> $ignoredBacktracePaths
31-
*/
29+
/** @param array<string|int, mixed> $messages */
3230
public function __construct(
3331
string $message,
34-
private readonly string $fullMessage,
35-
private readonly array $messages,
36-
array $ignoredBacktracePaths = [],
32+
private ResultQuery $resultQuery,
33+
string ...$ignoredBacktracePaths,
3734
) {
3835
$this->overwriteFileAndLine($ignoredBacktracePaths);
3936

@@ -42,13 +39,13 @@ public function __construct(
4239

4340
public function getFullMessage(): string
4441
{
45-
return $this->fullMessage;
42+
return $this->resultQuery->toFullMessage();
4643
}
4744

4845
/** @return array<string|int, mixed> */
4946
public function getMessages(): array
5047
{
51-
return $this->messages;
48+
return $this->resultQuery->toArrayMessages();
5249
}
5350

5451
/** @param array<string> $ignoredBacktracePaths */

library/Message/Stringifier/NameStringifier.php renamed to library/Message/Handler/NameHandler.php

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,14 @@
88
* SPDX-FileContributor: Henrique Moody <henriquemoody@gmail.com>
99
*/
1010

11-
namespace Respect\Validation\Message\Stringifier;
11+
namespace Respect\Validation\Message\Handler;
1212

13-
use Respect\Stringifier\Stringifier;
13+
use Respect\Stringifier\Handler;
1414
use Respect\Validation\Name;
1515

16-
final readonly class NameStringifier implements Stringifier
16+
final readonly class NameHandler implements Handler
1717
{
18-
public function stringify(mixed $raw, int $depth): string|null
18+
public function handle(mixed $raw, int $depth): string|null
1919
{
2020
if (!$raw instanceof Name) {
2121
return null;

library/Message/Stringifier/PathStringifier.php renamed to library/Message/Handler/PathHandler.php

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,23 +8,23 @@
88
* SPDX-FileContributor: Henrique Moody <henriquemoody@gmail.com>
99
*/
1010

11-
namespace Respect\Validation\Message\Stringifier;
11+
namespace Respect\Validation\Message\Handler;
1212

13+
use Respect\Stringifier\Handler;
1314
use Respect\Stringifier\Quoter;
14-
use Respect\Stringifier\Stringifier;
1515
use Respect\Validation\Path;
1616

1717
use function array_reverse;
1818
use function implode;
1919

20-
final readonly class PathStringifier implements Stringifier
20+
final readonly class PathHandler implements Handler
2121
{
2222
public function __construct(
2323
private Quoter $quoter,
2424
) {
2525
}
2626

27-
public function stringify(mixed $raw, int $depth): string|null
27+
public function handle(mixed $raw, int $depth): string|null
2828
{
2929
if (!$raw instanceof Path) {
3030
return null;
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
<?php
2+
3+
/*
4+
* Copyright (c) Alexandre Gomes Gaigalas <alganet@gmail.com>
5+
* SPDX-License-Identifier: MIT
6+
*/
7+
8+
declare(strict_types=1);
9+
10+
namespace Respect\Validation\Message\Handler;
11+
12+
use Respect\Stringifier\Handler;
13+
use Respect\Validation\Result;
14+
15+
use function sprintf;
16+
17+
final readonly class ResultHandler implements Handler
18+
{
19+
public function __construct(
20+
private Handler $handler,
21+
) {
22+
}
23+
24+
public function handle(mixed $raw, int $depth): string|null
25+
{
26+
if (!$raw instanceof Result) {
27+
return null;
28+
}
29+
30+
if ($raw->path === null && $raw->name === null) {
31+
return $this->handler->handle($raw->input, $depth);
32+
}
33+
34+
if ($raw->name === null) {
35+
return $this->handler->handle($raw->path, $depth);
36+
}
37+
38+
if ($raw->path === null || $raw->hasPrecedentName) {
39+
return $this->handler->handle($raw->name, $depth);
40+
}
41+
42+
return sprintf(
43+
'%s (<- %s)',
44+
$this->handler->handle($raw->path, $depth),
45+
$this->handler->handle($raw->name, $depth),
46+
);
47+
}
48+
}

library/Message/InterpolationRenderer.php

Lines changed: 8 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -10,38 +10,32 @@
1010

1111
namespace Respect\Validation\Message;
1212

13+
use Respect\StringFormatter\PlaceholderFormatter;
1314
use Respect\Validation\Message\Formatter\TemplateResolver;
14-
use Respect\Validation\Message\Placeholder\Subject;
1515
use Respect\Validation\Result;
16-
17-
use function array_key_exists;
18-
use function array_pad;
19-
use function assert;
20-
use function is_string;
21-
use function preg_replace_callback;
16+
use Symfony\Contracts\Translation\TranslatorInterface;
2217

2318
final readonly class InterpolationRenderer implements Renderer
2419
{
2520
public function __construct(
26-
private Translator $translator,
27-
private Modifier $modifier,
21+
private TranslatorInterface $translator,
22+
private PlaceholderFormatter $formatter,
2823
private TemplateResolver $templateResolver,
2924
) {
3025
}
3126

3227
/** @param array<string|int, mixed> $templates */
3328
public function render(Result $result, array $templates): string
3429
{
35-
$parameters = ['path' => $result->path, 'input' => $result->input, 'subject' => Subject::fromResult($result)];
30+
$parameters = ['path' => $result->path, 'input' => $result->input, 'subject' => $result];
3631
$parameters += $result->parameters;
3732

3833
$givenTemplate = $this->templateResolver->getGivenTemplate($result, $templates);
3934
$ruleTemplate = $this->templateResolver->getValidatorTemplate($result);
4035

41-
$rendered = (string) preg_replace_callback(
42-
'/{{(\w+)(\|([^}]+))?}}/',
43-
fn(array $matches) => $this->processPlaceholder($parameters, $matches),
44-
$this->translator->translate($givenTemplate ?? $ruleTemplate),
36+
$rendered = $this->formatter->formatUsing(
37+
$this->translator->trans($givenTemplate ?? $ruleTemplate),
38+
$parameters,
4539
);
4640

4741
if (!$result->hasCustomTemplate() && $givenTemplate === null && $result->adjacent !== null) {
@@ -50,20 +44,4 @@ public function render(Result $result, array $templates): string
5044

5145
return $rendered;
5246
}
53-
54-
/**
55-
* @param array<string, mixed> $parameters
56-
* @param array<int, string|null> $matches
57-
*/
58-
private function processPlaceholder(array $parameters, array $matches): string
59-
{
60-
[$placeholder, $name, , $pipe] = array_pad($matches, 4, null);
61-
assert(is_string($placeholder));
62-
assert(is_string($name));
63-
if (!array_key_exists($name, $parameters)) {
64-
return $placeholder;
65-
}
66-
67-
return $this->modifier->modify($parameters[$name], $pipe);
68-
}
6947
}

library/Message/Modifier.php

Lines changed: 0 additions & 16 deletions
This file was deleted.

0 commit comments

Comments
 (0)