Ciao a tutti ragazzi, da qualche giorno sto iniziando a studiare le classi per la programmazione ad oggetti.

Ho trovato un bel codice, che sto usando per rifarmi il sito personale. E' il template engine usato da phppBB2. Lo sto riadattando piano piano alle mie esigenze, ma mi sono bloccato nell'aggiunta di alcune funzioni, che sono gli IF e gli INCLUDE nei .tpl.

Questa è la classe che uso: http://biccheddu.altervista.org/template.class.txt (la linko perchè è più lungo di 13mila caratteri.

Ora, questa è la parte che mi interessa del template engine di phpbb3, la funzione compile() è così scritta (prendo solo la parte che mi interessa):
Codice PHP:
<?php
    
function compile($code$no_echo false$echo_var '')
    {
        global 
$config;

        if (
$echo_var)
        {
            global $
$echo_var;
        }

        
// Remove any "loose" php ... we want to give admins the ability
        // to switch on/off PHP for a given template. Allowing unchecked
        // php is a no-no. There is a potential issue here in that non-php
        // content may be removed ... however designers should use entities
        // if they wish to display < and >
        
$this->remove_php_tags($code);

        
// Pull out all block/statement level elements and separate plain text
        
preg_match_all('#(.*?)#s'$code$matches);
        
$php_blocks $matches[1];
        
$code preg_replace('#.*?#s'''$code);

        
preg_match_all('##'$code$matches);
        
$include_blocks $matches[1];
        
$code preg_replace('##'''$code);

        
preg_match_all('##'$code$matches);
        
$includephp_blocks $matches[1];
        
$code preg_replace('##'''$code);

        
preg_match_all('##'$code$blocksPREG_SET_ORDER);

        
$text_blocks preg_split('##'$code);

        for (
$i 0$j sizeof($text_blocks); $i $j$i++)
        {
            
$this->compile_var_tags($text_blocks[$i]);
        }
        
$compile_blocks = array();

        for (
$curr_tb 0$tb_size sizeof($blocks); $curr_tb $tb_size$curr_tb++)
        {
            
$block_val = &$blocks[$curr_tb];

            switch (
$block_val[1])
            {
                case 
'BEGIN':
                    
$this->block_else_level[] = false;
                    
$compile_blocks[] = '<?php ' $this->compile_tag_block($block_val[2]) . ' ?>';
                break;

                case 
'END':
                    
array_pop($this->block_names);
                    
$compile_blocks[] = '<?php ' . ((array_pop($this->block_else_level)) ? '}' '}}') . ' ?>';
                break;

                case 
'IF':
                    
$compile_blocks[] = '<?php ' $this->compile_tag_if($block_val[2], false) . ' ?>';
                break;

                case 
'ELSE':
                    
$compile_blocks[] = '<?php } else { ?>';
                break;

                case 
'ELSEIF':
                    
$compile_blocks[] = '<?php ' $this->compile_tag_if($block_val[2], true) . ' ?>';
                break;

                case 
'ENDIF':
                    
$compile_blocks[] = '<?php } ?>';
                break;

                case 
'INCLUDE':
                    
$temp array_shift($include_blocks);
                    
$compile_blocks[] = '<?php ' $this->compile_tag_include($temp) . ' ?>';
                    
$this->template->_tpl_include($tempfalse);
                break;

                case 
'INCLUDEPHP':
                    
$compile_blocks[] = ($config['tpl_allow_php']) ? '<?php ' $this->compile_tag_include_php(array_shift($includephp_blocks)) . ' ?>' '';
                break;

                default:
                    
$this->compile_var_tags($block_val[0]);
                    
$trim_check trim($block_val[0]);
                    
$compile_blocks[] = (!$no_echo) ? ((!empty($trim_check)) ? $block_val[0] : '') : ((!empty($trim_check)) ? $block_val[0] : '');
                break;
            }
        }

        
$template_php '';
        for (
$i 0$size sizeof($text_blocks); $i $size$i++)
        {
            
$trim_check_text trim($text_blocks[$i]);
            
$template_php .= (!$no_echo) ? (($trim_check_text != '') ? $text_blocks[$i] : '') . ((isset($compile_blocks[$i])) ? $compile_blocks[$i] : '') : (($trim_check_text != '') ? $text_blocks[$i] : '') . ((isset($compile_blocks[$i])) ? $compile_blocks[$i] : '');
        }

        
// There will be a number of occasions where we switch into and out of
        // PHP mode instantaneously. Rather than "burden" the parser with this
        // we'll strip out such occurences, minimising such switching
        
$template_php str_replace(' ?><?php '' '$template_php);

        return (!
$no_echo) ? $template_php "\$$echo_var .= '" $template_php "'";
    }
