页:
[1]
|
不知道有多少位能够读懂
[php]<?php
/*
* 模板处理程序
*
* 这不是一个免费程序
*
* @开发时间:2006年10月18日 22:29
* @开发者:zx
* @版本:1.0
*
* 对象假定:
* 先使用readInfo接口读取模板
* 假设模板循环参数的首参数为循环数组,第二个参数为数组值标识符,
* 第三个参数为数组键值标识符
*/
class zxtemplate implements zxtemplateInterface
{
private $kernel;
/*
* 库主控文件
*
* @var kernel
* @access private
*/
private $content;
/*
* 模板内容
*
* @var string
* @access private
*/
private $compiler;
/*
* 重新编译
*
* @var bool
* @access private
*/
private $parameter;
/*
* 模板参数
*
* @var array
* @access private
*/
private $assigns;
/*
* 模板参数值
*
* @var array
* @access private
*/
private $tags = array
(
'left' => '{',
'right' => '}',
'var' => '$',
'assign' => '=',
'system' => array
(
'for' => array
(
'name' => 'for',
'endName' => 'endfor',
),
'if' => array
(
'name' => 'if',
'endName' => 'endif',
'else' => 'else',
'elseIf' => 'elseif'
),
),
'function' => array
(
'left' => '(',
'right' => ')',
'split' => ','
),
'order' => array
(
'start' => '[',
'end' => ']',
'split' => ';'
)
);
/*
* 模板标识符
*
* @var array
* @access private
*/
private $code = array
(
'var' => '$',
'start' => '<?',
'echo' => '=',
'end' => '?>',
'suffix' => '.php',
'split' => ';',
'sub' => array
(
'start' => '{',
'end' => '}'
),
'function' => array
(
'left' => '(',
'right' => ')',
'split' => ','
)
);
/*
* 定义PHP程序标识符
*
* @var array
* @access private
*/
private $path = array
(
'compilerDir' => './compiler/',
'compilerPath' => '',
'templateDir' => './template/',
'templateFile' => ''
);
/*
* 路径信息设定
*
* @var array
* @access private
*/
public function __construct($kernel)
{
$this->kernel = &$kernel;
}
public function setLeftSign($sign)
{
$this->tags['left'] = $sign;
}
public function getLeftSign( )
{
return($this->tags['left']);
}
public function setRightSign($sign)
{
$this->tags['right'] = $sign;
}
public function getRightSign( )
{
return($this->tags['right']);
}
public function setVarSign($sign)
{
$this->tags['var'] = $sign;
}
public function getVarSign( )
{
return($this->tags['var']);
}
public function setFunctionLeftSign($sign)
{
$this->tags['function']['left'] = $sign;
}
public function getFunctionLeftSign( )
{
return($this->tags['function']['left']);
}
public function setFunctionRightSign($sign)
{
$this->tags['function']['right'] = $sign;
}
public function getFunctionRightSign( )
{
return($this->tags['function']['right']);
}
public function setFunctionSplitSign($sign)
{
$this->tags['function']['split'] = $sign;
}
public function getFunctionSplitSign( )
{
return($this->tags['function']['split']);
}
public function setOrderStartSign($sign)
{
$this->tags['order']['start'] = $sign;
}
public function getOrderStartSign( )
{
return($this->tags['order']['start']);
}
public function setOrderEndSign($sign)
{
$this->tags['order']['end'] = $sign;
}
public function getOrderEndSign( )
{
return($this->tags['order']['end']);
}
public function setOrderSplitSign($sign)
{
$this->tags['order']['split'] = $sign;
}
public function getOrderSplitSign( )
{
return($this->tags['order']['split']);
}
public function getForTag( )
{
return($this->tags['system']['for']['name']);
}
public function getEndForTag( )
{
return($this->tags['system']['for']['endName']);
}
public function getIfTag( )
{
return($this->tags['system']['if']['name']);
}
public function getElseIfTag( )
{
return($this->tags['system']['if']['elseIf']);
}
public function getElseTag( )
{
return($this->tags['system']['if']['else']);
}
public function getEndIfTag( )
{
return($this->tags['system']['if']['endName']);
}
/*获取程序开始标记*/
private function getProgramStart( )
{
return($this->code['start']);
}
/*获取程序结束标记*/
private function getProgramEnd( )
{
return($this->code['end']);
}
/*获取程序输出标记*/
private function getProgramEcho( )
{
return($this->code['echo']);
}
/*获取程序变量标识*/
private function getProgramVar( )
{
return($this->code['var']);
}
/*获取程序函数左标记*/
private function getProgramFunctionLeft( )
{
return($this->code['function']['left']);
}
/*获取程序函数右标记*/
private function getProgramFunctionRight( )
{
return($this->code['function']['right']);
}
/*获取程序函数参数分隔标记*/
private function getProgramFunctionSplit( )
{
return($this->code['function']['split']);
}
/*获取程序子过程起始标记*/
private function getProgramSubStart( )
{
return($this->code['sub']['start']);
}
/*获取程序子过程结束标记*/
private function getProgramSubEnd( )
{
return($this->code['sub']['end']);
}
/*获取程序分隔标记*/
private function getProgramSplit( )
{
return($this->code['split']);
}
/*获取程序文件后缀名*/
private function getProgramSuffix( )
{
return($this->code['suffix']);
}
/*设置编译目录(路径)*/
public function setCompilerDir($dir)
{
$this->path['compilerDir'] = $dir;
}
public function setCompiler($close=true)
{
$this->compiler = $close;
}
public function isCompiler( )
{
return(true);
}
public function readInfo($templateFile)
{
/*获取模板路经*/
$filePath = self::getTemplatePath($templateFile);
/*如果需要读取模板则*/
if(self::isReadTemplate($filePath))
{
/*如果模板文件存在则*/
if(fileExists($filePath))
{
/*读取并保存模板文件*/
$templateContent = self::readFile($filePath);
self::saveContent($templateContent);
/*提取模板参数*/
if(self::pickUpParameter( ))
{
/*转换模板文件为模板程序文件并保存模板程序文件*/
$phpFile = self::converToProgram( );
self::saveProgram($phpFile);
return(true);
}
else
{
return(false);
}
}
else
{
/*处理错误*/
self::errorReport('{$Template}{$File}{$Not}{$Found}', 'readInfo("' . $templateFile . '")', ERROR_PROGRAME);
return(false);
}
}
return(true);
}
/*获取模板文件路径(文件名)*/
private function getTemplatePath($file)
{
return(fileExists($file) ? $file : $this->path['templateDir'] . $file);
}
/*是否读取模板(模板路径)*/
private function isReadTemplate($file)
{
return((!self::programExists($file) || self::isCompiler( )) ? true : false);
}
/*程序文件存在(模板路径)*/
private function programExists($templateFile='')
{
$programPath = self::getProgramPath($templateFile);
return(fileExists($programPath));
}
/*获取程序文件名(模板文件)*/
private function getProgramFile($templateFile='')
{
if($templateFile)
{
$this->path['templateFile'] = $templateFile;
}
$this->path['compilerPath'] = md5($this->path['templateFile']) . self::getProgramSuffix( );
return($this->path['compilerPath']);
}
/*获取模板程序文件路径*/
private function getProgramPath($templateFile='')
{
$programFile = self::getProgramFile($templateFile);
return($this->path['compilerDir'] . $programFile);
}
/*读取文件内容(文件路径)*/
private function readFile($file)
{
$files = &$this->kernel->object('zxfiles');
return($files->read($file));
}
/*保存模板内容(内容)*/
private function saveContent($content)
{
$this->content = $content;
}
/*获取模板内容*/
private function getContent( )
{
return($this->content);
}
/*提取模板参数()*/
private function pickUpParameter( )
{
/*提取模板中所有的PHP标记*/
$tags = self::searchTags();
if($tags)
{
/*保存模板标记*/
self::saveTags($tags);
return(true);
}
return(false);
}
/*保存模板标记(模板标记数组)*/
private function saveTags($tags)
{
$this->parameter = $tags;
}
/*获取模板标记*/
private function getTags( )
{
return($this->parameter);
}
/*搜索模板标记(模板内容)*/
private function searchTags( )
{
/*标记的存储结构:名称(name),起始位置(start),长度(len)*/
/*获取模板内容*/
$content = self::getContent( );
$contentLen = strLen($content);
/*获取标记左边界符*/
$leftSign = self::getLeftSign( );
$leftSignLen = strLen($leftSign);
/*获取标记右边界符*/
$rightSign = self::getRightSign( );
$rightSignLen = strLen($rightSign);
/*遍历模板内容*/
$pos = 0;
$tags = array( );
$leftSignStack = array( );
$lastID = 0;
for($i = 0; $i < $contentLen; $i++)
{
/*如果匹配到左标记则*/
if(self::isLeftSign(subStr($content, $i, $leftSignLen)))
{
/*将标记及其位置入标记栈*/
arrayPush($leftSignStack, $i);
}
/*如果匹配到右标记则*/
else if(self::isRightSign(subStr($content, $i, $rightSignLen)))
{
/*如果左标记栈不为空则*/
if(arrayNotNull($leftSignStack))
{
/*弹出左标记,将左标记与右标记之间的内容保存*/
$leftSignPos = arrayPop($leftSignStack);
$nameStart = $leftSignPos + $leftSignLen;
$tagLen = $i - $nameStart;
$tags[$lastID++] = array
(
'name' => subStr($content, $nameStart, $tagLen),
'start' => $leftSignPos,
'len' => $leftSignLen + $tagLen + $rightSignLen
);
}
else
{
/*提示出错,找不到左标记符*/
self::errorReport('{$Not}{$Found}{$LeftSign}', 'searchTags( )', ERROR_PROGRAMEE);
return(false);
}
}
}
/*返回模板标记信息数组*/
return($tags);
}
/*是否是左标记(标记)*/
private function isLeftSign($sign)
{
/*获取标记左边界符*/
$leftSign = self::getLeftSign( );
return(isSameStr($sign, $leftSign) ? true : false);
}
/*是否是右标记(标记)*/
private function isRightSign($sign)
{
/*获取标记右边界符*/
$rightSign = self::getRightSign( );
return(isSameStr($sign, $rightSign) ? true : false);
}
/*模板转换为程序()*/
private function converToProgram( )
{
/*获取模板内容*/
$content = self::getContent( );
if(!$content)
{
return('');
}
/*获取模板参数*/
$parameters = self::getTags( );
$parametersLen = arrayCount($parameters);
$program = '';
$code['start'] = self::getProgramStart( );
$code['end'] = self::getProgramEnd( );
$code['echo'] = self::getProgramEcho( );
$code['subStart'] = self::getProgramSubStart( );
$code['subEnd'] = self::getProgramSubEnd( );
$converPoint = 0;
for($i = 0; $i < $parametersLen; $i++)
{
$program .= subStr($content, $converPoint, $parameters[$i]['start'] - $converPoint) . $code['start'];
$converPoint = $parameters[$i]['start'] + $parameters[$i]['len'];
if(self::isVarTag($parameters[$i]['name']))
{
$program .= $code['echo'] . self::converVarTag($parameters[$i]['name']);
}
else if(self::isForTag($parameters[$i]['name']))
{
$program .= self::converForTag($parameters[$i]['name']) . $code['subStart'] . entry( );
}
else if(self::isEndForTag($parameters[$i]['name']))
{
$program .= self::converEndForTag($parameters[$i]['name']) . $code['subEnd'] . entry( );
}
else if(self::isIfTag($parameters[$i]['name']))
{
$program .= self::converIfTag($parameters[$i]['name']) . $code['subStart'] . entry( );
}
else if(self::isElseIfTag($parameters[$i]['name']))
{
$program .= entry( ) . $code['subEnd'] . self::converElseIfTag($parameters[$i]['name']) . $code['subStart'] . entry( );
}
else if(self::isElseTag($parameters[$i]['name']))
{
$program .= entry( ) . $code['subEnd'] . self::converElseTag($parameters[$i]['name']) . $code['subStart'] . entry( );
}
else if(self::isEndIfTag($parameters[$i]['name']))
{
$program .= self::converEndIfTag($parameters[$i]['name']) . $code['subEnd'] . entry( );
}
else if(self::isFunctionTag($parameters[$i]['name']))
{
$program .= $code['echo'] . self::converFunctionTag($parameters[$i]['name']);
}
else if(self::isOrderTag($parameters[$i]['name']))
{
$program .= self::converOrderTag($parameters[$i]['name']);
}
$program .= $code['end'];
}
$program .= subStr($content, $converPoint);
/*返回转换后的程序*/
return($program);
}
/*是否是变量标记(标记名)*/
private function isVarTag($tag)
{
$tag = trim($tag);
/*获取变量标识符*/
$varSign = self::getVarSign( );
$varSignLen = strLen($varSign);
return(isSameStr(strToLower(subStr($tag, 0, $varSignLen)), $varSign) ? true : false);
}
/*转换变量标记(标记名)*/
private function converVarTag($tag)
{
/*获取变量标识符*/
$varSign = self::getVarSign( );
/*获取程序变量标识*/
$programVarSign = self::getProgramVar( );
$varSignLen = strLen($varSign);
return($programVarSign . subStr($tag, $varSignLen));
}
/*是否是循环起始标记(标记名)*/
private function isForTag($tag)
{
/*获取函数左标记*/
$leftSign = self::getFunctionLeftSign( );
/*获取循环起始标记*/
$for = self::getForTag( );
$nameLen = searchStr($leftSign, $tag);
if(!$nameLen)
{
return(false);
}
else if(!isSameStr(strToLower(subStr($tag, 0, $nameLen)), $for))
{
return(false);
}
return(true);
}
/*转换循环起始标记(标记名)*/
private function converForTag($tag)
{
/*假设模板循环参数的首参数为循环数组,第二个参数为数组值标识符,第三个参数为数组键值标识符*/
/*获取函数左标记*/
$leftSign = self::getFunctionLeftSign( );
$leftSignLen = strLen($leftSign);
/*获取函数右标记*/
$rightSign = self::getFunctionRightSign( );
/*获取函数分隔标记*/
$splitSign = self::getFunctionSplitSign( );
/*获取循环起始标记*/
$for = self::getForTag( );
$parameterStart = searchStr($leftSign, $tag) + $leftSignLen;
$parameterLen = lastSearchStr($rightSign, $tag) - $parameterStart;
$parameter = subStr($tag, $parameterStart, $parameterLen);
$parameters = split($splitSign, $parameter);
$parametersLen = arrayCount($parameters);
for($i = 0; $i < $parametersLen; $i++)
{
if(!self::isVarTag($parameters[$i]))
{
self::errorReport('{$Template}{$Loop}{$Parameters}{$Must}{$Is}{$Var}', 'converForTag("' . $tag . '")', ERROR_PROGRAME);
return(false);
}
}
$for = entry( ) . 'if(!isArray(' . $parameters[0] . '))' . entry( );
$for .= '{' . entry( );
$for .= ' ' . $parameters[0] . ' = array( );' . entry( );
$for .= '}' . entry( ) . entry( );
$for .= 'foreach(' . $parameters[0] . ' as ' . ($parameters[2] ? $parameters[2] . ' => ' . $parameters[1] : $parameters[1]) . ')' . entry( );
return($for);
}
/*是否是循环结束标记(标记名)*/
private function isEndForTag($tag)
{
/*获取循环结束标记*/
$endForTag = self::getEndForTag( );
return(isSameStr(strToLower($tag), $endForTag));
}
/*转换循环结束标记( )*/
private function converEndForTag( )
{
return(entry( ));
}
/*是否是判断起始标记(标记名)*/
private function isIfTag($tag)
{
/*获取函数左标记*/
$leftSign = self::getFunctionLeftSign( );
/*获取循环起始标记*/
$if = self::getIfTag( );
$nameLen = searchStr($leftSign, $tag);
if(!$nameLen)
{
return(false);
}
else if(!isSameStr(strToLower(subStr($tag, 0, $nameLen)), $if))
{
return(false);
}
return(true);
}
/*转换判断起始标记(标记名)*/
private function converIfTag($tag)
{
/*获取函数左标记*/
$leftSign = self::getFunctionLeftSign( );
$leftSignLen = strLen($leftSign);
/*获取函数右标记*/
$rightSign = self::getFunctionRightSign( );
/*获取循环起始标记*/
$if = self::getIfTag( );
$parameterStart = searchStr($leftSign, $tag) + $leftSignLen;
$parameterLen = lastSearchStr($rightSign, $tag) - $parameterStart;
$parameter = subStr($tag, $parameterStart, $parameterLen);
/*获取程序函数左标记*/
$programLeftSign = self::getProgramFunctionLeft( );
/*获取程序函数右标记*/
$programRightSign = self::getProgramFunctionRight( );
$program = entry( ) . 'if' . $programLeftSign . $parameter . $programRightSign . entry( );
return($program);
}
/*是否是否则如果函数标记(标记名)*/
private function isElseIfTag($tag)
{
/*获取函数左标记*/
$leftSign = self::getFunctionLeftSign( );
/*获取否则如果标记*/
$elseIf = self::getElseIfTag( );
$nameLen = searchStr($leftSign, $tag);
if(!$nameLen)
{
return(false);
}
else if(!isSameStr(strToLower(subStr($tag, 0, $nameLen)), $elseIf))
{
return(false);
}
return(true);
}
/*转换否则如果函数(标记名)*/
private function converElseIfTag($tag)
{
/*获取函数左标记*/
$leftSign = self::getFunctionLeftSign( );
$leftSignLen = strLen($leftSign);
/*获取函数右标记*/
$rightSign = self::getFunctionRightSign( );
/*获取否则如果标记*/
$if = self::getElseIfTag( );
$parameterStart = searchStr($leftSign, $tag) + $leftSignLen;
$parameterLen = lastSearchStr($rightSign, $tag) - $parameterStart;
$parameter = subStr($tag, $parameterStart, $parameterLen);
/*获取程序函数左标记*/
$programLeftSign = self::getProgramFunctionLeft( );
/*获取程序函数右标记*/
$programRightSign = self::getProgramFunctionRight( );
$program = entry( ) . 'elseif' . $programLeftSign . $parameter . $programRightSign . entry( );
return($program);
}
/*是否是否则标记(标记名)*/
private function isElseTag($tag)
{
/*获取否则标记*/
$else = self::getElseTag( );
return(isSameStr(strToLower($tag), $else) ? true : false);
}
/*转换否则标记(标记名)*/
private function converElseTag($tag)
{
return(entry( ) . 'else' . entry( ));
}
/*是否是判断结束标记(标记名)*/
private function isEndIfTag($tag)
{
/*获取判断结束标记*/
$endIf = self::getEndIfTag( );
return(isSameStr(strToLower($tag), $endIf) ? true : false);
}
/*转换判断结束标记(标记名)*/
private function converEndIfTag($tag)
{
return(entry( ));
}
/*是否是函数标记(标记名)*/
private function isFunctionTag($tag)
{
/*获取函数左标记*/
$leftSign = self::getFunctionLeftSign( );
/*获取函数右标记*/
$rightSign = self::getFunctionRightSign( );
return(searchStr($leftSign, $tag) < searchStr($rightSign, $tag) ? true : false);
}
/*转换函数标记*/
private function converFunctionTag($tag)
{
/*获取函数左标记*/
$leftSign = self::getFunctionLeftSign( );
$leftSignLen = strLen($leftSign);
/*获取函数右标记*/
$rightSign = self::getFunctionRightSign( );
/*获取函数分隔标记*/
$splitSign = self::getFunctionSplitSign( );
/*获取程序函数左标记*/
$programLeftSign = self::getProgramFunctionLeft( );
/*获取程序函数右标记*/
$programRightSign = self::getProgramFunctionRight( );
/*获取程序函数分隔标记*/
$programSplitSign = self::getProgramFunctionSplit( );
$parameterStart = searchStr($leftSign, $tag);
$name = subStr($tag, 0, $parameterStart);
$parameterEnd = lastSearchStr($rightSign, $tag);
$start = $parameterStart + $leftSignLen;
$parameter = split($splitSign, subStr($tag, $start, $parameterEnd - $start));
$parameterLen = arrayCount($parameter);
for($i = 0; $i < $parameterLen; $i++)
{
if(!self::isVarTag($parameter[$i]))
{
if(!isNumber($parameter[$i]))
{
$parameter[$i] = '\'' . $parameter[$i] . '\'';
}
}
}
$program = $name . $programLeftSign . implode($programSplitSign, $parameter) . $programRightSign;
return($program);
}
/*是否是约定标记(标记名)*/
private function isOrderTag($tag)
{
/*获取约定起始标记*/
$startSign = self::getOrderStartSign( );
/*获取约定结束标记*/
$endSign = self::getOrderEndSign( );
$startSignLen = strLen($startSign);
$endSignLen = strLen($endSign);
$tagStartSign = strToLower(subStr($tag, 0, $startSignLen));
$tagEndSign = strToLower(subStr($tag, $contentLen-$endSignLen));
return((isSameStr($tagStartSign, $startSign) && isSameStr($tagEndSign, $endSign)) ? true : false);
}
/*转换约定标记(标记名)*/
private function converOrderTag($tag)
{
/*获取约定起始标记*/
$startSign = self::getOrderStartSign( );
$startSignLen = strLen($startSign);
/*获取约定结束标记*/
$endSign = self::getOrderEndSign( );
/*获取约定分隔标记*/
$splitSign = self::getOrderSplitSign( );
$splitSignLen = strLen($splitSign);
/*获取程序分隔标记*/
$programSplitSign = self::getProgramSplit( );
/*获取程序变量标识*/
$programVarSign = self::getProgramVar( );
$program = '';
$tagLen = strLen($tag);
$var = false;
$value = false;
$program = entry( );
for($i = $startSignLen; $i < $tagLen; $i++)
{
if(isChar($tag[$i]) && !$var)
{
$program .= $programVarSign;
$var = true;
}
else if(self::isAssignSign($tag[$i]))
{
$program .= $tag[$i];
$value = true;
}
else if(self::isOrderSplitSign(subStr($tag, $i, $splitSignLen)))
{
$program .= $programSplitSign . entry( );
$i += $splitSignLen;
$value = false;
$var = false;
continue;
}
else if(!isNumber($tag[$i]) && $value)
{
$program .= '\'' . $tag[$i] . '\'';
}
else
{
$program .= $tag[$i];
}
}
return($program);
}
/*是否是赋值运算符*/
private function isAssignSign($sign)
{
return(isSameStr($sign, $this->tags['assign']) ? true : false);
}
/*是否是约定分隔符*/
private function isOrderSplitSign($sign)
{
return(isSameStr($sign, $this->tags['order']['split']) ? true : false);
}
/*保存程序(程序内容)*/
private function saveProgram($program)
{
$file = &$this->kernel->object('zxfiles');
$path = self::getProgramPath( );
return($file->save($path, $program));
}
/*模板赋值(模板参数名,值)*/
public function assign($argumentName, $value)
{
/*保存模板参数的值*/
$this->assigns[$argumentName] = $value;
}
/*获取模板参数值*/
public function getAssign($name='')
{
return($name ? $this->assigns[$name] : $this->assigns);
}
/*输出界面( )*/
public function outPut( )
{
/*读取模板参数*/
$arguments = self::getAssign( );
if(isArray($arguments))
{
foreach($arguments as $name => $value)
{
$$name = $value;
}
}
/*如果模板程序文件存在则*/
if(self::programExists( ))
{
$programFile = self::getProgramPath( );
/*输出模板程序文件*/
include($programFile);
}
}
private function errorReport($message, $method, $level)
{
$error = &$this->kernel->object('zxerror');
$error->pop($message, $method, 'zxtemplate', $level);
}
public function __destruct( )
{
}
}
?>[/php] |
| jtql420 | 2008-3-11 01:35 AM |
|
| 没读懂。:( |
| changxiaob | 2008-3-14 05:55 AM |
|
| 太厂了~看的头疼 |
| henanren | 2008-5-7 08:46 AM |
|
| 这是干什么用的 |
| Karl.zeng | 2008-5-10 05:58 AM |
|
| 太长了....看了1/10就没耐心了... |
|
| 哈哈,让我看这代码我也会很没有耐心,这些只是编译代码,原稿代码是一堆汉字(伪代码),之所以会这么长是细分伪代码得出的 |
|
| 赏你三毛钱米饭两毛钱豆腐,另外你再找我10块钱车钱 |
| znznzn333 | 2008-6-24 06:05 AM |
|
| 好诱人 哦 |
|
| 看了前面三行:这不是一个免费程序。再看了第一个函数就没兴趣了。 |
| jiayuwoa | 2008-7-19 07:53 AM |
|
| 不知道要做什么,希望给个完整的再研究一下 |
|
| 是Hoyong网店系统里面废弃的一段代码而已,只是测试下这样的代码方不方便阅读,另外,Hoyong网店系统1.3即将发布,1.3版不仅功能增强而且将要开发源代码 |
Powered by Discuz! Archiver 6.1.0
© 2001-2006 Comsenz Inc.
Processed in 0.047363 second(s), 2 queries |