Index: branches/RC/core/kernel/nparser/nparser.php =================================================================== diff -u -N -r10669 -r11067 --- branches/RC/core/kernel/nparser/nparser.php (.../nparser.php) (revision 10669) +++ branches/RC/core/kernel/nparser/nparser.php (.../nparser.php) (revision 11067) @@ -2,6 +2,9 @@ include_once(KERNEL_PATH.'/nparser/ntags.php'); +define('TAG_NAMESPACE', 'inp2:'); +define('TAG_NAMESPACE_LENGTH', 5); + class NParser extends kBase { var $Stack = array(); @@ -13,31 +16,40 @@ var $Params = array(); var $ParamsStack = array(); var $ParamsLevel = 0; - + var $Definitions = ''; var $Elements = array(); // holds dynamic elements to function names mapping during execution + + /** + * Holds location of element definitions inside templates. + * key - element function name, value - array of 2 keys: {from_pos, to_pos} + * + * @var Array + */ + var $ElementLocations = Array (); + var $DataExists = false; - + var $TemplateName = null; var $TempalteFullPath = null; - + var $CachePointers = array(); var $Cachable = array(); - - + + function NParser() { parent::kBase(); } - function Compile($pre_parsed) + function Compile($pre_parsed, $template_name = 'unknown') { $data = file_get_contents($pre_parsed['tname']); - $this->CompileRaw($data, $pre_parsed['tname']); + $this->CompileRaw($data, $pre_parsed['tname'], $template_name); // saving compiled version $compiled = fopen($pre_parsed['fname'], 'w'); @@ -58,19 +70,20 @@ return ob_get_clean(); } - function CompileRaw($data, $t_name) + function CompileRaw($data, $t_name, $template_name = 'unknown') { $code = "extract (\$_parser->Params);\n"; - + $code .= "\$_parser->ElementLocations['{$template_name}'] = Array('file' => '{$t_name}', 'start_pos' => 0, 'end_pos' => " . strlen($data) . ");\n"; + // $code .= "__@@__DefinitionsMarker__@@__\n"; - + // $code .= "if (!\$this->CacheStart('".abs(crc32($t_name))."_0')) {\n"; $this->Buffers[0] = '\n"; $this->Cacheable[0] = true; $this->Definitions = ''; // finding all the tags - $reg = '(.*?)(<[\\/]?)inp2:([^>]*?)([\\/]?>)(\r\n){0,1}'; + $reg = '(.*?)(<[\\/]?)' . TAG_NAMESPACE . '([^>]*?)([\\/]?>)(\r\n){0,1}'; preg_match_all('/'.$reg.'/s', $data, $results, PREG_SET_ORDER + PREG_OFFSET_CAPTURE); $this->InsideComment = false; @@ -80,6 +93,7 @@ 'tag' => $tag_data[3][0], 'closing' => $tag_data[4][0], 'line' => substr_count(substr($data, 0, $tag_data[2][1]), "\n")+1, + 'pos' => $tag_data[2][1], 'file' => $t_name, ); @@ -187,6 +201,7 @@ opened at line '.$opening_tag['line'].')', $tag['file'], $tag['line']); return false; } + $o .= $this->Stack[$this->Level]->Close($tag); // DO NOT use $this->Level-- here because it's used inside Close $this->Level--; } @@ -213,12 +228,12 @@ $this->Buffers[$this->Level] .= $o; return true; } - + function GetPointer($tag) { return abs(crc32($tag['file'])).'_'.$tag['line']; } - + function BreakCache($code, $pointer, $condition='') { return "\$_parser->CacheEnd();\n}\n" . $code."\nif ( !\$_parser->CacheStart('{$pointer}'" . ($condition ? ", {$condition}" : '') . ") ) {\n"; @@ -280,7 +295,7 @@ } if (!$pre_parsed || !$pre_parsed['active'] || defined('DBG_NPARSER_FORCE_COMPILE') && DBG_NPARSER_FORCE_COMPILE) { $inc_parser = new NParser(); - if (!$inc_parser->Compile($pre_parsed)) return false; + if (!$inc_parser->Compile($pre_parsed, $t)) return false; } return $pre_parsed; } @@ -307,7 +322,7 @@ $this->TemplateName = $backup_template; $this->TempalteFullPath = $backup_fullpath; - + return $output; } @@ -373,9 +388,9 @@ unset($params['default_element']); return $this->ParseBlock($params, $pass_params); } - + $original_params = $params; - + if ($pass_params || isset($params['pass_params'])) $params = array_merge($this->Params, $params); $this->PushParams($params); $data_exists_bak = $this->DataExists; @@ -390,7 +405,14 @@ if (!array_key_exists($params['name'], $this->Elements)) { $pre_parsed = $this->Application->TemplatesCache->GetPreParsed($params['name']); if ($pre_parsed) { - return $this->IncludeTemplate($params); + $ret = $this->IncludeTemplate($params); + + if (array_key_exists('no_editing', $params) && $params['no_editing']) { + // when individual render element don't want to be edited + return $ret; + } + + return defined('DBG_DECORATE_BLOCKS') && DBG_DECORATE_BLOCKS ? $this->DecorateBlock($ret, $params, true) : $ret; } if ($this->Application->isDebugMode()) { @@ -411,32 +433,61 @@ $this->CheckNoData($ret, $params); $this->DataExists = $data_exists_bak || $this->DataExists; - + if (isset($original_params['cache_timeout'])) { $this->CacheSet($this->FormCacheKey('element_'.$original_params['name']), $ret, $original_params['cache_timeout']); } - + + if (array_key_exists('no_editing', $params) && $params['no_editing']) { + // when individual render element don't want to be edited + return $ret; + } + return defined('DBG_DECORATE_BLOCKS') && DBG_DECORATE_BLOCKS ? $this->DecorateBlock($ret, $params) : $ret; } - - function DecorateBlock($block_content, $block_params) + + function DecorateBlock($block_content, $block_params, $is_template = false) { - if (preg_match('/^(\s*)(.*)<\/td>(.*)$/is', $block_content, $regs)) { - // block with td -> put div inside td - return $regs[1].'
'.$regs[3].'
'.$regs[4]; + static $used_ids = Array (); + + $block_name = $block_params['name']; + $function_name = $is_template ? $block_name : $this->Elements[$block_name]; + $element_location = $this->ElementLocations[$function_name]; + + // ensure unique id for every div (used from print lists) + $container_num = 1; + $container_id = 'parser_block[' . $function_name . ']'; + while (in_array($container_id . '_' . $container_num, $used_ids)) { + $container_num++; } - return '
'.$block_content.'
'; + $container_id .= '_' . $container_num; + $used_ids[] = $container_id; + + // prepare parameter string + $param_string = "$block_name:$function_name:{$element_location['file']}:{$element_location['start_pos']}:{$element_location['end_pos']}"; + $block_editor = '
+ edit
+ %s +
'; + + // 1 - text before, 2 - open tag, 3 - open tag attributes, 4 - content inside tag, 5 - closing tag, 6 - text after closing tag + if (preg_match('/^(\s*)<(td|span)(.*?)>(.*)<\/(td|span)>(.*)$/is', $block_content, $regs)) { + // div inside span -> put div outside span + return $regs[1] . '<' . $regs[2] . ' ' . $regs[3] . '>' . str_replace('%s', $regs[4], $block_editor) . '' . $regs[6]; + } + + return str_replace('%s', $block_content, $block_editor); } function IncludeTemplate($params, $silent=null) { $t = is_array($params) ? $this->SelectParam($params, 't,template,block,name') : $params; - + if (isset($params['cache_timeout']) && ($ret = $this->CacheGet('template:'.$t))) { return $ret; } - + $t = eregi_replace("\.tpl$", '', $t); $data_exists_bak = $this->DataExists; $this->DataExists = false; @@ -451,11 +502,11 @@ $this->CheckNoData($ret, $params); $this->DataExists = $data_exists_bak || $this->DataExists; - + if (isset($params['cache_timeout'])) { $this->CacheSet('template:'.$t, $ret, $params['cache_timeout']); } - + return $ret; } @@ -471,27 +522,27 @@ } } } - + function CacheGet($name) { if (!$this->Application->ConfigValue('SystemTagCache')) return false; return $this->Application->CacheGet($name); } - + function CacheSet($name, $value, $expiration=0) { if (!$this->Application->ConfigValue('SystemTagCache')) return false; return $this->Application->CacheSet($name, $value, $expiration); } - + function FormCacheKey($element, $file=null, $add_prefixes=null) { if (!isset($file)) { $file = str_replace(FULL_PATH, '', $this->TempalteFullPath).':'.$this->Application->GetVar('t'); } $parts = array( 'file_'.$file.'('.filemtime($this->TempalteFullPath).')' => 'serials:file_ts', // theme + template timestamp - 'm_lang_'.$this->Application->GetVar('m_lang') => 'serials:lang_ts', + 'm_lang_'.$this->Application->GetVar('m_lang') => 'serials:lang_ts', 'm_cat_id_'.$this->Application->GetVar('m_cat_id') => 'serials:cat_'.$this->Application->GetVar('m_cat_id').'_ts', 'm_cat_page'.$this->Application->GetVar('m_cat_page') => false, ); @@ -512,21 +563,21 @@ } } $key .= $element; - + return crc32($key); } - + function PushPointer($pointer) { $this->CachePointers[++$this->CacheLevel] = $this->FormCacheKey('pointer:'.$pointer); return $this->CachePointers[$this->CacheLevel]; } - + function PopPointer() { return $this->CachePointers[$this->CacheLevel--]; } - + function CacheStart($pointer=null) { if ($ret = $this->CacheGet($this->PushPointer($pointer)) ) { @@ -537,7 +588,7 @@ ob_start(); return false; } - + function CacheEnd($elem=null) { $ret = ob_get_clean();