Problem/Motivation
The theme registry has several problems, which make it impossible to move it into a proper service and keep finding functions.
1. - Especially all modules and includes need to be loaded.
The reason is that theme engines search for the theme functions instead of the registry searching for the theme functions for this particular "entity" processed.
2. - You can only define a theme suggestion in the registry by registering a template or hacking the registry. It should be possible to use a theme suggestion, but fall back to the "base hook" for the rendering.
3. - You cannot define a hook that is only used for suggestions and has neither a template nor a theme function. A theme_link is very necessary, but completely useless and performance problem if not using a suggestion or inline template.
These changes are all not BC breaking however.
Especially 1) might be necessary as it seems that update functions use theme() and so theme() cannot use the ModuleHandler to invoke things ...
Proposed resolution
- Change the order of registry execution to find theme functions and theme__suggestion functions as part of the "entity" processed not as part of the theme engine.
- Make it possible to define a stub in the registry, by introducing a public "base hook" key that is the only one that needs to be set (or again use function => FALSE, or inherit => TRUE or something).
- Make it possible to define 'function' => FALSE explicitly and have the theme registry react on this.
Remaining tasks
* Fix the theme registry.
* Write tests.
User interface changes
* None.
API changes
Just additions, no BC breaking:
* Changes theme registry processing order to make sure what is processed is loaded.
* Allow to set function => FALSE and introduce another key for (inherit or base hook) to specify only a suggestion.
Related Issues
* #2004872: [meta] Theme system architecture changes
Original report by Fabianx
The process we use to build the theme registry is updated in the following ways:
- A theme's callbacks, default arguments, and template file name are defined in
hook_theme
. This remains unchanged from D7. - Let modules and themes define suggestions for base hooks, by adding
hook_theme_suggestions
. This will allow preprocess functions to run for the suggestion without having to define a template or specific preprocess function. - Let modules and themes define a render function for specific template suggestions by adding
hook_theme_render_TEMPLATE_SUGGESTION
to replacetheme_THEMEID__suggestion
and[module]_THEMEID
; the highest priority implementation wins. - Priority will be determined by a single
theme_stack
. A theme in this stack may have an associated theme engine. This simplifies things by replacing the distinction between base themes and themes. - Processing in the registry will be executed in the following order: Modules first, Theme Stack second.
Processing in the registry will execute the following steps, for each module and theme:
- Invoke
hook_theme()
. - Invoke
hook_theme_suggestions()
where suggestions may be registered and base_hook may be set, if it exists, otherwise ignore it. The precedence on suggestions is structured such that suggestions added later overrule earlier ones. - Foreach of those
$theme_ids
returned in hook_theme (not the suggestions) execute the following:- Call
theme_retrieve_render_functions([hook], $theme_id)
on each themes produced from- Looks for
hook_theme_render_THEME_ID()
andhook_theme_render_THEME_ID__*
- Registers suggestions if needed and sets
base_hook
to$theme_id
and'function' => found function
.
- Looks for
- Call
- For the whole module or theme call:
- Call
theme_retrieve_templates($engine, [hook], $path, $hooks)
- Foreach found template matching of of $hooks, the engine sets
'template' => 'path'
and'function' => 'engine_render_function'
.
- Foreach found template matching of of $hooks, the engine sets
- Call
The above process changes are beneficial in the following ways:
- Functions will now be found during registry build, they just need to be in the "include" or file defining hook_theme(). If hook_theme() can be called, so can the theme or render functions. This is the biggest and most important change to the status quo, which currently uses the engine to search for the theme functions (WHAT?).
- Theme engines will set render_function directly. No more need to special case the template case.
- There will be one single theme stack, listed in reverse order. No more need to special case base_themes.
- Later implementations overwrite earlier implementations completely.
- The theme registry will now be much simpler to build because a function will be defined for each hook, base hooks may now be nested, and the first hook to implement 'function' wins - regardless whether it is a theme function or a template rendered via engine function.
Comments
Comment #0.0
Fabianx CreditAttribution: Fabianx commentedadded original report
Comment #3
joelpittet@Fabianx, is this still valid proposal/plan for 8.x? I'm sure this could use an issue summary clean-up/refactor considering the age of the issue.
Comment #4
joelpittetComment #5
Fabianx CreditAttribution: Fabianx as a volunteer commentedI think it is outdated.
Comment #6
joelpittet@Fabianx, they are likely to resurface by others or you I'd bet if they still are relevant. Thanks for closing.