Here is the situation:
{% for entry in entries %}
{{ action('entry_modify', entry) }}
{{ entry.title }}
{% endfor %}
action($action, $params) method is some sort of trigger for plugins that registered themselves for an action. In this case, i call for 'entry_modify' action and a plugin responds to this action with 'entry' parameter which is an array.
function plugin(&$params)
{
$params['title'] = 'changed to ...';
}
But as far as i understand Twig is not passes variables by reference, is there any way to do this ?
All i want is just modify the variable passed to action function.
Thanks...
I might have a solution for your problem. I'm developing a Wordpress Theme with Twig and I wanted to pass variables by reference and add some data to them. My goal was to make something like this
{{ load_data('all_posts',foo) }}
and I wanted to execute a function named load_all_posts
and the result of this function to be assigned to foo
(the twig variable I passed as a second argument).
Also I wanted the following to also work:
{% set foo = {'bar':'bar'} %}
{#foo is#}
array(1) {
["bar"]=>
string(3) "bar"
}
{{load_data('all_posts',foo.posts)}}
{#foo is#}
array(2) {
["bar"]=>
string(3) "bar"
["posts"]=>
array(3) {
[0]=>
string(5) "post1"
[1]=>
string(5) "post2"
[2]=>
string(5) "post3"
}
}
Since not all variables are passed by reference to the functions. We can't use functions for this purpose. Instead I created my own tag and used it like so:
{% set foo = {'bar':'bar'} %}
{% load all_pots in foo.posts %}
To do the following we have to do 2 things:
The creation of the token is easy. We just need to tell twig how to parse this token with the following class:
class Load_Data_TokenParser extends Twig_TokenParser
{
public function parse(Twig_Token $token)
{
$stream = $this->parser->getStream();
$variable_array = array(); //an array where we'll store the destination variable, as it can be just foo or foo.post, or foo.bar.foo.bar.posts
$function_name = $stream->expect(Twig_Token::NAME_TYPE)->getValue(); //here we say that we expect a name. In our case it'll be 'all_posts' (the name of the function we will execute)
$in = $stream->expect(Twig_Token::OPERATOR_TYPE)->getValue(); //here we say that the next thing should be the operator 'in'
while(Twig_Token::typeToEnglish($stream->getCurrent()->getType()) === 'name'){ //and with this while, we get all the variable names that are separated with '.'
array_push($variable_array,$stream->getCurrent()->getValue());
$stream->next();
$new = $stream->getCurrent();
if(Twig_Token::typeToEnglish($new->getType()) === 'punctuation'){
$stream->next();
} else {
break;
}
}
//in our case $variable_array here will be ['foo','posts']
$stream->expect(Twig_Token::BLOCK_END_TYPE);
return new Load_Node($variable_array, $function_name, $token->getLine(), $this->getTag());
}
public function getTag()
{
return 'load';
}
}
And at the end we return a new "Load_Node" and passing it the $variable_array, $function_name
the line and the current tag.
class Load_Node extends Twig_Node
{
public function __construct($variable_array, $function_name, $line, $tag = null)
{
$value = new Twig_Node();
parent::__construct(array('value'=>$value),array(
'variable_array'=>$variable_array,
'function_name'=>$function_name
),$line,$tag);
}
public function compile(Twig_Compiler $compiler)
{
$variable_access_string = '';
$variable_array = $this->getAttribute('variable_array');
foreach ($variable_array as $single_variable) {
$variable_access_string.= '[\''.$single_variable.'\']';
} //here we prepare the string that will be used to access the correct variables. In our case here $variable_access_string will be "['foo']['posts']"
$compiler
->addDebugInfo($this)
->write('$context'.$variable_access_string.' = load_'.$this->getAttribute('function_name').'()')
->raw(";\n"); //and the here we call load_{function_name} and assign the result to the correct variable
}
}
Currently it works only with arrays. If you try to load data inside an object it throws an exception. I'll edit it later and add support for objects. I hope this will help you and other people. Have a nice day :)