2005-12-04 20:25:51 +00:00
< ? php
2007-10-05 14:30:11 +00:00
/**
2005-12-04 20:25:51 +00:00
*
* @ package phpBB3
* @ version $Id $
* @ copyright ( c ) 2005 phpBB Group , sections ( c ) 2001 ispi of Lincoln Inc
2007-10-05 14:30:11 +00:00
* @ license http :// opensource . org / licenses / gpl - license . php GNU Public License
2005-12-04 20:25:51 +00:00
*
*/
2006-03-19 14:23:21 +00:00
/**
2007-10-05 14:30:11 +00:00
* @ ignore
2006-03-19 14:23:21 +00:00
*/
if ( ! defined ( 'IN_PHPBB' ))
{
exit ;
}
2005-12-04 20:25:51 +00:00
/**
* Extension of template class - Functions needed for compiling templates only .
*
2006-06-06 20:53:46 +00:00
* psoTFX , phpBB Development Team - Completion of file caching , decompilation
* routines and implementation of conditionals / keywords and associated changes
2006-04-08 17:48:54 +00:00
*
2005-12-04 20:25:51 +00:00
* The interface was inspired by PHPLib templates , and the template file ( formats are
* quite similar )
*
* The keyword / conditional implementation is currently based on sections of code from
* the Smarty templating engine ( c ) 2001 ispi of Lincoln , Inc . which is released
* ( on its own and in whole ) under the LGPL . Section 3 of the LGPL states that any code
* derived from an LGPL application may be relicenced under the GPL , this applies
* to this source
2007-10-05 14:30:11 +00:00
*
2005-12-04 20:25:51 +00:00
* DEFINE directive inspired by a request by Cyberalien
2006-06-13 21:06:29 +00:00
*
* @ package phpBB3
2005-12-04 20:25:51 +00:00
*/
class template_compile
{
2006-04-08 17:48:54 +00:00
var $template ;
2006-04-17 13:09:50 +00:00
// Various storage arrays
var $block_names = array ();
var $block_else_level = array ();
2005-12-04 20:25:51 +00:00
/**
* constuctor
*/
2005-12-13 20:58:28 +00:00
function template_compile ( & $template )
2005-12-04 20:25:51 +00:00
{
$this -> template = & $template ;
}
2008-08-16 13:03:00 +00:00
2005-12-04 20:25:51 +00:00
/**
* Load template source from file
2006-08-22 21:26:06 +00:00
* @ access private
2005-12-04 20:25:51 +00:00
*/
2007-04-06 14:03:20 +00:00
function _tpl_load_file ( $handle , $store_in_db = false )
2005-12-04 20:25:51 +00:00
{
// Try and open template for read
2006-01-04 06:37:17 +00:00
if ( ! file_exists ( $this -> template -> files [ $handle ]))
2005-12-04 20:25:51 +00:00
{
trigger_error ( " template->_tpl_load_file(): File { $this -> template -> files [ $handle ] } does not exist or is empty " , E_USER_ERROR );
}
2006-01-04 06:37:17 +00:00
$this -> template -> compiled_code [ $handle ] = $this -> compile ( trim ( @ file_get_contents ( $this -> template -> files [ $handle ])));
2005-12-04 20:25:51 +00:00
// Actually compile the code now.
$this -> compile_write ( $handle , $this -> template -> compiled_code [ $handle ]);
2007-04-06 14:03:20 +00:00
// Store in database if required...
if ( $store_in_db )
{
global $db , $user ;
2008-08-16 13:03:00 +00:00
2007-04-06 14:03:20 +00:00
$sql_ary = array (
2008-07-28 14:24:37 +00:00
'template_id' => $this -> template -> files_template [ $handle ],
2007-04-06 14:03:20 +00:00
'template_filename' => $this -> template -> filename [ $handle ],
'template_included' => '' ,
'template_mtime' => time (),
'template_data' => trim ( @ file_get_contents ( $this -> template -> files [ $handle ])),
);
2008-08-16 13:03:00 +00:00
2007-04-06 14:03:20 +00:00
$sql = 'INSERT INTO ' . STYLES_TEMPLATE_DATA_TABLE . ' ' . $db -> sql_build_array ( 'INSERT' , $sql_ary );
$db -> sql_query ( $sql );
}
2005-12-04 20:25:51 +00:00
}
2006-07-20 17:57:56 +00:00
/**
2007-10-04 16:56:35 +00:00
* Remove any PHP tags that do not belong , these regular expressions are derived from
* the ones that exist in zend_language_scanner . l
* @ access private
2006-07-20 17:57:56 +00:00
*/
function remove_php_tags ( & $code )
{
2006-09-23 02:46:43 +00:00
// This matches the information gathered from the internal PHP lexer
$match = array (
'#<([\?%])=?.*?\1>#s' ,
'#<script\s+language\s*=\s*(["\']?)php\1\s*>.*?</script\s*>#s' ,
'#<\?php(?:\r\n?|[ \n\t]).*?\?>#s'
);
2006-07-23 22:16:05 +00:00
2006-09-23 02:46:43 +00:00
$code = preg_replace ( $match , '' , $code );
2006-07-20 17:57:56 +00:00
}
2005-12-04 20:25:51 +00:00
/**
2006-04-29 17:19:24 +00:00
* The all seeing all doing compile method . Parts are inspired by or directly from Smarty
2006-08-22 21:26:06 +00:00
* @ access private
2005-12-04 20:25:51 +00:00
*/
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 >
2006-07-20 18:39:00 +00:00
$this -> remove_php_tags ( $code );
2006-07-20 17:57:56 +00:00
2007-01-21 18:33:45 +00:00
// Pull out all block/statement level elements and separate plain text
2005-12-04 20:25:51 +00:00
preg_match_all ( '#<!-- PHP -->(.*?)<!-- ENDPHP -->#s' , $code , $matches );
$php_blocks = $matches [ 1 ];
2006-12-23 18:27:15 +00:00
$code = preg_replace ( '#<!-- PHP -->.*?<!-- ENDPHP -->#s' , '<!-- PHP -->' , $code );
2005-12-04 20:25:51 +00:00
2009-06-11 16:53:45 +00:00
preg_match_all ( '#<!-- INCLUDE (\{\$?[A-Z0-9\-_]+\}|[a-zA-Z0-9\_\-\+\./]+) -->#' , $code , $matches );
2005-12-04 20:25:51 +00:00
$include_blocks = $matches [ 1 ];
2009-06-11 16:53:45 +00:00
$code = preg_replace ( '#<!-- INCLUDE (?:\{\$?[A-Z0-9\-_]+\}|[a-zA-Z0-9\_\-\+\./]+) -->#' , '<!-- INCLUDE -->' , $code );
2005-12-04 20:25:51 +00:00
2006-12-23 18:27:15 +00:00
preg_match_all ( '#<!-- INCLUDEPHP ([a-zA-Z0-9\_\-\+\./]+) -->#' , $code , $matches );
2005-12-04 20:25:51 +00:00
$includephp_blocks = $matches [ 1 ];
2006-12-23 18:27:15 +00:00
$code = preg_replace ( '#<!-- INCLUDEPHP [a-zA-Z0-9\_\-\+\./]+ -->#' , '<!-- INCLUDEPHP -->' , $code );
2005-12-04 20:25:51 +00:00
2006-12-23 18:27:15 +00:00
preg_match_all ( '#<!-- ([^<].*?) (.*?)? ?-->#' , $code , $blocks , PREG_SET_ORDER );
$text_blocks = preg_split ( '#<!-- [^<].*? (?:.*?)? ?-->#' , $code );
2006-06-06 20:53:46 +00:00
2005-12-04 20:25:51 +00:00
for ( $i = 0 , $j = sizeof ( $text_blocks ); $i < $j ; $i ++ )
{
$this -> compile_var_tags ( $text_blocks [ $i ]);
}
$compile_blocks = array ();
2006-12-23 18:27:15 +00:00
for ( $curr_tb = 0 , $tb_size = sizeof ( $blocks ); $curr_tb < $tb_size ; $curr_tb ++ )
2005-12-04 20:25:51 +00:00
{
2006-12-23 18:27:15 +00:00
$block_val = & $blocks [ $curr_tb ];
2005-12-04 20:25:51 +00:00
2006-12-23 18:27:15 +00:00
switch ( $block_val [ 1 ])
2005-12-04 20:25:51 +00:00
{
case 'BEGIN' :
2006-04-17 13:09:50 +00:00
$this -> block_else_level [] = false ;
2006-12-23 18:27:15 +00:00
$compile_blocks [] = '<?php ' . $this -> compile_tag_block ( $block_val [ 2 ]) . ' ?>' ;
2006-04-17 13:09:50 +00:00
break ;
2005-12-04 20:25:51 +00:00
case 'BEGINELSE' :
2006-04-17 13:09:50 +00:00
$this -> block_else_level [ sizeof ( $this -> block_else_level ) - 1 ] = true ;
2005-12-04 20:25:51 +00:00
$compile_blocks [] = '<?php }} else { ?>' ;
2006-04-17 13:09:50 +00:00
break ;
2005-12-04 20:25:51 +00:00
case 'END' :
2006-04-17 13:09:50 +00:00
array_pop ( $this -> block_names );
$compile_blocks [] = '<?php ' . (( array_pop ( $this -> block_else_level )) ? '}' : '}}' ) . ' ?>' ;
break ;
2005-12-04 20:25:51 +00:00
case 'IF' :
2006-12-23 18:27:15 +00:00
$compile_blocks [] = '<?php ' . $this -> compile_tag_if ( $block_val [ 2 ], false ) . ' ?>' ;
2006-04-17 13:09:50 +00:00
break ;
2005-12-04 20:25:51 +00:00
case 'ELSE' :
$compile_blocks [] = '<?php } else { ?>' ;
2006-04-17 13:09:50 +00:00
break ;
2005-12-04 20:25:51 +00:00
case 'ELSEIF' :
2006-12-23 18:27:15 +00:00
$compile_blocks [] = '<?php ' . $this -> compile_tag_if ( $block_val [ 2 ], true ) . ' ?>' ;
2006-04-17 13:09:50 +00:00
break ;
2005-12-04 20:25:51 +00:00
case 'ENDIF' :
$compile_blocks [] = '<?php } ?>' ;
2006-04-17 13:09:50 +00:00
break ;
2005-12-04 20:25:51 +00:00
case 'DEFINE' :
2006-12-23 18:27:15 +00:00
$compile_blocks [] = '<?php ' . $this -> compile_tag_define ( $block_val [ 2 ], true ) . ' ?>' ;
2006-04-17 13:09:50 +00:00
break ;
2005-12-04 20:25:51 +00:00
case 'UNDEFINE' :
2006-12-23 18:27:15 +00:00
$compile_blocks [] = '<?php ' . $this -> compile_tag_define ( $block_val [ 2 ], false ) . ' ?>' ;
2006-04-17 13:09:50 +00:00
break ;
2005-12-04 20:25:51 +00:00
case 'INCLUDE' :
2006-04-17 13:09:50 +00:00
$temp = array_shift ( $include_blocks );
2009-06-11 16:53:45 +00:00
// Dynamic includes
// Cheap match rather than a full blown regexp, we already know
// the format of the input so just use string manipulation.
if ( $temp [ 0 ] == '{' )
{
$file = false ;
if ( $temp [ 1 ] == '$' )
{
$var = substr ( $temp , 2 , - 1 );
//$file = $this->template->_tpldata['DEFINE']['.'][$var];
$temp = " \$ this->_tpldata['DEFINE']['.'][' $var '] " ;
}
else
{
$var = substr ( $temp , 1 , - 1 );
//$file = $this->template->_rootref[$var];
$temp = " \$ this->_rootref[' $var '] " ;
}
}
else
{
$file = $temp ;
}
2005-12-04 20:25:51 +00:00
$compile_blocks [] = '<?php ' . $this -> compile_tag_include ( $temp ) . ' ?>' ;
2009-06-11 16:53:45 +00:00
// No point in checking variable includes
if ( $file )
{
$this -> template -> _tpl_include ( $file , false );
}
2006-04-17 13:09:50 +00:00
break ;
2005-12-04 20:25:51 +00:00
case 'INCLUDEPHP' :
2006-06-06 20:53:46 +00:00
$compile_blocks [] = ( $config [ 'tpl_allow_php' ]) ? '<?php ' . $this -> compile_tag_include_php ( array_shift ( $includephp_blocks )) . ' ?>' : '' ;
2006-04-29 17:19:24 +00:00
break ;
2005-12-04 20:25:51 +00:00
case 'PHP' :
2006-06-06 20:53:46 +00:00
$compile_blocks [] = ( $config [ 'tpl_allow_php' ]) ? '<?php ' . array_shift ( $php_blocks ) . ' ?>' : '' ;
2006-04-29 17:19:24 +00:00
break ;
2005-12-04 20:25:51 +00:00
default :
2006-12-23 18:27:15 +00:00
$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 ] : '' );
2006-04-29 17:19:24 +00:00
break ;
2005-12-04 20:25:51 +00:00
}
}
$template_php = '' ;
for ( $i = 0 , $size = sizeof ( $text_blocks ); $i < $size ; $i ++ )
{
$trim_check_text = trim ( $text_blocks [ $i ]);
2007-04-20 09:09:20 +00:00
$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 ] : '' );
2005-12-04 20:25:51 +00:00
}
2009-07-21 10:58:31 +00:00
// Remove unused opening/closing tags
$template_php = str_replace ( ' ?><?php ' , ' ' , $template_php );
// Now add a newline after each php closing tag which already has a newline
// PHP itself strips a newline if a closing tag is used (this is documented behaviour) and it is mostly not intended by style authors to remove newlines
$template_php = preg_replace ( '#\?\>([\r\n])#' , '?>\1\1' , $template_php );
2007-01-21 18:33:45 +00:00
// There will be a number of occasions where we switch into and out of
2005-12-04 20:25:51 +00:00
// PHP mode instantaneously. Rather than "burden" the parser with this
// we'll strip out such occurences, minimising such switching
2009-03-11 12:53:54 +00:00
if ( $no_echo )
{
2009-07-21 10:58:31 +00:00
return " \$ $echo_var .= ' " . $template_php . " ' " ;
2009-03-11 12:53:54 +00:00
}
2005-12-04 20:25:51 +00:00
2009-07-21 10:58:31 +00:00
return $template_php ;
2005-12-04 20:25:51 +00:00
}
/**
* Compile variables
2006-08-22 21:26:06 +00:00
* @ access private
2005-12-04 20:25:51 +00:00
*/
function compile_var_tags ( & $text_blocks )
{
// change template varrefs into PHP varrefs
$varrefs = array ();
// This one will handle varrefs WITH namespaces
2006-12-23 18:27:15 +00:00
preg_match_all ( '#\{((?:[a-z0-9\-_]+\.)+)(\$)?([A-Z0-9\-_]+)\}#' , $text_blocks , $varrefs , PREG_SET_ORDER );
2005-12-04 20:25:51 +00:00
2006-12-23 18:27:15 +00:00
foreach ( $varrefs as $var_val )
2005-12-04 20:25:51 +00:00
{
2006-12-23 18:27:15 +00:00
$namespace = $var_val [ 1 ];
$varname = $var_val [ 3 ];
$new = $this -> generate_block_varref ( $namespace , $varname , true , $var_val [ 2 ]);
2005-12-04 20:25:51 +00:00
2006-12-23 18:27:15 +00:00
$text_blocks = str_replace ( $var_val [ 0 ], $new , $text_blocks );
2005-12-04 20:25:51 +00:00
}
// This will handle the remaining root-level varrefs
2006-04-29 17:19:24 +00:00
// transform vars prefixed by L_ into their language variable pendant if nothing is set within the tpldata array
2006-06-06 20:53:46 +00:00
if ( strpos ( $text_blocks , '{L_' ) !== false )
{
2009-03-31 12:21:36 +00:00
$text_blocks = preg_replace ( '#\{L_([A-Z0-9\-_]+)\}#' , " <?php echo ((isset( \$ this->_rootref['L_ \\ 1'])) ? \$ this->_rootref['L_ \\ 1'] : ((isset( \$ user->lang[' \\ 1'])) ? \$ user->lang[' \\ 1'] : ' { \\ 1 }')); ?> " , $text_blocks );
2006-06-06 20:53:46 +00:00
}
2006-04-29 17:19:24 +00:00
// Handle addslashed language variables prefixed with LA_
// If a template variable already exist, it will be used in favor of it...
2006-06-06 20:53:46 +00:00
if ( strpos ( $text_blocks , '{LA_' ) !== false )
{
2009-03-31 12:21:36 +00:00
$text_blocks = preg_replace ( '#\{LA_([A-Z0-9\-_]+)\}#' , " <?php echo ((isset( \$ this->_rootref['LA_ \\ 1'])) ? \$ this->_rootref['LA_ \\ 1'] : ((isset( \$ this->_rootref['L_ \\ 1'])) ? addslashes( \$ this->_rootref['L_ \\ 1']) : ((isset( \$ user->lang[' \\ 1'])) ? addslashes( \$ user->lang[' \\ 1']) : ' { \\ 1 }'))); ?> " , $text_blocks );
2006-06-06 20:53:46 +00:00
}
2006-02-21 10:32:19 +00:00
2006-04-29 17:19:24 +00:00
// Handle remaining varrefs
2009-03-31 12:21:36 +00:00
$text_blocks = preg_replace ( '#\{([A-Z0-9\-_]+)\}#' , " <?php echo (isset( \$ this->_rootref[' \\ 1'])) ? \$ this->_rootref[' \\ 1'] : ''; ?> " , $text_blocks );
$text_blocks = preg_replace ( '#\{\$([A-Z0-9\-_]+)\}#' , " <?php echo (isset( \$ this->_tpldata['DEFINE']['.'][' \\ 1'])) ? \$ this->_tpldata['DEFINE']['.'][' \\ 1'] : ''; ?> " , $text_blocks );
2005-12-04 20:25:51 +00:00
return ;
}
/**
* Compile blocks
2006-08-22 21:26:06 +00:00
* @ access private
2005-12-04 20:25:51 +00:00
*/
function compile_tag_block ( $tag_args )
{
2006-04-06 17:15:45 +00:00
$no_nesting = false ;
2006-04-29 17:19:24 +00:00
// Is the designer wanting to call another loop in a loop?
2006-04-06 17:15:45 +00:00
if ( strpos ( $tag_args , '!' ) === 0 )
{
2011-04-21 12:00:04 -04:00
// Count the number of ! occurrences (not allowed in vars)
2006-04-08 10:56:08 +00:00
$no_nesting = substr_count ( $tag_args , '!' );
2006-04-06 17:15:45 +00:00
$tag_args = substr ( $tag_args , $no_nesting );
}
2005-12-04 20:25:51 +00:00
// 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
2006-02-21 10:32:19 +00:00
if ( preg_match ( '#^([^()]*)\(([\-\d]+)(?:,([\-\d]+))?\)$#' , $tag_args , $match ))
2005-12-04 20:25:51 +00:00
{
$tag_args = $match [ 1 ];
2006-06-06 20:53:46 +00:00
2005-12-04 20:25:51 +00:00
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 ] . ')' ;
}
2006-02-21 10:32:19 +00:00
if ( strlen ( $match [ 3 ]) < 1 || $match [ 3 ] == - 1 )
2005-12-04 20:25:51 +00:00
{
$loop_end = '$_' . $tag_args . '_count' ;
}
2006-02-21 10:32:19 +00:00
else if ( $match [ 3 ] >= 0 )
2005-12-04 20:25:51 +00:00
{
2006-02-21 10:32:19 +00:00
$loop_end = '(' . ( $match [ 3 ] + 1 ) . ' > $_' . $tag_args . '_count ? $_' . $tag_args . '_count : ' . ( $match [ 3 ] + 1 ) . ')' ;
2005-12-04 20:25:51 +00:00
}
2006-02-21 10:32:19 +00:00
else //if ($match[3] < -1)
2005-12-04 20:25:51 +00:00
{
2006-02-21 10:32:19 +00:00
$loop_end = '$_' . $tag_args . '_count' . ( $match [ 3 ] + 1 );
2005-12-04 20:25:51 +00:00
}
}
else
{
$loop_start = 0 ;
$loop_end = '$_' . $tag_args . '_count' ;
}
$tag_template_php = '' ;
2006-04-17 13:09:50 +00:00
array_push ( $this -> block_names , $tag_args );
2005-12-04 20:25:51 +00:00
2006-12-26 13:56:50 +00:00
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 )
2005-12-04 20:25:51 +00:00
{
// Block is not nested.
2007-01-26 16:09:51 +00:00
$tag_template_php = '$_' . $tag_args . " _count = (isset( \$ this->_tpldata[' $tag_args '])) ? sizeof( \$ this->_tpldata[' $tag_args ']) : 0; " ;
2006-12-23 18:27:15 +00:00
$varref = " \$ this->_tpldata[' $tag_args '] " ;
2005-12-04 20:25:51 +00:00
}
else
{
// This block is nested.
// Generate a namespace string for this block.
2006-12-26 13:56:50 +00:00
$namespace = implode ( '.' , $block );
2005-12-04 20:25:51 +00:00
// 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 ( $namespace , false );
// 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) {' ;
2006-12-23 18:27:15 +00:00
/**
* 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];' ;
2005-12-04 20:25:51 +00:00
return $tag_template_php ;
}
/**
* Compile IF tags - much of this is from Smarty with
* some adaptions for our block level methods
2006-08-22 21:26:06 +00:00
* @ access private
2005-12-04 20:25:51 +00:00
*/
function compile_tag_if ( $tag_args , $elseif )
{
// Tokenize args for 'if' tag.
preg_match_all ( ' / ( ? :
2006-06-06 20:53:46 +00:00
" [^ " \\\\ ] * ( ? : \\\\ . [ ^ " \\ \\ ]*)* " |
\ ' [ ^ \ ' \\\\ ] * ( ? : \\\\ . [ ^ \ ' \\\\ ] * ) * \ ' |
[(),] |
[ ^ \s (),] + ) / x ' , $tag_args , $match );
2005-12-04 20:25:51 +00:00
$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 '@' :
2006-04-29 17:19:24 +00:00
break ;
2005-12-04 20:25:51 +00:00
2006-04-29 17:19:24 +00:00
case '==' :
2005-12-04 20:25:51 +00:00
case 'eq' :
$token = '==' ;
2006-04-29 17:19:24 +00:00
break ;
2005-12-04 20:25:51 +00:00
2006-04-29 17:19:24 +00:00
case '!=' :
case '<>' :
2005-12-04 20:25:51 +00:00
case 'ne' :
case 'neq' :
$token = '!=' ;
2006-04-29 17:19:24 +00:00
break ;
2005-12-04 20:25:51 +00:00
2006-04-29 17:19:24 +00:00
case '<' :
2005-12-04 20:25:51 +00:00
case 'lt' :
$token = '<' ;
2006-04-29 17:19:24 +00:00
break ;
2005-12-04 20:25:51 +00:00
2006-04-29 17:19:24 +00:00
case '<=' :
2005-12-04 20:25:51 +00:00
case 'le' :
case 'lte' :
$token = '<=' ;
2006-04-29 17:19:24 +00:00
break ;
2005-12-04 20:25:51 +00:00
2006-04-29 17:19:24 +00:00
case '>' :
2005-12-04 20:25:51 +00:00
case 'gt' :
$token = '>' ;
2006-04-29 17:19:24 +00:00
break ;
2005-12-04 20:25:51 +00:00
2006-04-29 17:19:24 +00:00
case '>=' :
2005-12-04 20:25:51 +00:00
case 'ge' :
case 'gte' :
$token = '>=' ;
2006-04-29 17:19:24 +00:00
break ;
2005-12-04 20:25:51 +00:00
2006-04-29 17:19:24 +00:00
case '&&' :
2005-12-04 20:25:51 +00:00
case 'and' :
$token = '&&' ;
2006-04-29 17:19:24 +00:00
break ;
2005-12-04 20:25:51 +00:00
2006-04-29 17:19:24 +00:00
case '||' :
2005-12-04 20:25:51 +00:00
case 'or' :
$token = '||' ;
2006-04-29 17:19:24 +00:00
break ;
2005-12-04 20:25:51 +00:00
2006-04-29 17:19:24 +00:00
case '!' :
2005-12-04 20:25:51 +00:00
case 'not' :
$token = '!' ;
2006-04-29 17:19:24 +00:00
break ;
2005-12-04 20:25:51 +00:00
2006-04-29 17:19:24 +00:00
case '%' :
2005-12-04 20:25:51 +00:00
case 'mod' :
$token = '%' ;
2006-04-29 17:19:24 +00:00
break ;
2005-12-04 20:25:51 +00:00
case '(' :
array_push ( $is_arg_stack , $i );
2006-04-29 17:19:24 +00:00
break ;
2005-12-04 20:25:51 +00:00
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_arg , array_slice ( $tokens , $i + 1 ));
array_splice ( $tokens , $is_arg_start , sizeof ( $tokens ), $new_tokens );
$i = $is_arg_start ;
2006-04-29 17:19:24 +00:00
// no break
2005-12-04 20:25:51 +00:00
default :
2006-04-05 01:17:05 +00:00
if ( preg_match ( '#^((?:[a-z0-9\-_]+\.)+)?(\$)?(?=[A-Z])([A-Z0-9\-_]+)#s' , $token , $varrefs ))
2005-12-04 20:25:51 +00:00
{
2006-12-23 18:27:15 +00:00
$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 ] . '\']' );
2005-12-04 20:25:51 +00:00
}
2006-12-23 18:27:15 +00:00
else if ( preg_match ( '#^\.((?:[a-z0-9\-_]+\.?)+)$#s' , $token , $varrefs ))
2005-12-04 20:25:51 +00:00
{
2006-09-28 15:04:59 +00:00
// Allow checking if loops are set with .loopname
// It is also possible to check the loop count by doing <!-- IF .loopname > 1 --> for example
2006-12-23 18:27:15 +00:00
$blocks = explode ( '.' , $varrefs [ 1 ]);
2007-01-20 17:58:27 +00:00
2006-12-23 18:27:15 +00:00
// 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 ( $namespace , true );
2007-01-20 17:58:27 +00:00
2006-12-23 18:27:15 +00:00
// Add the block reference for the last child.
$varref .= " [' " . $block . " '] " ;
}
else
{
$varref = '$this->_tpldata' ;
2007-01-20 17:58:27 +00:00
2006-12-23 18:27:15 +00:00
// Add the block reference for the last child.
$varref .= " [' " . $blocks [ 0 ] . " '] " ;
}
$token = " sizeof( $varref ) " ;
2005-12-04 20:25:51 +00:00
}
2008-08-01 14:35:11 +00:00
else if ( ! empty ( $token ))
{
$token = '(' . $token . ')' ;
}
2005-12-04 20:25:51 +00:00
2006-04-29 17:19:24 +00:00
break ;
2005-12-04 20:25:51 +00:00
}
}
2008-08-01 14:35:11 +00:00
// 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' );
}
2007-08-17 21:10:21 +00:00
return (( $elseif ) ? '} else if (' : 'if (' ) . ( implode ( ' ' , $tokens ) . ') { ' );
2005-12-04 20:25:51 +00:00
}
/**
* Compile DEFINE tags
2006-08-22 21:26:06 +00:00
* @ access private
2005-12-04 20:25:51 +00:00
*/
function compile_tag_define ( $tag_args , $op )
{
2006-04-05 01:17:05 +00:00
preg_match ( '#^((?:[a-z0-9\-_]+\.)+)?\$(?=[A-Z])([A-Z0-9_\-]*)(?: = (\'?)([^\']*)(\'?))?$#' , $tag_args , $match );
2005-12-04 20:25:51 +00:00
2006-07-01 19:11:52 +00:00
if ( empty ( $match [ 2 ]) || ( ! isset ( $match [ 4 ]) && $op ))
2005-12-04 20:25:51 +00:00
{
2006-12-23 18:27:15 +00:00
return '' ;
2005-12-04 20:25:51 +00:00
}
if ( ! $op )
{
2006-02-21 10:32:19 +00:00
return 'unset(' . (( $match [ 1 ]) ? $this -> generate_block_data_ref ( substr ( $match [ 1 ], 0 , - 1 ), true , true ) . '[\'' . $match [ 2 ] . '\']' : '$this->_tpldata[\'DEFINE\'][\'.\'][\'' . $match [ 2 ] . '\']' ) . ');' ;
2005-12-04 20:25:51 +00:00
}
// Are we a string?
2006-02-21 10:32:19 +00:00
if ( $match [ 3 ] && $match [ 5 ])
2005-12-04 20:25:51 +00:00
{
2006-04-25 03:28:10 +00:00
$match [ 4 ] = str_replace ( array ( '\\\'' , '\\\\' , '\'' ), array ( '\'' , '\\' , '\\\'' ), $match [ 4 ]);
2005-12-04 20:25:51 +00:00
// Compile reference, we allow template variables in defines...
2006-02-21 10:32:19 +00:00
$match [ 4 ] = $this -> compile ( $match [ 4 ]);
2005-12-04 20:25:51 +00:00
// Now replace the php code
2006-02-21 10:32:19 +00:00
$match [ 4 ] = " ' " . str_replace ( array ( '<?php echo ' , '; ?>' ), array ( " ' . " , " . ' " ), $match [ 4 ]) . " ' " ;
2005-12-04 20:25:51 +00:00
}
else
{
2006-02-21 10:32:19 +00:00
preg_match ( '#true|false|\.#i' , $match [ 4 ], $type );
2005-12-04 20:25:51 +00:00
2006-03-10 00:24:46 +00:00
switch ( strtolower ( $type [ 0 ]))
2005-12-04 20:25:51 +00:00
{
case 'true' :
case 'false' :
2006-02-21 10:32:19 +00:00
$match [ 4 ] = strtoupper ( $match [ 4 ]);
2006-04-29 17:19:24 +00:00
break ;
2006-06-06 20:53:46 +00:00
2006-05-16 17:46:47 +00:00
case '.' :
2006-02-21 10:32:19 +00:00
$match [ 4 ] = doubleval ( $match [ 4 ]);
2006-04-29 17:19:24 +00:00
break ;
2006-06-06 20:53:46 +00:00
2005-12-04 20:25:51 +00:00
default :
2006-02-21 10:32:19 +00:00
$match [ 4 ] = intval ( $match [ 4 ]);
2006-04-29 17:19:24 +00:00
break ;
2005-12-04 20:25:51 +00:00
}
}
2006-02-21 10:32:19 +00:00
return (( $match [ 1 ]) ? $this -> generate_block_data_ref ( substr ( $match [ 1 ], 0 , - 1 ), true , true ) . '[\'' . $match [ 2 ] . '\']' : '$this->_tpldata[\'DEFINE\'][\'.\'][\'' . $match [ 2 ] . '\']' ) . ' = ' . $match [ 4 ] . ';' ;
2005-12-04 20:25:51 +00:00
}
/**
* Compile INCLUDE tag
2006-08-22 21:26:06 +00:00
* @ access private
2005-12-04 20:25:51 +00:00
*/
function compile_tag_include ( $tag_args )
{
2009-06-11 16:53:45 +00:00
// Process dynamic includes
if ( $tag_args [ 0 ] == '$' )
{
return " if (isset( $tag_args )) { \$ this->_tpl_include( $tag_args ); } " ;
}
2005-12-04 20:25:51 +00:00
return " \$ this->_tpl_include(' $tag_args '); " ;
}
/**
* Compile INCLUDE_PHP tag
2006-08-22 21:26:06 +00:00
* @ access private
2005-12-04 20:25:51 +00:00
*/
function compile_tag_include_php ( $tag_args )
{
2009-06-19 22:07:27 +00:00
return " \$ this->_php_include(' $tag_args '); " ;
2005-12-04 20:25:51 +00:00
}
/**
* parse expression
* This is from Smarty
2006-08-22 21:26:06 +00:00
* @ access private
2005-12-04 20:25:51 +00:00
*/
function _parse_is_expr ( $is_arg , $tokens )
{
2006-11-10 13:49:52 +00:00
$expr_end = 0 ;
2005-12-04 20:25:51 +00:00
$negate_expr = false ;
if (( $first_token = array_shift ( $tokens )) == 'not' )
{
$negate_expr = true ;
$expr_type = array_shift ( $tokens );
}
else
{
$expr_type = $first_token ;
}
switch ( $expr_type )
{
case 'even' :
if ( @ $tokens [ $expr_end ] == 'by' )
{
$expr_end ++ ;
2006-11-10 13:49:52 +00:00
$expr_arg = $tokens [ $expr_end ++ ];
2007-08-17 21:29:20 +00:00
$expr = " !(( $is_arg / $expr_arg ) % $expr_arg ) " ;
2005-12-04 20:25:51 +00:00
}
else
{
2007-08-17 21:29:20 +00:00
$expr = " !( $is_arg & 1) " ;
2005-12-04 20:25:51 +00:00
}
2006-04-29 17:19:24 +00:00
break ;
2005-12-04 20:25:51 +00:00
case 'odd' :
if ( @ $tokens [ $expr_end ] == 'by' )
{
$expr_end ++ ;
2006-11-10 13:49:52 +00:00
$expr_arg = $tokens [ $expr_end ++ ];
2007-08-17 21:29:20 +00:00
$expr = " (( $is_arg / $expr_arg ) % $expr_arg ) " ;
2005-12-04 20:25:51 +00:00
}
else
{
2007-08-17 21:29:20 +00:00
$expr = " ( $is_arg & 1) " ;
2005-12-04 20:25:51 +00:00
}
2006-04-29 17:19:24 +00:00
break ;
2005-12-04 20:25:51 +00:00
case 'div' :
if ( @ $tokens [ $expr_end ] == 'by' )
{
$expr_end ++ ;
2006-11-10 13:49:52 +00:00
$expr_arg = $tokens [ $expr_end ++ ];
2007-08-17 21:29:20 +00:00
$expr = " !( $is_arg % $expr_arg ) " ;
2005-12-04 20:25:51 +00:00
}
2006-04-29 17:19:24 +00:00
break ;
2005-12-04 20:25:51 +00:00
}
if ( $negate_expr )
{
2006-11-10 13:49:52 +00:00
$expr = " !( $expr ) " ;
2005-12-04 20:25:51 +00:00
}
2006-11-10 13:49:52 +00:00
array_splice ( $tokens , 0 , $expr_end , $expr );
2005-12-04 20:25:51 +00:00
return $tokens ;
}
/**
* Generates a reference to the given variable inside the given ( possibly nested )
* block namespace . This is a string of the form :
* ' . $this->_tpldata[' parent '][$_parent_i][' $child1 '][$_child1_i][' $child2 '][$_child2_i]...[' varname '] . '
* It ' s ready to be inserted into an " echo " line in one of the templates .
* NOTE : expects a trailing " . " on the namespace .
2006-08-22 21:26:06 +00:00
* @ access private
2005-12-04 20:25:51 +00:00
*/
function generate_block_varref ( $namespace , $varname , $echo = true , $defop = false )
{
// Strip the trailing period.
$namespace = substr ( $namespace , 0 , - 1 );
// Get a reference to the data block for this namespace.
$varref = $this -> generate_block_data_ref ( $namespace , true , $defop );
// Prepend the necessary code to stick this in an echo line.
// Append the variable reference.
$varref .= " [' $varname '] " ;
$varref = ( $echo ) ? " <?php echo $varref ; ?> " : (( isset ( $varref )) ? $varref : '' );
return $varref ;
}
/**
* Generates a reference to the array of data values for the given
* ( possibly nested ) block namespace . This is a string of the form :
* $this -> _tpldata [ 'parent' ][ $_parent_i ][ '$child1' ][ $_child1_i ][ '$child2' ][ $_child2_i ] ... [ '$childN' ]
*
* If $include_last_iterator is true , then [ $_childN_i ] will be appended to the form shown above .
* NOTE : does not expect a trailing " . " on the blockname .
2006-08-22 21:26:06 +00:00
* @ access private
2005-12-04 20:25:51 +00:00
*/
function generate_block_data_ref ( $blockname , $include_last_iterator , $defop = false )
{
// Get an array of the blocks involved.
$blocks = explode ( '.' , $blockname );
$blockcount = sizeof ( $blocks ) - 1 ;
2006-12-23 18:27:15 +00:00
// DEFINE is not an element of any referenced variable, we must use _tpldata to access it
if ( $defop )
{
$varref = '$this->_tpldata[\'DEFINE\']' ;
// Build up the string with everything but the last child.
for ( $i = 0 ; $i < $blockcount ; $i ++ )
{
$varref .= " [' " . $blocks [ $i ] . " '][ \$ _ " . $blocks [ $i ] . '_i]' ;
}
// Add the block reference for the last child.
$varref .= " [' " . $blocks [ $blockcount ] . " '] " ;
// Add the iterator for the last child if requried.
if ( $include_last_iterator )
{
$varref .= '[$_' . $blocks [ $blockcount ] . '_i]' ;
}
return $varref ;
}
else if ( $include_last_iterator )
2005-12-04 20:25:51 +00:00
{
2006-12-23 18:27:15 +00:00
return '$_' . $blocks [ $blockcount ] . '_val' ;
2005-12-04 20:25:51 +00:00
}
2006-12-23 18:27:15 +00:00
else
2005-12-04 20:25:51 +00:00
{
2006-12-23 18:27:15 +00:00
return '$_' . $blocks [ $blockcount - 1 ] . '_val[\'' . $blocks [ $blockcount ] . '\']' ;
2005-12-04 20:25:51 +00:00
}
}
/**
* Write compiled file to cache directory
2006-08-22 21:26:06 +00:00
* @ access private
2005-12-04 20:25:51 +00:00
*/
2006-12-23 18:27:15 +00:00
function compile_write ( $handle , $data )
2005-12-04 20:25:51 +00:00
{
2006-12-23 18:27:15 +00:00
global $phpEx ;
2005-12-04 20:25:51 +00:00
2006-05-07 21:44:23 +00:00
$filename = $this -> template -> cachepath . str_replace ( '/' , '.' , $this -> template -> filename [ $handle ]) . '.' . $phpEx ;
2005-12-04 20:25:51 +00:00
2009-03-14 02:08:04 +00:00
$data = " <?php if (!defined('IN_PHPBB')) exit; " . (( strpos ( $data , '<?php' ) === 0 ) ? substr ( $data , 5 ) : ' ?>' . $data );
2005-12-04 20:25:51 +00:00
if ( $fp = @ fopen ( $filename , 'wb' ))
{
@ flock ( $fp , LOCK_EX );
@ fwrite ( $fp , $data );
@ flock ( $fp , LOCK_UN );
@ fclose ( $fp );
2008-12-19 20:36:18 +00:00
phpbb_chmod ( $filename , CHMOD_READ | CHMOD_WRITE );
2005-12-04 20:25:51 +00:00
}
return ;
}
}
?>