[wp-trac] [WordPress Trac] #50867: An API for assembling large bits of HTML
WordPress Trac
noreply at wordpress.org
Thu Aug 6 07:03:09 UTC 2020
#50867: An API for assembling large bits of HTML
-------------------------+-------------------------------------------------
Reporter: noisysocks | Owner: (none)
Type: enhancement | Status: new
Priority: normal | Milestone: Awaiting Review
Component: General | Version:
Severity: normal | Keywords: has-patch needs-unit-tests needs-
Focuses: | docs
-------------------------+-------------------------------------------------
It's common in WordPress to write PHP code that assembles a large bit of
HTML using conditional logic. A good example of this is
[https://github.com/WordPress/gutenberg/blob/master/packages/block-
library/src/navigation-link/index.php#L106
render_block_core_navigation_link]. Unfortunately this type of code can
become difficult to read and error prone. For example, we've had several
reported XSS vulnerabilities in code like this.
How do we feel about adding an API for building large bits of HTML?
Attached is a patch which implements an API inspired by `createElement` in
`@wordpress/element` and the external `classnames` JavaScript library.
The primary interface is `wp_el`. It takes three arguments: an HTML tag
name, an array of HTML attributes, and an array of child elements. You can
nest calls to `wp_el` within each other to cleanly create deeply nested
HTML.
{{{#!php
<?php
echo wp_el(
'figure',
array( 'class' => 'my-image' ),
array(
wp_el( 'img', array( 'src' =>
'https://pbs.twimg.com/media/Ed_W9VQXkAAtYQY?format=jpg&name=medium' ) ),
wp_el(
'figcaption',
null,
'A cold refreshing glass of pilk'
),
)
);
}}}
{{{
<figure class="my-image"><img
src="https://pbs.twimg.com/media/Ed_W9VQXkAAtYQY?format=jpg&name=medium"
/><figcaption>A cold refreshing glass of pilk</figcaption></figure>
}}}
Optional arguments and automatic handling of non associative array values
can be used to make usage quite succinct.
{{{#!php
<?php
echo wp_el( 'hr' );
echo wp_el( 'input', 'required' );
}}}
{{{
<hr /><input required />
}}}
The key design detail is that **all strings are automatically escaped**.
If you want to output unescaped HTML you have to do it explicitly.
{{{#!php
<?php
echo wp_el(
'article',
null,
wp_dangerous_html( '<marquee>Unescaped HTML</marquee>' )
);
}}}
{{{
<article><marquee>Unescaped HTML</marquee></article>
}}}
Lastly, `wp_classnames` provides a convenient way to assemble HTML `class`
attributes.
{{{#!php
<?php
echo wp_el(
'li',
array(
'class' => wp_classnames(
array(
'my-link',
'is-current' => $post->ID === $id,
)
),
),
array(
wp_el(
'a',
array(
'href' => $post->guid,
),
$post->post_name
),
)
);
}}}
{{{
<li class="my-link"><a href="http://localhost:8888/?p=215">navigation-
stored-in-old-way</a></li>
}}}
Thoughts? Are there alternative approaches common in the PHP ecosystem?
Does such an API belong in Core?
--
Ticket URL: <https://core.trac.wordpress.org/ticket/50867>
WordPress Trac <https://core.trac.wordpress.org/>
WordPress publishing platform
More information about the wp-trac
mailing list