In #2005970: In renderable arrays, #type should provide a #theme suggestion, similar to how drupal_prepare_form() works there's work towards making drupal_render() behave in a more predictable and consistent manner across all possible renderable arrays.

One of the main ideas there is that the internal behaviour of drupal_render() should be dictated solely by '#type' rather than the combination of '#type', '#markup' and '#theme'.

If that goes through, all renderable arrays *by definition* will have a '#type' and can explicitly declare that they don't want a theme function to handle rendering the array.

Currently, if we don't call a theme function we do this:

  // If #theme was not set and the element has children, render them now.
  // This is the same process as drupal_render_children() but is inlined
  // for speed.
  if ($elements['#children'] === '') {
    // Get the children of the element, sorted by weight.
    $children = element_children($elements, TRUE);
    foreach ($children as $key) {
      $elements['#children'] .= drupal_render($elements[$key]);
    }
  }

A bit of background info, '#children' is what drupal_render() uses internally to represent the "main" rendered string in a kind of "running total" fashion. Basically, drupal_render() will just keep recursively working through the elements that aren't prefixed with a #, looking for theme functions it can call.

We have a theme function for HTML tags -> theme_html_tag() (although #1825090: Remove theme_html_tag() from the theme system) but drupal_render() itself has no concept of producing a HTML tag. There are lots of little theme functions that many people want to get rid of entirely #1986116: Improve performance by replacing very small and simple templates and theme function with "Markup Utility Functions" but are not sure of the best way to go about it. If drupal_render() could just reliably preprocess (sanitisation, drillability) and then structure a single HTML tag from a standardized structure, as well as its children as it currently does, then I'm sure we could safely take away a lot of the responsibility theme() currently holds for rendering little atomic bits of markup all throughout core and contrib.

This would make things faster (preliminary profiling suggests ~4% faster than the '#theme' equivalent) and probably nicer to use (although that's obviously highly subjective). As an example though we could replace this:

array('#markup' => '<a href="foo">bar</a>')

and

array(
  '#prefix' => '<a href="foo">',
  'child' => array('#markup' => 'bar'),
  '#suffix' => '</a>,
);

with something that I imagine developers might find more natural to write and also process in their own hooks like:

array(
  '#type' => 'a',
  '#attributes' => array('href' => 'foo'),
  '#value' => 'bar',
);

In this example '#type' could be any HTML tag, current or future. If a browser releases a <smell sweetness="5">roses</smell> tag then you'd simply write:

array(
  '#type' => 'smell',
  '#attributes' => array('sweetness' => '5'),
  '#value' => 'roses',
)

and if there's no hook_element_info() for 'smell', it would be interpreted as a tag. If this new HTML tag conflicted with an existing '#type' in core, you could workaround this in between major core releases (one would hope that core resolves such a conflict asap) by clever use of '#theme'.

Comments

thedavidmeister’s picture

Issue summary: View changes

Updated issue summary.

thedavidmeister’s picture

Status: Active » Closed (duplicate)

I now think this is just a worse version of #2044105: Introduce #alters for \Drupal\Core\Render\Renderer::render() as this issue:

- has no inherent alterability, so it's less flexible (although the issue summary kind of assumes alterability "elsewhere" without explaining how it would be achieved)
- introduces a new #value attribute that functionally doubles up with the concept of child elements and I don't think we want to remove child elements
- could be implemented easily by a 'html_tag' #render callback as defined in the linked issue, but the linked issue allows for other useful implementations too
- does "bad things" with #type by moving the Drupal Render API further away from being built by configurable, re-usable "render components" and closer towards re-inventing HTML as a PHP API.

thedavidmeister’s picture

Issue summary: View changes

Updated issue summary.