Smarty Forum Index Smarty
WARNING: All discussion is moving to https://reddit.com/r/smarty, please go there! This forum will be closing soon.

Problems registering multiple pre-/post-/outputfilters

 
This forum is locked: you cannot post, reply to, or edit topics.   This topic is locked: you cannot edit posts or make replies.    Smarty Forum Index -> Bugs
View previous topic :: View next topic  
Author Message
c960657
Smarty Regular


Joined: 07 May 2003
Posts: 75
Location: Copenhagen, Denmark

PostPosted: Thu Jun 15, 2006 12:13 pm    Post subject: Problems registering multiple pre-/post-/outputfilters Reply with quote

I have several classes implementing the methods with the same name, e.g. Foo::filter() and Bar::filter().

If I register both using $smarty->register_outputfilter(array('Foo', 'filter')) and $smarty->register_outputfilter(array('Bar', 'filter')), only Bar::filter() is applied. This is because the method name is used as the key in the $smarty->plugins['outputfilter'][$key] array.

I'm not sure, what the key is used for. One way to fix this would be to just use a unique key generated using uniqid() or similar when the callable is an array. However, I suggest generating a string of the form 'Bar::filter', because this would allow these filters to be unregistered as well (currently filters implemented as class methods cannot be unregistered).

I haven't found a built-in PHP function that converts a callable to a nice string, so in order to do this you need to treat each of the three cases separately ($functionName, array($object, $methodName) and array($className, $methodName)).
Back to top
View user's profile Send private message Visit poster's website
boots
Administrator


Joined: 16 Apr 2003
Posts: 5611
Location: Toronto, Canada

PostPosted: Thu Jun 15, 2006 5:06 pm    Post subject: Reply with quote

Hi c960657.

Hmmm. That's a pickle.

The key is used mainly for unregistering. This presents some legacy issues. Consider registering an outputfilter (or any filter type) using an array callback:
[php:1:06fb119a00]$smarty->register_outputfilter( array( 'Foo', 'bar' ) );[/php:1:06fb119a00]
The key becomes the function name (as you already said) and so to unregister it:
[php:1:06fb119a00]$smarty->unregister_outputfilter( 'bar' );[/php:1:06fb119a00]
the unregister_*() methods only take a function name, which is unfortunate because anyone relying on this (meaning anyone currently using it) will be SOL if we change the implementation to address this bug.

A long time-ago I had privately proposed a generalized register()/unregister() pair looking to deprecate the zillions of register_*/unregister_* functions that smarty currently sports. Outside of a new mecahnism, I can't see how to address this without major BC issues.

You have good ideas about these sorts of issues so I'd be happy to hear any you might have Smile
Back to top
View user's profile Send private message
c960657
Smarty Regular


Joined: 07 May 2003
Posts: 75
Location: Copenhagen, Denmark

PostPosted: Fri Jun 16, 2006 4:19 pm    Post subject: Reply with quote

Hi boots,

boots wrote:

the unregister_*() methods only take a function name, which is unfortunate because anyone relying on this (meaning anyone currently using it) will be SOL if we change the implementation to address this bug.


One way to make register_*() and unregister_*() symmetrical while still allowing unregister_outputfilter('filter') to unregister ('Foo', 'filter') is something like this (not tested):
[php:1:0049d2b049]function register_prefilter($function)
{
$_name = $this->_get_callable_name($function);
$this->_plugins['prefilter'][$_name] = array($function, null, null, false);
}

/**
* Unregisters a prefilter function
*
* @param string $function name of PHP function
*/
function unregister_prefilter($function)
{
$_name = $this->_get_callable_name($function);
if (isset($this->_plugins['prefilter'][$_name])) {
unset($this->_plugins['prefilter'][$function]);
} elseif (is_string($function)) {
// BC compatibily
foreach ($this->_plugins['prefilter'] as $n => $_function) {
if (is_array($_function) && $_function[1] == $_name) {
// should we trigger a warning
unset($this->_plugins['prefilter'][$n]);
break;
}
}
}
}

// Returns a canonical string representation of a callable
function _get_callable_name($function)
if (is_array($function) && sizeof($function) == 2) {
if (is_string($function[0])) {
$_name = implode('::', $function);
} else {
$_name = get_class($function[0]) . '::' . $function[1];
}
} elseif (is_string($function)) {
$_name = $function;
} else {
$this->trigger_error('Invalid argument');
}
// PHP class and function names are case-insensitive
return strtolower($_name);
}[/php:1:0049d2b049]

It's not pretty, but I don't think it is very ugly either Smile
Back to top
View user's profile Send private message Visit poster's website
El Hombre Gris
Smarty Rookie


Joined: 21 Apr 2006
Posts: 23

PostPosted: Thu Jun 22, 2006 1:55 pm    Post subject: Reply with quote

If you just need to register a filter from static member functions without risking to overwrite some other filter, and you won't need to unregister them, you can use create_function():

Code:
$smarty->register_outputfilter(create_function('$tpl_output, &$smarty', 'return Foo::filter($tpl_output, $smarty);'));


This will create an "anonymous" function (not really anonymous, it has a unique name automatically generated) which will call the static member function.
Back to top
View user's profile Send private message
boots
Administrator


Joined: 16 Apr 2003
Posts: 5611
Location: Toronto, Canada

PostPosted: Thu Jun 22, 2006 3:14 pm    Post subject: Reply with quote

El Hombre Gris wrote:
If you just need to register a filter from static member functions without risking to overwrite some other filter, and you won't need to unregister them, you can use create_function():

Code:
$smarty->register_outputfilter(create_function('$tpl_output, &$smarty', 'return Foo::filter($tpl_output, $smarty);'));


This will create an "anonymous" function (not really anonymous, it has a unique name automatically generated) which will call the static member function.


Clever, as always, Mr Grey Smile
Back to top
View user's profile Send private message
Display posts from previous:   
This forum is locked: you cannot post, reply to, or edit topics.   This topic is locked: you cannot edit posts or make replies.    Smarty Forum Index -> Bugs All times are GMT
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group
Protected by Anti-Spam ACP