StopTag = $tag;
}
function StoreSkipMode()
{
$this->SkipMode = $this->Parser->SkipMode;
}
function RestoreSkipMode()
{
$this->Parser->SetSkipMode($this->SkipMode);
}
function RestoreThisLevelSkipMode()
{
$this->SkipMode = $this->Parser->Recursion[$this->Parser->RecursionIndex]->SkipMode;
}
function SuggestSkipMode($mode)
{
if ($mode >= 1) //if we need to skip - always forcing it
$this->Parser->SetSkipMode($mode);
else { //if we need to turn of skipping
if ($this->SkipMode == parse) //check if initially skipping was off
$this->Parser->SetSkipMode(parse); //set it to off only then
}
}
function GetLogic()
{
if ($this->Parser->SkipMode != parse) {
$this->Logic = false;
return;
}
$check = $this->GetParam('check');
if ($check) {
if (strpos($check, '_') !== false) {
list($prefix, $function) = explode('_', $check, 2);
}
else {
$function = $check;
$prefix = $this->Parser->GetParam('PrefixSpecial');
}
}
else {
$prefix = $this->GetParam('prefix');
$function = $this->GetParam('function');
}
$this->NP['prefix'] = $prefix;
$this->NP['function'] = $function;
$inverse = $this->GetParam('inverse');
if ($prefix !== false) {
$tag =& new Tag('', $this->Parser);
$tag->Tag = $function;
$tmp = $this->Application->processPrefix($prefix);
$tag->Processor = $tmp['prefix'];
$tag->Prefix=$tmp['prefix'];
$tag->Special=$tmp['special'];
$tag->NamedParams = $this->NP;
$this->Logic = $tag->DoProcessTag();
// echo " this->Logic : ".$this->Logic."
";
}
else
{
$this->Logic = $function;
}
if($inverse) $this->Logic = !$this->Logic;
}
function Process()
{
switch ($this->Tag) {
case 'if':
case 'ifnot':
$this->GetLogic();
$this->SetStopTag('endif'); //This recursion level should end when 'endif' is found
$this->Parser->Recurve($this); //Saving current tag in parser recursion array
$this->StoreSkipMode(); //Storing initial SkipMode
if ($this->Logic) {
$this->SuggestSkipMode(parse); //suggest we parse it
}
else {
$this->SuggestSkipMode(skip); //suggest we don't parse it
}
break;
case 'elseif':
$if_logic = $this->Parser->Recursion[$this->Parser->RecursionIndex]->Logic;
if (!$if_logic) { //if IF or ELSEIF above have not worked
$this->GetLogic();
if ($this->Logic) { //ELSEIF should run
$this->Parser->Recursion[$this->Parser->RecursionIndex]->Logic = $this->Logic; //To escape running ELSE or ELSEIF below
$this->SuggestSkipMode(parse);
}
else { //ELSEIF should NOT run
$this->SuggestSkipMode(skip);
}
}
else //IF or ELSEIF above HAVE worked - this ELSEIF should NOT run
$this->SuggestSkipMode(skip);
break;
case 'else':
$if_logic = $this->Parser->Recursion[$this->Parser->RecursionIndex]->Logic;
$this->RestoreThisLevelSkipMode();
if (!$if_logic) { //IF was false - ELSE should run
$this->SuggestSkipMode(parse);
}
else { //IF was true - ELSE should not run
$this->SuggestSkipMode(skip);
}
break;
}
}
function CheckRecursion(&$tag)
{
if ($this->CheckEndRecursion($tag)) {
if (defined('EXPERIMENTAL_PRE_PARSE')) {
if ($tag->Tag == 'if' || $tag->Tag == 'endif') {
$this->Parser->AppendCompiledCode('}');
$this->Parser->ResetCode();
}
}
$this->RestoreSkipMode(); //Restoring original SkipMode
return true;
}
else {
if (defined('EXPERIMENTAL_PRE_PARSE')) {
// && ($tag->Tag != 'RenderElement' && isset($tag->NP['_short_closing_']))
if ($tag->Tag != 'block' && $tag->Tag != 'DefineElement' && $tag->Tag != 'Capture' && !($tag->Tag == 'RenderElement' && isset($tag->NP['_short_closing_']))) {
$this->Parser->AppendCode($tag->GetCode());
}
// $this->Parser->AppendCompiledCode( $tag->GetCode() );
}
}
return false;
}
function CheckEndRecursion(&$tag)
{
if ($tag->GetParam('_closing_tag_') == 1 && $tag->Tag == $this->Tag) {
return true;
}
return ($tag->Tag == $this->StopTag); //Tag matches StopTag we are waiting for to close current recursion
}
}
class BlockTag extends ConstructTag {
var $BlockName = '';
var $InsideBlock = 0;
function Process()
{
switch ($this->Tag) {
case 'block':
case 'DefineElement':
case 'RenderElement':
if ($this->Tag == 'DefineElement') {
$this->SetStopTag('end_define'); //This recursion level should end when 'blockend' is found
}
else {
$this->SetStopTag('blockend'); //This recursion level should end when 'blockend' is found
}
if ($this->Tag == 'RenderElement') {
$this->NP['name'] = '__lambda_element_'.$this->Application->LambdaElements++;
$RenderTag =& new Tag($this->TagData.' name="'.$this->NP['name'].'"', $this->Parser);
$this->Parser->AppendCode($RenderTag->GetCode());
}
$this->Parser->Recurve($this); //Saving current tag in parser recursion array
$this->Parser->SetBuffer('');
$this->BlockName = $this->NP['name']; //Stroing BlockName
if (isset($this->NP['args']) ) {
$this->Parser->Args = explode(',', $this->NP['args']);
}
$this->StoreSkipMode();
$this->SuggestSkipMode(skip_tags); //We need to skip tags from now
break;
}
}
function CheckRecursion(&$tag)
{
if (parent::CheckRecursion($tag)) { //if endtag matches (SkipMode would be restored then)
//Creating template from buffer
//if (defined('EXPERIMENTAL_PRE_PARSE') && isset($this->Application->PreParsedBlocks[$this->BlockName])) return true;
$template = new Template();
$template->SetBody($this->Parser->GetBuffer());
//Adding template to application' cache
$this->Application->TemplatesCache->SetTemplate($this->BlockName, $template, $this->Parser->TemplateName);
if (defined('EXPERIMENTAL_PRE_PARSE')) {
$code = $this->Parser->GetCode();
/*if ($this->Parser->UsedProcessors) {
array_unshift($code, '$application->CheckProcessors(array("'.implode('", "', $this->Parser->UsedProcessors).'"));');
}
$this->Parser->UsedProcessors = null;*/
array_unshift($code, '$o = \'\';');
array_unshift($code, '$application->Parser->SetParams($params, false);');
array_unshift($code, '$application =& kApplication::Instance();');
array_unshift($code, 'extract($params);');
$defaults = '$defaults = Array(';
foreach ($this->NP as $name => $val) {
if ($name == 'name') continue;
$defaults .= '"'.$name.'" => "'.str_replace('"', '\"', $val).'",';
}
$defaults .= ');';
array_unshift($code, '$params = array_merge_recursive2($defaults, $params);');
array_unshift($code, $defaults);
$code[] = 'return $o;';
global $debugger;
$dbg_functions = $this->Application->isDebugMode() && constOn('DBG_PRINT_PREPARSED');
$f_body = '';
//echo "
"; $l = 0; if ($dbg_functions) echo "function ".$this->BlockName." {"; //caching func body $this->Application->PreParsedCache[$this->BlockName] = $f_body; $compile_body = preg_replace('/\/\*COMPILE-ONLY\*\/.*/m', '', $f_body); $func = create_function('$params', $compile_body); $this->Application->PreParsedBlocks[$this->BlockName] = $func; $this->Parser->Args = null; $this->Parser->ResetCode(); $real_name = $this->Parser->AppendCompiledFunction($this->BlockName, $f_body); if ($this->Tag == 'RenderElement') { $RenderTag =& new Tag($this->TagData.' name="'.$this->BlockName.'"', $this->Parser); // $this->Parser->AppendCompiledCode($RenderTag->GetCode()); // for compilation run $RenderTag->Process(); } } return true; } else { // append the tag itself to the block - while in block, we check every tag to be 'blockend' // if it is not - we need to append the tag to the buffer, which we'll parse later in 'parse_block' //if ($tag->Tag != 'block') { if (defined('EXPERIMENTAL_PRE_PARSE') && isset($this->Application->PreParsedBlocks[$this->BlockName])) { return; } if (defined('EXPERIMENTAL_PRE_PARSE')) { // $this->Parser->AppendCode($tag->GetCode()); } else { $this->Parser->AppendOutput($tag->GetFullTag()); } //} return false; } } } class CaptureTag extends ConstructTag { var $VarName = null; var $Mode = CM_LATE_PARSE; function Process() { switch ($this->Tag) { case 'Capture': $this->Parser->Recurve($this); //Saving current tag in parser recursion array $this->Parser->SetBuffer(''); $this->VarName = $this->NP['to_var']; //Stroing BlockName $this->StoreSkipMode(); if (isset($this->NP['mode']) && $this->NP['mode'] == 'parse_now') { $this->Mode = CM_PARSE; } $this->SuggestSkipMode(skip_tags); break; } } function RunCapture($f, $func, $cur_lambda) { $code = array(); $code[] = '/*COMPILE-ONLY*/ '.$f[2]; $code[] = '/*LAMBDA-ONLY*/ $application->PreParsedBlocks[\'capture_'.$this->VarName.'\'] = $application->PreParsedBlocks[\'capture_'.$this->VarName.$cur_lambda.'\'];'; $code[] = '$__f = $application->PreParsedBlocks[\'capture_'.$this->VarName.'\'];'; $code[] = '$application->Parser->SetParam(\''.$this->VarName.'\', $__f(array())'.');'; $code[] = '$'.$this->VarName.' = $application->Parser->GetParam(\''.$this->VarName.'\');'; $code[] = '$params[\''.$this->VarName.'\'] = $'.$this->VarName.';'; if ($this->Parser->RecursionIndex > 1) { $this->Parser->AppendCode($code, -1); } else { $this->Application->Parser->SetParam($this->VarName, $func(array())); $this->Parser->AppendCompiledCode($code); } } function CheckRecursion(&$tag) { if (parent::CheckRecursion($tag)) { //if endtag matches (SkipMode would be restored then) $f_code = $this->Parser->GetCode(); array_unshift($f_code, '$o = \'\';'); array_unshift($f_code, '$application =& kApplication::Instance();'); $f_code[] = 'return $o;'; $f = $this->Parser->PrepareCompiledFunction('capture_'.$this->VarName, $f_code, false); $f_code = trim(join("\n\t", $f_code)); $func = create_function('$params', $f_code); $this->Application->PreParsedBlocks['capture_'.$this->VarName] = $func; $cur_lambda = $this->Application->LambdaElements++; $this->Application->PreParsedBlocks['capture_'.$this->VarName.$cur_lambda] = $func; $this->Parser->AppendCompiledCode($f[1]); if ($this->Mode == CM_PARSE) { $this->RunCapture($f, $func, $cur_lambda); } elseif ($this->Mode == CM_LATE_PARSE) { $code = array(); $code[] = '/*COMPILE-ONLY*/ '.$f[2]; $code[] = '/*LAMBDA-ONLY*/ $application->PreParsedBlocks[\'capture_'.$this->VarName.'\'] = $application->PreParsedBlocks[\'capture_'.$this->VarName.$cur_lambda.'\'];'; $code[] = '$application->LateParsed[\''.$this->VarName.'\'] = '.$cur_lambda.';'; if ($this->Parser->RecursionIndex > 1) { $this->Parser->AppendCode($code, -1); } else { $this->Parser->AppendCompiledCode($code); } $this->Application->LateParsed[$this->VarName] = $cur_lambda; } $this->Parser->ResetCode(); return true; } return ($tag->Tag == $this->StopTag); //Tag matches StopTag we are waiting for to close current recursion } } ?>
"; foreach ($code as $line) { $l++; if ($dbg_functions) { echo $l.' '.$debugger->highlightString(trim($line)."\n", true); } $f_body .= "\t\t".rtrim($line, "\n")."\n"; } if ($dbg_functions) echo "} // function ".$this->BlockName." end
"; //echo "