$macros */ public function __construct( private Template $template, private array $macros, ) { } public function has(string $name, array $context): bool { $namespace = $this; while (true) { if (isset($namespace->macros[$name])) { return true; } if (null === $namespace = $namespace->getParent($context)) { return false; } } } /** * @param array $arguments */ public function call(string $name, array $arguments, array $context, int $line, Source $source): string|Markup { if (null !== $macro = $this->getDeclared($name)) { return $macro->call($arguments, $source, $line); } if (null === $macro = $this->getParent($context)?->resolve($name, $context)) { throw new RuntimeError(\sprintf('Macro "%s" is not defined in template "%s".', $name, $this->template->getTemplateName()), $line, $source); } return $macro->call($arguments, $source, $line); } private function getDeclared(string $name): ?TwigMacro { if (!isset($this->macros[$name])) { return null; } $this->template->ensureSecurityChecked(); return $this->macros[$name]; } private function resolve(string $name, array $context): ?TwigMacro { $namespace = $this; while (true) { if (null !== $macro = $namespace->getDeclared($name)) { return $macro; } if (null === $namespace = $namespace->getParent($context)) { return null; } } } private function getParent(array $context): ?self { if (!$parent = $this->template->getParent($context)) { return null; } return $parent->unwrap()->getMacroNamespace(); } }