Skip to content

Commit 8782d9a

Browse files
committed
WIP: Change how we track paths
1 parent c0b8baa commit 8782d9a

49 files changed

Lines changed: 436 additions & 254 deletions

Some content is hidden

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

library/Message/Formatter/FirstResultStringFormatter.php

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,6 @@
1616

1717
final readonly class FirstResultStringFormatter implements StringFormatter
1818
{
19-
use PathProcessor;
20-
2119
public function __construct(
2220
private Renderer $renderer,
2321
private TemplateResolver $templateResolver,
@@ -31,7 +29,7 @@ public function format(Result $result, array $templates, Translator $translator)
3129
if (!$this->templateResolver->hasMatch($result, $matchedTemplates)) {
3230
foreach ($result->children as $child) {
3331
return $this->format(
34-
$this->overwritePath($result, $child),
32+
$child,
3533
$matchedTemplates,
3634
$translator,
3735
);

library/Message/Formatter/NestedArrayFormatter.php

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,6 @@
1919

2020
final readonly class NestedArrayFormatter implements ArrayFormatter
2121
{
22-
use PathProcessor;
23-
2422
public function __construct(
2523
private Renderer $renderer,
2624
private TemplateResolver $templateResolver,
@@ -37,18 +35,18 @@ public function format(Result $result, array $templates, Translator $translator)
3735
$matchedTemplates = $this->templateResolver->selectMatches($result, $templates);
3836
if (count($result->children) === 0 || $this->templateResolver->hasMatch($result, $matchedTemplates)) {
3937
return [
40-
$result->getDeepestPath() ?? $result->id => $this->renderer->render(
41-
$this->templateResolver->resolve($result->withDeepestPath(), $matchedTemplates),
38+
$result->path->value ?? $result->id->value => $this->renderer->render(
39+
$this->templateResolver->resolve($result->withoutParentPath(), $matchedTemplates),
4240
$translator,
4341
),
4442
];
4543
}
4644

4745
$messages = [];
4846
foreach ($result->children as $child) {
49-
$key = $child->getDeepestPath() ?? $child->id ?? 0;
47+
$key = $child->path->value ?? $child->id->value;
5048
$messages[$key] = $this->format(
51-
$this->overwritePath($result, $child),
49+
$child->withoutParentPath()->withoutName(),
5250
$this->templateResolver->selectMatches($child, $matchedTemplates),
5351
$translator,
5452
);
@@ -62,7 +60,7 @@ public function format(Result $result, array $templates, Translator $translator)
6260
if (count($messages) > 1) {
6361
$self = [
6462
'__root__' => $this->renderer->render(
65-
$this->templateResolver->resolve($result->withDeepestPath(), $matchedTemplates),
63+
$this->templateResolver->resolve($result->withoutParentPath(), $matchedTemplates),
6664
$translator,
6765
),
6866
];

library/Message/Formatter/NestedListStringFormatter.php

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@
1515
use Respect\Validation\Result;
1616

1717
use function array_filter;
18-
use function array_map;
1918
use function array_reduce;
2019
use function count;
2120
use function rtrim;
@@ -26,8 +25,6 @@
2625

2726
final readonly class NestedListStringFormatter implements StringFormatter
2827
{
29-
use PathProcessor;
30-
3128
public function __construct(
3229
private Renderer $renderer,
3330
private TemplateResolver $templateResolver,
@@ -51,14 +48,16 @@ private function formatRecursively(
5148
$matchedTemplates = $this->templateResolver->selectMatches($result, $templates);
5249

5350
$formatted = '';
51+
$displayedName = null;
5452
if ($this->isVisible($result, ...$siblings)) {
5553
$indentation = str_repeat(' ', $depth * 2);
54+
$displayedName = $result->name;
5655
$formatted .= sprintf(
5756
'%s- %s' . PHP_EOL,
5857
$indentation,
5958
$this->renderer->render(
6059
$this->templateResolver->resolve(
61-
$depth > 0 ? $result->withDeepestPath() : $result,
60+
$result->withoutParentPath(),
6261
$matchedTemplates,
6362
),
6463
$translator,
@@ -68,17 +67,13 @@ private function formatRecursively(
6867
}
6968

7069
if (!$this->templateResolver->hasMatch($result, $matchedTemplates)) {
71-
$children = array_map(
72-
fn(Result $child) => $this->overwritePath($result, $child),
73-
$result->children,
74-
);
75-
foreach ($children as $child) {
70+
foreach ($result->children as $child) {
7671
$formatted .= $this->formatRecursively(
77-
$child,
72+
$displayedName === $child->name ? $child->withoutName() : $child,
7873
$matchedTemplates,
7974
$translator,
8075
$depth,
81-
...array_filter($children, static fn(Result $sibling) => $sibling !== $child),
76+
...array_filter($result->children, static fn(Result $sibling) => $sibling !== $child),
8277
);
8378
$formatted .= PHP_EOL;
8479
}

library/Message/Formatter/PathProcessor.php

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

library/Message/Formatter/TemplateResolver.php

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,9 @@ public function selectMatches(Result $result, array $templates): array
8080
/** @return non-empty-array<string|int> */
8181
private function getKeys(Result $result): array
8282
{
83-
return array_filter([$result->path, $result->name, $result->id], static fn($key) => $key !== null);
83+
return array_filter(
84+
[$result->path?->value, $result->name?->value, $result->id->value],
85+
static fn($key) => $key !== null,
86+
);
8487
}
8588
}

library/Message/InterpolationRenderer.php

Lines changed: 25 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,12 @@
1212
use ReflectionClass;
1313
use Respect\Stringifier\Stringifier;
1414
use Respect\Validation\Message\Placeholder\Listed;
15+
use Respect\Validation\Message\Placeholder\Name;
1516
use Respect\Validation\Message\Placeholder\Quoted;
1617
use Respect\Validation\Result;
1718
use Respect\Validation\Rule;
1819

20+
use function array_key_exists;
1921
use function is_array;
2022
use function is_bool;
2123
use function is_scalar;
@@ -35,12 +37,8 @@ public function __construct(
3537

3638
public function render(Result $result, Translator $translator): string
3739
{
38-
$parameters = $result->parameters;
39-
$parameters['path'] = $result->path !== null ? Quoted::fromPath($result->path) : null;
40-
$parameters['input'] = $result->input;
41-
42-
$builtName = $result->name ?? $parameters['path'] ?? $this->placeholder('input', $result->input, $translator);
43-
$parameters['name'] ??= $builtName;
40+
$parameters = ['path' => $result->path, 'input' => $result->input, 'name' => $this->getName($result)];
41+
$parameters += $result->parameters;
4442

4543
$rendered = (string) preg_replace_callback(
4644
'/{{(\w+)(\|([^}]+))?}}/',
@@ -100,10 +98,6 @@ private function placeholder(
10098
return $translator->translate($value);
10199
}
102100

103-
if ($name === 'name' && is_string($value)) {
104-
return $value;
105-
}
106-
107101
return $this->stringifier->stringify($value, 0) ?? print_r($value, true);
108102
}
109103

@@ -127,4 +121,25 @@ private function getTemplateMessage(Result $result): string
127121

128122
return $result->template;
129123
}
124+
125+
private function getName(Result $result): Name
126+
{
127+
if (array_key_exists('name', $result->parameters) && is_string($result->parameters['name'])) {
128+
return new Name($result->parameters['name']);
129+
}
130+
131+
if (array_key_exists('name', $result->parameters)) {
132+
return new Name((string) $this->stringifier->stringify($result->parameters['name'], 0));
133+
}
134+
135+
if ($result->name !== null) {
136+
return $result->path ? $result->name->withPath($result->path) : $result->name;
137+
}
138+
139+
if ($result->path?->value !== null) {
140+
return new Name((string) $this->stringifier->stringify($result->path, 0));
141+
}
142+
143+
return new Name((string) $this->stringifier->stringify($result->input, 0));
144+
}
130145
}

library/Message/Placeholder/Id.php

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
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\Placeholder;
11+
12+
use Respect\Validation\Rule;
13+
14+
use function lcfirst;
15+
use function strrchr;
16+
use function substr;
17+
use function ucfirst;
18+
19+
final readonly class Id
20+
{
21+
public function __construct(
22+
public string $value,
23+
) {
24+
}
25+
26+
public static function fromRule(Rule $rule): self
27+
{
28+
return new self(lcfirst(substr((string) strrchr($rule::class, '\\'), 1)));
29+
}
30+
31+
public function withPrefix(string $prefix): self
32+
{
33+
return new self($prefix . ucfirst($this->value));
34+
}
35+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
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\Placeholder;
11+
12+
final readonly class Name
13+
{
14+
public function __construct(
15+
public string $value,
16+
public Path|null $path = null,
17+
) {
18+
}
19+
20+
public function withPath(Path $path): Name
21+
{
22+
return new self($this->value, $path);
23+
}
24+
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
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\Placeholder;
11+
12+
final class Path
13+
{
14+
public function __construct(
15+
public int|string $value,
16+
public Path|null $parent = null,
17+
) {
18+
}
19+
20+
public function isOrphan(): bool
21+
{
22+
return $this->parent === null;
23+
}
24+
25+
public function withParent(self $parent): self
26+
{
27+
if ($parent === $this->parent) {
28+
return $this;
29+
}
30+
31+
$this->parent = $parent;
32+
33+
return $this;
34+
}
35+
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
/*
6+
* Copyright (c) Alexandre Gomes Gaigalas <alganet@gmail.com>
7+
* SPDX-License-Identifier: MIT
8+
*/
9+
10+
namespace Respect\Validation\Message\Stringifier;
11+
12+
use Respect\Stringifier\Stringifier;
13+
use Respect\Validation\Message\Placeholder\Name;
14+
15+
use function sprintf;
16+
17+
final readonly class NameStringifier implements Stringifier
18+
{
19+
public function __construct(
20+
private Stringifier $stringifier,
21+
) {
22+
}
23+
24+
public function stringify(mixed $raw, int $depth): string|null
25+
{
26+
if (!$raw instanceof Name) {
27+
return null;
28+
}
29+
30+
if ($raw->path?->value === null || $raw->path->isOrphan()) {
31+
return $raw->value;
32+
}
33+
34+
return sprintf(
35+
'%s (<- %s)',
36+
$this->stringifier->stringify($raw->path, $depth),
37+
$raw->value,
38+
);
39+
}
40+
}

0 commit comments

Comments
 (0)