Index: branches/5.1.x/core/kernel/parser/template_parser.php =================================================================== diff -u -N --- branches/5.1.x/core/kernel/parser/template_parser.php (revision 12127) +++ branches/5.1.x/core/kernel/parser/template_parser.php (revision 0) @@ -1,766 +0,0 @@ -Ses =& $this->Application->recallObject('Session'); - } - - function AddParam($pattern, $value, $dont_sort=0) - { - $this->ForSort[] = Array($pattern, $value); - if (!$dont_sort) //used when mass-adding params, to escape sorting after every new param - $this->SortParams(); //but do sort by default! - } - - //We need to sort params by its name length desc, so that params starting with same word get parsed correctly - function SortParams() - { - uasort($this->ForSort, array ("TemplateParser", "CmpParams")); - -// commented out by Kostja, otherwise when rednerElement is done into var (result_to_var) the other params are reset -// $this->Pattern = Array(); -// $this->Values = Array(); - foreach($this->ForSort as $pair) - { - $this->Pattern[] = $pair[0]; - $this->Values[] = $pair[1]; - } - } - - function CmpParams($a, $b) - { - $a_len = strlen($a[0]); - $b_len = strlen($b[0]); - if ($a_len == $b_len) return 0; - return $a_len > $b_len ? -1 : 1; - } - - function SetParams($params, $for_parsing=true) - { - if (!is_array($params)) $params = Array(); - - $this->ForSort = array(); - $this->Params = $params; - $this->ParamsStack[$this->ParamsRecursionIndex] = $params; - - if (!$for_parsing) return ; - - foreach ($params as $key => $val) { - $this->AddParam('/[{]{0,1}\$'.$key.'[}]{0,1}/i', $val, 1); //Do not sort every time - } - $this->SortParams(); //Sort once after adding is done - } - - /** - * Returns parser parameter value at specified deep level - * - * @param string $name - * @param int $deep_level if greather then 0 then use from ParamsStack - * @return mixed - */ - function GetParam($name, $deep_level = 0) - { - if ($deep_level > 0) { - return isset($this->ParamsStack[$deep_level][$name]) ? $this->ParamsStack[$deep_level][$name] : false; - } - - return isset($this->Params[$name]) ? $this->Params[$name] : false; - } - - /** - * Set's template parser parameter, that could be retrieved from template - * - * @param string $name - * @param mixed $value - */ - function SetParam($name, $value) - { - $this->Params[strtolower($name)] = $value; - $this->AddParam('/[{]{0,1}\$'.$name.'[}]{0,1}/i', $value, $this->FromPreParseCache); - $this->ParamsStack[$this->ParamsRecursionIndex][$name] = $value; - } - - function SetBuffer($body) - { - $this->Buffers[$this->RecursionIndex] = $body; - } - - function GetBuffer() - { - return $this->Buffers[$this->RecursionIndex]; - } - - function GetCode() - { - return $this->Code[$this->RecursionIndex]; - } - - function AppendBuffer($append) - { - $this->Buffers[$this->RecursionIndex] .= $append; - $this->AppendCode( $this->ConvertToCode($append) ); - } - - function AppendOutput($append, $append_code=false) - { - if ($this->SkipMode == parse) { - $this->Output .= $append; //append to Ouput only if we are parsing - if ($append_code) $this->AppendCompiledHTML($append); - } - elseif ($this->SkipMode == skip) { - if ($append_code) $this->AppendCompiledHTML($append); - } - elseif ($this->SkipMode == skip_tags) { - $this->AppendBuffer($append); //append to buffer if we are skipping tags - } - } - - function ConvertToCode($data) - { - $data = str_replace("\\", "\\\\", $data); // escape any "\" - $data = str_replace("'", "\'", $data); // escape "'" - - $code = '$o .= \''. $data .'\';'; - $code = explode("\n", $code); - return $code; - } - - function AppendCode($code, $level_offset=0) - { - if ($this->RecursionIndex+$level_offset <= 0 ) $level_offset = 0; - if (defined('EXPERIMENTAL_PRE_PARSE')) { - if (!isset($this->Code[$this->RecursionIndex+$level_offset])) { - $this->Code[$this->RecursionIndex+$level_offset] = Array(); - } - if (is_array($code)) { - foreach ($code as $line) { - $this->Code[$this->RecursionIndex+$level_offset][] = rtrim($line, "\n")."\n"; - } - } - else { - $this->Code[$this->RecursionIndex+$level_offset][] .= rtrim($code, "\n")."\n"; - } - } - } - - function PrepareCompiledFunction($f_name, $f_body, $add_reference=true) - { - $real_name = 'f_'.abs(crc32($this->TemplateName)).'_'.$f_name; - $real_code = ''; - if (defined('EXPERIMENTAL_PRE_PARSE')) { - // if such function already compiled - if ( isset($this->Application->CompiledFunctions[$f_name]) || - function_exists($real_name) - ) - { - if (!isset($this->Application->CompiledFunctions[$f_name])) { - $real_name = $real_name.'_'; - } - else { - $real_name = $this->Application->CompiledFunctions[$f_name].'_'; - } - } - - if (is_array($f_body)) { - $real_body = ''; - foreach ($f_body as $line) { - if (preg_match('/^\/\*LAMBDA-ONLY\*\//', $line)) continue; - $real_body .= "\t\t".rtrim($line, "\n")."\n"; - }; - $f_body = $real_body; - } - else { - $f_body = preg_replace('/\/\*LAMBDA-ONLY\*\/.*/m', '', $f_body); - } - - $ref = "\t".'$application->PreParsedBlocks[\''.$f_name.'\'] = \''.$real_name.'\';'."\n"; - if ($add_reference) $real_code .= $ref; - $real_code .= 'if (!function_exists(\''.$real_name.'\')) {'."\n"; - $real_code .= "\t".'function '.$real_name.'($params)'."\n\t{\n"; - $real_code .= $f_body; - $real_code .= "\t}\n\n"; - $real_code .= '}'."\n"; - - /*if (defined('DEBUG_MODE') && DEBUG_MODE && defined('DBG_PRE_PARSE') && DBG_PRE_PARSE) { - // this shows newly compiled functions (blocks) - global $debugger; - $f_body = "\t".'function '.$real_name.'($params)'."\n\t{\n".$f_body."\t}\n\n"; - $debugger->appendHTML($debugger->highlightString($f_body)); - }*/ - $this->Application->CompiledFunctions[$f_name] = $real_name; - - return array($real_name, $real_code, $ref); - } - } - - function AppendCompiledFunction($f_name, $f_body) - { - $f = $this->PrepareCompiledFunction($f_name, $f_body); - $this->CompiledBuffer .= $f[1]; - } - - function AppendCompiledCode($code) - { - if (defined('EXPERIMENTAL_PRE_PARSE')) { - if (is_array($code)) { - foreach ($code as $line) { - if (preg_match('/^\/\*LAMBDA-ONLY\*\//', $line)) continue; - $this->CompiledBuffer .= "\t".rtrim($line, "\n")."\n"; - } - } - else { - $this->CompiledBuffer .= $code; - } - $this->CompiledBuffer .= "\t".'echo $o;'."\n\t".'$o = \'\';'."\n"; - } - } - - function AppendCompiledHTML($append) - { - if (defined('EXPERIMENTAL_PRE_PARSE')) { - $this->CompiledBuffer .= '?'.'>'."\n"; - $this->CompiledBuffer .= rtrim($append, "\t"); - $this->CompiledBuffer .= '<'.'?php'."\n"; - } - } - - function ResetCode() - { - $this->Code[$this->RecursionIndex] = Array(); - } - - function FindTag2() - { - $openings = Array('<%' => '%>', ' Array('>', '/>'), ' '>', '' => '', ''); - - $tag_open_pos = false; - foreach ($openings as $an_opening => $closings) { - $pos = strpos($this->Template, $an_opening, $this->Position); - if ($pos !== false && ($tag_open_pos === false || (int) $pos <= (int) $tag_open_pos)) { - $tag_open_pos = $pos; - $open_len = strlen($an_opening); - $opening_tag = $an_opening; - $tag_closings = $closings; - } - } - - if ($tag_open_pos === false) { //If no tags left - adding all other data - $this->AppendOutput(substr($this->Template, $this->Position), true); - return false; - } - - //Adding all data before tag open - $this->AppendOutput(substr($this->Template, $this->Position, $tag_open_pos - $this->Position), true); - - if (is_array($tag_closings)) { - $tag_close_pos = false; - foreach ($tag_closings as $a_closing) { - $pos = strpos($this->Template, $a_closing, $tag_open_pos); - if ($pos !== false && ($tag_close_pos === false || (int) $pos <= (int) $tag_close_pos)) { - $tag_close_pos = $pos; - $closing_tag = $a_closing; - } - } - } - elseif ($opening_tag == '') { - $closing_tag = ''; - $tag_close_pos = $tag_open_pos + $open_len; - } - else { - $closing_tag = $tag_closings; - $tag_close_pos = strpos($this->Template, $closing_tag, $tag_open_pos); - } - $close_len = strlen($closing_tag); - - - // Cutting trailing line-breaks after tags (same way PHP does it) - if (substr($this->Template, $tag_close_pos+$close_len, 2) == "\r\n") { - $this->Template = substr_replace($this->Template, '', $tag_close_pos, 2); - } - elseif (substr($this->Template, $tag_close_pos+$close_len, 1) == "\n") { - $this->Template = substr_replace($this->Template, '', $tag_close_pos, 1); - } - - - //Cutting out the tag itself - $tag = substr($this->Template, $tag_open_pos + $open_len, $tag_close_pos - $tag_open_pos - $open_len); - - - if ($opening_tag == '') { //empty closing means old style in-portal if .... - $tag = 'm:endif'; - } - - if ($opening_tag == 'Params, 'PrefixSpecial'); - $tag = $prefix.$tag.' _auto_prefix_="1"'; - } - - // temporary - for backward compatability with in-portal style if - $compat_tags = array('m_if', 'm_DefineElement', 'm_Capture', 'm_RenderElement'); - if ($opening_tag == '' && !in_array($tag_part, $compat_tags)) { - if (strpos($the_tag, ' ') !== false) { - list($function, $params) = explode(' ', $the_tag, 2); - } - else { - $function = $the_tag; - $params = ''; - } - $tag = 'm:if prefix="'.$prefix.'" function="'.$function.'" '.$params; - } - - if ($opening_tag == ''); - } - else { - $this->AppendOutput(''); - $this->AppendCompiledHTML(''); - } - $tag = '__COMMENT__'; - } - - if ($closing_tag == '>') $tag .= ' _short_closing_="1"'; - - $this->Position = $tag_close_pos + $close_len; - return $tag; - } - - function CurrentLineNumber() - { - return substr_count(substr($this->Template, 0, $this->Position), "\n")+1; - } - - function SkipModeName() - { - switch ($this->SkipMode) { - case skip: return 'skip'; - case skip_tags: return 'skip_tags'; - case parse: return 'parse'; - } - } - - /** - * Recursive mkdir - * - * @param string $dir - * @param string $base_path base path to directory where folders should be created in - */ - function CheckDir($dir, $base_path = '') - { - if (file_exists($dir)) { - return; - } - else { - // remove $base_path from beggining because it is already created during install - $dir = preg_replace('/^'.preg_quote($base_path.'/', '/').'/', '', $dir, 1); - $segments = explode('/', $dir); - $cur_path = $base_path; - - foreach ($segments as $segment) { - // do not add leading / for windows paths (c:\...) - $cur_path .= preg_match('/^[a-zA-Z]{1}:/', $segment) ? $segment : '/'.$segment; - if (!file_exists($cur_path)) { - mkdir($cur_path); - } - } - } - } - - function ParseTemplate($name, $pre_parse = 1, $params=array(), $silent=0) - { - $this->FromPreParseCache = false; - if ($this->GetParam('from_inportal')) $pre_parse = 0; - if ($pre_parse) { - $pre_parsed = $this->Application->TemplatesCache->GetPreParsed($name); - if ($pre_parsed === false) { - // template not found -> don't compile - return ''; - } - - if ($pre_parsed && $pre_parsed['active']) { // active means good (not expired) pre-parsed cache - $this->FromPreParseCache = true; - $this->SetParams($params, 0); // 0 to disable params sorting and regexp generation - not needed when processing pre-parsed - ob_start(); - if ($pre_parsed['mode'] == 'file') { - $this->TemplateName = str_replace(FULL_PATH, '', realpath($pre_parsed['fname'])); - include($pre_parsed['fname']); - } - else { - eval('?'.'>'.$pre_parsed['content']); - } - $output = ob_get_contents(); - ob_end_clean(); - } - else { - $this->SetParams($params); - - $this->CompiledBuffer .= '<'.'?php'."\n"; - $this->CompiledBuffer .= 'global $application;'."\n"; - - $this->CompiledBuffer .= '$params =& $application->Parser->Params;'."\n"; - $this->CompiledBuffer .= 'extract($params);'."\n"; - - $this->CompiledBuffer .= '$o = \'\';'."\n"; - - $body = $this->Application->TemplatesCache->GetTemplateBody($name, $silent); - $this->TemplateName = $name; - $output = $this->NewParse($body, $name); - - $this->CompiledBuffer .= '?'.'>'."\n"; - - if (defined('SAFE_MODE') && SAFE_MODE) { - if (!isset($conn)) $conn =& $this->Application->GetADODBConnection(); - $conn->Query('REPLACE INTO '.TABLE_PREFIX.'Cache (VarName, Data, Cached) VALUES ('.$conn->qstr($pre_parsed['fname']).','.$conn->qstr($this->CompiledBuffer).','.adodb_mktime().')'); - } - else { - $compiled = fopen($pre_parsed['fname'], 'w'); - fwrite($compiled, $this->CompiledBuffer); - fclose($compiled); - } - - } - if ( !$this->GetParam('from_inportal') && strpos($output, 'Application->recallObject('Inp1Parser'); -// $name = $this->Application->TemplatesCache->GetTemplateFileName($name) . '-block:' . $name; // may be is needed (by Alex) - $output = $inp1_parser->Parse($name, $output); - } - return $output; - } - - // pre-parse is OFF - $this->SetParams($params); - return $this->NewParse($this->Application->TemplatesCache->GetTemplateBody($name), $name, $pre_parse); - } - - function NewParse($template, $name='unknown', $pre_parse = 1) - { - $this->Template = $template; - $this->TemplateName = $name; - $this->Position = 0; - $this->Output = ''; - $this->TagHolder = new MyTagHolder(); - - $has_inp_tags = false; - - if (!getArrayValue($this->Params, 'PrefixSpecial')) { - $this->Params['PrefixSpecial'] = '$PrefixSpecial'; - } - - //While we have more tags - while ($tag_data = $this->FindTag2()) - { - if ($tag_data == '__COMMENT__') continue; - //Create tag object from passed tag data - if( $this->Application->isDebugMode() && constOn('DBG_SHOW_TAGS') ) - { - global $debugger; - $debugger->appendHTML('mode: '.$this->SkipModeName().' tag '.$debugger->highlightString($tag_data).' in '.$debugger->getFileLink($debugger->getLocalFile(FULL_PATH.THEMES_PATH.'/'.$this->TemplateName).'.tpl', $this->CurrentLineNumber(), '', true)); - } - $tag =& $this->TagHolder->GetTag($tag_data, $this); - - if (!$this->CheckRecursion($tag)) //we do NOT process closing tags - { - $tag->Process(); - } - } - return $this->Output; - } - - function Parse($template, $name='unknown', $pre_parse = 1) - { - $this->Template = $template; - $this->TemplateName = $name; - $this->Position = 0; - $this->Output = ''; - $this->TagHolder = new MyTagHolder(); - - $has_inp_tags = false; - - if ($this->GetParam('from_inportal')) $pre_parse = 0; - - if (defined('EXPERIMENTAL_PRE_PARSE') && $pre_parse) { - $fname = $this->Application->TemplatesCache->GetRealFilename($this->TemplateName).'.php'; - - $fname = str_replace(FULL_PATH, FULL_PATH.'/kernel/cache', $fname); - - if (!defined('SAFE_MODE') || !SAFE_MODE) { - $this->CheckDir(dirname($fname), FULL_PATH.'/kernel/cache'); - } - - $tname = $this->Application->TemplatesCache->GetRealFilename($this->TemplateName).'.tpl'; - $output = ''; - $is_cached = false; - ob_start(); - if (defined('SAFE_MODE') && SAFE_MODE) { - $conn =& $this->Application->GetADODBConnection(); - $cached = $conn->GetRow('SELECT * FROM '.TABLE_PREFIX.'Cache WHERE VarName = "'.$fname.'"'); - if ($cached !== false && $cached['Cached'] > filemtime($tname)) { - eval('?'.'>'.$cached['Data']); - $is_cached = true; - } - } - else { - if (file_exists($fname) && file_exists($tname) && filemtime($fname) > filemtime($tname)) { - include($fname); - $is_cached = true; - } - } - $output = ob_get_contents(); - ob_end_clean(); - - if ( $is_cached && !$this->GetParam('from_inportal') ) { - if ( strpos($output, 'Application->recallObject('Inp1Parser'); - $output = $inp1_parser->Parse($name, $output); - } - return $output; - } - - $this->CompiledBuffer .= '<'.'?php'."\n"; - $this->CompiledBuffer .= 'global $application;'."\n"; - - $this->CompiledBuffer .= '$params =& $application->Parser->Params;'."\n"; - $this->CompiledBuffer .= 'extract($params);'."\n"; - - $this->CompiledBuffer .= '$o = \'\';'."\n"; - } - - if (!getArrayValue($this->Params, 'PrefixSpecial')) { - $this->Params['PrefixSpecial'] = '$PrefixSpecial'; - } - - //While we have more tags - while ($tag_data = $this->FindTag2()) - { - if ($tag_data == '__COMMENT__') continue; - //Create tag object from passed tag data - if( $this->Application->isDebugMode() && constOn('DBG_SHOW_TAGS') ) - { - global $debugger; - $debugger->appendHTML('mode: '.$this->SkipModeName().' tag '.$debugger->highlightString($tag_data).' in '.$debugger->getFileLink($debugger->getLocalFile(FULL_PATH.THEMES_PATH.'/'.$this->TemplateName).'.tpl', $this->CurrentLineNumber(), '', true)); - } -// $tag = new MyTag($tag_data, $this); - $tag =& $this->TagHolder->GetTag($tag_data, $this); - - if (!$this->CheckRecursion($tag)) //we do NOT process closing tags - { - $tag->Process(); - } - } - - if ( !$this->GetParam('from_inportal') ) { - if ( strpos($this->Output, 'Application->recallObject('Inp1Parser'); - $this->Output = $inp1_parser->Parse($name, $this->Output); - $has_inp_tags = true; - } - } - - - if (defined('EXPERIMENTAL_PRE_PARSE') && $pre_parse && !$has_inp_tags) { -// $this->CompiledBuffer .= 'echo $o;'."\n"; - $this->CompiledBuffer .= '?'.'>'."\n"; - - if (defined('SAFE_MODE') && SAFE_MODE) { - if (!isset($conn)) $conn =& $this->Application->GetADODBConnection(); - $conn->Query('REPLACE INTO '.TABLE_PREFIX.'Cache (VarName, Data, Cached) VALUES ('.$conn->qstr($fname).','.$conn->qstr($this->CompiledBuffer).','.adodb_mktime().')'); - } - else { - $compiled = fopen($fname, 'w'); - fwrite($compiled, $this->CompiledBuffer); - fclose($compiled); - } - } - - return $this->Output; - } - - function ParseBlock($params, $force_pass_params=0, $as_template=false) - { - if( $this->Application->isDebugMode() && constOn('DBG_SHOW_TAGS') ) - { - global $debugger; - $debugger->appendHTML('ParseBlock '.$params['name'].' pass_params is '.$params['pass_params'].' force is '.$force_pass_params.' in '.$debugger->getFileLink($debugger->getLocalFile(FULL_PATH.THEMES_PATH.'/'.$this->TemplateName).'.tpl', $this->CurrentLineNumber(), '', true)); - - } - /*if ( $this->Application->isDebugMode() && constOn('DBG_PRE_PARSE') ) { - global $debugger; - $debugger->CurrentPreParsedBlock = $params['name']; - }*/ - if (defined('EXPERIMENTAL_PRE_PARSE')) { - $this->MainParser = false; - if (isset($this->Application->PreParsedBlocks[$params['name']]) ) { - - if ($this->ParamsRecursionIndex == 0) { - $this->ParamsStack[$this->ParamsRecursionIndex] = $this->Params; - } - - if (isset($params['pass_params']) || $force_pass_params) { - $pass_params = array_merge($this->ParamsStack[$this->ParamsRecursionIndex], $params); - } - else { - $pass_params = $params; - } - - $this->ParamsStack[++$this->ParamsRecursionIndex] = $pass_params; - $this->Params = $pass_params; - - $f = $this->Application->PreParsedBlocks[$params['name']]; - -// $this->ParamsRecursionIndex--; - - //$this->SetParams($params); - if( !isset($pass_params['PrefixSpecial']) && isset($pass_params['prefix']) ) $pass_params['PrefixSpecial'] = $pass_params['prefix']; - - $ret = $f($pass_params); - - if (isset($params['return_params']) && $params['return_params']) { - $this->ParamsStack[$this->ParamsRecursionIndex - 1] = array_merge($this->ParamsStack[$this->ParamsRecursionIndex - 1], $this->ParamsStack[$this->ParamsRecursionIndex]); - } - - unset($this->ParamsStack[$this->ParamsRecursionIndex--]); - $this->Params = $this->ParamsStack[$this->ParamsRecursionIndex]; - $this->MainParser = true; - return defined('DBG_DECORATE_BLOCKS') && DBG_DECORATE_BLOCKS ? $this->decorateBlock($ret, $pass_params) : $ret; - } - } - - $BlockParser =& $this->Application->makeClass('TemplateParser'); - if (isset($params['pass_params']) || $force_pass_params) { - $BlockParser->SetParams(array_merge($this->Params, $params)); - } - else - $BlockParser->SetParams($params); - $this->Application->Parser =& $BlockParser; - if (!isset($params['name'])) { - trigger_error('***Error: Block name not passed to ParseBlock', E_USER_ERROR); - } - $templates_cache =& $this->Application->recallObject('TemplatesCache'); - - $template_name = $as_template ? $params['name'] : $templates_cache->GetTemplateFileName($params['name']) . '-block:'.$params['name']; - - $silent = getArrayValue($params, 'from_inportal') && !defined('DBG_TEMPLATE_FAILURE'); - - $o = $BlockParser->Parse( - $templates_cache->GetTemplateBody($params['name'], $silent), - $template_name - ); - if (getArrayValue($params, 'BlockNoData') && !$BlockParser->DataExists) { - $template_name = $as_template ? $params['BlockNoData'] : $templates_cache->GetTemplateFileName($params['BlockNoData']) . '-block:'.$params['BlockNoData']; - $o = $BlockParser->Parse( - $templates_cache->GetTemplateBody($params['BlockNoData'], $silent), - $template_name - ); - } - - $this->Application->Parser =& $this; - $this->Application->Parser->DataExists = $this->Application->Parser->DataExists || $BlockParser->DataExists; - - return $o; - } - - function decorateBlock(&$block_content, $block_params) - { - if (preg_match('/^(\s*)(.*)<\/td>(.*)$/is', $block_content, $regs)) { - // block with td -> put div inside td - return $regs[1].'
'.$regs[3].'
'.$regs[4]; - } - - return '
'.$block_content.'
'; - } - - function Recurve(&$tag) - { - $this->Recursion[++$this->RecursionIndex] =& $tag; - } - - function CheckRecursion(&$tag) - { - if ($this->RecursionIndex > 0) { //If we are inside the recursion - if ($this->Recursion[$this->RecursionIndex]->CheckRecursion($tag)) { //If we can close this recursion - unset($this->Recursion[$this->RecursionIndex--]); //unsetting current recursion level and decreasing it at the same time - return true; //we should inform not to process closing tag - } - } - return false; - } - - function SetSkipMode($mode) - { - $this->SkipMode = $mode; - } -} - -?> \ No newline at end of file