oTemplate = $oTemplate; } /** * @brief compile a template file with comment syntax **/ function parse($buff) { // replace include $buff = preg_replace_callback('!<\!--#include\(([^\)]*?)\)-->!is', array($this, '_compileIncludeToCode'), $buff); // replace variables $buff = preg_replace_callback('/\{[^@^ ]([^\{\}\n]+)\}/i', array($this, '_compileVarToContext'), $buff); // replace parts not displaying results $buff = preg_replace_callback('/\{\@([^\{\}]+)\}/i', array($this, '_compileVarToSilenceExecute'), $buff); // replace $buff = preg_replace_callback('!<\!--@(.*?)-->!is', array($this, '_compileFuncToCode'), $buff); // remove comments $buff = preg_replace('!(\n?)( *?)<\!--//(.*?)-->!is', '', $buff); // import xml filter/ css/ js/ files (media is applied to only css) $buff = preg_replace_callback('!<\!--%import\(\"([^\"]*?)\"(,optimized\=(true|false))?(,media\=\"([^\"]*)\")?(,targetie=\"([^\"]*)\")?\)-->!is', array($this, '_compileImportCode'), $buff); // unload css/ js (media is applied to only css) $buff = preg_replace_callback('!<\!--%unload\(\"([^\"]*?)\"(,optimized\=(true|false))?(,media\=\"([^\"]*)\")?(,targetie=\"([^\"]*)\")?\)-->!is', array($this, '_compileUnloadCode'), $buff); // javascript plugin import $buff = preg_replace_callback('!<\!--%load_js_plugin\(\"([^\"]*?)\"\)-->!is', array($this, '_compileLoadJavascriptPlugin'), $buff); return $buff; } /** * @brief replace with php code * @param[in] $matches match * @return replaced result **/ function _compileIncludeToCode($matches) { // if target string to include contains variables handle them $arg = str_replace(array('"','\''), '', $matches[1]); if(!$arg) return; $tmp_arr = explode("/", $arg); for($i=0;$ioTemplate->file), $arg); // step2: check path from root if(!file_exists($source_filename)) $source_filename = './'.$arg; if(!file_exists($source_filename)) return; // split into path and filename $tmp_arr = explode('/', $source_filename); $filename = array_pop($tmp_arr); $path = implode('/', $tmp_arr).'/'; // try to include $output = sprintf( 'compile(\'%s\',\'%s\');%s'. '?>%s', "\n", "\n", $path, $filename, "\n", "\n" ); return $output; } /** * @brief replace $... variables in { } with Context::get(...) * @param[in] $matches match * @return replaced result in case of success or NULL in case of error **/ function _compileVarToContext($matches) { $str = trim(substr($matches[0],1,strlen($matches[0])-2)); if(!$str) return $matches[0]; if(!in_array(substr($str,0,1),array('(','$','\'','"'))) { if(preg_match('/^([^\( \.]+)(\(| \.)/i',$str,$m)) { $func = trim($m[1]); if(strpos($func,'::')===false) { if(!function_exists($func)) { return $matches[0]; } } else { list($class, $method) = explode('::',$func); // FIXME regardless of whether class/func name is case-sensitive, it is safe // to assume names are case sensitive. We don't have compare twice. if(!class_exists($class) || !in_array($method, get_class_methods($class))) { // In some environment, the name of classes and methods may be case-sensitive list($class, $method) = explode('::',strtolower($func)); if(!class_exists($class) || !in_array($method, get_class_methods($class))) { return $matches[0]; } } } } else { if(!defined($str)) return $matches[0]; } } return ']+)/i','$__Context->\\1', $str).');?>'; } /** * @brief replace @... function in { } into print func(..) * @param[in] $matches match * @return replaced result **/ function _compileVarToSilenceExecute($matches) { if(strtolower(trim(str_replace(array(';',' '),'', $matches[1])))=='return') return ''; return ']+)/i','$__Context->\\1', trim($matches[1])).';?>'; } /** * @brief replace code in with php code * @param[in] $matches match * @return changed result **/ function _compileFuncToCode($matches) { static $idx = 0; $code = trim($matches[1]); if(!$code) return; switch(strtolower($code)) { case 'else' : $output = '}else{'; break; case 'end' : case 'endif' : case 'endfor' : case 'endforeach' : case 'endswitch' : $output = '}'; break; case 'break' : $output = 'break;'; break; case 'default' : $output = 'default :'; break; case 'break@default' : $output = 'break; default :'; break; default : $suffix = '{'; if(substr($code, 0, 4) == 'else') { $code = '}'.$code; } elseif(substr($code, 0, 7) == 'foreach') { $tmp_str = substr($code, 8); $tmp_arr = explode(' ', $tmp_str); $var_name = $tmp_arr[0]; $prefix = '$Context->__idx['.$idx.']=0;'; if(substr($var_name, 0, 1) == '$') { $prefix .= sprintf('if(count($__Context->%s)) ', substr($var_name, 1)); } else { $prefix .= sprintf('if(count(%s)) ', $var_name); } $idx++; $suffix .= '$__idx['.$idx.']=($__idx['.$idx.']+1)%2; $cycle_idx = $__idx['.$idx.']+1;'; } elseif(substr($code, 0, 4) == 'case') { $suffix = ':'; } elseif(substr($code, 0, 10) == 'break@case') { $code = 'break; case'.substr($code, 10); $suffix = ':'; } $output = preg_replace('/\$([a-zA-Z0-9\_\-]+)/i', '$__Context->\\1', $code.$suffix); break; } return sprintf('', $prefix, $output); } /** * @brief replace xe specific code, "" with appropriate php code * @param[in] $matches match * @return Returns modified result or NULL in case of error **/ function _compileImportCode($matches) { // find xml file $base_path = $this->oTemplate->path; $given_file = trim($matches[1]); if(!$given_file) return; if(isset($matches[3])) $optimized = strtolower(trim($matches[3])); if(!$optimized) $optimized = 'true'; if(isset($matches[5])) $media = trim($matches[5]); if(!$media) $media = 'all'; if(isset($matches[7])) $targetie = trim($matches[7]); if(!$targetie) $targetie = ''; else $optimized = 'false'; // if given_file ends with lang, load language pack if(substr($given_file, -4)=='lang') { if(substr($given_file,0,2)=='./') $given_file = substr($given_file, 2); $lang_dir = $base_path.$given_file; if(is_dir($lang_dir)) $output = sprintf('', $lang_dir); // otherwise try to load xml, css, js file } else { if(substr($given_file,0,1)!='/') $source_filename = sprintf("%s%s",$base_path, $given_file); else $source_filename = $given_file; // get filename and path $tmp_arr = explode("/",$source_filename); $filename = array_pop($tmp_arr); $base_path = implode("/",$tmp_arr)."/"; // get the ext $tmp_arr = explode(".",$filename); $ext = strtolower(array_pop($tmp_arr)); // according to ext., import the file switch($ext) { // xml js filter case 'xml' : // create an instance of XmlJSFilter class, then create js and handle Context::addJsFile $output = sprintf( 'compile();%s'. '?>%s', "\n", "\n", $base_path, $filename, "\n", "\n", "\n" ); break; // css file case 'css' : if(preg_match('/^(http|\/)/i',$source_filename)) { $output = sprintf('', $source_filename, 'false', $media, $targetie); } else { $meta_file = sprintf('%s%s', $base_path, $filename); $output = sprintf('', $base_path, $filename, $optimized, $media, $targetie); } break; // js file case 'js' : if(preg_match('/^(http|\/)/i',$source_filename)) { $output = sprintf('', $source_filename, 'false', $targetie); } else { $meta_file = sprintf('%s%s', $base_path, $filename); $output = sprintf('', $base_path, $filename, $optimized, $targetie); } break; } } if($meta_file) $output = ''.$output; return $output; } /** * @brief import javascript plugin * @param[in] $matches match * @return result loading the plugin * @remarks javascript plugin works as optimized = false **/ function _compileLoadJavascriptPlugin($matches) { $base_path = $this->oTemplate->path; $plugin = trim($matches[1]); return sprintf('', $plugin); } /** * @brief remove loading part of css/ js file * @param[in] $matches match * @return removed result **/ function _compileUnloadCode($matches) { // find xml file $base_path = $this->oTemplate->path; $given_file = trim($matches[1]); if(!$given_file) return; if(isset($matches[3])) $optimized = strtolower(trim($matches[3])); if(!$optimized) $optimized = 'true'; if(isset($matches[5])) $media = trim($matches[5]); if(!$media) $media = 'all'; if(isset($matches[7])) $targetie = trim($matches[7]); if(!$targetie) $targetie = ''; else $optimized = 'false'; if(substr($given_file,0,1)!='/') $source_filename = sprintf("%s%s",$base_path, $given_file); else $source_filename = $given_file; // get path and file nam $tmp_arr = explode("/",$source_filename); $filename = array_pop($tmp_arr); $base_path = implode("/",$tmp_arr)."/"; // get an ext. $tmp_arr = explode(".",$filename); $ext = strtolower(array_pop($tmp_arr)); switch($ext) { // css file case 'css' : if(preg_match('/^(http|\/)/i',$source_filename)) { $output = sprintf('', $source_filename, 'false', $media, $targetie); } else { $meta_file = sprintf('%s%s', $base_path, $filename); $output = sprintf('', $base_path, $filename, $optimized, $media, $targetie); } break; // js file case 'js' : if(preg_match('/^(http|\/)/i',$source_filename)) { $output = sprintf('', $source_filename, 'false', $targetie); } else { $meta_file = sprintf('%s%s', $base_path, $filename); $output = sprintf('', $base_path, $filename, $optimized, $targetie); } break; } return $output; } } ?>