diff --git a/NEW_FEATURES.txt b/NEW_FEATURES.txt index b2c18c99b..d08c830fd 100644 --- a/NEW_FEATURES.txt +++ b/NEW_FEATURES.txt @@ -2,6 +2,20 @@ This file contains a brief description of new features which have been added to Smarty 3.1 +Smarty 3.1.28 + + Filter support + ============== + Optional filter names + An optional filter name was added to $smarty->registerFilter(). It can be used to unregister a filter by name. + - $smarty->registerFilter('output', $callback, 'name'); + $smarty->unregister('output', 'name'); + + Closures + $smarty->registerFilter() does now accept closures. + - $smarty->registerFilter('pre', function($source) {return $source;}); + If no optional filter name was specified it gets the default name 'closure'. + Smarty 3.1.22 Namespace support within templates diff --git a/change_log.txt b/change_log.txt index 5606b1d83..575f3133e 100644 --- a/change_log.txt +++ b/change_log.txt @@ -1,13 +1,17 @@ - ===== 3.1.27===== (18.06.2015) -18.06.2015 - - bugfix another update on file path normalization failed on path containing something like "/.foo/" https://github.com/smarty-php/smarty/issues/56 + ===== 3.1.28-dev===== (xx.xx.2015) + 19.06.2015 + - improvement allow closures as callback at $smarty->registerFilter() https://github.com/smarty-php/smarty/issues/59 + + ===== 3.1.27===== (18.06.2015) + 18.06.2015 + - bugfix another update on file path normalization failed on path containing something like "/.foo/" https://github.com/smarty-php/smarty/issues/56 ===== 3.1.26===== (18.06.2015) -18.06.2015 - - bugfix file path normalization failed on path containing something like "/.foo/" https://github.com/smarty-php/smarty/issues/56 + 18.06.2015 + - bugfix file path normalization failed on path containing something like "/.foo/" https://github.com/smarty-php/smarty/issues/56 -17.06.2015 - - bugfix calling a plugin with nocache option but no other attributes like {foo nocache} caused call to undefined function https://github.com/smarty-php/smarty/issues/55 + 17.06.2015 + - bugfix calling a plugin with nocache option but no other attributes like {foo nocache} caused call to undefined function https://github.com/smarty-php/smarty/issues/55 ===== 3.1.25===== (15.06.2015) 15.06.2015 diff --git a/libs/Smarty.class.php b/libs/Smarty.class.php index 1f0f2634a..791546bb7 100644 --- a/libs/Smarty.class.php +++ b/libs/Smarty.class.php @@ -27,7 +27,7 @@ * @author Uwe Tews * @author Rodney Rehm * @package Smarty - * @version 3.1.27 + * @version 3.1.28-dev */ /** @@ -111,7 +111,7 @@ class Smarty extends Smarty_Internal_TemplateBase /** * smarty version */ - const SMARTY_VERSION = '3.1.27'; + const SMARTY_VERSION = '3.1.28-dev/1'; /** * define variable scopes diff --git a/libs/sysplugins/smarty_internal_extension_filter.php b/libs/sysplugins/smarty_internal_extension_filter.php new file mode 100644 index 000000000..1fd8fcaf4 --- /dev/null +++ b/libs/sysplugins/smarty_internal_extension_filter.php @@ -0,0 +1,150 @@ + true, 'post' => true, 'output' => true, 'variable' => true); + + /** + * Registers a filter function + * + * @param \Smarty_Internal_Template|\Smarty $obj + * @param string $type filter type + * @param callback $callback + * @param string|null $name optional filter name + * + * @throws \SmartyException + */ + static function registerFilter($obj, $type, $callback, $name) + { + self::_checkFilterType($type); + $name = isset($name) ? $name : self::_getFilterName($callback); + if (!is_callable($callback)) { + throw new SmartyException("{$type}filter \"{$name}\" not callable"); + } + $smarty = isset($obj->smarty) ? $obj->smarty : $obj; + $smarty->registered_filters[$type][$name] = $callback; + } + + /** + * Unregisters a filter function + * + * @param \Smarty_Internal_Template|\Smarty $obj + * @param string $type filter type + * @param callback|string $callback + * + */ + static function unregisterFilter($obj, $type, $callback) + { + self::_checkFilterType($type); + $smarty = isset($obj->smarty) ? $obj->smarty : $obj; + if (isset($smarty->registered_filters[$type])) { + $name = is_string($callback) ? $callback : self::_getFilterName($callback); + if (isset($smarty->registered_filters[$type][$name])) { + unset($smarty->registered_filters[$type][$name]); + if (empty($smarty->registered_filters[$type])) { + unset($smarty->registered_filters[$type]); + } + } + } + } + + /** + * load a filter of specified type and name + * + * @param \Smarty_Internal_Template|\Smarty $obj + * @param string $type filter type + * @param string $name filter name + * + * @return bool + * @throws SmartyException if filter could not be loaded + */ + static function loadFilter($obj, $type, $name) + { + self::_checkFilterType($type); + $smarty = isset($obj->smarty) ? $obj->smarty : $obj; + $_plugin = "smarty_{$type}filter_{$name}"; + $_filter_name = $_plugin; + if ($smarty->loadPlugin($_plugin)) { + if (class_exists($_plugin, false)) { + $_plugin = array($_plugin, 'execute'); + } + if (is_callable($_plugin)) { + $smarty->registered_filters[$type][$_filter_name] = $_plugin; + return true; + } + } + throw new SmartyException("{$type}filter \"{$name}\" not callable"); + } + + /** + * unload a filter of specified type and name + * + * @param \Smarty_Internal_Template|\Smarty $obj + * @param string $type filter type + * @param string $name filter name + * + */ + static function unloadFilter($obj, $type, $name) + { + self::_checkFilterType($type); + $smarty = isset($obj->smarty) ? $obj->smarty : $obj; + if (isset($smarty->registered_filters[$type])) { + $_filter_name = "smarty_{$type}filter_{$name}"; + if (isset($smarty->registered_filters[$type][$_filter_name])) { + unset ($smarty->registered_filters[$type][$_filter_name]); + if (empty($smarty->registered_filters[$type])) { + unset($smarty->registered_filters[$type]); + } + } + } + } + + /** + * Return internal filter name + * + * @param callback $function_name + * + * @return string internal filter name + */ + static function _getFilterName($function_name) + { + if (is_array($function_name)) { + $_class_name = (is_object($function_name[0]) ? get_class($function_name[0]) : $function_name[0]); + + return $_class_name . '_' . $function_name[1]; + } elseif (is_string($function_name)) { + return $function_name; + } else { + return 'closure'; + } + } + + /** + * Check if filter type is valid + * + * @param string $type + * + * @throws \SmartyException + */ + static function _checkFilterType($type) + { + if (!isset(self::$filterTypes[$type])) { + throw new SmartyException("Illegal filter type \"{$type}\""); + } + } +} \ No newline at end of file diff --git a/libs/sysplugins/smarty_internal_filter_handler.php b/libs/sysplugins/smarty_internal_filter_handler.php index 4f0f3981c..754f924f9 100644 --- a/libs/sysplugins/smarty_internal_filter_handler.php +++ b/libs/sysplugins/smarty_internal_filter_handler.php @@ -43,22 +43,21 @@ public static function runFilter($type, $content, Smarty_Internal_Template $temp $output = $plugin_name($output, $template); } elseif (class_exists($plugin_name, false)) { // loaded class of filter plugin + if (!is_callable(array($plugin_name, 'execute'))) { + throw new SmartyException("Auto load {$type}-filter plugin method \"{$plugin_name}::execute\" not callable"); + } $output = call_user_func(array($plugin_name, 'execute'), $output, $template); } } else { // nothing found, throw exception - throw new SmartyException("Unable to load filter {$plugin_name}"); + throw new SmartyException("Unable to auto load {$type}-filter plugin \"{$plugin_name}\""); } } } // loop over registerd filters of specified type if (!empty($template->smarty->registered_filters[$type])) { foreach ($template->smarty->registered_filters[$type] as $key => $name) { - if (is_array($template->smarty->registered_filters[$type][$key])) { $output = call_user_func($template->smarty->registered_filters[$type][$key], $output, $template); - } else { - $output = $template->smarty->registered_filters[$type][$key]($output, $template); - } } } // return filtered output diff --git a/libs/sysplugins/smarty_internal_templatebase.php b/libs/sysplugins/smarty_internal_templatebase.php index 68fd4be2e..8fab99be4 100644 --- a/libs/sysplugins/smarty_internal_templatebase.php +++ b/libs/sysplugins/smarty_internal_templatebase.php @@ -23,6 +23,7 @@ abstract class Smarty_Internal_TemplateBase extends Smarty_Internal_Data * @var string */ public $cache_id = null; + /** * Set this if you want different sets of compiled files for the same * templates. @@ -30,12 +31,14 @@ abstract class Smarty_Internal_TemplateBase extends Smarty_Internal_Data * @var string */ public $compile_id = null; + /** * caching enabled * * @var boolean */ public $caching = false; + /** * cache lifetime in seconds * @@ -46,7 +49,7 @@ abstract class Smarty_Internal_TemplateBase extends Smarty_Internal_Data /** * test if cache is valid * - * @param string|object $template the resource handle of the template file or template object + * @param string|\Smarty_Internal_Template $template the resource handle of the template file or template object * @param mixed $cache_id cache id to be used with this template * @param mixed $compile_id compile id to be used with this template * @param object $parent next higher level of Smarty variables @@ -121,7 +124,7 @@ public function getTemplateId($template_name, $cache_id = null, $compile_id = nu * @param string $type plugin type * @param string $tag name of template tag * @param callback $callback PHP callback to register - * @param boolean $cacheable if true (default) this fuction is cachable + * @param boolean $cacheable if true (default) this function is cache able * @param array $cache_attr caching attributes if any * * @return Smarty_Internal_Templatebase current Smarty_Internal_Templatebase (or Smarty or @@ -174,7 +177,8 @@ public function unregisterPlugin($type, $tag) public function registerResource($type, $callback) { $smarty = isset($this->smarty) ? $this->smarty : $this; - $smarty->registered_resources[$type] = $callback instanceof Smarty_Resource ? $callback : array($callback, false); + $smarty->registered_resources[$type] = $callback instanceof Smarty_Resource ? $callback : array($callback, + false); return $this; } @@ -265,8 +269,8 @@ public function registerObject($object_name, $object_impl, $allowed = array(), $ } // register the object $smarty = isset($this->smarty) ? $this->smarty : $this; - $smarty->registered_objects[$object_name] = - array($object_impl, (array) $allowed, (boolean) $smarty_args, (array) $block_methods); + $smarty->registered_objects[$object_name] = array($object_impl, (array) $allowed, (boolean) $smarty_args, + (array) $block_methods); return $this; } @@ -387,83 +391,47 @@ public function registerDefaultConfigHandler($callback) /** * Registers a filter function * - * @param string $type filter type - * @param callback $callback + * @param string $type filter type + * @param callback $callback + * @param null|string $name option filter name * - * @return Smarty_Internal_Templatebase current Smarty_Internal_Templatebase (or Smarty or + * @return \Smarty_Internal_TemplateBase current Smarty_Internal_Templatebase (or Smarty or * Smarty_Internal_Template) instance for chaining + * @throws \SmartyException */ - public function registerFilter($type, $callback) + public function registerFilter($type, $callback, $name = null) { - $smarty = isset($this->smarty) ? $this->smarty : $this; - $smarty->registered_filters[$type][$this->_get_filter_name($callback)] = $callback; - + Smarty_Internal_Extension_Filter::registerFilter($this, $type, $callback, $name); return $this; } /** * Unregisters a filter function * - * @param string $type filter type - * @param callback $callback + * @param string $type filter type + * @param callback|string $callback * * @return Smarty_Internal_Templatebase current Smarty_Internal_Templatebase (or Smarty or * Smarty_Internal_Template) instance for chaining */ public function unregisterFilter($type, $callback) { - $name = $this->_get_filter_name($callback); - $smarty = isset($this->smarty) ? $this->smarty : $this; - if (isset($smarty->registered_filters[$type][$name])) { - unset($smarty->registered_filters[$type][$name]); - } - + Smarty_Internal_Extension_Filter::unregisterFilter($this, $type, $callback); return $this; } - /** - * Return internal filter name - * - * @param callback $function_name - * - * @return string internal filter name - */ - public function _get_filter_name($function_name) - { - if (is_array($function_name)) { - $_class_name = (is_object($function_name[0]) ? - get_class($function_name[0]) : $function_name[0]); - - return $_class_name . '_' . $function_name[1]; - } else { - return $function_name; - } - } - /** * load a filter of specified type and name * * @param string $type filter type * @param string $name filter name * + * @return bool * @throws SmartyException if filter could not be loaded */ public function loadFilter($type, $name) { - $smarty = isset($this->smarty) ? $this->smarty : $this; - $_plugin = "smarty_{$type}filter_{$name}"; - $_filter_name = $_plugin; - if ($smarty->loadPlugin($_plugin)) { - if (class_exists($_plugin, false)) { - $_plugin = array($_plugin, 'execute'); - } - if (is_callable($_plugin)) { - $smarty->registered_filters[$type][$_filter_name] = $_plugin; - - return true; - } - } - throw new SmartyException("{$type}filter \"{$name}\" not callable"); + return Smarty_Internal_Extension_Filter::loadFilter($this, $type, $name); } /** @@ -477,12 +445,7 @@ public function loadFilter($type, $name) */ public function unloadFilter($type, $name) { - $smarty = isset($this->smarty) ? $this->smarty : $this; - $_filter_name = "smarty_{$type}filter_{$name}"; - if (isset($smarty->registered_filters[$type][$_filter_name])) { - unset ($smarty->registered_filters[$type][$_filter_name]); - } - + Smarty_Internal_Extension_Filter::unloadFilter($this, $type, $name); return $this; } @@ -491,7 +454,7 @@ public function unloadFilter($type, $name) * * @param string $match match string * - * @return string replacemant + * @return string replacement */ private function replaceCamelcase($match) {