?>
Questa è la funzione per compilare gli if:
Codice PHP:
<?php
function compile_tag_if($tag_args$elseif)
    {
        
// Tokenize args for 'if' tag.
        
preg_match_all('/(?:
            "[^"\\\\]*(?:\\\\.[^"\\\\]*)*"         |
            \'[^\'\\\\]*(?:\\\\.[^\'\\\\]*)*\'     |
            [(),]                                  |
            [^\s(),]+)/x'
$tag_args$match);

        
$tokens $match[0];
        
$is_arg_stack = array();

        for (
$i 0$size sizeof($tokens); $i $size$i++)
        {
            
$token = &$tokens[$i];

            switch (
$token)
            {
                case 
'!==':
                case 
'===':
                case 
'<<':
                case 
'>>':
                case 
'|':
                case 
'^':
                case 
'&':
                case 
'~':
                case 
')':
                case 
',':
                case 
'+':
                case 
'-':
                case 
'*':
                case 
'/':
                case 
'@':
                break;

                case 
'==':
                case 
'eq':
                    
$token '==';
                break;

                case 
'!=':
                case 
'<>':
                case 
'ne':
                case 
'neq':
                    
$token '!=';
                break;

                case 
'<':
                case 
'lt':
                    
$token '<';
                break;

                case 
'<=':
                case 
'le':
                case 
'lte':
                    
$token '<=';
                break;

                case 
'>':
                case 
'gt':
                    
$token '>';
                break;

                case 
'>=':
                case 
'ge':
                case 
'gte':
                    
$token '>=';
                break;

                case 
'&&':
                case 
'and':
                    
$token '&&';
                break;

                case 
'||':
                case 
'or':
                    
$token '||';
                break;

                case 
'!':
                case 
'not':
                    
$token '!';
                break;

                case 
'%':
                case 
'mod':
                    
$token '%';
                break;

                case 
'(':
                    
array_push($is_arg_stack$i);
                break;

                case 
'is':
                    
$is_arg_start = ($tokens[$i-1] == ')') ? array_pop($is_arg_stack) : $i-1;
                    
$is_arg    implode('    'array_slice($tokens,    $is_arg_start$i -    $is_arg_start));

                    
$new_tokens    $this->_parse_is_expr($is_argarray_slice($tokens$i+1));

                    
array_splice($tokens$is_arg_startsizeof($tokens), $new_tokens);

                    
$i $is_arg_start;

                
// no break

                
default:
                    if (
preg_match('#^((?:[a-z0-9\-_]+\.)+)?(\$)?(?=[A-Z])([A-Z0-9\-_]+)#s'$token$varrefs))
                    {
                        
$token = (!empty($varrefs[1])) ? $this->generate_block_data_ref(substr($varrefs[1], 0, -1), true$varrefs[2]) . '[\'' $varrefs[3] . '\']' : (($varrefs[2]) ? '$this->_tpldata[\'DEFINE\'][\'.\'][\'' $varrefs[3] . '\']' '$this->_rootref[\'' $varrefs[3] . '\']');
                    }
                    else if (
preg_match('#^\.((?:[a-z0-9\-_]+\.?)+)$#s'$token$varrefs))
                    {
                        
// Allow checking if loops are set with .loopname
                        // It is also possible to check the loop count by doing  for example
                        
$blocks explode('.'$varrefs[1]);

                        
// If the block is nested, we have a reference that we can grab.
                        // If the block is not nested, we just go and grab the block from _tpldata
                        
if (sizeof($blocks) > 1)
                        {
                            
$block array_pop($blocks);
                            
$namespace implode('.'$blocks);
                            
$varref $this->generate_block_data_ref($namespacetrue);

                            
// Add the block reference for the last child.
                            
$varref .= "['" $block "']";
                        }
                        else
                        {
                            
$varref '$this->_tpldata';

                            
// Add the block reference for the last child.
                            
$varref .= "['" $blocks[0] . "']";
                        }
                        
$token "sizeof($varref)";
                    }
                    else if (!empty(
$token))
                    {
                        
$token '(' $token ')';
                    }

                break;
            }
        }

        
// If there are no valid tokens left or only control/compare characters left, we do skip this statement
        
if (!sizeof($tokens) || str_replace(array(' ''=''!''<''>''&''|''%''('')'), ''implode(''$tokens)) == '')
        {
            
$tokens = array('false');
        }
        return ((
$elseif) ? '} else if (' 'if (') . (implode(' '$tokens) . ') { ');
    }
