Skip to content

Commit 661ce71

Browse files
committed
Unrelated: remove the responsibility of formatter to select templates
1 parent a002f13 commit 661ce71

File tree

3 files changed

+128
-94
lines changed

3 files changed

+128
-94
lines changed

library/Message/StandardFormatter.php

Lines changed: 15 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -9,20 +9,15 @@
99

1010
namespace Respect\Validation\Message;
1111

12-
use Respect\Validation\Exceptions\ComponentException;
1312
use Respect\Validation\Result;
14-
1513
use Respect\Validation\ResultSet;
14+
1615
use function array_filter;
1716
use function array_key_exists;
18-
use function array_map;
1917
use function array_reduce;
2018
use function array_values;
2119
use function count;
2220
use function current;
23-
use function is_array;
24-
use function is_string;
25-
use function Respect\Stringifier\stringify;
2621
use function rtrim;
2722
use function sprintf;
2823
use function str_repeat;
@@ -41,14 +36,14 @@ public function __construct(
4136
*/
4237
public function main(Result $result, array $templates, Translator $translator): string
4338
{
44-
$selectedTemplates = $this->selectTemplates($result, $templates);
45-
if (!$this->isFinalTemplate($result, $selectedTemplates)) {
39+
$selector = new TemplateSelector($result, $templates);
40+
if (!$selector->hasOnlyItsOwnTemplate()) {
4641
foreach (new ResultSet($result) as $child) {
47-
return $this->main($child, $selectedTemplates, $translator);
42+
return $this->main($child, $selector->templates, $translator);
4843
}
4944
}
5045

51-
return $this->renderer->render($this->getTemplated($result, $selectedTemplates), $translator);
46+
return $this->renderer->render($selector->getResult(), $translator);
5247
}
5348

5449
/**
@@ -61,29 +56,27 @@ public function full(
6156
int $depth = 0,
6257
Result ...$siblings
6358
): string {
64-
$selectedTemplates = $this->selectTemplates($result, $templates);
65-
$isFinalTemplate = $this->isFinalTemplate($result, $selectedTemplates);
66-
59+
$selector = new TemplateSelector($result, $templates);
6760
$rendered = '';
68-
if ($this->isAlwaysVisible($result, ...$siblings) || $isFinalTemplate) {
61+
if ($this->isAlwaysVisible($result, ...$siblings) || $selector->hasOnlyItsOwnTemplate()) {
6962
$indentation = str_repeat(' ', $depth * 2);
7063
$rendered .= sprintf(
7164
'%s- %s' . PHP_EOL,
7265
$indentation,
7366
$this->renderer->render(
74-
$this->getTemplated($depth > 0 ? $result->withDeepestPath() : $result, $selectedTemplates),
67+
$depth > 0 ? $selector->getResult()->withDeepestPath() : $selector->getResult(),
7568
$translator
7669
),
7770
);
7871
$depth++;
7972
}
8073

81-
if (!$isFinalTemplate) {
74+
if (!$selector->hasOnlyItsOwnTemplate()) {
8275
$results = new ResultSet($result);
8376
foreach ($results as $child) {
8477
$rendered .= $this->full(
8578
$child,
86-
$selectedTemplates,
79+
$selector->templates,
8780
$translator,
8881
$depth,
8982
...array_filter($results->getArrayCopy(), static fn (Result $sibling) => $sibling !== $child)
@@ -102,12 +95,12 @@ public function full(
10295
*/
10396
public function array(Result $result, array $templates, Translator $translator): array
10497
{
105-
$selectedTemplates = $this->selectTemplates($result, $templates);
98+
$selector = new TemplateSelector($result, $templates);
10699
$deduplicatedChildren = $this->extractDeduplicatedChildren($result);
107-
if (count($deduplicatedChildren) === 0 || $this->isFinalTemplate($result, $selectedTemplates)) {
100+
if (count($deduplicatedChildren) === 0 || $selector->hasOnlyItsOwnTemplate()) {
108101
return [
109102
$result->path ?? $result->id => $this->renderer->render(
110-
$this->getTemplated($result->withDeepestPath(), $selectedTemplates),
103+
$selector->getResult()->withDeepestPath(),
111104
$translator
112105
),
113106
];
@@ -118,7 +111,7 @@ public function array(Result $result, array $templates, Translator $translator):
118111
$key = $child->path ?? $child->id;
119112
$messages[$key] = $this->array(
120113
$this->resultWithPath($result, $child),
121-
$this->selectTemplates($child, $selectedTemplates),
114+
$selector->templates,
122115
$translator
123116
);
124117
if (count($messages[$key]) !== 1) {
@@ -130,10 +123,7 @@ public function array(Result $result, array $templates, Translator $translator):
130123

131124
if (count($messages) > 1) {
132125
$self = [
133-
'__root__' => $this->renderer->render(
134-
$this->getTemplated($result->withDeepestPath(), $selectedTemplates),
135-
$translator
136-
),
126+
'__root__' => $this->renderer->render($selector->getResult()->withDeepestPath(), $translator),
137127
];
138128

139129
return $self + $messages;
@@ -190,71 +180,6 @@ private function isAlwaysVisible(Result $result, Result ...$siblings): bool
190180
);
191181
}
192182

193-
/** @param array<string|int, mixed> $templates */
194-
private function getTemplated(Result $result, array $templates): Result
195-
{
196-
if ($result->hasCustomTemplate()) {
197-
return $result;
198-
}
199-
200-
foreach ([$result->path, $result->name, $result->id, '__root__'] as $key) {
201-
if (!isset($templates[$key])) {
202-
continue;
203-
}
204-
205-
if (is_string($templates[$key])) {
206-
return $result->withTemplate($templates[$key]);
207-
}
208-
209-
throw new ComponentException(
210-
sprintf('Template for "%s" must be a string, %s given', $key, stringify($templates[$key]))
211-
);
212-
}
213-
214-
return $result;
215-
}
216-
217-
/**
218-
* @param array<string|int, mixed> $templates
219-
*/
220-
private function isFinalTemplate(Result $result, array $templates): bool
221-
{
222-
$keys = [$result->path, $result->name, $result->id];
223-
foreach ($keys as $key) {
224-
if (isset($templates[$key]) && is_string($templates[$key])) {
225-
return true;
226-
}
227-
}
228-
229-
if (count($templates) !== 1) {
230-
return false;
231-
}
232-
233-
foreach ($keys as $key) {
234-
if (isset($templates[$key])) {
235-
return true;
236-
}
237-
}
238-
239-
return isset($templates['__root__']);
240-
}
241-
242-
/**
243-
* @param array<string|int, mixed> $templates
244-
*
245-
* @return array<string|int, mixed>
246-
*/
247-
private function selectTemplates(Result $result, array $templates): array
248-
{
249-
foreach ([$result->path, $result->name, $result->id] as $key) {
250-
if (isset($templates[$key]) && is_array($templates[$key])) {
251-
return $templates[$key];
252-
}
253-
}
254-
255-
return $templates;
256-
}
257-
258183
/** @return array<Result> */
259184
private function extractDeduplicatedChildren(Result $result): array
260185
{
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
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;
11+
12+
use Respect\Validation\Exceptions\ComponentException;
13+
use Respect\Validation\Result;
14+
15+
use function count;
16+
use function is_array;
17+
use function is_string;
18+
use function Respect\Stringifier\stringify;
19+
use function sprintf;
20+
21+
final class TemplateSelector
22+
{
23+
/** @var array<string|int, mixed> */
24+
public readonly array $templates;
25+
26+
/** @param array<string|int, mixed> $templates */
27+
public function __construct(
28+
private readonly Result $result,
29+
array $templates,
30+
) {
31+
$this->templates = $this->selectedTemplates($templates);
32+
}
33+
34+
public function getResult(): Result
35+
{
36+
if ($this->result->hasCustomTemplate()) {
37+
return $this->result;
38+
}
39+
40+
foreach ([$this->result->getDeepestPath(), $this->result->name, $this->result->id, '__root__'] as $key) {
41+
if (!isset($this->templates[$key])) {
42+
continue;
43+
}
44+
45+
if (is_string($this->templates[$key])) {
46+
return $this->result->withTemplate($this->templates[$key]);
47+
}
48+
49+
throw new ComponentException(
50+
sprintf('Template for "%s" must be a string, %s given', $key, stringify($this->templates[$key]))
51+
);
52+
}
53+
54+
return $this->result;
55+
}
56+
57+
public function hasOnlyItsOwnTemplate(): bool
58+
{
59+
$keys = [$this->result->getDeepestPath(), $this->result->name, $this->result->id];
60+
foreach ($keys as $key) {
61+
if (isset($this->templates[$key]) && is_string($this->templates[$key])) {
62+
return true;
63+
}
64+
}
65+
66+
if (count($this->templates) !== 1) {
67+
return false;
68+
}
69+
70+
foreach ($keys as $key) {
71+
if (isset($this->templates[$key])) {
72+
return true;
73+
}
74+
}
75+
76+
return isset($this->templates['__root__']);
77+
}
78+
79+
/**
80+
* @param array<string|int, mixed> $templates
81+
* @return array<string|int, mixed>
82+
*/
83+
private function selectedTemplates(array $templates): array
84+
{
85+
foreach ([$this->result->getDeepestPath(), $this->result->name, $this->result->id] as $key) {
86+
if (isset($templates[$key]) && is_array($templates[$key])) {
87+
return $templates[$key];
88+
}
89+
}
90+
91+
return $templates;
92+
}
93+
}

library/ResultSet.php

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
<?php
22

3+
declare(strict_types=1);
4+
35
/*
46
* Copyright (c) Alexandre Gomes Gaigalas <alganet@gmail.com>
57
* SPDX-License-Identifier: MIT
@@ -10,18 +12,31 @@
1012
use Countable;
1113
use Iterator;
1214

15+
use function array_filter;
16+
use function array_key_exists;
17+
use function array_map;
18+
use function array_values;
19+
use function count;
20+
use function current;
21+
use function key;
22+
use function next;
23+
use function reset;
24+
1325
/**
1426
* @implements Iterator<int, Result>
1527
*/
1628
final class ResultSet implements Iterator, Countable
1729
{
30+
/** @var array<int, Result> */
1831
private array $children;
32+
1933
public function __construct(
2034
private readonly Result $result,
2135
) {
2236
$this->children = $this->extractDeduplicatedChildren();
2337
}
2438

39+
/** @return array<int, Result> */
2540
public function extractDeduplicatedChildren(): array
2641
{
2742
/** @var array<string, Result> $deduplicatedResults */
@@ -62,14 +77,15 @@ function (Result $child): Result {
6277
);
6378
}
6479

65-
public function current(): Result|false
80+
/** @return array<int, Result> */
81+
public function getArrayCopy(): array
6682
{
67-
return current($this->children);
83+
return $this->children;
6884
}
6985

70-
public function getArrayCopy(): array
86+
public function current(): Result|false
7187
{
72-
return $this->children;
88+
return current($this->children);
7389
}
7490

7591
public function next(): void

0 commit comments

Comments
 (0)