fabpot/Twig — pull request #806 by Fustrate (2012-08-14 02:07:55+00:00)
Title: Adding needs_template to Functions & Filters

I added a simple same-file dynamic macro name function to my installation of Twig, and had to add `needs_template` to `Twig_Function_Function`'s options array so that I could call the method. Here it is, in case you think it might be useful.

Here's the (partial/edited) extension code that needed it:

```php
new Twig_Function_Function(__CLASS__ . '::function_dynamic_macro', array(
'needs_template' => true,
'is_safe' => array('html'),
)),
);
}

public function getName()
{
return 'MyTwigExtension';
}

public static function function_dynamic_macro(Twig_Template $template, $name)
{
$arguments = array_slice(func_get_args(), 2);

static $reserved = null;

if (null === $reserved)
{
$reserved = array_map('strtolower', get_class_methods('Twig_Template') + array('getdebuginfo', 'gettemplatename'));
}

if (in_array('get' . strtolower($name), $reserved))
{
throw new Twig_Error_Runtime(sprintf('Cannot call reserved name %s as a dynamic macro.', $name));
}

if (!method_exists($template, 'get' . $name))
{
throw new Twig_Error_Runtime(sprintf('Dynamic macro calls only work on macros defined in the same file. Macro "%s" is undefined.', $name));
}

return call_user_method_array('get' . $name, $template, $arguments);
}
?>
```

It's called via `{{ dynamic_macro('form_element_' ~ control.type, control) }}` while looping through form controls. I guess it could be altered to try to load macros from other files at run time, or take a first parameter for the imported file name (`{% import "other_file" as other %} {{ dynamic_macro(other, 'another_' ~ name)`) but I'll figure that out later.