From c79338b9c8a066cea690c3b329de14744dca9e0e Mon Sep 17 00:00:00 2001 From: Sergei Predvoditelev Date: Tue, 17 Mar 2026 10:37:21 +0300 Subject: [PATCH 1/4] Allow pass int, float and null as content --- src/Html.php | 176 +++++++++++++++---------------- src/Tag/Base/ListTag.php | 5 +- src/Tag/Base/TagContentTrait.php | 12 +-- src/Tag/Button.php | 7 +- src/Tag/Optgroup.php | 2 +- src/Tag/Script.php | 6 +- src/Tag/Select.php | 6 +- src/Tag/Style.php | 7 +- src/Tag/Table.php | 3 +- src/Tag/Textarea.php | 4 +- src/Tag/Tr.php | 9 +- 11 files changed, 121 insertions(+), 116 deletions(-) diff --git a/src/Html.php b/src/Html.php index b3e71a9b..9bebe1d0 100644 --- a/src/Html.php +++ b/src/Html.php @@ -261,12 +261,12 @@ public static function escapeJavaScriptStringValue(mixed $value): string * @see CustomTag * * @param string $name The tag name. - * @param string|Stringable $content The tag content. + * @param string|Stringable|int|float|null $content The tag content. * @param array $attributes The tag attributes in terms of name-value pairs. * * @psalm-param non-empty-string $name */ - public static function tag(string $name, string|Stringable $content = '', array $attributes = []): CustomTag + public static function tag(string $name, string|Stringable|int|float|null $content = '', array $attributes = []): CustomTag { $tag = new CustomTag($name); if ($content !== '') { @@ -284,12 +284,12 @@ public static function tag(string $name, string|Stringable $content = '', array * @see CustomTag * * @param string $name The tag name. - * @param string|Stringable $content The tag content. + * @param string|Stringable|int|float|null $content The tag content. * @param array $attributes The tag attributes in terms of name-value pairs. * * @psalm-param non-empty-string $name */ - public static function normalTag(string $name, string|Stringable $content = '', array $attributes = []): CustomTag + public static function normalTag(string $name, string|Stringable|int|float|null $content = '', array $attributes = []): CustomTag { $tag = (new CustomTag($name))->normal(); if ($content !== '') { @@ -348,10 +348,10 @@ public static function closeTag(string $name): string /** * Generates a {@see Style} tag. * - * @param string $content The style content. + * @param string|Stringable $content The style content. * @param array $attributes The tag attributes in terms of name-value pairs. */ - public static function style(string $content = '', array $attributes = []): Style + public static function style(string|Stringable $content = '', array $attributes = []): Style { $tag = new Style(); if ($content !== '') { @@ -366,10 +366,10 @@ public static function style(string $content = '', array $attributes = []): Styl /** * Generates a {@see Script} tag. * - * @param string $content The script content. + * @param string|Stringable $content The script content. * @param array $attributes The tag attributes in terms of name-value pairs. */ - public static function script(string $content = '', array $attributes = []): Script + public static function script(string|Stringable $content = '', array $attributes = []): Script { $tag = new Script(); if ($content !== '') { @@ -384,9 +384,9 @@ public static function script(string $content = '', array $attributes = []): Scr /** * Generates a {@see Noscript} tag. * - * @param string|Stringable $content Tag content. + * @param string|Stringable|int|float|null $content Tag content. */ - public static function noscript(string|Stringable $content = ''): Noscript + public static function noscript(string|Stringable|int|float|null $content = ''): Noscript { $tag = new Noscript(); return $content === '' ? $tag : $tag->content($content); @@ -395,10 +395,10 @@ public static function noscript(string|Stringable $content = ''): Noscript /** * Generates a {@see Title} tag. * - * @param string|Stringable $content Tag content. + * @param string|Stringable|int|float|null $content Tag content. * @param array $attributes The tag attributes in terms of name-value pairs. */ - public static function title(string|Stringable $content = '', array $attributes = []): Title + public static function title(string|Stringable|int|float|null $content = '', array $attributes = []): Title { $tag = new Title(); if (!empty($attributes)) { @@ -472,12 +472,12 @@ public static function javaScriptFile(string $url, array $attributes = []): Scri /** * Generates a hyperlink tag. * - * @param string|Stringable $content The tag content. + * @param string|Stringable|int|float|null $content The tag content. * @param array $attributes The tag attributes in terms of name-value pairs. * * @see A */ - public static function a(string|Stringable $content = '', ?string $url = null, array $attributes = []): A + public static function a(string|Stringable|int|float|null $content = '', ?string $url = null, array $attributes = []): A { $tag = new A(); if (!empty($attributes)) { @@ -499,11 +499,11 @@ public static function a(string|Stringable $content = '', ?string $url = null, a * * @see A */ - public static function mailto(string $content, ?string $mail = null, array $attributes = []): A + public static function mailto(string|Stringable|int|float|null $content, ?string $mail = null, array $attributes = []): A { $tag = (new A()) ->content($content) - ->mailto($mail ?? $content); + ->mailto($mail ?? ($content === null ? null : (string) $content)); if (!empty($attributes)) { $tag = $tag->addAttributes($attributes); } @@ -571,11 +571,11 @@ public static function form(?string $action = null, ?string $method = null, arra /** * Generates a {@see Label} tag. * - * @param string|Stringable $content Label text. + * @param string|Stringable|int|float|null $content Label text. * @param string|null $for The ID of the HTML element that this label is associated with. * If this is null, the "for" attribute will not be generated. */ - public static function label(string|Stringable $content = '', ?string $for = null): Label + public static function label(string|Stringable|int|float|null $content = '', ?string $for = null): Label { $tag = new Label(); if ($for !== null) { @@ -590,10 +590,10 @@ public static function label(string|Stringable $content = '', ?string $for = nul /** * Generates a {@see Legend} tag. * - * @param string|Stringable $content The tag content. + * @param string|Stringable|int|float|null $content The tag content. * @param array $attributes The tag attributes in terms of name-value pairs. */ - public static function legend(string|Stringable $content = '', array $attributes = []): Legend + public static function legend(string|Stringable|int|float|null $content = '', array $attributes = []): Legend { $tag = new Legend(); if ($content !== '') { @@ -610,10 +610,10 @@ public static function legend(string|Stringable $content = '', array $attributes * * @see Button::button() * - * @param string $content The content enclosed within the button tag. + * @param string|Stringable|int|float|null $content The content enclosed within the button tag. * @param array $attributes The tag attributes in terms of name-value pairs. */ - public static function button(string $content = 'Button', array $attributes = []): Button + public static function button(string|Stringable|int|float|null $content = 'Button', array $attributes = []): Button { $tag = Button::button($content); if (!empty($attributes)) { @@ -627,10 +627,10 @@ public static function button(string $content = 'Button', array $attributes = [] * * @see Button::submit() * - * @param string $content The content enclosed within the button tag. + * @param string|Stringable|int|float|null $content The content enclosed within the button tag. * @param array $attributes The tag attributes in terms of name-value pairs. */ - public static function submitButton(string $content = 'Submit', array $attributes = []): Button + public static function submitButton(string|Stringable|int|float|null $content = 'Submit', array $attributes = []): Button { $tag = Button::submit($content); if (!empty($attributes)) { @@ -644,10 +644,10 @@ public static function submitButton(string $content = 'Submit', array $attribute * * @see Button::reset() * - * @param string $content The content enclosed within the button tag. + * @param string|Stringable|int|float|null $content The content enclosed within the button tag. * @param array $attributes The tag attributes in terms of name-value pairs. */ - public static function resetButton(string $content = 'Reset', array $attributes = []): Button + public static function resetButton(string|Stringable|int|float|null $content = 'Reset', array $attributes = []): Button { $tag = Button::reset($content); if (!empty($attributes)) { @@ -925,11 +925,11 @@ public static function optgroup(): Optgroup /** * Generates a {@see Option} tag. * - * @param string|Stringable $content Tag content. + * @param string|Stringable|int|float|null $content Tag content. * @param bool|float|int|string|Stringable|null $value The value attribute. */ public static function option( - string|Stringable $content = '', + string|Stringable|int|float|null $content = '', bool|float|int|string|Stringable|null $value = null, ): Option { $tag = new Option(); @@ -965,10 +965,10 @@ public static function radioList(string $name): RadioList /** * Generates a {@see Div} tag. * - * @param string|Stringable $content Tag content. + * @param string|Stringable|int|float|null $content Tag content. * @param array $attributes The tag attributes in terms of name-value pairs. */ - public static function div(string|Stringable $content = '', array $attributes = []): Div + public static function div(string|Stringable|int|float|null $content = '', array $attributes = []): Div { $tag = new Div(); if (!empty($attributes)) { @@ -980,12 +980,12 @@ public static function div(string|Stringable $content = '', array $attributes = /** * Generates a {@see Code} tag. * - * @param string|Stringable $content Tag content. If content includes HTML tags or special characters like `<`, `>`, + * @param string|Stringable|int|float|null $content Tag content. If content includes HTML tags or special characters like `<`, `>`, * or `&`, and you want them to be displayed as plain text, you need to enable encoding by calling `->encode(true)`. * This ensures they are not interpreted as actual HTML. * @param array $attributes The tag attributes in terms of name-value pairs. */ - public static function code(string|Stringable $content = '', array $attributes = []): Code + public static function code(string|Stringable|int|float|null $content = '', array $attributes = []): Code { $tag = new Code(); if (!empty($attributes)) { @@ -997,12 +997,12 @@ public static function code(string|Stringable $content = '', array $attributes = /** * Generates a {@see Pre} tag. * - * @param string|Stringable $content Tag content. If content includes HTML tags or special characters like `<`, `>`, + * @param string|Stringable|int|float|null $content Tag content. If content includes HTML tags or special characters like `<`, `>`, * or `&`, and you want them to be displayed as plain text, you need to enable encoding by calling `->encode(true)`. * This ensures they are not interpreted as actual HTML. * @param array $attributes The tag attributes in terms of name-value pairs. */ - public static function pre(string|Stringable $content = '', array $attributes = []): Pre + public static function pre(string|Stringable|int|float|null $content = '', array $attributes = []): Pre { $tag = new Pre(); if (!empty($attributes)) { @@ -1014,10 +1014,10 @@ public static function pre(string|Stringable $content = '', array $attributes = /** * Generates a {@see Span} tag. * - * @param string|Stringable $content Tag content. + * @param string|Stringable|int|float|null $content Tag content. * @param array $attributes The tag attributes in terms of name-value pairs. */ - public static function span(string|Stringable $content = '', array $attributes = []): Span + public static function span(string|Stringable|int|float|null $content = '', array $attributes = []): Span { $tag = new Span(); if (!empty($attributes)) { @@ -1029,10 +1029,10 @@ public static function span(string|Stringable $content = '', array $attributes = /** * Generates a {@see Em} tag. * - * @param string|Stringable $content Tag content. + * @param string|Stringable|int|float|null $content Tag content. * @param array $attributes The tag attributes in terms of name-value pairs. */ - public static function em(string|Stringable $content = '', array $attributes = []): Em + public static function em(string|Stringable|int|float|null $content = '', array $attributes = []): Em { $tag = new Em(); if (!empty($attributes)) { @@ -1044,10 +1044,10 @@ public static function em(string|Stringable $content = '', array $attributes = [ /** * Generates a {@see Strong} tag. * - * @param string|Stringable $content Tag content. + * @param string|Stringable|int|float|null $content Tag content. * @param array $attributes The tag attributes in terms of name-value pairs. */ - public static function strong(string|Stringable $content = '', array $attributes = []): Strong + public static function strong(string|Stringable|int|float|null $content = '', array $attributes = []): Strong { $tag = new Strong(); if (!empty($attributes)) { @@ -1059,10 +1059,10 @@ public static function strong(string|Stringable $content = '', array $attributes /** * Generates a {@see Small} tag. * - * @param string|Stringable $content Tag content. + * @param string|Stringable|int|float|null $content Tag content. * @param array $attributes The tag attributes in terms of name-value pairs. */ - public static function small(string|Stringable $content = '', array $attributes = []): Small + public static function small(string|Stringable|int|float|null $content = '', array $attributes = []): Small { $tag = new Small(); if (!empty($attributes)) { @@ -1074,10 +1074,10 @@ public static function small(string|Stringable $content = '', array $attributes /** * Generates a {@see B} tag. * - * @param string|Stringable $content Tag content. + * @param string|Stringable|int|float|null $content Tag content. * @param array $attributes The tag attributes in terms of name-value pairs. */ - public static function b(string|Stringable $content = '', array $attributes = []): B + public static function b(string|Stringable|int|float|null $content = '', array $attributes = []): B { $tag = new B(); if (!empty($attributes)) { @@ -1089,10 +1089,10 @@ public static function b(string|Stringable $content = '', array $attributes = [] /** * Generates a {@see I} tag. * - * @param string|Stringable $content Tag content. + * @param string|Stringable|int|float|null $content Tag content. * @param array $attributes The tag attributes in terms of name-value pairs. */ - public static function i(string|Stringable $content = '', array $attributes = []): I + public static function i(string|Stringable|int|float|null $content = '', array $attributes = []): I { $tag = new I(); if (!empty($attributes)) { @@ -1104,10 +1104,10 @@ public static function i(string|Stringable $content = '', array $attributes = [] /** * Generates a {@see H1} tag. * - * @param string|Stringable $content Tag content. + * @param string|Stringable|int|float|null $content Tag content. * @param array $attributes The tag attributes in terms of name-value pairs. */ - public static function h1(string|Stringable $content = '', array $attributes = []): H1 + public static function h1(string|Stringable|int|float|null $content = '', array $attributes = []): H1 { $tag = new H1(); if (!empty($attributes)) { @@ -1119,10 +1119,10 @@ public static function h1(string|Stringable $content = '', array $attributes = [ /** * Generates a {@see H2} tag. * - * @param string|Stringable $content Tag content. + * @param string|Stringable|int|float|null $content Tag content. * @param array $attributes The tag attributes in terms of name-value pairs. */ - public static function h2(string|Stringable $content = '', array $attributes = []): H2 + public static function h2(string|Stringable|int|float|null $content = '', array $attributes = []): H2 { $tag = new H2(); if (!empty($attributes)) { @@ -1134,10 +1134,10 @@ public static function h2(string|Stringable $content = '', array $attributes = [ /** * Generates a {@see H3} tag. * - * @param string|Stringable $content Tag content. + * @param string|Stringable|int|float|null $content Tag content. * @param array $attributes The tag attributes in terms of name-value pairs. */ - public static function h3(string|Stringable $content = '', array $attributes = []): H3 + public static function h3(string|Stringable|int|float|null $content = '', array $attributes = []): H3 { $tag = new H3(); if (!empty($attributes)) { @@ -1149,10 +1149,10 @@ public static function h3(string|Stringable $content = '', array $attributes = [ /** * Generates a {@see H4} tag. * - * @param string|Stringable $content Tag content. + * @param string|Stringable|int|float|null $content Tag content. * @param array $attributes The tag attributes in terms of name-value pairs. */ - public static function h4(string|Stringable $content = '', array $attributes = []): H4 + public static function h4(string|Stringable|int|float|null $content = '', array $attributes = []): H4 { $tag = new H4(); if (!empty($attributes)) { @@ -1164,10 +1164,10 @@ public static function h4(string|Stringable $content = '', array $attributes = [ /** * Generates a {@see H5} tag. * - * @param string|Stringable $content Tag content. + * @param string|Stringable|int|float|null $content Tag content. * @param array $attributes The tag attributes in terms of name-value pairs. */ - public static function h5(string|Stringable $content = '', array $attributes = []): H5 + public static function h5(string|Stringable|int|float|null $content = '', array $attributes = []): H5 { $tag = new H5(); if (!empty($attributes)) { @@ -1179,10 +1179,10 @@ public static function h5(string|Stringable $content = '', array $attributes = [ /** * Generates a {@see H6} tag. * - * @param string|Stringable $content Tag content. + * @param string|Stringable|int|float|null $content Tag content. * @param array $attributes The tag attributes in terms of name-value pairs. */ - public static function h6(string|Stringable $content = '', array $attributes = []): H6 + public static function h6(string|Stringable|int|float|null $content = '', array $attributes = []): H6 { $tag = new H6(); if (!empty($attributes)) { @@ -1194,10 +1194,10 @@ public static function h6(string|Stringable $content = '', array $attributes = [ /** * Generates a {@see P} tag. * - * @param string|Stringable $content Tag content. + * @param string|Stringable|int|float|null $content Tag content. * @param array $attributes The tag attributes in terms of name-value pairs. */ - public static function p(string|Stringable $content = '', array $attributes = []): P + public static function p(string|Stringable|int|float|null $content = '', array $attributes = []): P { $tag = new P(); if (!empty($attributes)) { @@ -1237,10 +1237,10 @@ public static function ol(array $attributes = []): Ol /** * Generates a {@see Li} tag. * - * @param string|Stringable $content Tag content. + * @param string|Stringable|int|float|null $content Tag content. * @param array $attributes The tag attributes in terms of name-value pairs. */ - public static function li(string|Stringable $content = '', array $attributes = []): Li + public static function li(string|Stringable|int|float|null $content = '', array $attributes = []): Li { $tag = new Li(); @@ -1268,10 +1268,10 @@ public static function datalist(array $attributes = []): Datalist /** * Generates a {@see Caption} tag. * - * @param string|Stringable $content Tag content. + * @param string|Stringable|int|float|null $content Tag content. * @param array $attributes The tag attributes in terms of name-value pairs. */ - public static function caption(string|Stringable $content = '', array $attributes = []): Caption + public static function caption(string|Stringable|int|float|null $content = '', array $attributes = []): Caption { $tag = new Caption(); if ($content !== '') { @@ -1363,10 +1363,10 @@ public static function tr(array $attributes = []): Tr /** * Generates a {@see Td} tag. * - * @param string|Stringable $content Tag content. + * @param string|Stringable|int|float|null $content Tag content. * @param array $attributes The tag attributes in terms of name-value pairs. */ - public static function td(string|Stringable $content = '', array $attributes = []): Td + public static function td(string|Stringable|int|float|null $content = '', array $attributes = []): Td { $tag = new Td(); if ($content !== '') { @@ -1381,10 +1381,10 @@ public static function td(string|Stringable $content = '', array $attributes = [ /** * Generates a {@see Th} tag. * - * @param string|Stringable $content Tag content. + * @param string|Stringable|int|float|null $content Tag content. * @param array $attributes The tag attributes in terms of name-value pairs. */ - public static function th(string|Stringable $content = '', array $attributes = []): Th + public static function th(string|Stringable|int|float|null $content = '', array $attributes = []): Th { $tag = new Th(); if ($content !== '') { @@ -1448,11 +1448,11 @@ public static function source(): Source /** * Generates a {@see Html} tag. * - * @param string|Stringable $content Tag content. + * @param string|Stringable|int|float|null $content Tag content. * @param string|null $lang The document language. * @param array $attributes The tag attributes in terms of name-value pairs. */ - public static function html(string|Stringable $content = '', ?string $lang = null, array $attributes = []): Tag\Html + public static function html(string|Stringable|int|float|null $content = '', ?string $lang = null, array $attributes = []): Tag\Html { $tag = new Tag\Html(); if (!empty($attributes)) { @@ -1470,10 +1470,10 @@ public static function html(string|Stringable $content = '', ?string $lang = nul /** * Generates a {@see Body} tag. * - * @param string|Stringable $content Tag content. + * @param string|Stringable|int|float|null $content Tag content. * @param array $attributes The tag attributes in terms of name-value pairs. */ - public static function body(string|Stringable $content = '', array $attributes = []): Body + public static function body(string|Stringable|int|float|null $content = '', array $attributes = []): Body { $tag = new Body(); if (!empty($attributes)) { @@ -1485,10 +1485,10 @@ public static function body(string|Stringable $content = '', array $attributes = /** * Generates a {@see Article} tag. * - * @param string|Stringable $content Tag content. + * @param string|Stringable|int|float|null $content Tag content. * @param array $attributes The tag attributes in terms of name-value pairs. */ - public static function article(string|Stringable $content = '', array $attributes = []): Article + public static function article(string|Stringable|int|float|null $content = '', array $attributes = []): Article { $tag = new Article(); if (!empty($attributes)) { @@ -1500,10 +1500,10 @@ public static function article(string|Stringable $content = '', array $attribute /** * Generates a {@see Section} tag. * - * @param string|Stringable $content Tag content. + * @param string|Stringable|int|float|null $content Tag content. * @param array $attributes The tag attributes in terms of name-value pairs. */ - public static function section(string|Stringable $content = '', array $attributes = []): Section + public static function section(string|Stringable|int|float|null $content = '', array $attributes = []): Section { $tag = new Section(); if (!empty($attributes)) { @@ -1515,10 +1515,10 @@ public static function section(string|Stringable $content = '', array $attribute /** * Generates a {@see Nav} tag. * - * @param string|Stringable $content Tag content. + * @param string|Stringable|int|float|null $content Tag content. * @param array $attributes The tag attributes in terms of name-value pairs. */ - public static function nav(string|Stringable $content = '', array $attributes = []): Nav + public static function nav(string|Stringable|int|float|null $content = '', array $attributes = []): Nav { $tag = new Nav(); if (!empty($attributes)) { @@ -1530,10 +1530,10 @@ public static function nav(string|Stringable $content = '', array $attributes = /** * Generates a {@see Aside} tag. * - * @param string|Stringable $content Tag content. + * @param string|Stringable|int|float|null $content Tag content. * @param array $attributes The tag attributes in terms of name-value pairs. */ - public static function aside(string|Stringable $content = '', array $attributes = []): Aside + public static function aside(string|Stringable|int|float|null $content = '', array $attributes = []): Aside { $tag = new Aside(); if (!empty($attributes)) { @@ -1545,10 +1545,10 @@ public static function aside(string|Stringable $content = '', array $attributes /** * Generates a {@see Hgroup} tag. * - * @param string|Stringable $content Tag content. + * @param string|Stringable|int|float|null $content Tag content. * @param array $attributes The tag attributes in terms of name-value pairs. */ - public static function hgroup(string|Stringable $content = '', array $attributes = []): Hgroup + public static function hgroup(string|Stringable|int|float|null $content = '', array $attributes = []): Hgroup { $tag = new Hgroup(); if (!empty($attributes)) { @@ -1560,10 +1560,10 @@ public static function hgroup(string|Stringable $content = '', array $attributes /** * Generates a {@see Header} tag. * - * @param string|Stringable $content Tag content. + * @param string|Stringable|int|float|null $content Tag content. * @param array $attributes The tag attributes in terms of name-value pairs. */ - public static function header(string|Stringable $content = '', array $attributes = []): Header + public static function header(string|Stringable|int|float|null $content = '', array $attributes = []): Header { $tag = new Header(); if (!empty($attributes)) { @@ -1587,10 +1587,10 @@ public static function hr(array $attributes = []): Hr /** * Generates a {@see Footer} tag. * - * @param string|Stringable $content Tag content. + * @param string|Stringable|int|float|null $content Tag content. * @param array $attributes The tag attributes in terms of name-value pairs. */ - public static function footer(string|Stringable $content = '', array $attributes = []): Footer + public static function footer(string|Stringable|int|float|null $content = '', array $attributes = []): Footer { $tag = new Footer(); if (!empty($attributes)) { @@ -1602,10 +1602,10 @@ public static function footer(string|Stringable $content = '', array $attributes /** * Generates a {@see Address} tag. * - * @param string|Stringable $content Tag content. + * @param string|Stringable|int|float|null $content Tag content. * @param array $attributes The tag attributes in terms of name-value pairs. */ - public static function address(string|Stringable $content = '', array $attributes = []): Address + public static function address(string|Stringable|int|float|null $content = '', array $attributes = []): Address { $tag = new Address(); if (!empty($attributes)) { diff --git a/src/Tag/Base/ListTag.php b/src/Tag/Base/ListTag.php index f4cc2052..844eb6cc 100644 --- a/src/Tag/Base/ListTag.php +++ b/src/Tag/Base/ListTag.php @@ -4,6 +4,7 @@ namespace Yiisoft\Html\Tag\Base; +use Stringable; use Yiisoft\Html\Tag\Li; /** @@ -27,14 +28,14 @@ public function items(Li ...$items): static } /** - * @param string[] $strings Array of list items as strings. + * @param (string|Stringable|int|float|null)[] $strings Array of list items as strings. * @param array $attributes The tag attributes in terms of name-value pairs. * @param bool $encode Whether to encode strings passed. */ public function strings(array $strings, array $attributes = [], bool $encode = true): static { $items = array_map( - static fn(string $string) => (new Li()) + static fn(string|Stringable|int|float|null $string) => (new Li()) ->content($string) ->attributes($attributes) ->encode($encode), diff --git a/src/Tag/Base/TagContentTrait.php b/src/Tag/Base/TagContentTrait.php index 7d450e89..66846ebe 100644 --- a/src/Tag/Base/TagContentTrait.php +++ b/src/Tag/Base/TagContentTrait.php @@ -17,7 +17,7 @@ trait TagContentTrait private bool $doubleEncode = true; /** - * @psalm-var list + * @psalm-var list */ private array $content = []; @@ -48,9 +48,9 @@ final public function doubleEncode(bool $doubleEncode): static } /** - * @param string|Stringable ...$content Tag content. + * @param string|Stringable|int|float|null ...$content Tag content. */ - final public function content(string|Stringable ...$content): static + final public function content(string|Stringable|int|float|null ...$content): static { $new = clone $this; $new->content = array_values($content); @@ -58,9 +58,9 @@ final public function content(string|Stringable ...$content): static } /** - * @param string|Stringable ...$content Tag content. + * @param string|Stringable|int|float|null ...$content Tag content. */ - final public function addContent(string|Stringable ...$content): static + final public function addContent(string|Stringable|int|float|null ...$content): static { $new = clone $this; $new->content = array_merge($new->content, array_values($content)); @@ -79,7 +79,7 @@ final protected function generateContent(): string $item = Html::encode($item, $this->doubleEncode); } - $content .= $item; + $content .= (string) $item; } return $content; diff --git a/src/Tag/Button.php b/src/Tag/Button.php index c370eb5a..b7642a7c 100644 --- a/src/Tag/Button.php +++ b/src/Tag/Button.php @@ -4,6 +4,7 @@ namespace Yiisoft\Html\Tag; +use Stringable; use Yiisoft\Html\Tag\Base\NormalTag; use Yiisoft\Html\Tag\Base\TagContentTrait; @@ -14,21 +15,21 @@ final class Button extends NormalTag { use TagContentTrait; - public static function button(string $content = ''): self + public static function button(string|Stringable|int|float|null $content = ''): self { $button = (new self())->content($content); $button->attributes['type'] = 'button'; return $button; } - public static function submit(string $content = ''): self + public static function submit(string|Stringable|int|float|null $content = ''): self { $button = (new self())->content($content); $button->attributes['type'] = 'submit'; return $button; } - public static function reset(string $content = ''): self + public static function reset(string|Stringable|int|float|null $content = ''): self { $button = (new self())->content($content); $button->attributes['type'] = 'reset'; diff --git a/src/Tag/Optgroup.php b/src/Tag/Optgroup.php index 83f9cbe5..03260112 100644 --- a/src/Tag/Optgroup.php +++ b/src/Tag/Optgroup.php @@ -27,7 +27,7 @@ public function options(Option ...$options): self /** * Options as a set of value-content pairs. * - * @param string[] $data Value-content set of options. + * @param (string|Stringable|int|float|null)[] $data Value-content set of options. * @param bool $encode Whether to encode option content. * @param array[] $optionsAttributes Array of option attribute sets indexed by option values from {@see $data}. */ diff --git a/src/Tag/Script.php b/src/Tag/Script.php index 4716c01c..792bc3fe 100644 --- a/src/Tag/Script.php +++ b/src/Tag/Script.php @@ -23,12 +23,12 @@ final class Script extends NormalTag /** * @link https://www.w3.org/TR/html52/semantics-scripting.html#script-content-restrictions * - * @param string $content Tag content. + * @param string|Stringable $content Tag content. */ - public function content(string $content): self + public function content(string|Stringable $content): self { $new = clone $this; - $new->content = $content; + $new->content = (string) $content; return $new; } diff --git a/src/Tag/Select.php b/src/Tag/Select.php index 1d81dc0d..b535990d 100644 --- a/src/Tag/Select.php +++ b/src/Tag/Select.php @@ -17,7 +17,7 @@ * * @link https://www.w3.org/TR/html52/sec-forms.html#the-select-element * - * @psalm-type OptionsData = array> + * @psalm-type OptionsData = array> */ final class Select extends NormalTag { @@ -168,10 +168,10 @@ public function optionsData( } /** - * @param string|null $text Text of the option that has dummy value and is rendered + * @param string|Stringable|null $text Text of the option that has dummy value and is rendered * as an invitation to select a value. */ - public function prompt(?string $text): self + public function prompt(string|Stringable|null $text): self { $new = clone $this; $new->prompt = $text === null ? null : (new Option()) diff --git a/src/Tag/Style.php b/src/Tag/Style.php index 5f45cd1b..3ebfa518 100644 --- a/src/Tag/Style.php +++ b/src/Tag/Style.php @@ -4,6 +4,7 @@ namespace Yiisoft\Html\Tag; +use Stringable; use Yiisoft\Html\Tag\Base\NormalTag; /** @@ -14,12 +15,12 @@ final class Style extends NormalTag private string $content = ''; /** - * @param string $content Tag content. + * @param string|Stringable $content Tag content. */ - public function content(string $content): self + public function content(string|Stringable $content): self { $new = clone $this; - $new->content = $content; + $new->content = (string) $content; return $new; } diff --git a/src/Tag/Table.php b/src/Tag/Table.php index 28a11d2e..83d21add 100644 --- a/src/Tag/Table.php +++ b/src/Tag/Table.php @@ -4,6 +4,7 @@ namespace Yiisoft\Html\Tag; +use Stringable; use Yiisoft\Html\Tag\Base\NormalTag; /** @@ -44,7 +45,7 @@ public function caption(?Caption $caption): self return $new; } - public function captionString(string $content, bool $encode = true): self + public function captionString(string|Stringable|int|float|null $content, bool $encode = true): self { $caption = (new Caption())->content($content); if (!$encode) { diff --git a/src/Tag/Textarea.php b/src/Tag/Textarea.php index 36e40be2..29c5e0c7 100644 --- a/src/Tag/Textarea.php +++ b/src/Tag/Textarea.php @@ -40,9 +40,9 @@ public function columns(?int $count): self } /** - * @param string|string[]|Stringable|null $value + * @param string|string[]|Stringable|int|float|null $value */ - public function value(string|Stringable|array|null $value): self + public function value(string|Stringable|int|float|array|null $value): self { $content = is_array($value) ? implode("\n", $value) diff --git a/src/Tag/Tr.php b/src/Tag/Tr.php index 7179dcd6..1df6d152 100644 --- a/src/Tag/Tr.php +++ b/src/Tag/Tr.php @@ -4,6 +4,7 @@ namespace Yiisoft\Html\Tag; +use Stringable; use Yiisoft\Html\Tag\Base\NormalTag; use Yiisoft\Html\Tag\Base\TableCellTag; @@ -90,14 +91,14 @@ protected function getName(): string } /** - * @param string[] $strings + * @param (string|Stringable|int|float|null)[] $strings * * @return Td[] */ private function makeDataCells(array $strings, array $attributes, bool $encode): array { return array_map( - static fn(string $string) => (new Td()) + static fn(string|Stringable|int|float|null $string) => (new Td()) ->content($string) ->attributes($attributes) ->encode($encode), @@ -106,14 +107,14 @@ private function makeDataCells(array $strings, array $attributes, bool $encode): } /** - * @param string[] $strings + * @param (string|Stringable|int|float|null)[] $strings * * @return Th[] */ private function makeHeaderCells(array $strings, array $attributes, bool $encode): array { return array_map( - static fn(string $string) => (new Th()) + static fn(string|Stringable|int|float|null $string) => (new Th()) ->content($string) ->attributes($attributes) ->encode($encode), From 9f156407e21c37d10e2bc47c7e6893006910e605 Mon Sep 17 00:00:00 2001 From: Sergei Predvoditelev Date: Tue, 17 Mar 2026 10:59:24 +0300 Subject: [PATCH 2/4] tests --- tests/HtmlTest.php | 77 ++++++++++++++++++++++++++ tests/Tag/Base/ListTagTest.php | 4 +- tests/Tag/Base/TagContentTraitTest.php | 58 ++++++++++++++----- tests/Tag/ButtonTest.php | 61 +++++++++++++++----- tests/Tag/CustomTagTest.php | 5 +- tests/Tag/OptgroupTest.php | 4 ++ tests/Tag/ScriptTest.php | 10 ++++ tests/Tag/SelectTest.php | 15 ++++- tests/Tag/StyleTest.php | 10 ++++ tests/Tag/TableTest.php | 17 +++++- tests/Tag/TextareaTest.php | 2 + tests/Tag/TrTest.php | 8 +-- 12 files changed, 233 insertions(+), 38 deletions(-) diff --git a/tests/HtmlTest.php b/tests/HtmlTest.php index 597f2e76..188cbe8d 100644 --- a/tests/HtmlTest.php +++ b/tests/HtmlTest.php @@ -67,6 +67,9 @@ public function testTag(): void $this->assertSame('

hello

', Html::tag('h1', 'hello')->render()); $this->assertSame('

hello

', Html::tag('h1', 'hello', ['id' => 'main'])->render()); $this->assertSame('

Hello

', Html::tag('div', Html::p('Hello'))->render()); + $this->assertSame('

42

', Html::tag('h1', 42)->render()); + $this->assertSame('

3.14

', Html::tag('h1', 3.14)->render()); + $this->assertSame('

', Html::tag('h1', null)->render()); } public function testNormalTag(): void @@ -76,6 +79,9 @@ public function testNormalTag(): void $this->assertSame('

hello

', Html::normalTag('h1', 'hello')->render()); $this->assertSame('

hello

', Html::normalTag('h1', 'hello', ['id' => 'main'])->render()); $this->assertSame('

Hello

', Html::normalTag('div', Html::p('Hello'))->render()); + $this->assertSame('

42

', Html::normalTag('h1', 42)->render()); + $this->assertSame('

3.14

', Html::normalTag('h1', 3.14)->render()); + $this->assertSame('

', Html::normalTag('h1', null)->render()); } public function testVoidTag(): void @@ -106,6 +112,10 @@ public function testStyle(): void '', Html::style('.red{color:#f00}', ['id' => 'main'])->render(), ); + $this->assertSame( + '', + Html::style(new StringableObject('body{}'))->render(), + ); } public function testScript(): void @@ -116,6 +126,10 @@ public function testScript(): void '', Html::script('alert(15)', ['id' => 'main'])->render(), ); + $this->assertSame( + '', + Html::script(new StringableObject('alert(1)'))->render(), + ); } public function testNoscript(): void @@ -123,6 +137,9 @@ public function testNoscript(): void $this->assertSame('', Html::noscript()->render()); $this->assertSame('', Html::noscript('hello')->render()); $this->assertSame('', Html::noscript(new Div())->render()); + $this->assertSame('', Html::noscript(42)->render()); + $this->assertSame('', Html::noscript(3.14)->render()); + $this->assertSame('', Html::noscript(null)->render()); } public function testTitle(): void @@ -131,6 +148,9 @@ public function testTitle(): void $this->assertSame('hello', Html::title('hello')->render()); $this->assertSame('hello', Html::title('hello', ['id' => 'main'])->render()); $this->assertSame('hello', Html::title(new StringableObject('hello'))->render()); + $this->assertSame('42', Html::title(42)->render()); + $this->assertSame('3.14', Html::title(3.14)->render()); + $this->assertSame('', Html::title(null)->render()); } public function testMeta(): void @@ -195,6 +215,9 @@ public function testA(): void Html::a('link', 'https://example.com', ['id' => 'home'])->render(), ); $this->assertSame('Hello', Html::a(Html::span('Hello'))->render()); + $this->assertSame('42', Html::a(42)->render()); + $this->assertSame('3.14', Html::a(3.14)->render()); + $this->assertSame('', Html::a(null)->render()); } public function testMailto(): void @@ -211,6 +234,18 @@ public function testMailto(): void 'contact me', Html::mailto('contact me', 'info@example.com', ['id' => 'contact'])->render(), ); + $this->assertSame( + '42', + Html::mailto(42)->render(), + ); + $this->assertSame( + '42', + Html::mailto(42, 'info@example.com')->render(), + ); + $this->assertSame( + '', + Html::mailto(null)->render(), + ); } public function testImg(): void @@ -261,6 +296,8 @@ public function testLabel(): void $this->assertSame('', Html::label('Name', '')->render()); $this->assertSame('', Html::label('Name', 'fieldName')->render()); $this->assertSame('', Html::label(Html::span('Hello'))->render()); + $this->assertSame('', Html::label(42)->render()); + $this->assertSame('', Html::label(null)->render()); } public function testLegend(): void @@ -277,6 +314,8 @@ public function testLegend(): void 'Your data', Html::legend('Your data', ['id' => 'MyLegend'])->render(), ); + $this->assertSame('42', Html::legend(42)->render()); + $this->assertSame('', Html::legend(null)->render()); } public function testButton(): void @@ -289,6 +328,14 @@ public function testButton(): void '', Html::button('Button', ['id' => 'main'])->render(), ); + $this->assertSame( + '', + Html::button(42)->render(), + ); + $this->assertSame( + '', + Html::button(null)->render(), + ); } public function testSubmitButton(): void @@ -301,6 +348,10 @@ public function testSubmitButton(): void '', Html::submitButton('Submit', ['id' => 'main'])->render(), ); + $this->assertSame( + '', + Html::submitButton(42)->render(), + ); } public function testResetButton(): void @@ -313,6 +364,10 @@ public function testResetButton(): void '', Html::resetButton('Reset', ['id' => 'main'])->render(), ); + $this->assertSame( + '', + Html::resetButton(42)->render(), + ); } public function testInput(): void @@ -515,6 +570,9 @@ public function testOption(): void $this->assertSame('', Html::option('test')->render()); $this->assertSame('', Html::option('test', 42)->render()); $this->assertSame('', Html::option(Html::span('Hello'))->render()); + $this->assertSame('', Html::option(42)->render()); + $this->assertSame('', Html::option(3.14)->render()); + $this->assertSame('', Html::option(null)->render()); } public function testTextarea(): void @@ -571,6 +629,9 @@ public function testDiv(): void $this->assertSame('
hello
', Html::div('hello')->render()); $this->assertSame('
hello
', Html::div('hello', ['id' => 'main'])->render()); $this->assertSame('
Hello
', Html::div(Html::span('Hello'))->render()); + $this->assertSame('
42
', Html::div(42)->render()); + $this->assertSame('
3.14
', Html::div(3.14)->render()); + $this->assertSame('
', Html::div(null)->render()); } public function testSpan(): void @@ -579,6 +640,8 @@ public function testSpan(): void $this->assertSame('hello', Html::span('hello')->render()); $this->assertSame('hello', Html::span('hello', ['id' => 'main'])->render()); $this->assertSame('Hello', Html::span(Html::span('Hello'))->render()); + $this->assertSame('42', Html::span(42)->render()); + $this->assertSame('', Html::span(null)->render()); } public function testEm(): void @@ -627,6 +690,8 @@ public function testH1(): void $this->assertSame('

hello

', Html::h1('hello')->render()); $this->assertSame('

hello

', Html::h1('hello', ['id' => 'main'])->render()); $this->assertSame('

Hello

', Html::h1(Html::span('Hello'))->render()); + $this->assertSame('

42

', Html::h1(42)->render()); + $this->assertSame('

', Html::h1(null)->render()); } public function testH2(): void @@ -675,6 +740,8 @@ public function testP(): void $this->assertSame('

hello

', Html::p('hello')->render()); $this->assertSame('

hello

', Html::p('hello', ['id' => 'main'])->render()); $this->assertSame('

Hello

', Html::p(Html::span('Hello'))->render()); + $this->assertSame('

42

', Html::p(42)->render()); + $this->assertSame('

', Html::p(null)->render()); } public function testUl(): void @@ -712,6 +779,9 @@ public function testLi(): void Html::li('Content', ['class' => 'item', 'id' => 'item-1'])->render(), ); $this->assertSame('
  • ', Html::li(attributes: ['class' => 'empty'])->render()); + $this->assertSame('
  • 42
  • ', Html::li(42)->render()); + $this->assertSame('
  • 3.14
  • ', Html::li(3.14)->render()); + $this->assertSame('
  • ', Html::li(null)->render()); } public function testDatalist(): void @@ -729,6 +799,8 @@ public function testCaption(): void Html::caption('Hello', ['class' => 'red'])->render(), ); $this->assertSame('Hello', Html::caption(Html::span('Hello'))->render()); + $this->assertSame('42', Html::caption(42)->render()); + $this->assertSame('', Html::caption(null)->render()); } public function testCol(): void @@ -779,6 +851,9 @@ public function testTd(): void $this->assertSame('Hello', Html::td('Hello')->render()); $this->assertSame('Hello', Html::td('Hello', ['class' => 'red'])->render()); $this->assertSame('Hello', Html::td(Html::span('Hello'))->render()); + $this->assertSame('42', Html::td(42)->render()); + $this->assertSame('3.14', Html::td(3.14)->render()); + $this->assertSame('', Html::td(null)->render()); } public function testTh(): void @@ -787,6 +862,8 @@ public function testTh(): void $this->assertSame('Hello', Html::th('Hello')->render()); $this->assertSame('Hello', Html::th('Hello', ['class' => 'red'])->render()); $this->assertSame('Hello', Html::th(Html::span('Hello'))->render()); + $this->assertSame('42', Html::th(42)->render()); + $this->assertSame('', Html::th(null)->render()); } public function testBr(): void diff --git a/tests/Tag/Base/ListTagTest.php b/tests/Tag/Base/ListTagTest.php index 22ab0cff..8c21c4aa 100644 --- a/tests/Tag/Base/ListTagTest.php +++ b/tests/Tag/Base/ListTagTest.php @@ -22,9 +22,9 @@ public function testItems(): void public function testStrings(): void { - $tag = (new TestListTag())->strings(['A', 'B']); + $tag = (new TestListTag())->strings(['A', 'B', 1, 2.5, null]); - $this->assertSame("\n
  • A
  • \n
  • B
  • \n
    ", (string) $tag); + $this->assertSame("\n
  • A
  • \n
  • B
  • \n
  • 1
  • \n
  • 2.5
  • \n
  • \n
    ", (string) $tag); } public function testStringsAttributes(): void diff --git a/tests/Tag/Base/TagContentTraitTest.php b/tests/Tag/Base/TagContentTraitTest.php index db201736..9de843e3 100644 --- a/tests/Tag/Base/TagContentTraitTest.php +++ b/tests/Tag/Base/TagContentTraitTest.php @@ -57,11 +57,14 @@ public static function dataContent(): array 'Hello > World!', ['Hello', ' > ', (new Span())->content('World'), '!'], ], + 'int' => ['42', 42], + 'float' => ['3.14', 3.14], + 'null' => ['', null], ]; } #[DataProvider('dataContent')] - public function testContent(string $expected, string|array|Stringable $content): void + public function testContent(string $expected, string|int|float|array|Stringable|null $content): void { $tag = new TestTagContentTrait(); $tag = is_array($content) ? $tag->content(...$content) : $tag->content($content); @@ -80,16 +83,36 @@ public function testEncodeContent(): void ); } - public function testAddContent(): void + public static function dataAddContent(): array { - $this->assertSame( - 'Hello World', - (new TestTagContentTrait()) - ->content('Hello') - ->addContent(' ') - ->addContent(new StringableObject('World')) - ->render(), - ); + return [ + 'stringable' => [ + 'Hello World', + 'Hello', + [' ', new StringableObject('World')], + ], + 'int' => [ + 'Value: 42', + 'Value: ', + [42], + ], + 'float' => [ + 'Value: 3.14', + 'Value: ', + [3.14], + ], + ]; + } + + #[DataProvider('dataAddContent')] + public function testAddContent(string $expected, string $initial, array $additions): void + { + $tag = (new TestTagContentTrait())->content($initial); + foreach ($additions as $addition) { + $tag = $tag->addContent($addition); + } + + $this->assertSame($expected, $tag->render()); } public function testAddContentVariadic(): void @@ -115,11 +138,20 @@ public function testNamedParametersContent(): void ); } - public function testContentArray(): void + public static function dataContentArray(): array + { + return [ + 'strings' => [['1', '2'], ['a' => '1', 'b' => '2']], + 'int-float-null' => [[42, 3.14, null], ['a' => 42, 'b' => 3.14, 'c' => null]], + ]; + } + + #[DataProvider('dataContentArray')] + public function testContentArray(array $expected, array $args): void { - $tag = (new TestTagContentTrait())->content(a: '1', b: '2'); + $tag = (new TestTagContentTrait())->content(...$args); - $this->assertSame(['1', '2'], $tag->getContentArray()); + $this->assertSame($expected, $tag->getContentArray()); } public function testImmutability(): void diff --git a/tests/Tag/ButtonTest.php b/tests/Tag/ButtonTest.php index fd09ac46..11c3d964 100644 --- a/tests/Tag/ButtonTest.php +++ b/tests/Tag/ButtonTest.php @@ -20,11 +20,22 @@ public function testBase(): void ); } - public function testButton(): void + public static function dataButton(): array + { + return [ + 'string' => ['Agree', 'Agree'], + 'int' => ['42', 42], + 'float' => ['3.14', 3.14], + 'null' => ['', null], + ]; + } + + #[DataProvider('dataButton')] + public function testButton(string $expectedContent, string|int|float|null $content): void { $this->assertSame( - '', - (string) Button::button('Agree'), + "", + (string) Button::button($content), ); } @@ -36,6 +47,25 @@ public function testButtonWithoutContent(): void ); } + public static function dataSubmit(): array + { + return [ + 'string' => ['Send', 'Send'], + 'int' => ['1', 1], + 'float' => ['3.14', 3.14], + 'null' => ['', null], + ]; + } + + #[DataProvider('dataSubmit')] + public function testSubmit(string $expectedContent, string|int|float|null $content): void + { + $this->assertSame( + "", + (string) Button::submit($content), + ); + } + public function testSubmitWithoutContent(): void { $this->assertSame( @@ -44,27 +74,30 @@ public function testSubmitWithoutContent(): void ); } - public function testResetWithoutContent(): void + public static function dataReset(): array { - $this->assertSame( - '', - (string) Button::reset(), - ); + return [ + 'string' => ['Reset form', 'Reset form'], + 'int' => ['1', 1], + 'float' => ['3.14', 3.14], + 'null' => ['', null], + ]; } - public function testSubmit(): void + #[DataProvider('dataReset')] + public function testReset(string $expectedContent, string|int|float|null $content): void { $this->assertSame( - '', - (string) Button::submit('Send'), + "", + (string) Button::reset($content), ); } - public function testReset(): void + public function testResetWithoutContent(): void { $this->assertSame( - '', - (string) Button::reset('Reset form'), + '', + (string) Button::reset(), ); } diff --git a/tests/Tag/CustomTagTest.php b/tests/Tag/CustomTagTest.php index 38e4ab26..48ab921e 100644 --- a/tests/Tag/CustomTagTest.php +++ b/tests/Tag/CustomTagTest.php @@ -121,11 +121,14 @@ public static function dataContent(): array 'Hello > World!', ['Hello', ' > ', (new Span())->content('World'), '!'], ], + 'int' => ['42', 42], + 'float' => ['3.14', 3.14], + 'null' => ['', null], ]; } #[DataProvider('dataContent')] - public function testContent(string $expected, string|array|Stringable $content): void + public function testContent(string $expected, string|int|float|array|Stringable|null $content): void { $tag = new CustomTag('test'); $tag = is_array($content) ? $tag->content(...$content) : $tag->content($content); diff --git a/tests/Tag/OptgroupTest.php b/tests/Tag/OptgroupTest.php index 1d272419..467657c7 100644 --- a/tests/Tag/OptgroupTest.php +++ b/tests/Tag/OptgroupTest.php @@ -53,6 +53,10 @@ public function testOptionsData(): void "\n\n\n", (string) (new Optgroup())->optionsData(['1' => 'One', '2' => 'Two']), ); + $this->assertSame( + "\n\n\n", + (string) (new Optgroup())->optionsData(['1' => 42, '2' => 3.14]), + ); } public function testOptionsDataEncode(): void diff --git a/tests/Tag/ScriptTest.php b/tests/Tag/ScriptTest.php index 65adb8a7..c82e33c4 100644 --- a/tests/Tag/ScriptTest.php +++ b/tests/Tag/ScriptTest.php @@ -10,6 +10,7 @@ use Yiisoft\Html\Tag\Div; use Yiisoft\Html\Tag\Noscript; use Yiisoft\Html\Tag\Script; +use Yiisoft\Html\Tests\Objects\StringableObject; final class ScriptTest extends TestCase { @@ -30,6 +31,15 @@ public function testContent(): void $this->assertSame('', $tag->render()); } + public function testContentWithStringable(): void + { + $content = new StringableObject('alert("hello");'); + $tag = (new Script())->content($content); + + $this->assertSame('alert("hello");', $tag->getContent()); + $this->assertSame('', $tag->render()); + } + public static function dataUrl(): array { return [ diff --git a/tests/Tag/SelectTest.php b/tests/Tag/SelectTest.php index 6a428e7f..5898dac8 100644 --- a/tests/Tag/SelectTest.php +++ b/tests/Tag/SelectTest.php @@ -6,9 +6,11 @@ use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; +use Stringable; use Yiisoft\Html\Tag\Optgroup; use Yiisoft\Html\Tag\Option; use Yiisoft\Html\Tag\Select; +use Yiisoft\Html\Tests\Objects\StringableObject; use Yiisoft\Html\Tests\Support\IntegerEnum; use Yiisoft\Html\Tests\Support\StringEnum; @@ -291,6 +293,10 @@ public function testOptionsData(): void "", (string) (new Select())->optionsData(['1' => 'One', '2' => 'Two']), ); + $this->assertSame( + "", + (string) (new Select())->optionsData(['1' => 42, '2' => 3.14]), + ); } public function testOptionsDataEncode(): void @@ -393,11 +399,18 @@ public static function dataPrompt(): array . '', 'Please select...', ], + [ + '', + new StringableObject('Choose an option'), + ], ]; } #[DataProvider('dataPrompt')] - public function testPrompt(string $expected, ?string $text): void + public function testPrompt(string $expected, string|Stringable|null $text): void { $this->assertSame( $expected, diff --git a/tests/Tag/StyleTest.php b/tests/Tag/StyleTest.php index 9dc8310d..536e8934 100644 --- a/tests/Tag/StyleTest.php +++ b/tests/Tag/StyleTest.php @@ -7,6 +7,7 @@ use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; use Yiisoft\Html\Tag\Style; +use Yiisoft\Html\Tests\Objects\StringableObject; final class StyleTest extends TestCase { @@ -27,6 +28,15 @@ public function testContent(): void $this->assertSame('', $tag->render()); } + public function testContentWithStringable(): void + { + $content = new StringableObject('body { color: red }'); + $tag = (new Style())->content($content); + + $this->assertSame('body { color: red }', $tag->getContent()); + $this->assertSame('', $tag->render()); + } + public static function dataMedia(): array { return [ diff --git a/tests/Tag/TableTest.php b/tests/Tag/TableTest.php index d3339990..514f3716 100644 --- a/tests/Tag/TableTest.php +++ b/tests/Tag/TableTest.php @@ -38,12 +38,23 @@ public function testCaption(string $expected, ?Caption $caption): void ->render()); } - public function testCaptionString(): void + public static function dataCaptionString(): array + { + return [ + 'string' => ['Hello', 'Hello'], + 'int' => ['42', 42], + 'float' => ['3.14', 3.14], + 'null' => ['', null], + ]; + } + + #[DataProvider('dataCaptionString')] + public function testCaptionString(string $expectedContent, string|int|float|null $content): void { $this->assertSame( - "\n\n
    Hello
    ", + "\n\n
    $expectedContent
    ", (new Table()) - ->captionString('Hello') + ->captionString($content) ->render(), ); } diff --git a/tests/Tag/TextareaTest.php b/tests/Tag/TextareaTest.php index e77ebd37..0f2b7ade 100644 --- a/tests/Tag/TextareaTest.php +++ b/tests/Tag/TextareaTest.php @@ -71,6 +71,8 @@ public static function dataValue(): array ['', new StringableObject('')], ['', 'content'], ['', new StringableObject('content')], + ['', 42], + ['', 3.14], [ <<a diff --git a/tests/Tag/TrTest.php b/tests/Tag/TrTest.php index 6fd75942..5ff52b92 100644 --- a/tests/Tag/TrTest.php +++ b/tests/Tag/TrTest.php @@ -48,9 +48,9 @@ public function testAddCells(): void public function testDataStrings(): void { $tr = (new Tr()) - ->dataStrings(['A', 'B']); + ->dataStrings(['A', 'B', null, 1, 2.5]); - $this->assertSame("\nA\nB\n", (string) $tr); + $this->assertSame("\nA\nB\n\n1\n2.5\n", (string) $tr); } public function testDataStringsAttributes(): void @@ -116,9 +116,9 @@ public function testAddDataStringsWithoutEncode(): void public function testHeaderStrings(): void { $tr = (new Tr()) - ->headerStrings(['A', 'B']); + ->headerStrings(['A', 'B', 1, 2.5, null]); - $this->assertSame("\nA\nB\n", (string) $tr); + $this->assertSame("\nA\nB\n1\n2.5\n\n", (string) $tr); } public function testHeaderStringsAttributes(): void From 9ec4e93f8d09d42c437bb62cf4fd11b24de59097 Mon Sep 17 00:00:00 2001 From: Sergei Predvoditelev Date: Tue, 17 Mar 2026 11:00:15 +0300 Subject: [PATCH 3/4] changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index dc6c9a28..93687b96 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ - Chg #234: Remove tag attributes sorting (@FrankiFixx) - Chg #269: Rename `$options` parameter to `$attributes` in `Html::addCssClass()`, `Html::removeCssClass()`, `Html::addCssStyle()` and `Html::removeCssStyle()` methods (@vjik) +- New #270: Allow pass `int`, `float` and `null` as tag content (@vjik) ## 3.13.0 March 13, 2026 From 538b1d373af521d169bcb35a9a8b186374b483fe Mon Sep 17 00:00:00 2001 From: Sergei Predvoditelev Date: Tue, 17 Mar 2026 11:11:57 +0300 Subject: [PATCH 4/4] improve --- CHANGELOG.md | 2 +- src/Tag/Base/ListTag.php | 4 ++-- src/Tag/Select.php | 6 +++--- src/Tag/Tr.php | 4 ++-- tests/Tag/SelectTest.php | 26 +++++++++++++++++++++++++- tests/Tag/TrTest.php | 7 +++++-- 6 files changed, 38 insertions(+), 11 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 93687b96..f7ea444b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,7 +7,7 @@ - Chg #234: Remove tag attributes sorting (@FrankiFixx) - Chg #269: Rename `$options` parameter to `$attributes` in `Html::addCssClass()`, `Html::removeCssClass()`, `Html::addCssStyle()` and `Html::removeCssStyle()` methods (@vjik) -- New #270: Allow pass `int`, `float` and `null` as tag content (@vjik) +- New #270: Allow passing `int`, `float` and `null` as tag content (@vjik) ## 3.13.0 March 13, 2026 diff --git a/src/Tag/Base/ListTag.php b/src/Tag/Base/ListTag.php index 844eb6cc..a0d6edda 100644 --- a/src/Tag/Base/ListTag.php +++ b/src/Tag/Base/ListTag.php @@ -28,9 +28,9 @@ public function items(Li ...$items): static } /** - * @param (string|Stringable|int|float|null)[] $strings Array of list items as strings. + * @param (string|Stringable|int|float|null)[] $strings Array of list item contents. * @param array $attributes The tag attributes in terms of name-value pairs. - * @param bool $encode Whether to encode strings passed. + * @param bool $encode Whether to encode the item contents when rendering. */ public function strings(array $strings, array $attributes = [], bool $encode = true): static { diff --git a/src/Tag/Select.php b/src/Tag/Select.php index b535990d..5a13e88c 100644 --- a/src/Tag/Select.php +++ b/src/Tag/Select.php @@ -17,7 +17,7 @@ * * @link https://www.w3.org/TR/html52/sec-forms.html#the-select-element * - * @psalm-type OptionsData = array> + * @psalm-type OptionsData = array> */ final class Select extends NormalTag { @@ -168,10 +168,10 @@ public function optionsData( } /** - * @param string|Stringable|null $text Text of the option that has dummy value and is rendered + * @param string|Stringable|int|float|null $text Text of the option that has dummy value and is rendered * as an invitation to select a value. */ - public function prompt(string|Stringable|null $text): self + public function prompt(string|Stringable|int|float|null $text): self { $new = clone $this; $new->prompt = $text === null ? null : (new Option()) diff --git a/src/Tag/Tr.php b/src/Tag/Tr.php index 1df6d152..9c2c1f08 100644 --- a/src/Tag/Tr.php +++ b/src/Tag/Tr.php @@ -59,7 +59,7 @@ public function addDataStrings(array $strings, array $attributes = [], bool $enc } /** - * @param string[] $strings Array of header cells ({@see Th}) as strings. + * @param (string|Stringable|int|float|null)[] $strings Array of header cells ({@see Th}) contents. * @param array $attributes The tag attributes in terms of name-value pairs. * @param bool $encode Whether to encode strings passed. */ @@ -69,7 +69,7 @@ public function headerStrings(array $strings, array $attributes = [], bool $enco } /** - * @param string[] $strings Array of header cells ({@see Th}) as strings. + * @param (string|Stringable|int|float|null)[] $strings Array of header cells ({@see Th}) contents. * @param array $attributes The tag attributes in terms of name-value pairs. * @param bool $encode Whether to encode strings passed. */ diff --git a/tests/Tag/SelectTest.php b/tests/Tag/SelectTest.php index 5898dac8..afc1dd54 100644 --- a/tests/Tag/SelectTest.php +++ b/tests/Tag/SelectTest.php @@ -297,6 +297,10 @@ public function testOptionsData(): void "", (string) (new Select())->optionsData(['1' => 42, '2' => 3.14]), ); + $this->assertSame( + "", + (string) (new Select())->optionsData(['1' => null]), + ); } public function testOptionsDataEncode(): void @@ -323,6 +327,9 @@ public function testOptionsDataWithGroups(): void 'Test Group' => [ 2 => 'Two', 3 => 'Three', + 4 => 42, + 5 => 3.14, + 6 => null, ], ]); @@ -333,6 +340,9 @@ public function testOptionsDataWithGroups(): void + + + HTML, @@ -406,11 +416,25 @@ public static function dataPrompt(): array . '', new StringableObject('Choose an option'), ], + [ + '', + 42, + ], + [ + '', + 3.14, + ], ]; } #[DataProvider('dataPrompt')] - public function testPrompt(string $expected, string|Stringable|null $text): void + public function testPrompt(string $expected, string|Stringable|int|float|null $text): void { $this->assertSame( $expected, diff --git a/tests/Tag/TrTest.php b/tests/Tag/TrTest.php index 5ff52b92..efe55b00 100644 --- a/tests/Tag/TrTest.php +++ b/tests/Tag/TrTest.php @@ -149,9 +149,12 @@ public function testAddHeaderStrings(): void { $tr = (new Tr()) ->headerStrings(['A']) - ->addHeaderStrings(['B', 'C']); + ->addHeaderStrings(['B', 'C', 1, 2.5, null]); - $this->assertSame("\nA\nB\nC\n", (string) $tr); + $this->assertSame( + "\nA\nB\nC\n1\n2.5\n\n", + (string) $tr, + ); } public function testAddHeaderStringsAttributes(): void