Skip to content

Commit c717614

Browse files
committed
feat: add PlaceholderTrait for improved placeholder handling in error formatting
1 parent e542f2f commit c717614

2 files changed

Lines changed: 88 additions & 62 deletions

File tree

src/Formatter/AbstractErrorFormatter.php

Lines changed: 8 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212

1313
abstract class AbstractErrorFormatter implements ErrorFormatter
1414
{
15+
use PlaceholderTrait;
16+
1517
public function __construct(
1618
protected readonly bool $debug = false,
1719
protected readonly ?ExceptionTransformer $transformer = null,
@@ -39,6 +41,11 @@ public function format(\Throwable $exception): HttpError
3941
$problem = $this->createProblem($exception);
4042
}
4143

44+
return $this->createHttpError($problem);
45+
}
46+
47+
protected function createHttpError(Problem $problem): HttpError
48+
{
4249
$context = $this->debug && $problem instanceof DebuggableProblem
4350
? $problem->debugContext()
4451
: $problem->context();
@@ -51,67 +58,6 @@ public function format(\Throwable $exception): HttpError
5158
$headers = $problem->getHeaders();
5259
}
5360

54-
\array_walk_recursive($format, $this->replacePlaceHolder(...), $context);
55-
56-
return new HttpError($this->removeEmptyPlaceHolders($format), $status, $headers);
57-
}
58-
59-
/**
60-
* @param array<string, mixed> $context
61-
*/
62-
private function replacePlaceHolder(mixed &$value, string $key, array $context): void
63-
{
64-
if (! \is_string($value)) {
65-
return;
66-
}
67-
68-
$placeholder = \trim($value, '{}');
69-
70-
if (isset($context[$placeholder])) {
71-
$value = $context[$placeholder];
72-
73-
return;
74-
}
75-
76-
$cache = [];
77-
78-
/** @var string */
79-
$value = \preg_replace_callback(
80-
'/{\s*([A-Za-z_\-\.0-9]+)\s*}/',
81-
function (array $matches) use ($context, &$cache) {
82-
if (isset($cache[$matches[1]])) {
83-
return $cache[$matches[1]];
84-
}
85-
86-
$result = $context[$matches[1]] ?? '<NULL>';
87-
88-
$cache[$matches[1]] = $result;
89-
90-
return $result;
91-
},
92-
$value
93-
);
94-
}
95-
96-
/**
97-
* @param array<array-key, mixed> $input
98-
*
99-
* @return array<string, mixed>
100-
*/
101-
private function removeEmptyPlaceHolders(array $input): array
102-
{
103-
foreach ($input as &$value) {
104-
if (is_array($value)) {
105-
$value = $this->removeEmptyPlaceHolders($value);
106-
}
107-
}
108-
109-
return \array_filter($input, static function ($value) {
110-
if (is_string($value)) {
111-
return ! str_contains($value, '<NULL>');
112-
}
113-
114-
return true;
115-
});
61+
return new HttpError($this->replacePlaceholders($this->getFormat(), $context), $status, $headers);
11662
}
11763
}

src/Formatter/PlaceholderTrait.php

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Jenky\ApiError\Formatter;
6+
7+
trait PlaceholderTrait
8+
{
9+
/**
10+
* @param array<string, mixed> $format
11+
* @param array<string, mixed> $context
12+
*
13+
* @return array<string, mixed>
14+
*/
15+
private function replacePlaceholders(array $format, array $context): array
16+
{
17+
\array_walk_recursive($format, $this->replacePlaceholder(...), $context);
18+
19+
return $this->removeEmptyPlaceholders($format);
20+
}
21+
22+
/**
23+
* @param array<string, mixed> $context
24+
*/
25+
private function replacePlaceholder(mixed &$value, string $key, array $context): void
26+
{
27+
if (! \is_string($value)) {
28+
return;
29+
}
30+
31+
$placeholder = \trim($value, '{}');
32+
33+
if (isset($context[$placeholder])) {
34+
$value = $context[$placeholder];
35+
36+
return;
37+
}
38+
39+
$cache = [];
40+
41+
/** @var string */
42+
$value = \preg_replace_callback(
43+
'/{\s*([A-Za-z_\-\.0-9]+)\s*}/',
44+
function (array $matches) use ($context, &$cache) {
45+
if (isset($cache[$matches[1]])) {
46+
return $cache[$matches[1]];
47+
}
48+
49+
$result = $context[$matches[1]] ?? '<NULL>';
50+
51+
$cache[$matches[1]] = $result;
52+
53+
return $result;
54+
},
55+
$value
56+
);
57+
}
58+
59+
/**
60+
* @param array<array-key, mixed> $input
61+
*
62+
* @return array<string, mixed>
63+
*/
64+
private function removeEmptyPlaceholders(array $input): array
65+
{
66+
foreach ($input as &$value) {
67+
if (is_array($value)) {
68+
$value = $this->removeEmptyPlaceholders($value);
69+
}
70+
}
71+
72+
return \array_filter($input, static function ($value) {
73+
if (is_string($value)) {
74+
return ! str_contains($value, '<NULL>');
75+
}
76+
77+
return true;
78+
});
79+
}
80+
}

0 commit comments

Comments
 (0)