Support » Developing with WordPress » quasi recursion in apply_filters…help

  • 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);
    add_filter('foo','foo3',12,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;
    	}
    }

    4. Add the testing shortcode:

    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.

  • The topic ‘quasi recursion in apply_filters…help’ is closed to new replies.