?>
Questa per gli include:
Codice PHP:
<?php
function compile_tag_include($tag_args)
{
    return 
"\$this->_tpl_include('$tag_args');";
}
?>
Questa per gli altri:
Codice PHP:
<?php
function compile_tag_block($tag_args)
    {
        
$no_nesting false;

        
// Is the designer wanting to call another loop in a loop?
        
if (strpos($tag_args'!') === 0)
        {
            
// Count the number if ! occurrences (not allowed in vars)
            
$no_nesting substr_count($tag_args'!');
            
$tag_args substr($tag_args$no_nesting);
        }

        
// Allow for control of looping (indexes start from zero):
        // foo(2)    : Will start the loop on the 3rd entry
        // foo(-2)   : Will start the loop two entries from the end
        // foo(3,4)  : Will start the loop on the fourth entry and end it on the fifth
        // foo(3,-4) : Will start the loop on the fourth entry and end it four from last
        
if (preg_match('#^([^()]*)\(([\-\d]+)(?:,([\-\d]+))?\)$#'$tag_args$match))
        {
            
$tag_args $match[1];

            if (
$match[2] < 0)
            {
                
$loop_start '($_' $tag_args '_count ' $match[2] . ' < 0 ? 0 : $_' $tag_args '_count ' $match[2] . ')';
            }
            else
            {
                
$loop_start '($_' $tag_args '_count < ' $match[2] . ' ? $_' $tag_args '_count : ' $match[2] . ')';
            }

            if (
strlen($match[3]) < || $match[3] == -1)
            {
                
$loop_end '$_' $tag_args '_count';
            }
            else if (
$match[3] >= 0)
            {
                
$loop_end '(' . ($match[3] + 1) . ' > $_' $tag_args '_count ? $_' $tag_args '_count : ' . ($match[3] + 1) . ')';
            }
            else 
//if ($match[3] < -1)
            
{
                
$loop_end '$_' $tag_args '_count' . ($match[3] + 1);
            }
        }
        else
        {
            
$loop_start 0;
            
$loop_end '$_' $tag_args '_count';
        }

        
$tag_template_php '';
        
array_push($this->block_names$tag_args);

        if (
$no_nesting !== false)
        {
            
// We need to implode $no_nesting times from the end...
            
$block array_slice($this->block_names, -$no_nesting);
        }
        else
        {
            
$block $this->block_names;
        }

        if (
sizeof($block) < 2)
        {
            
// Block is not nested.
            
$tag_template_php '$_' $tag_args "_count = (isset(\$this->_tpldata['$tag_args'])) ? sizeof(\$this->_tpldata['$tag_args']) : 0;";
            
$varref "\$this->_tpldata['$tag_args']";
        }
        else
        {
            
// This block is nested.
            // Generate a namespace string for this block.
            
$namespace implode('.'$block);

            
// Get a reference to the data array for this block that depends on the
            // current indices of all parent blocks.
            
$varref $this->generate_block_data_ref($namespacefalse);

            
// Create the for loop code to iterate over this block.
            
$tag_template_php '$_' $tag_args '_count = (isset(' $varref ')) ? sizeof(' $varref ') : 0;';
        }

        
$tag_template_php .= 'if ($_' $tag_args '_count) {';

        
/**
        * The following uses foreach for iteration instead of a for loop, foreach is faster but requires PHP to make a copy of the contents of the array which uses more memory
        * <code>
        *    if (!$offset)
        *    {
        *        $tag_template_php .= 'foreach (' . $varref . ' as $_' . $tag_args . '_i => $_' . $tag_args . '_val){';
        *    }
        * </code>
        */

        
$tag_template_php .= 'for ($_' $tag_args '_i = ' $loop_start '; $_' $tag_args '_i < ' $loop_end '; ++$_' $tag_args '_i){';
        
$tag_template_php .= '$_'$tag_args '_val = &' $varref '[$_'$tag_args'_i];';

        return 
$tag_template_php;
    }
?>
Come posso integrarle con la mia classe?