| file name: | includes/rain.tpl.compile.class.php |
| Size: | 15.81 KB |
| date: | 7 months ago |
This file is located in raintpl_1.7.6.zip
<?php
/**
* Project: RainTPL, compile HTML template to PHP
*
* File: raintpl.compile.class.php
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* @link http://www.raintpl.com
* @author Federico Ulfo <info@rainelemental.net>
* @version 1.7.6
* @copyright 2006 - 2008 Federico Ulfo | www.RainElemental.net
* @package RainTPL
*/
/**
*
* FALSE more security (DEFAULT)
* TRUE enable <?php ?> tag in templates.
*
*/
define( "RAINTPL_PHP_ENABLED", false );
/**
*
*Cache enabled:
* TRUE improve speed
* FALSE recompile template each executions
*
*/
define( "RAINTPL_VERSION", '1.7.5' );
/**
* Template engine, compile HTML template to PHP, cache templates, wysiwyg: change image src to the
right path.
*
* @access private
*
*/
class RainTPLCompile{
/**
* Template directory, default: themes
* @access private
* @var string
*/
var $tpl_dir = "themes";
/**
* Regular expression pattern
* @access private
* @var string
*/
var $split_pattern =
'/(\{(?:loop(?:\s+)name="(?:.*?)")\})|(\{(?:\/loop)\})|(\{(?:if(?:\s+)condition="(?:.
*?)")\})|(\{(?:elseif(?:\s+)condition="(?:.*?)")\})|(\{(?:else)\})|(\{(?:\/if)\})|(\{
noparse\})|(\{\/noparse\})|(\{ignore\})|(\{\/ignore\})|(\{include="(?:.*?)"\})/';
/**
* Regular expression pattern
* @access private
* @var string
*/
var $show_copyright = true;
/**
* Compile and write the compiled template file
*
* @access private
* @param string $template_name
* @param string $template_directory
*/
function compileFile( $template_name, $template_directory ){
//set the temlate directory
$this->tpl_dir = $template_directory;
//if directory $this->tpl_dir/compiled doesn't exist, create its and compile all file into
$this->tpl_dir
if( !file_exists( $this->tpl_dir . '/compiled/' ) )
mkdir( $this->tpl_dir . '/compiled/', 0755 );
if( $compiled_file = glob( $this->tpl_dir . '/compiled/' . $template_name . '*.php' ) )
foreach( $compiled_file as $file_name )
unlink( $file_name );
//leggo il template
$template_code = file_get_contents( $this->tpl_dir . '/' . $template_name . '.' . TPL_EXT );
//sostituzione per xml
$template_code = preg_replace( "/\<\?xml(.*?)\?\>/", "##XML\\1XML##",
$template_code );
//se i tag php sono disabilitati nei template
if( !RAINTPL_PHP_ENABLED ){
$template_code = str_replace( "<?", "<?", $template_code );
$template_code = str_replace( "?>", "?>", $template_code );
}
//sostituzione per xml
$template_code = preg_replace( "/\#\#XML(.*?)XML\#\#/", "<?php echo
'<?xml\\1?>'; ?>", $template_code );
//compilo il template
$template_compiled = $this->compileTemplate( $template_code, $template_name );
$template_compiled = "<?php if(!defined('IN_RAINTPL')){exit('Hacker attempt');}?>"
. $template_compiled;
//scrivo il file compilato
fwrite( $fp = fopen( $this->tpl_dir . "/compiled/" . $template_name . "_" .
filemtime( $this->tpl_dir . '/' . $template_name . '.' . TPL_EXT ) . ".php", 'w' ),
$template_compiled );
//chiudo l'handler del file
fclose( $fp );
}
/**
* Compile the template
*
* @param string $template_code
* @param string template_name
* @param string
*/
function compileTemplate( $template_code, $template_name ){
//divido il codice del template nei vari tag
$template_code = preg_split ( $this->split_pattern, $template_code, -1,
PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY );
//compilo il codice parsato in codice php
$compiled_code = $this->compileCode( $template_code );
if( !$this->show_copyright )
return $compiled_code;
else
//creo il codice da inserire nel template
return "<!-- $template_name | generated by RainTPL v " . RAINTPL_VERSION . " |
www.RainTPL.com -->" . "\n" .
$compiled_code . "\n" .
"<!--/ $template_name -->" . "\n";
}
/**
* Compilo il codice parsato in php
*
* @access private
* @param string $parsed_code Array che contiene codice html e tag
* @return string codice compilato
*/
function compileCode( $parsed_code ){
//inizializzo tutte le variabili
$parent_loop[ $level = 0 ] = $loop_name = $compiled_code = $compiled_return_code = null;
$open_if = $comment_is_open = $ignore_is_open = 0;
//leggo tutti gli elementi dell'array del codice parsato
while( $html = array_shift( $parsed_code ) ){
//calcolo lo spazio per l'indentazione del codice compilato
for( $space_counter = 0, $space = ""; $space_counter < $level + $open_if;
$space_counter++, $space .= " " );
//Chiudo il tag ignore
if( !$comment_is_open && preg_match( '/\{\/ignore\}/', $html ) )
$ignore_is_open = false;
//tutto il codice tra il tag ignore ed /ignore viene cancellato
elseif( $ignore_is_open ){
//non faccio niente
}
//Chiudo il tag noparse
elseif( preg_match( '/\{\/noparse\}/', $html ) )
$comment_is_open = false;
//tutto il codice tra il tag noparse e /noparse non viene compilato
elseif( $comment_is_open ){
$compiled_code .= $html;
}
//Apro il tag ignore
elseif( preg_match( '/\{ignore\}/', $html ) )
$ignore_is_open = true;
//apro il tag noparse
elseif( preg_match( '/\{noparse\}/', $html ) )
$comment_is_open = true;
//inserisco il comando include
elseif( preg_match( '/(?:\{include="(.*?)"\})/', $html, $code ) ){
//sostituisco le variabili che si trovano nel tag include
$include_var = $this->var_replace( $code[ 1 ], $left_delimiter = null, $right_delimiter =
null, $php_left_delimiter = '".' , $php_right_delimiter = '."', $this_loop_name =
$parent_loop[ $level ] );
//inserisco il codice php per includere il file dinamicamente con il RainTPL
$compiled_code .= "<?php\n" .
"\$RainTPL_include_obj = new RainTPL();\n" .
"\$RainTPL_include_obj->assign( \$var );\n" .
"\$RainTPL_directory_template_temp = \$RainTPL_include_obj->tpl_dir;" .
"\n" .
( ( $this_loop_name ) ? "\$RainTPL_include_obj->assign( \"key\",
\$key" . $this_loop_name . " );\n" . "\$RainTPL_include_obj->assign(
\"value\", \$value" . $this_loop_name . " );\n" : null ) .
"\$this->tpl_dir = \$GLOBALS[ 'RainTPL_tpl_dir' ] =
\$RainTPL_include_obj->tpl_dir . \"/\" . dirname( \"$include_var\" );" .
"\n" .
"\$RainTPL_include_obj->draw( \"$include_var\" );" . "\n"
.
"\$this->tpl_dir = \$GLOBALS[ 'RainTPL_tpl_dir' ] =
\$RainTPL_directory_template_temp;" . "\n" .
"?>";
}
//apro il tag loop
elseif( preg_match( '/(?:\{loop(?:\s+)name="(.*?)"\})/', $html, $code ) ){
//incremento la variabile level, che tiene conto del numero di tag loop aperti
$level++;
//inserisco nell'array parent_loop il nome di questo loop
$parent_loop[ $level ] = $level;
$var = $this->var_replace( '$' . $code[ 1 ], "","",
"","", $level-1 );
//creo le variabili php per il loop
$counter = "\$counter$level";
$key = "\$key$level";
$value = "\$value$level";
//scrivo il codice per aprire il tag loop
$compiled_code .= "<?php" . "\n" .
$space . " if( isset( $var ) ){" . "\n" .
$space . " $counter = 0;" . "\n" .
$space . " foreach( $var as $key => $value ){ " . "\n" .
"?>";
}
//chiudo il tag loop
elseif( preg_match( '/\{\/loop\}/', $html ) ){
//carico la variabile counter
$counter = "\$counter$level";
//diminuisco il livello del loop
$level--;
//scrivo il codice per chiudere il tag loop
$compiled_code .= "<?php" . "\n" .
$space . " $counter++;" . "\n" .
$space . " }" . "\n" .
$space . "}" . "\n" .
"?>";
}
//apro il tag if
elseif( preg_match( '/(?:\{if(?:\s+)condition="(.*?)"\})/', $html, $code ) ){
//incremento open_if (serve per l'indentazione del codice)
$open_if++;
//recupero l'attributo condition del tag if
$condition = $code[ 1 ];
//sostituisco le variabili all'interno della condizione del tag if, le variabili nell'if vengono
inserite senza i delimitatori
$parsed_condition = $this->var_replace( $condition, $tag_left_delimiter = '',
$tag_right_delimiter = '', $php_left_delimiter = null, $php_right_delimiter = null, $parent_loop[
$level ] );
//scrivo il codice php del tag if
$compiled_code .= "<?php" . "\n" .
$space . " if( $parsed_condition ){" . "\n" .
"?>";
}
//apro il tag elseif
elseif( preg_match( '/(?:\{elseif(?:\s+)condition="(.*?)"\})/', $html, $code ) ){
//incremento open_if
$open_if++;
//recupero l'attributo condition del tag elseif
$condition = $code[ 1 ];
//sostituisco le variabili all'interno della condizione del tag elseif, le variabili nell'elseif
vengono inserite senza i delimitatori
$parsed_condition = $this->var_replace( $condition, $tag_left_delimiter = '',
$tag_right_delimiter = '', $php_left_delimiter = null, $php_right_delimiter = null, $parent_loop[
$level ] );
//scrivo il codice php del tag elseif
$compiled_code .= "<?php" . "\n" .
$space . "}" . "\n" .
$space . " elseif( $parsed_condition ){" . "\n" .
"?>";
}
//apro il tag else
elseif( preg_match( '/\{else\}/', $html ) ){
//scrivo il codice php del tag else
$compiled_code .= "<?php" . "\n" .
$space . "}" . "\n" .
$space . "else{" . "\n" .
"?>";
}
//chido il tag if
elseif( preg_match( '/\{\/if}/', $html ) ){
//decremento $open_if
$open_if--;
//scrivo il codice php del tag /if
$compiled_code .= "<?php" . "\n" .
$space . "}" . "\n" .
"?>";
}
//scrivo il codice html, cio?tutto il codice che non e incluso tra tag
else{
//sostituisco i percorsi di immagini e collegamenti a fogli di stile
$html = $this->path_replace( $html );
//eseguo la sostituzione delle variabili nel codice
$compiled_code .= $this->var_replace( $html, $left_delimiter = '\{', $right_delimiter = '\}',
$php_left_delimiter = '<?php echo ', $php_right_delimiter = ';?>', $parent_loop[ $level ] );
}
}
//restituisco il codice compilato
return $compiled_code;
}
/**
* Sostituisce il percorso dei fogli di stile, dell'src delle immagini e del tag background
*
* @param string $html
* @return string html sostituito
*/
function path_replace( $html ){
// sostituisco i percorsi di img, link e background:
// url => template_dir/url
// url# => url#
// http://url => http://url
$exp = array( '/src=(?:")http\:\/\/([^"]+?)(?:")/i',
'/src=(?:")([^"]+?)#(?:")/i', '/src="(.*?)"/',
'/src=(?:\@)([^"]+?)(?:\@)/i', '/background=(?:")http\:\/\/([^"]+?)(?:")/i',
'/background=(?:")([^"]+?)#(?:")/i', '/background="(.*?)"/',
'/background=(?:\@)([^"]+?)(?:\@)/i',
'/<link(.*?)href=(?:")http\:\/\/([^"]+?)(?:")/i',
'/<link(.*?)href=(?:")([^"]+?)#(?:")/i', '/<link(.*?)href="(.*?)"/',
'/<link(.*?)href=(?:\@)([^"]+?)(?:\@)/i' );
$sub = array( 'src=@http://$1@', 'src=@$1@', 'src="' . $this->tpl_dir . '\\1"',
'src="$1"', 'background=@http://$1@', 'background=@$1@', 'background="' .
$this->tpl_dir . '\\1"', 'background="$1"', '<link$1href=@http://$2@',
'<link$1href=@$2@' , '<link$1href="' . $this->tpl_dir . '$2"',
'<link$1href="$2"' );
return preg_replace( $exp, $sub, $html );
}
/**
* Sostituisco le variabili con il codice php
*
* @param string $html Html da sostituire
* @param string $tag_left_delimiter Delimitatore sinistro del tag delle variabili. Di default ? {
* @param string $tag_right_delimiter Delimitatore destro del tag delle variabili. Di default ? }
* @param string $php_left_delimiter Delimitatore sinistro della sostituzione php. Es. <?php=
* @param string $php_right_delimiter Delimitatore destro della sostituzione php. Es. ;?>
* @param string $loop_name Nome del loop
* @return string Codice sostituito
*/
function var_replace( $html, $tag_left_delimiter, $tag_right_delimiter, $php_left_delimiter = null,
$php_right_delimiter = null, $loop_name = null ){
$html = preg_replace( '/\{\#(\w+)\#\}/', $php_left_delimiter . '\\1' . $php_right_delimiter, $html
);
preg_match_all( '/' . $tag_left_delimiter .
'\$(\w+(?:\.\${0,1}(?:\w+))*(?:\[\${0,1}(?:\w+)\])*(?:\-\>\${0,1}(?:\w+))*)(.*?)' .
$tag_right_delimiter . '/', $html, $matches );
for( $i = 0; $i < count( $matches[ 0 ] ); $i++ ){
//inserisco nella variabile $tag il tag completo, es: {$news.title|substr:0,100}
$tag = $matches[ 0 ][ $i ];
//inserisco in $var la variabile es: news.title
$var = $matches[ 1 ][ $i ];
//inserisco in $extra_var le eventuali funzioni associate alla variabile, es: substr:0,100
$extra_var = $matches[ 2 ][ $i ];
$function_var = ( $extra_var and $extra_var[0] == '|') ? substr( $extra_var, 1 ) : null;
//divido la variabile se ? un array (es. $news.title o $news[title]) o un oggetto (es.
$news->title)
$temp = preg_split( "/\.|\[|\-\>/", $var );
//prendo il nome della variabile
$var_name = $temp[ 0 ];
//prendo gli elementi dell'array successivi al nome
$variable_path = substr( $var, strlen( $var_name ) );
//trasformo le parentesi [ e ] in [" e in "]
$variable_path = str_replace( '[', '["', $variable_path );
$variable_path = str_replace( ']', '"]', $variable_path );
//trasformo .$variabile in ["$variabile"]
$variable_path = preg_replace('/\.\$(\w+)/', '["$\\1"]', $variable_path );
//trasformo [variabile] in ["variabile]
$variable_path = preg_replace('/\.(\w+)/', '["\\1"]', $variable_path );
//se alla funzione ? associata una funzione
if( $function_var ){
//divido la funzione dai parametri (es: substr:0,100)
$function_split = explode( ':', $function_var, 2 );
//prendo la funzione
$function = $function_split[ 0 ];
//prendo i parametri
$params = ( isset( $function_split[ 1 ] ) ) ? $function_split[ 1 ] : null;
}
else
$function = $params = null;
//if it is inside a loop
if( $loop_name ){
//verify the variable name
if( $var_name == 'key' )
$php_var = '$key' . $loop_name;
elseif( $var_name == 'value' )
$php_var = '$value' . $loop_name . $variable_path;
elseif( $var_name == 'counter' )
$php_var = '$counter' . $loop_name;
else
$php_var = '$var["' . $var_name . '"]' . $variable_path;
}
elseif( $var_name == 'GLOBALS' )
$php_var = '$GLOBALS' . $variable_path;
elseif( $var_name == '_SESSION' )
$php_var = '$_SESSION' . $variable_path;
elseif( $var_name == '_COOKIE' )
$php_var = '$_COOKIE' . $variable_path;
elseif( $var_name == '_SERVER' )
$php_var = '$_SERVER' . $variable_path;
elseif( $var_name == '_GET' )
$php_var = '$_GET' . $variable_path;
elseif( $var_name == '_POST' )
$php_var = '$_POST' . $variable_path;
else
$php_var = '$var["' . $var_name . '"]' . $variable_path;
if( isset( $function ) )
$php_var = $php_left_delimiter . ( $params ? "( $function( $php_var, $params ) )" :
"$function( $php_var )" ) . $php_right_delimiter;
else
$php_var = $php_left_delimiter . $php_var . $extra_var . $php_right_delimiter;
$html = str_replace( $tag, $php_var, $html );
}
return $html;
}
}
?>