quasi recursion in apply_filters...help (1 post)

1. topquarkproductions
Member
Posted 3 years ago #

Hi there,

I'd say I'm a WordPres Ninja Brown Belt - not the highest skilled ninja, but definitely not a newbie. I've come across something that I could use some help on. I'll keep trying to figure it out myself, but if anyone can offer suggestions, I'd appreciate it.

Here's the (I think) minimal code to reproduce:

1. Add two filters to the same hook. Make it so that the first one you add has a later priority than the second.

``````add_filter('foo','foo2',13,2);

2. Define foo2 and foo3 (note, dump is just a debug trace for myself which I've included below for reference):

``````function foo2(\$var,\$args){
\$smarty = \$args[0];
dump("2: (start)",\$smarty,\$var);
if (\$var == 'why'){
\$smarty->internal = 'foo2';
bar(\$smarty);
}
dump("2: (end)",\$smarty,\$var);
return \$var;
}
function foo3(\$var,\$args){
\$smarty = \$args[0];
dump("3: (start)",\$smarty,\$var);
if (\$var == 'why'){
\$smarty->internal = 'foo3';
bar(\$smarty);
}
dump("3: (end)",\$smarty,\$var);
return \$var;
}
function bar(&\$smarty){
\$smarty->foo('var2');
}
function dump(\$foo,&\$smarty,\$_var){
echo "<pre>";
echo "In foo\$foo: \n";
print_r('internal: '.\$smarty->internal."\n");
print_r('var: '.\$_var."\n");
echo "</pre>";
}``````

3. Define the class wtf():

``````class wtf{
var \$internal;
function wtf(){
}

function foo(\$var){
\$var = apply_filters('foo',\$var,array(&\$this));
return \$this->internal;
}
}``````

``````add_shortcode('tester','trying');
function trying(\$content){
\$smarty = new wtf();
\$smarty->internal = 'internal';
\$blah = \$smarty->foo('why');
return \$blah;
}``````

Note that `foo2` and `foo3` both set the `\$smarty->internal` variable. That's the thing that I'm ultimately interested in and it's what's returned by the function `\$smarty->foo()`. Because `foo2` is prioritized to happen after `foo3`, I __expect/desire__ the value of `\$blah` to be 'foo2'.

The behaviour is complicated by the fact that `foo2` and `foo3` both call the `bar()` function, which in turn calls `\$smarty->foo()`, which in turn applies the same `foo` filters. (Yes, there's a reason I'm doing all of this, I'll explain it below).

When all of the above code is executed, the value of `\$blah` does not end up being the desired 'foo2', but instead it is 'foo3'.

I would expect the filters to be applied in this order:

foo3('why') - (see \$smarty->foo('why') in the trying() function)
- foo3('var2') - (see \$smarty->foo('var2') in the bar() function)
- foo2('var2')

foo2('why') - the next filter I added
- foo3('var2')
- foo2('var2')

However, what ends up happening is the foo2('why') filter never gets applied. I can't figure out why. I think it gets removed from the wp_filters array somehow within the apply_filters() function because of the quasi-recursion.

WHY I'M TRYING TO DO THIS
-------------------------
The variable is named \$smarty for a reason. I'm using the Smarty templating engine for a series of plugins I'm creating. I've extended the Smarty class with a Smarty_Instance class to allow a call to filters. The Smarty_Instance::fetch function looks like:

``````function fetch(\$resource_name, \$cache_id = null, \$compile_id = null, \$display = false){
\$resource_name = apply_filters('Smarty_Instance_resource_name',\$resource_name,array(&\$this));
return parent::fetch(\$resource_name,\$cache_id,\$compile_id,\$display);
}``````

This allows me to add display customizations to plugin templates without touching them. The use case I've used most often is to have a plugin change the template_directory of the \$smarty object to be a directory within its structure, as opposed to the directory within the original plugin (that's what \$smarty->internal in the above code represents).

The quasi-recursion comes when a template gets content by fetching another template, thus calling the filters again. But, it __SHOULD__ be acceptable because it's calling it with different \$resource_name values (corresponds to `\$var` in the above code).

I'm sure this belongs in the Advanced forum, but I'm not a moderator, so I can't post there. If appropriate, I'll trust someone will move it there.

Do any of you black belts out there have any ideas on what's going on and/or a way to avoid the problem?

I hope I've explained this accordingly. I'm happy to clarify anything if it'll help.

Thanks for any help that comes back to me.

This topic has been closed to new replies.