templates_dir = (substr($templates_dir, -1) != '/' ? $templates_dir.'/' : $templates_dir);
if(is_dir($compiled_templates_dir))$this -> compiled_templates_dir = (substr($compiled_templates_dir, -1) != '/' ? $compiled_templates_dir.'/' : $compiled_templates_dir);
$this -> templates_ext = $templates_ext;
}
/**
* __set
*
* Установка переменных, доступных в шаблоне
*
* @param string $var_name имя переменной
* @param string $var_value значение переменной
**/
public function __set($var_name, $var_value)
{
$this -> vars[$var_name] = $var_value;
}
/**
* __get
*
* Получения значения переменной
*
* @param string $var_name имя переменной
* @return mixed значение переменной
**/
public function __get($var_name)
{
if(isset($this -> vars[$var_name]))return $this -> vars[$var_name];
return false;
}
/**
* __set
*
* Установка переменных, доступных в шаблоне
*
* @param string $var_name имя переменной
* @param string $var_value значение переменной
**/
public function assign($var_name, $var_value = false)
{
if(is_array($var_name) && $var_value == false)
{
foreach($var_name as $name => $value)
{
$this -> assign($name, $value);
}
}
else
{
$this -> vars[$var_name] = $var_value;
}
return true;
}
/**
* debug
*
* Просмотр значений всех переменных
*
* @param bool $exit требуется ли завершение работы скрипта
**/
public function debug($exit = true)
{
echo 'templates_dir = '.$this -> templates_dir.'
';
echo 'templates_ext = '.$this -> templates_ext.'
';
print_r($this -> vars);
if($exit)exit;
return true;
}
/**
* display
*
* Обработка шаблона, и вывод на экран
*
* @param string $template_name имя файла-шаблона
* @return bool возникли ли ошибки
**/
public function display($template_name)
{
if(!file_exists($this -> templates_dir.$template_name.'.'.$this -> templates_ext))return false;
if($this -> debug_compiler || (!file_exists($this -> compiled_templates_dir.$template_name.'.'.$this -> templates_ext.'.php') || filemtime($this -> compiled_templates_dir.$template_name.'.'.$this -> templates_ext.'.php') < filemtime($this -> templates_dir.$template_name.'.'.$this -> templates_ext)))
{
if(!isset($this -> cfgs[$template_name]))$this -> cfgs[$template_name] = array();
// генерируем php файл из шаблона
$content = $this -> prepare_tpl($template_name);
// вставляем комментарий
$content = ' compiled_templates_dir.$template_name.'.'.$this -> templates_ext.' */ ?>'.EOL.$content;
if(!file_put_contents($this -> compiled_templates_dir.$template_name.'.'.$this -> templates_ext.'.php', $content))return false;
}
#if(!isset($content))$content = file_get_contents($this -> compiled_templates_dir.$template_name.'.'.$this -> templates_ext.'.php');
require $this -> compiled_templates_dir.$template_name.'.'.$this -> templates_ext.'.php';
#if($this -> debug_compiler)unlink($this -> compiled_templates_dir.$template_name.'.'.$this -> templates_ext.'.php');
return true;
}
/**
* prepare_tpl
*
* Обработка шаблона
*
* @param string $filename имя файла-шаблона
* @return string PHP-код шаблона
**/
private function prepare_tpl($filename)
{
$code = file_get_contents($this -> templates_dir.$filename.'.'.$this -> templates_ext);
#d($code);
// блоки
$code = $this -> process_blocks($code, $filename);
// циклы
$code = $this -> process_cycles($code, $filename);
// условия
$code = $this -> process_ifs($code);
// переменные
$code = $this -> process_vars($code);
#d($code);
return $code;
}
/**
* process_blocks
*
* обработка блоков в шаблоне типа
* {block index}
* ...
* {/block index}
* в switch ... case ... break ... endswtich;
*
*
* @param string $code код шаблона
* @return string обработанный код
**/
private function process_blocks($code)
{
$new_code = $code;
// циклы
preg_match_all('~\{block ((\!)?([^!]*))\}(.*)\{\/block \\1\}~uUs', $code, $blocks, PREG_SET_ORDER ^ PREG_OFFSET_CAPTURE);
#d($blocks,0);
$use_blocks = false;
// код до/после/между блоками
$after_code = $before_code = $rest = null;
$count_blocks = count($blocks);
if($count_blocks > 0)
{
$use_blocks = true;
$lenght_shift = 0;
for($i = 0;$i < $count_blocks;$i ++)
{
if($i == 0 && $blocks[$i][0][1] > 0)
{
// записываем код "до"
$after_code = trim(substr($code, 0, $blocks[$i][0][1]));
#d(substr($code, $blocks[$i][0][1]));
$code = substr($code, $blocks[$i][0][1]);
$lenght_shift = strlen($after_code);
#d(trim(substr($code, 0, $blocks[$i][0][1])),0);
#$result = null;
}
if($blocks[$i][2][0] == '!')
{
#d($blocks[$i],0);
$result_code = ' vars[\'block\'] != \''.$blocks[$i][3][0].'\'): ?>'.EOL;
$result_code .= $blocks[$i][4][0];
$result_code .= EOL.''.EOL;
if($i == 0)$after_code .= $result_code;
else $before_code .= $result_code;
$result = null;
}
else
{
$result = ''.EOL;
$result .= $blocks[$i][4][0];
$result .= EOL.''.EOL;
#d($blocks[$i],0);
#d($result,0);
}
if(($i + 1) == $count_blocks && ($blocks[$i][0][1] + strlen($blocks[$i][0][0])) < strlen($new_code))
{
// записываем код "после"
$before_code .= trim(substr($code, ($blocks[$i][0][1] + strlen($blocks[$i][0][0])) + $lenght_shift));
$code = trim(substr($code, 0, ($blocks[$i][0][1] + strlen($blocks[$i][0][0])) - $lenght_shift));
#d(($blocks[$i][0][1] + strlen($blocks[$i][0][0])),0);
#d($blocks[$i]);
#$result = null;
}
$code = preg_replace('~'.preg_quote($blocks[$i][0][0], '~').'~uUs', $result, $code, 1);
}
}
if($use_blocks)
{
$code = (!empty($after_code) ? $after_code.EOL : null).' vars[\'block\']): ?>'."\r\n".$code.''.(!empty($before_code) ? EOL.$before_code : null);
/*$code = ' vars[\'block\']): ?>'."\r\n".$code.'';*/
}
#d($after_code,0);
#d($before_code,0);
return $code;
}
/**
* process_ifs
*
* обработка условий в шаблоне
* {if $somevar}
* ...
* {/if $somevar}
* в if(...) ... endif;
*
*
* @param string $code код шаблона
* @return string обработанный код
**/
private function process_ifs($code)
{
// условии
preg_match_all('~\{if ((\!)?(\~)?\$((.+)(\.(.*))?)( (.*) (\$((.+)(\.(.*))?)|.+))?)\}(?:\r\n|\n)?(.*)(?:\r\n|\n)?\{\/if \\1\}~uUs', $code, $ifs, PREG_SET_ORDER);
$count_ifs = count($ifs);
if($count_ifs > 0)
{
for($i = 0;$i < $count_ifs;$i ++)
{
$var = $this -> get_var($ifs[$i][4], false);
$chapter1 = 'isset('.$var.') && ';
if(!empty($ifs[$i][10]))
{
// если это переменная
if($ifs[$i][10] == '$'.$ifs[$i][11])
{
$var2 = $this -> get_var($ifs[$i][11], false);
$chapter1 .= 'isset('.$var2.') && ';
$strlen = strlen($ifs[$i][10]);
$chapter2 = $var.substr($ifs[$i][8], 0, -$strlen).$var2;
}
else
{
$chapter2 = $var.$ifs[$i][8];
}
}
else
{
if($ifs[$i][2] == '!')
{
$chapter1 = '!isset('.$var.') || ';
if($ifs[$i][3] == '~')$chapter2 = '!(bool)'.$var;
else $chapter2 = $var.' !== true';
}
else
{
if($ifs[$i][3] == '~')$chapter2 = '(bool)'.$var;
else $chapter2 = $var.' === true';
}
#if($ifs[$i][3] == '~')$chapter2 = ($ifs[$i][2] == '!' ? '!' : null).'(bool)'.$var;
#else $chapter2 = $var.($ifs[$i][2] == '!' ? '!' : '=').'== true';
}
$result = '';
$result .= $this -> process_ifs($ifs[$i][15]);
$result .= '';
$code = preg_replace('~'.preg_quote($ifs[$i][0], '~').'~uUs', $result, $code, 1);
}
}
return $code;
}
/**
* process_cycles
*
* обработка циклов в шаблоне типа
* {foreach $a}
* ...
* {/foreach $a}
* в for(...) ... endfor;
*
* @param string $code код шаблона
* @return string обработанный код
**/
private function process_cycles($code, $template)
{
// циклы
preg_match_all('~\{foreach (\$(.*))\}(?:\r\n|\n)?(.*)(?:\r\n|\n)?\{\/foreach \\1\}~uUs', $code, $cycles, PREG_SET_ORDER);
#d($cycles);
$count_cycles = count($cycles);
if($count_cycles > 0)
{
for($i = 0;$i < $count_cycles;$i ++)
{
$result = null;
$var = $this -> get_var($cycles[$i][2], false);
#eval('$is_set = isset('.$var.');');
#eval('$array = (isset('..'))'.$var.';');
$last_value = (isset($this -> cfgs['cycles_values']['last_value'])) ? ($this -> cfgs['cycles_values']['last_value'] + 1) : 1;
$this -> cfgs['cycles_values']['last_value'] = $last_value;
$index = '_cycles_'.$last_value;
/*#$this -> vars[$index] = $array;
#d('{$'.preg_quote($cycles[$i][2], '~').'(.*)}');
#d($this -> get_recursive_values($array));
#d($index,0);
*/
$cycles[$i][3] = preg_replace('~\{\$'.preg_quote($cycles[$i][2], '~').'\.(.+)\}~uUs', '', $cycles[$i][3]);
$cycles[$i][3] = preg_replace('~if (\!)?(\~)?\$'.preg_quote($cycles[$i][2], '~').'\.(.*)~uUs', 'if $1$2$'.$cycles[$i][2].'.$'.$index.'_i.$3', $cycles[$i][3]);
// if ($'.$index.'[\'$2\']
#$count_values = count($array);
$result = ''.EOL;
$result .= ' '.EOL;
$result .= ' '.EOL;
$result .= $this -> process_cycles($cycles[$i][3], $template);
$result .= ' '.EOL;
$result .= '';
$code = preg_replace('~'.preg_quote($cycles[$i][0], '~').'~uUs', $result, $code, 1);
}
}
return $code;
}
/**
* process_vars
*
* обработка переменных в шаблоне типа
* {$somevar}
* в echo $somevar;
*
* @param string $code код шаблона
* @return string обработанный код
**/
private function process_vars($code)
{
preg_match_all('~\{\$(.+)\}~uUs', $code, $vars, PREG_SET_ORDER);
$count_vars = count($vars);
if($count_vars > 0)
{
for($i = 0;$i < $count_vars;$i ++)
{
$var = $this -> get_var($vars[$i][1], false);
#$result = null;
#if(!empty($var))
# {
$result = '';
# }
$code = preg_replace('~'.preg_quote($vars[$i][0], '~').'~uUs', $result, $code, 1);
}
}
return $code;
}
/**
* get_var
*
* форматирование переменной типа
* $one.two.three
* в $this -> vars['one']['two']['three']
*
* @param string $code код шаблона
* @return string обработанный код
**/
private function get_var($string_var, $isset = true, $type = false)
{
// разбиваем строку на секции
$sections = explode('.', $string_var);
$count_sections = count($sections);
if($count_sections > 0)
{
$var = null;
for($i = 0;$i < $count_sections;$i ++)
{
if(substr($sections[$i], 0, 1) == '$' || is_numeric($sections[$i]))$var .= '['.$sections[$i].']';
else $var .= '[\''.$sections[$i].'\']';
}
#eval('$var = \'[\\\'\'.implode(\'\\\'][\\\'\', $sections).\'\\\']\';');
if(!$isset)return '$this -> vars'.$var;
eval('$is_set = isset($this -> vars'.$var.');');
$is_type = true;
if($is_set && is_string($type))eval('$is_type = is_'.$type.'($this -> vars'.$var.');');
if($is_set && $is_type)
{
return '$this -> vars'.$var;
}
return 0;
}
return 0;
}
}
# Morgan
?>