Macros defined in parent are considered as not defined
Nobody has claimed this yet.
- Dominant language
- PHP
- Stars
- 8.4k
- Forks
- 1.3k
- Avg merge
- 1d 13h
- Merged PRs (30d)
- 37
Description
When a macro is defined in a parent template, it is considered as not defined even though it is available in the template:
{% extends "parent.twig" %}
{% block f %}
{% import _self as s %}
{{ s.bar() }} // works
{% if (s.bar is defined) %} // returns false
TRUE
{% else %}
FALSE
{% endif %}
{% endblock %}
- parent.twig
{% block f %}
{% endblock %}
{% macro bar() %}
BAR
{% endmacro %}
This is due to the fact that when calling a macro, parent macros are also considered:
/**
* @internal
*/
function twig_call_macro(Template $template, string $method, array $args, int $lineno, array $context, Source $source)
{
if (!method_exists($template, $method)) {
$parent = $template;
while ($parent = $parent->getParent($context)) {
if (method_exists($parent, $method)) {
return $parent->$method(...$args);
}
}
throw new RuntimeError(sprintf('Macro "%s" is not defined in template "%s".', substr($method, \strlen('macro_')), $template->getTemplateName()), $lineno, $source);
}
return $template->$method(...$args);
}
But when a macro is tested for existence (via the is defined test), parent macros are not considered:
if ($this->getAttribute('is_defined_test')) {
$compiler
->raw('method_exists($macros[')
->repr($this->getNode('node')->getAttribute('name'))
->raw('], ')
->repr($this->getAttribute('method'))
->raw(')')
;
return;
}
It looks inconsistent to me. The purpose of the defined test is to ensure that the template can safely call a macro. But it is actually impossible to know if a macro is defined before using it - macros coming from parents will always be considered as not defined even though they are perfectly usable.
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Reproduce the parent.twig and child template example, then inspect the twig_call_macro runtime path and the compiler branch handling is_defined_test. Add a regression test covering a macro inherited from a parent and verify that the defined test agrees with the existing callable behavior.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- php
- Domain
- web-dev
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Clearly specified
- Newbie friendliness
- 35/100