Skip to content

Commit 9323a82

Browse files
committed
Render backed enums using their backing value in the html_attr function
1 parent ec0f5d5 commit 9323a82

3 files changed

Lines changed: 53 additions & 0 deletions

File tree

CHANGELOG

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
# 3.28.0 (2026-XX-XX)
22

3+
* Render backed enums using their backing value in the `html_attr` function
34
* Fix empty Markup values being treated as truthy in and, or, xor, not, ternary, and elvis expressions
45
* Fix a PHP 8.5 `chr()` deprecation when decoding an octal string escape sequence larger than `\377` (such as `"\777"`)
56
* Mark `Twig\Markup` as `@final`; it will be final in Twig 4.0

extra/html-extra/HtmlExtension.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,10 @@ public static function htmlAttr(Environment $env, iterable|string|false|null ...
200200
$runtime = $env->getRuntime(EscaperRuntime::class);
201201

202202
foreach ($attr as $name => $value) {
203+
if ($value instanceof \BackedEnum) {
204+
$value = $value->value;
205+
}
206+
203207
if (str_starts_with($name, 'aria-')) {
204208
// For aria-*, convert booleans to "true" and "false" strings
205209
if (true === $value) {

extra/html-extra/Tests/HtmlAttrTest.php

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,42 @@ public static function htmlAttrProvider(): \Generator
247247
['value' => new StringableStub('stringable-object')],
248248
],
249249
];
250+
251+
// Backed enums are rendered using their backing value
252+
yield 'string-backed enum renders its value' => [
253+
'class="card"',
254+
[
255+
['class' => StringBackedStub::CARD],
256+
],
257+
];
258+
259+
yield 'int-backed enum renders its value' => [
260+
'tabindex="10"',
261+
[
262+
['tabindex' => IntBackedStub::HIGH],
263+
],
264+
];
265+
266+
yield 'string-backed enum in data-* attribute renders its value without JSON encoding' => [
267+
'data-view="card"',
268+
[
269+
['data-view' => StringBackedStub::CARD],
270+
],
271+
];
272+
273+
yield 'int-backed enum in data-* attribute renders its value' => [
274+
'data-level="10"',
275+
[
276+
['data-level' => IntBackedStub::HIGH],
277+
],
278+
];
279+
280+
yield 'backed enum in aria-* attribute renders its value' => [
281+
'aria-label="card"',
282+
[
283+
['aria-label' => StringBackedStub::CARD],
284+
],
285+
];
250286
}
251287

252288
public function testIterableObjectCastedToArray()
@@ -317,3 +353,15 @@ public function getValue(): ?string
317353
return $this->value;
318354
}
319355
}
356+
357+
enum StringBackedStub: string
358+
{
359+
case CARD = 'card';
360+
case TABLE = 'table';
361+
}
362+
363+
enum IntBackedStub: int
364+
{
365+
case LOW = 1;
366+
case HIGH = 10;
367+
}

0 commit comments

Comments
 (0)