diff --git a/classes/template/TemplateHandler.class.php b/classes/template/TemplateHandler.class.php index 55c6b7b63..6e2fa4f88 100644 --- a/classes/template/TemplateHandler.class.php +++ b/classes/template/TemplateHandler.class.php @@ -63,12 +63,7 @@ $this->compiled_file = sprintf('%s%s.compiled.php',$this->compiled_path, md5($this->file)); // compare various file's modified time for check changed - $_handler = filemtime(_XE_PATH_.'classes/template/TemplateHandler.class.php'); - if($this->handler_mtime<$_handler) $this->handler_mtime = $_handler; - $_comment = filemtime(_XE_PATH_.'classes/template/TemplateParser.comment.php'); - if($this->handler_mtime<$_comment) $this->handler_mtime = $_comment; - $_tag = filemtime(_XE_PATH_.'classes/template/TemplateParser.tag.php'); - if($this->handler_mtime<$_tag) $this->handler_mtime = $_tag; + $this->handler_mtime = filemtime(_XE_PATH_.'classes/template/TemplateHandler.class.php'); $this->buff = null; } @@ -153,22 +148,57 @@ function parse() { if(!file_exists($this->file)) return; - // load template parser - require_once(_XE_PATH_.'classes/template/TemplateParser.comment.php'); - require_once(_XE_PATH_.'classes/template/TemplateParser.tag.php'); - // read tpl file $buff = FileHandler::readFile($this->file); // replace value of src in img/input/script tag $buff = preg_replace_callback('/<(img|input|script)([^>]*)src="([^"]*?)"/is', array($this, '_replacePath'), $buff); - // replace template syntax to php script syntax - $oCommentParser = new TemplateParserComment($this); - $buff = $oCommentParser->parse($buff); + // loop 템플릿 문법을 변환 + $buff = $this->_replaceLoop($buff); + + // |cond 템플릿 문법을 변환 + $buff = preg_replace_callback("/<\/?(\w+)((\s+\w+(\s*=\s*(?:\".*?\"|'.*?'|[^'\">\s]+))?)+\s*|\s*)\/?>/i", array($this, '_replacePipeCond'), $buff); + + // cond 템플릿 문법을 변환 + $buff = $this->_replaceCond($buff); + + // include 태그의 변환 + $buff = preg_replace_callback('!]+)>!is', array($this, '_replaceInclude'), $buff); + + // unload/ load 태그의 변환 + $buff = preg_replace_callback('!<(unload|load) ([^>]+)>!is', array($this, '_replaceLoad'), $buff); + + // 가상 태그인 block의 변환 + $buff = preg_replace('/|<\/block>/is','',$buff); + + // replace include + $buff = preg_replace_callback('!<\!--#include\(([^\)]*?)\)-->!is', array($this, '_compileIncludeToCode'), $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); + + // replace variables + $buff = preg_replace_callback('/\{[^@^ ]([^\{\}\n]+)\}/i', array($this, '_compileVarToContext'), $buff); + + // PHP 변수형의 변환 ($문자등을 공유 context로 변환) + $buff = $this->_replaceVarInPHP($buff); + + // replace parts not displaying results + $buff = preg_replace_callback('/\{\@([^\{\}]+)\}/i', array($this, '_compileVarToSilenceExecute'), $buff); - $oTagParser = new TemplateParserTag($this); - $buff = $oTagParser->parse($buff); // prevent from calling directly before writing into file $this->buff = ''.$buff; @@ -215,5 +245,614 @@ } return '<'.$matches[1].$matches[2].'src="'.$target.'"'; } + + /** + * @brief loop 문법의 변환 + **/ + function _replaceLoop($buff) + { + while(false !== $pos = strpos($buff, ' loop="')) + { + $pre = substr($buff,0,$pos); + $next = substr($buff,$pos); + + $pre_pos = strrpos($pre, '<'); + + preg_match('/^ loop="([^"]+)"/i',$next,$m); + $tag = substr($next,0,strlen($m[0])); + $next = substr($next,strlen($m[0])); + $next_pos = strpos($next, '<'); + + $tag = substr($pre, $pre_pos). $tag. substr($next, 0, $next_pos); + $pre = substr($pre, 0, $pre_pos); + $next = substr($next, $next_pos); + + $tag_name = trim(substr($tag,1,strpos($tag,' '))); + $tag_head = $tag_tail = ''; + + if(!preg_match('/ loop="([^"]+)"/is',$tag)) { + print "Invalid XpressEngine Template Syntax
"; + print "File : ".$this->file."
"; + print "Code : ".htmlspecialchars($tag); + exit(); + } + + preg_match_all('/ loop="([^"]+)"/is',$tag,$m); + $tag = preg_replace('/ loop="([^"]+)"/is','', $tag); + + for($i=0,$c=count($m[0]);$i<$c;$i++) + { + $loop = $m[1][$i]; + if(false!== $fpos = strpos($loop,'=>')) + { + $target = trim(substr($loop,0,$fpos)); + $vars = trim(substr($loop,$fpos+2)); + if(false===strpos($vars,',')) + { + $tag_head .= ''; + $tag_tail .= ''; + } + else + { + $t = explode(',',$vars); + $tag_head .= ' '.trim($t[1]).') { ?>'; + $tag_tail .= ''; + } + } + elseif(false!==strpos($loop,';')) + { + $tag_head .= ''; + $tag_tail .= ''; + } + else + { + $t = explode('=',$loop); + if(count($t)==2) + { + $tag_head .= ''; + $tag_tail .= ''; + } + } + } + + if(substr(trim($tag),-2)!='/>') + { + while(false !== $close_pos = strpos($next, '')); + $tag .= $tmp_buff; + $next = substr($next, strlen($tmp_buff)); + if(false === strpos($tmp_buff, '<'.$tag_name)) break; + } + } + + $buff = $pre.$tag_head.$tag.$tag_tail.$next; + } + return $buff; + } + + /** + * @brief pipe cond, |cond= 의 변환 + **/ + function _replacePipeCond($matches) + { + while(strpos($matches[0],'|cond="')!==false) { + if(preg_match('/ (\w+)=\"([^\"]+)\"\|cond=\"([^\"]+)\"/is', $matches[0], $m)) + $matches[0] = str_replace($m[0], sprintf(' %s="%s"', $m[3], $m[1], $m[2]), $matches[0]); + } + + return $matches[0]; + } + + /** + * @brief cond 문법의 변환 + **/ + function _replaceCond($buff) + { + if($this->filename != '_style.list.html') return $buff; + + while(false !== ($pos = strpos($buff, ' cond="'))) + { + $pre = substr($buff,0,$pos); + $next = substr($buff,$pos); + + $pre_pos = strrpos($pre, '<'); + $next_pos = strpos($next, '<'); + + $tag = substr($pre, $pre_pos). substr($next, 0, $next_pos); + $pre = substr($pre, 0, $pre_pos); + $next = substr($next, $next_pos); + $tag_name = trim(substr($tag,1,strpos($tag,' '))); + $tag_head = $tag_tail = ''; + + if(preg_match_all('/ cond=\"([^\"]+)"/is',$tag,$m)) + { + for($i=0,$c=count($m[0]);$i<$c;$i++) + { + $tag_head .= ''; + $tag_tail .= ''; + } + } + + if(!preg_match('/ cond="([^"]+)"/is',$tag)) { + print "Invalid XpressEngine Template Syntax
"; + print "File : ".$this->file."
"; + print "Code : ".htmlspecialchars($tag); + exit(); + } + + $tag = preg_replace('/ cond="([^"]+)"/is','', $tag); + if(substr(trim($tag),-2)=='/>') + { + $buff = $pre.$tag_head.$tag.$tag_tail.$next; + } + else + { + while(false !== $close_pos = strpos($next, '')); + $tag .= $tmp_buff; + $next = substr($next, strlen($tmp_buff)); + if(false === strpos($tmp_buff, '<'.$tag_name)) break; + } + $buff = $pre.$tag_head.$tag.$tag_tail.$next; + } + } + + return $buff; + } + + /** + * @brief 다른 template파일을 include하는 include tag의 변환 + **/ + function _replaceInclude($matches) + { + if(!preg_match('/target=\"([^\"]+)\"/is',$matches[0], $m)) throw new Exception('"target" attribute missing in "'.htmlspecialchars($matches[0]).'"'); + + $target = $m[1]; + if(substr($target,0,1)=='/') + { + $target = substr($target,1); + $pos = strrpos('/',$target); + $filename = substr($target,$pos+1); + $path = substr($target,0,$pos); + } else { + if(substr($target,0,2)=='./') $target = substr($target,2); + $pos = strrpos('/',$target); + $filename = substr($target,$pos); + $path = substr($target,0,$pos); + } + + return sprintf( + 'compile(\'%s\',\'%s\');%s'. + '?>%s', + "\n", + "\n", + $path, $filename, "\n", + "\n" + ); + } + + /** + * @brief load 태그의 변환 + **/ + function _replaceLoad($matches) { + $output = $matches[0]; + if(!preg_match_all('/ ([^=]+)=\"([^\"]+)\"/is',$matches[0], $m)) return $matches[0]; + + $type = $matches[1]; + for($i=0,$c=count($m[1]);$i<$c;$i++) + { + if(!trim($m[1][$i])) continue; + $attrs[trim($m[1][$i])] = trim($m[2][$i]); + } + + if(!$attrs['target']) return $matches[0]; + + $web_path = $this->web_path; + $base_path = $this->path; + + $target = $attrs['target']; + if(substr($target,0,2)=='./') $target = substr($target,2); + if(!substr($target,0,1)!='/') $target = $web_path.$target; + + + // if target ends with lang, load language pack + if(substr($target, -4)=='lang') { + if(substr($target,0,2)=='./') $target = substr($target, 2); + $lang_dir = $base_path.$target; + if(is_dir($lang_dir)) $output = sprintf('', $lang_dir); + + // otherwise try to load xml, css, js file + } else { + if(substr($target,0,1)!='/') $source_filename = $base_path.$target; + else $source_filename = $target; + + // 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)) $source_filename = $base_path.$filename; + if($type == 'unload') $output = ''; + else $output = ''; + break; + // js file + case 'js' : + if(!preg_match('/^(http|\/)/i',$source_filename)) $source_filename = $base_path.$filename; + if($type == 'unload') $output = ''; + else $output = ''; + break; + } + } + return $output; + } + + /** + * @brief $문자 의 PHP 변수 변환 + **/ + private function _replaceVarInPHP($buff) { + $head = $tail = ''; + while(false !== $pos = strpos($buff, ''); + $body = substr($buff,0,$pos+2); + $head .= preg_replace_callback('/(.?)\$([a-z0-9\_\-\[\]\'\"]+)/is',array($this, '_replaceVarString'), $body); + + $buff = substr($buff,$pos+2); + } + return $head.$buff; + } + + + /** + * @brief php5의 class::$변수명의 경우 context를 사용하지 않아야 하기에 함수로 대체 + **/ + private function _replaceVarString($matches) + { + if($matches[1]==':') return $matches[0]; + if(substr($matches[2],0,1)=='_') return $matches[0]; + return $matches[1].'$__Context->'.$matches[2]; + } + + /** + * @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;$ifile), $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->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->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->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; + } } ?> diff --git a/classes/template/TemplateParser.comment.php b/classes/template/TemplateParser.comment.php deleted file mode 100644 index 8a4bcef0a..000000000 --- a/classes/template/TemplateParser.comment.php +++ /dev/null @@ -1,360 +0,0 @@ -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; - } - - } -?> diff --git a/classes/template/TemplateParser.tag.php b/classes/template/TemplateParser.tag.php deleted file mode 100644 index 233fa96f2..000000000 --- a/classes/template/TemplateParser.tag.php +++ /dev/null @@ -1,326 +0,0 @@ -oTemplate = $oTemplate; - } - - /** - * @brief compile a template file with comment syntax - **/ - function parse($buff) { - - // loop 템플릿 문법을 변환 - $buff = $this->_replaceLoop($buff); - - // |cond 템플릿 문법을 변환 - $buff = preg_replace_callback('/<([a-z]+)([^>\|]*)\|cond=\"([^\"]+)\"([^>]*)>/is', array($this, '_replacePipeCond'), $buff); - - // cond 템플릿 문법을 변환 - $buff = $this->_replaceCond($buff); - - // include 태그의 변환 - $buff = preg_replace_callback('!]+)>!is', array($this, '_replaceInclude'), $buff); - - - // unload/ load 태그의 변환 - $buff = preg_replace_callback('!<(unload|load) ([^>]+)>!is', array($this, '_replaceLoad'), $buff); - - // 가상 태그인 block의 변환 - $buff = preg_replace('/|<\/block>/is','',$buff); - - // 컴파일 결과물 return - return $buff; - } - - /** - * @brief 경로 변경 - **/ - - /** - * @brief loop 문법의 변환 - **/ - function _replaceLoop($buff) - { - while(false !== $pos = strpos($buff, ' loop="')) - { - $pre = substr($buff,0,$pos); - $next = substr($buff,$pos); - - $pre_pos = strrpos($pre, '<'); - - preg_match('/^ loop="([^"]+)"/i',$next,$m); - $tag = substr($next,0,strlen($m[0])); - $next = substr($next,strlen($m[0])); - $next_pos = strpos($next, '<'); - - $tag = substr($pre, $pre_pos). $tag. substr($next, 0, $next_pos); - $pre = substr($pre, 0, $pre_pos); - $next = substr($next, $next_pos); - - $tag_name = trim(substr($tag,1,strpos($tag,' '))); - $tag_head = $tag_tail = ''; - - preg_match_all('/ loop="([^"]+)"/is',$tag,$m); - $tag = preg_replace('/ loop="([^"]+)"/is','', $tag); - - for($i=0,$c=count($m[0]);$i<$c;$i++) - { - $loop = $m[1][$i]; - if(false!== $fpos = strpos($loop,'=>')) - { - $target = trim(substr($loop,0,$fpos)); - $vars = trim(substr($loop,$fpos+2)); - if(false===strpos($vars,',')) - { - $tag_head .= ''; - $tag_tail .= ''; - } - else - { - $t = explode(',',$vars); - $tag_head .= ' '.trim($t[1]).') { ?>'; - $tag_tail .= ''; - } - } - elseif(false!==strpos($loop,';')) - { - $tag_head .= ''; - $tag_tail .= ''; - } - else - { - $t = explode('=',$loop); - if(count($t)==2) - { - $tag_head .= ''; - $tag_tail .= ''; - } - } - } - - if(substr(trim($tag),-2)!='/>') - { - while(false !== $close_pos = strpos($next, '')); - $tag .= $tmp_buff; - $next = substr($next, strlen($tmp_buff)); - if(false === strpos($tmp_buff, '<'.$tag_name)) break; - } - } - - for($i=0,$c=count($loop_var);$i<$c;$i++) - { - $k = $loop_var[$i]; - $tag_head = str_replace($k, 'context->'.$k,$tag_head); - } - - preg_match_all('/(.?)(\$[a-z0-9\_]+)/i',$loop,$lm); - for($i=0,$c=count($lm[1]);$i<$c;$i++) - { - $h = trim($lm[1][$i]); - $k = trim($lm[2][$i]); - if($h==':'||$h=='>') continue; - if($target && $k == $target) continue; - $tag_head = str_replace($k, '$_'.substr($k,1), $tag_head); - $tag = str_replace($k, '$_'.substr($k,1), $tag); - } - - $buff = $pre.$tag_head.$tag.$tag_tail.$next; - } - return $buff; - } - - /** - * @brief pipe cond, |cond= 의 변환 - **/ - function _replacePipeCond($matches) - { - $tag = $matches[1]; - - if(preg_match_all('/ ([^=]+)=\"([^"]+)\"/is', $matches[2], $m)) - { - $t = array_pop($m[0]); - return '<'.$matches[1].implode($m[0],' ').' '.$t.' '.$matches[4].'>'; - } - - return $matches[0]; - } - - /** - * @brief cond 문법의 변환 - **/ - function _replaceCond($buff) - { - while(false !== $pos = strpos($buff, ' cond="')) - { - $pre = substr($buff,0,$pos); - $next = substr($buff,$pos); - - $pre_pos = strrpos($pre, '<'); - $next_pos = strpos($next, '<'); - - $tag = substr($pre, $pre_pos). substr($next, 0, $next_pos); - $pre = substr($pre, 0, $pre_pos); - $next = substr($next, $next_pos); - $tag_name = trim(substr($tag,1,strpos($tag,' '))); - $tag_head = $tag_tail = ''; - - if(preg_match_all('/ cond=\"([^\"]+)"/is',$tag,$m)) - { - for($i=0,$c=count($m[0]);$i<$c;$i++) - { - $tag_head .= ''; - $tag_tail .= ''; - } - } - - $tag = preg_replace('/ cond="([^"]+)"/is','', $tag); - if(substr(trim($tag),-2)=='/>') - { - $buff = $pre.$tag_head.$tag.$tag_tail.$next; - } - else - { - while(false !== $close_pos = strpos($next, '')); - $tag .= $tmp_buff; - $next = substr($next, strlen($tmp_buff)); - if(false === strpos($tmp_buff, '<'.$tag_name)) break; - } - $buff = $pre.$tag_head.$tag.$tag_tail.$next; - } - } - return $buff; - } - - /** - * @brief 다른 template파일을 include하는 include tag의 변환 - **/ - function _replaceInclude($matches) - { - if(!preg_match('/target=\"([^\"]+)\"/is',$matches[0], $m)) throw new Exception('"target" attribute missing in "'.htmlspecialchars($matches[0]).'"'); - - $target = $m[1]; - if(substr($target,0,1)=='/') - { - $target = substr($target,1); - $pos = strrpos('/',$target); - $filename = substr($target,$pos+1); - $path = substr($target,0,$pos); - } else { - if(substr($target,0,2)=='./') $target = substr($target,2); - $pos = strrpos('/',$target); - $filename = substr($target,$pos); - $path = substr($target,0,$pos); - } - - return sprintf( - 'compile(\'%s\',\'%s\');%s'. - '?>%s', - "\n", - "\n", - $path, $filename, "\n", - "\n" - ); - } - - /** - * @brief load 태그의 변환 - **/ - function _replaceLoad($matches) { - $output = $matches[0]; - if(!preg_match_all('/ ([^=]+)=\"([^\"]+)\"/is',$matches[0], $m)) return $matches[0]; - - $type = $matches[1]; - for($i=0,$c=count($m[1]);$i<$c;$i++) - { - if(!trim($m[1][$i])) continue; - $attrs[trim($m[1][$i])] = trim($m[2][$i]); - } - - if(!$attrs['target']) return $matches[0]; - - $web_path = $this->oTemplate->web_path; - $base_path = $this->oTemplate->path; - - $target = $attrs['target']; - if(substr($target,0,2)=='./') $target = substr($target,2); - if(!substr($target,0,1)!='/') $target = $web_path.$target; - - - // if target ends with lang, load language pack - if(substr($target, -4)=='lang') { - if(substr($target,0,2)=='./') $target = substr($target, 2); - $lang_dir = $base_path.$target; - if(is_dir($lang_dir)) $output = sprintf('', $lang_dir); - - // otherwise try to load xml, css, js file - } else { - if(substr($target,0,1)!='/') $source_filename = $base_path.$target; - else $source_filename = $target; - - // 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)) $source_filename = $base_path.$filename; - if($type == 'unload') $output = ''; - else $output = ''; - break; - // js file - case 'js' : - if(!preg_match('/^(http|\/)/i',$source_filename)) $source_filename = $base_path.$filename; - if($type == 'unload') $output = ''; - else $output = ''; - break; - } - } - return $output; - } - } -?>