Welcome to the compiler.defun-plugin

compiler.defun is a plugin for the Smarty template Engine.

It started in this thread on the smarty-forum

compiler.defun provides the ability to define a block in the template and to reference this block from within itself (recursion)

An example:

TODO

Output:

TODO

The Sourcecode:

<?php

/* create code for a function call */
function smarty_compiler_fun($tag_args, &$compiler) {
    
$_attrs $compiler->_parse_attrs($tag_args);

    if (!isset(
$_attrs['name'])) $compiler->_syntax_error("fun: missing name parameter");
    
$_func_name $compiler->_dequote($_attrs['name']);
    
$_func 'smarty_fun_'.$_func_name;
    
$_params 'array(';
    
$_sep '';
    unset(
$_attrs['name']);
    foreach (
$_attrs as $_key=>$_value) {
        
$_params .= "$_sep'$_key'=>$_value";
        
$_sep ',';
    }
    
$_params .= ')';
    return 
"$_func(\$this, $_params); ";

}
$this->register_compiler_function('fun''smarty_compiler_fun');


/* create code for a function declaration */
function smarty_compiler_defun($tag_args, &$compiler) {   
    
$attrs $compiler->_parse_attrs($tag_args);
    
$func_key '"' md5('php-5') . '[[' md5(uniqid('sucks')) . '";';
    
array_push($compiler->_tag_stack, array('defun'$attrs$tag_args$func_key));
    if (!isset(
$attrs['name'])) $compiler->_syntax_error("defun: missing name parameter");

    
$func_name $compiler->_dequote($attrs['name']);
    
$func 'smarty_fun_'.$func_name;
    return 
$func_key "if (!function_exists('$func')) { function $func(&\$this, \$params) { \$_fun_tpl_vars = \$this->_tpl_vars; \$this->assign(\$params); ";

}
    

/* create code for closing a function definition and calling said function */
function smarty_compiler_defun_close($tag_args, &$compiler) {
    list(
$name$attrs$open_tag_args$func_key) = array_pop($compiler->_tag_stack);
    if (
$name!='defun'$compiler->_syntax_error("unexpected {/defun}");
    return 
" \$this->_tpl_vars = \$_fun_tpl_vars; }} " $func_key smarty_compiler_fun($open_tag_args$compiler);
}
$this->register_compiler_function('/defun''smarty_compiler_defun_close');


/* callback to replace all $this with $smarty */
function smarty_replace_fun($match) {
    
$tokens token_get_all('<?php ' $match[2]);

    
/* remove trailing <?php */
    
$open_tag '';
    while (
$tokens) {
        
$token array_shift($tokens);
        if (
is_array($token)) {
            
$open_tag .= $token[1];
        } else {
            
$open_tag .= $token;
        }
        if (
$open_tag == '<?php ') break;
    }

    
/* replace */
    
for ($i=0$count=count($tokens); $i<$count$i++) {
        if (
is_array($tokens[$i])) {
            if (
$tokens[$i][0] == T_VARIABLE && $tokens[$i][1] == '$this') {
                
$tokens[$i] = '$smarty';
            } else {
                
$tokens[$i] = $tokens[$i][1];
            }
        }
    }
    return 
implode(''$tokens);
}


/* postfilter to squeeze the code to make php5 happy */
function smarty_postfilter_defun($source, &$compiler) {
    
$search '("' md5('php-5') . '\[\[[0-9a-f]{32}";)';
    if ((double)
phpversion()>=5.0) {
        
/* filter sourcecode. look for func_keys and replace all $this
           in-between with $smarty */
        
while (1) {
            
$new_source preg_replace_callback('/' $search '(.*)\\1/Us''smarty_replace_fun'$source);
            if (
strcmp($new_source$source)==0) break;
            
$source $new_source;
        }
    } else {
        
/* remove func_keys */
        
$source preg_replace('/' $search '/'''$source);
    }
    return 
$source;
}
$this->register_postfilter('smarty_postfilter_defun');


?>

Or just download it.

To install the plugin just drop the file in one of your site's plugins-dirs.