-
Improvement
-
Resolution: Unresolved
-
Minor
-
None
-
4.1.2, 5.0
-
MOODLE_401_STABLE, MOODLE_500_STABLE
-
- Verify that the PHPUnit tests in lib/tests/output/mustache_template_finder_test.php are passing.
-
Themes can override a component template by placing a template with the same name in their template directory. However, they cannot include the original template in their overridden version.
For example, theme_foo can override the template core/test by creating the file theme/foo/templates/core/test.mustache. However, there is currently no way for theme_foo to include the original core/test template in any of its own templates, since all references to core/test will be resolved to the overridden version in theme_foo by the mustache_template_finder. This means that themes cannot benefit from the template inheritance feature using mustache blocks.
Suppose we want to override the heading in this template, but keep the original content:
{{!
|
@template core/test
|
}}
|
<h1> |
{{$heading}} Original title {{/heading}}
|
</h1> |
<div> |
{{$content}} Original content {{/content}}
|
</div> |
In theme/foo/templates/core/test.mustache we would like to do something like this:
{{!
|
@template theme_foo/core/test
|
}}
|
{{< core/test }}
|
{{$heading}} Overridden heading {{/heading}}
|
{{/ core/test}}
|
This is not possible because
{{< core/test }}
|
...
|
{{/ core/test}}
|
includes the overridden template, not the original one. In fact, this code leads to the following error when rendering the template:
Fatal error: Allowed memory size of 134217728 bytes exhausted (tried to allocate 20480 bytes) in /var/www/html/lib/mustache/src/Mustache/Engine.php on line 286
This is because the template including itself causes an infinite recursion.
Note that it is already possible to reference a template from a parent theme by including the parent theme in the template name:
{{!
|
@template theme_foo/core/test
|
}}
|
{{< theme_bar/core/test }}
|
{{$heading}} Overridden heading {{/heading}}
|
{{/ theme_bar/core/test }}
|
This includes the theme theme/bar/templates/core/test.mustache, which itself overrides the core/test template. What we are missing is an equivalent way of referencing the original core/test template.
Proposal
I propose this syntax to explicitly reference the original template:
{{!
|
@template theme_foo/core/test
|
}}
|
{{< /core/test }}
|
{{$heading}} Overridden heading {{/heading}}
|
{{/ /core/test}}
|
Note the forward slash before the template name. This can be thought of as indicating an "absolute path", i.e. a template path which is not "relative" to the current theme. Internally, the forward slash tells the mustache_template_finder to ignore theme overrides when looking for the template file. This is easy to implement in Moodle without having to change any upstream Mustache.php code, and it's backward-compatible since component names always start with a letter.
This has two disadvantages:
- There are several places in the Moodle core code which split the template name on the first forward slash to separate the component name from the template name. These places now yield an empty string as a component name if the new syntax is used. This does not seem to break any functionality as of now, but it is quite unintuitive and could lead to problems down the line.
- The PhpStorm Mustache Plugin marks the new syntax as invalid, even though Mustache.php parses it just fine. I don't know who is right here.
- has a non-specific relationship to
-
MDL-79319 Theme layouts should inherit from parent theme
-
- Waiting for component lead review
-