Postponed on #2052253: [META] Add #render property to drupal_render() and convert #type "#pre_render -> #markup" calls to use it.

Also the #theme_info part might not be compatible with #theme_wrappers.

Problem/Motivation

Use cases:

* We want to drill down into #type render arrays, but do not want the overhead of the theme system on every call.
* We want to implement theme => xyz without it being always used.

Example:

#type => link,
#theme => array('link__pager__next'),

We only want to render this template via the theme system if the suggestion matches the theme registry, e.g. we have a link--pager--next.html.twig in our theme.

* We need a way to prepare variables for the template, but do not want to run it always, but only if we actually go through the theme system.
( we need to allow a hook_theme() implementation that is itself empty for that, too)

Proposed resolution

* Introduce theme_info($element) function, which works purely with render arrays.
* Deprecate theme() - make it a wrapper around either drupal_render or theme_info().
* Have theme_info() return an array with the following properties, e.g.:

array(
  '#render_function' => 'twig_render_template',
  '#theme_info' => array(
     '#variables' => array(...),
     '#template' => 'core/modules/node/node.html.twig',
     '#suggestions' => array(...),
  ),
)

How this solves things, example for link:

#type => link,
#theme => array('link__pager__next'),

- element_info('link') sets #render_function = 'drupal_render_link'
- theme_info($element) checks:

* Does a hook like this exist in the system? - Yes, link__pager__next is set.
* Does the hook have a 'function' or 'template' set? - Yes, 'template' is set.
* What is the base hook? "link"

invokeAll('theme_prepare', 'theme_prepare_link', 'theme_prepare_link__pager__next')
alter('theme_prepare_alter', 'theme_prepare_link_alter', 'theme_prepare_link__pager__next_alter')

=> * Call system_theme_prepare_link() (this sets up the $variables for a link)

* Set #render_function = 'twig_render_template_element' and #theme_info to be processed by drupal_render.
* drupal_render calls #render_function($element)
* twig_render_template_element renders the twig template from $element['#theme_info']['#template_file'] with $element['#theme_info']['#variables']

Example for hook not implemented

#type => link,
#theme => array('link__not_exist'),

- element_info('link') sets #render_function = 'drupal_render_link'
- theme_info($element) checks:

* Does a hook like this (link__not_exist) exist in the system? - No.
* Does a hook like this (link) exist in the system? - Yes!
* Does the hook have a 'function' or 'template' set? - No!
=> We can't render this with the theme layer.
* return FALSE;

* drupal_render calls #render_function($element)
* drupal_render_link($element) is called and renders the link

Remaining tasks

@todo

User interface changes

@todo

API changes

@todo

* #2052253: [META] Add #render property to drupal_render() and convert #type "#pre_render -> #markup" calls to use it

Comments

Fabianx’s picture

Issue summary: View changes

Markup structure

Fabianx’s picture

Issue summary: View changes

markup

markhalliwell’s picture

Just to also clarify, this would effectively remove the "need" for having a theme registry entirely.

Also referencing: #2053385: Find a better name for "theme hook" and use it in documentation as a follow-up to this issue, which would be extremely hard to implement given how the registry deeply embeds the concept of theme "hooks".

jenlampton’s picture

Guys, does this make any sense in D9 if we don't have render arrays anymore? I'd rather not change theme() to make it work "more like other render arrays" if the long term goal is to have the whole theme system work differently than inner parts like just elements.

thedavidmeister’s picture

It might not make any sense. It's a little early to say :)

thedavidmeister’s picture

Issue summary: View changes

Update

star-szr’s picture

Priority: Major » Normal
Issue summary: View changes

No activity on this front in a while, demoting priority.

joelpittet’s picture

Project: Drupal core » Theme system sandbox
Version: 8.0.x-dev » 8.x-1.x-dev
Component: theme system » Code
Status: Postponed » Active

We want to do this, moving to our sandbox.

markhalliwell’s picture