WordPress.org

Ready to get started?Download WordPress

Forums

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);
    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.

Topic Closed

This topic has been closed to new replies.

About this Topic