[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