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
Comments
Comment #0.0
fabianx commentedMarkup structure
Comment #0.1
fabianx commentedmarkup
Comment #1
markhalliwellJust 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".
Comment #2
jenlamptonGuys, 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.
Comment #3
thedavidmeister commentedIt might not make any sense. It's a little early to say :)
Comment #3.0
thedavidmeister commentedUpdate
Comment #4
star-szrNo activity on this front in a while, demoting priority.
Comment #5
joelpittetWe want to do this, moving to our sandbox.
Comment #6
markhalliwellClosing in favor of #2869859: [PP-1] Refactor theme hooks/registry into plugin managers.