'', 'classname' => 'ObjTemplate.class.php', 'version' => '0.1' ); var $tag = array( 'begin' => '%', 'delim' => ':', 'end' => '%' ); var $cmd = array( /* Both sides must be lowercase. */ 'if' => 'if', 'else' => 'else', 'endif' => 'endif', 'file' => 'file' ); var $filename; var $array; function ObjTemplate($filename = '') { $this->filename = $filename; return $this->reload(); } function set_tags($begin_tag = '', $end_tag = '') { if (strlen($begin_tag) > 0) $this->tag['begin'] = $begin_tag; if (strlen($end_tag) > 0) $this->tag['end'] = $end_tag; } function load($filename) { if (file_exists($filename)) { # DEBUG $this->array = $this->_string_transform(join('', file($filename)), 0); return true; } return false; } function reload() { if (strlen($this->filename) > 0) return $this->load($this->filename); return false; } function add_before($string) { return array_unshift($this->array, $this->_string_transform($string)); } function add_after($string) { return array_push($this->array, $this->_string_transform($string)); } function is_key($key) { return $this->_is_key(strtolower($key), $this->array); } function _is_key($key, $ar) { /* * TODO: optimalization * try foreach() loop instead for() loop */ for ($i = 0; $i < count($ar); $i++) { if (is_array($ar[$i])) { if (is_array($ar[$i]['key'])) { if (true == $this->_is_key($key, $ar[$i]['key'])) return true; } elseif (! strcmp($key, $ar[$i]['key'])) { return true; } elseif (! strcmp($this->cmd['if'], $ar[$i]['key'])) { if (is_array($ar[$i]['conditions'])) { if (is_array($ar[$i]['conditions']['key'])) { if (true == $this->_is_key($key, $ar[$i]['conditions']['key'])) return true; } else { if (! strcmp($key, $ar[$i]['conditions']['key'])) return true; } } if (is_array($ar[$i]['true'])) { if (true == $this->_is_key($key, $ar[$i]['true'])) return true; } if (is_array($ar[$i]['false'])) { if (true == $this->_is_key($key, $ar[$i]['false'])) return true; } } else { if (true == $this->_is_key($key, $ar[$i])) return true; } } } return false; } function set($key, $value = "") { if (is_array($key)) { while (list($k, $v) = each($key)) { if (! empty($k)) { /* Empty values are allowed. Empty keys are NOT. */ $this->set($k, $v); } } } else { $this->_set(strtolower($key), $this->_string_transform($value), $this->array); } return; } function _set($key, $value, &$ar) { for ($i = 0; $i < count($ar); $i++) { if (is_array($ar[$i])) { if (isset($ar[$i]['key'])) { if (is_array($ar[$i]['key'])) $this->_set($key, $value, $ar[$i]['key']); elseif (! strcmp($this->cmd['if'], $ar[$i]['key'])) { if (is_array($ar[$i]['conditions'])) { if (is_array($ar[$i]['conditions']['key'])) { $this->_set($key, $value, $ar[$i]['conditions']['key']); } else { if (! strcmp($key, $ar[$i]['conditions']['key'])) $ar[$i]['conditions'] = $value; } } if (is_array($ar[$i]['true'])) $this->_set($key, $value, $ar[$i]['true']); if (is_array($ar[$i]['false'])) $this->_set($key, $value, $ar[$i]['false']); } else { if (! strcmp($key, $ar[$i]['key'])) $ar[$i] = $value; } } else { $this->_set($key, $value, $ar[$i]); } } } return; } /* TODO: fix conditions in IF */ function get_keys() { return array_unique($this->_get_keys($this->array)); } function _get_keys($ar) { $ar_out = array(); for ($i = 0; $i < count($ar); $i++) { if (is_array($ar[$i])) { if (! strcmp($this->cmd['if'], $ar[$i]['key'])) { if (is_array($ar[$i]['conditions'])) { if (is_array($ar[$i]['conditions']['key'])) { $ar_out = array_merge($ar_out, $this->_get_keys($ar[$i]['conditions']['key'])); } else array_push($ar_out, $ar[$i]['conditions']['key']); } if (is_array($ar[$i]['true'])) $ar_out = array_merge($ar_out, $this->_get_keys($ar[$i]['true'])); if (is_array($ar[$i]['false'])) $ar_out = array_merge($ar_out, $this->_get_keys($ar[$i]['false'])); } elseif (isset($ar[$i]['key'])) { if (is_array($ar[$i]['key'])) $ar_out = array_merge($ar_out, $this->_get_keys($ar[$i]['key'])); else array_push($ar_out, $ar[$i]['key']); } else { $ar_out = array_merge($ar_out, $this->_get_keys($ar[$i])); } } } return $ar_out; } function hide() { return $this->_get_content($this->array, 'hide'); } function clean() { return $this->_get_content($this->array, 'clean'); } function html() { return $this->_get_content($this->array, 'normal'); } function _get_content($ar, $mode = "") { $string = ''; for ($i = 0; $i < count($ar); $i++) { if (is_array($ar[$i])) { if (! strcmp($this->cmd['if'], $ar[$i]['key'])) { if (is_array($ar[$i]['conditions'])) $evalstr = $this->_final_join($ar[$i]['conditions']['key'], $mode); else $evalstr = '"' . $ar[$i]['conditions'] . '"'; if (is_array($evalstr)) { $string .= $this->tag['begin'] . $this->cmd['if'] . $this->tag['delim']; $string .= $evalstr['uncompleted'] . $this->tag['end']; if (is_array($ar[$i]['true'])) $string .= $this->_get_content($ar[$i]['true'], $mode); else $string .= $ar[$i]['true']; if (is_array($ar[$i]['false'])) $string .= $this->tag['begin'].$this->cmd['else'].$this->tag['end'] . $this->_get_content($ar[$i]['false'], $mode); else $string .= $this->tag['begin'].$this->cmd['else'].$this->tag['end'] . $ar[$i]['false']; $string .= $this->tag['begin'].$this->cmd['endif'].$this->tag['end']; } else { $evalcode = "return ($evalstr);"; //print "evalcode = $evalcode
"; if (eval($evalcode)) { //echo "- returned true
"; if (isset($ar[$i]['true'])) { if (is_array($ar[$i]['true'])) $string .= $this->_get_content($ar[$i]['true'], $mode); else $string .= $ar[$i]['true']; } } else { //echo "- returned false
"; if (isset($ar[$i]['false'])) { if (is_array($ar[$i]['false'])) $string .= $this->_get_content($ar[$i]['false'], $mode); else $string .= $ar[$i]['false']; } } } } elseif (isset($ar[$i]['key'])) { if (is_array($ar[$i]['key'])) { $evalcode = "return (".$this->_final_join($ar[$i]['key']).");"; //print "NORMAL evalcode = $evalcode
"; $string .= eval($evalcode); } else { switch ($mode) { case "clean": ; break; case "hide": $string .= $this->_generate_error("hide: " . $ar[$i]['key']); break; default: $string .= $this->tag['begin'] . $ar[$i]['key'] . $this->tag['end']; break; } } } else { $string .= $this->_get_content($ar[$i], $mode); } } else { $string .= $ar[$i]; } } return $string; } function html_array($prefix) { $html = $this->html(); $regexp = $this->tag['begin'] . $prefix . $this->tag['delim'] . '([^%\b]+)' . ( isset($this->tag['end']) ? $this->tag['end'] : '\b' ) . ''; preg_match_all("/$regexp/is", $html, $matches); return array(preg_split("/$regexp/is", $html), $matches[1]); } function get_array() { return $this->array; } function _start_explode($str) { if (preg_match("/^[\w:]+$/", $str)) return strtolower($str); $out_ar = array(); $tmpstr = ''; if (preg_match("/^[a-zA-Z]$/", $str[0])) $type = 1; else $type = 0; for ($i = 0; $i < strlen($str); $i++) { if ($type == 1) { if (preg_match("/^[\w:]$/", $str[$i])) { $tmpstr .= $str[$i]; } else { array_push($out_ar, array('key' => strtolower($tmpstr))); $tmpstr = $str[$i]; $type = 0; } } else { if (preg_match("/^[a-zA-Z]$/", $str[$i])) { array_push($out_ar, $tmpstr); $tmpstr = $str[$i]; $type = 1; } else { $tmpstr .= $str[$i]; } } } array_push($out_ar, $type ? array('key' => strtolower($tmpstr)) : $tmpstr); return $out_ar; } function _final_join($ar, $mode = "") { $uncompleted = 0; if (is_array($ar)) { // TODO comment //print "Entering _final_join() with mode [$mode] / array set
"; $ret = ''; foreach ($ar as $i) { if (is_array($i)) { switch ($mode) { case "clean": ; break; case "hide": // $string .= $this->_generate_error("hide: " . $ar[$i]['key']); break; default: $uncompleted = 1; $ret .= $i['key']; break; } } else $ret .= $i; } } else { switch ($mode) { case "clean": $ret = "0"; break; case "hide": $ret = "0"; // $string .= $this->_generate_error("hide: " . $ar[$i]['key']); break; default: $uncompleted = 1; $ret = $ar; break; } } if ($uncompleted) { // TODO comment //print "_final_join(): returning uncompleted ($uncompleted)[$ret]
"; } return $uncompleted ? array('uncompleted' => $ret) : $ret; } function _string_transform($string, $debug = 0) { /* * Spliting string into two arrays by tags. First array ($m_tags) will * contain only tags without starting prefix and ending sufix. * The second array ($m_texts) will contain text between tags. * Elemets goes in this order: $m_texts[0], $m_tags[0], $m_texts[1], ... * * Optimalization for this array spliting is strongly required. */ $m_texts = $m_tags = array(); if (0) { /* * Old method -- remove this. */ $regexp = $this->tag['begin'] . '(\w[\w\d_]*(' . $this->tag['delim'] . '[^\b%]+)*)' . ( isset($this->tag['end']) ? $this->tag['end'] : '\b' ); preg_match_all("/$regexp/is", $string, $m_tags); $m_tags = $m_tags[1]; $m_texts = preg_split("/$regexp/im", $string); } else { $begin_tag_len = strlen($this->tag['begin']); $end_tag_len = strlen($this->tag['end']); $append = 0; while (1) { $pos_begin = strpos($string, $this->tag['begin']); if ($pos_begin === false) { if ($append) { $m_texts[count($m_texts) - 1] .= $string; $append = 0; } else { array_push($m_texts, $string); } break; } else { $pos_real_begin = $pos_begin + $begin_tag_len; $pos_end = strpos($string, $this->tag['end'], $pos_real_begin); if ($pos_end === false) { if ($append) { $m_texts[count($m_texts) - 1] .= $string; $append = 0; } else { array_push($m_texts, $string); } break; } else { $tmpstr = substr($string, $pos_real_begin, $pos_end - $pos_real_begin); $pos_real_end = $pos_end + $end_tag_len; if (preg_match('/[\s]/', $tmpstr)) { if ($debug) echo "MATCHED: [$tmpstr]
"; $pos_begin_2nd = strpos($tmpstr . $this->tag['end'], $this->tag['begin']); if ($pos_begin_2nd === false) ; else $pos_real_end = $pos_real_begin + $pos_begin_2nd; if ($append) { $m_texts[count($m_texts) - 1] .= substr($string, 0, $pos_real_end); if ($debug) print "-- appending: [".substr($string, 0, $pos_real_end)."]
"; } else { array_push($m_texts, substr($string, 0, $pos_real_end)); if ($debug) print "-- pushing: [".substr($string, 0, $pos_real_end)."]
"; } $append = 1; } else { if ($debug) echo "NOT MATCHED: [$tmpstr]
"; if ($append) { $m_texts[count($m_texts) - 1] .= substr($string, 0, $pos_begin); $append = 0; } else { array_push($m_texts, substr($string, 0, $pos_begin)); } array_push($m_tags, $tmpstr); } $string = substr($string, $pos_real_end); } } } } /* * Debug informations printing. */ if ($debug) { print "_string_transform() DEBUG: m_tags: "; var_dump($m_tags); print "
"; print "_string_transform() DEBUG: m_texts: "; var_dump($m_texts); print "
"; } /* * Main loop. */ $ar_out_idx = 0; for ($i = 0; $i < count($m_texts); $i++) { /* Text processing. */ if (strlen($m_texts[$i]) > 0) { if ($ar_out_idx > 0 && ! is_array($ar_out[$ar_out_idx - 1])) { $ar_out[$ar_out_idx - 1] .= $m_texts[$i]; } else { $ar_out[$ar_out_idx] = $m_texts[$i]; $ar_out_idx++; } } /* Tag processing. */ if (strlen($m_tags[$i]) > 0) { $cmd_parts = explode($this->tag['delim'], $m_tags[$i], 2); /* FILE tag. */ if (! strcasecmp($this->cmd['file'], $cmd_parts[0]) && strlen($cmd_parts[1]) > 0) { $filename_with_path = dirname($this->filename) . '/' . $cmd_parts[1]; if (file_exists($filename_with_path)) $ar_out[$ar_out_idx] = $this->_string_transform(join('', file($filename_with_path))); else $ar_out[$ar_out_idx] = $this->_generate_error("file not found: $filename_with_path"); } /* IF tag. */ elseif (! strcasecmp($this->cmd['if'], $cmd_parts[0])) { $ar_out[$ar_out_idx] = array( 'key' => $this->cmd['if'], 'conditions' => array('key' => $this->_start_explode($cmd_parts[1])) ); $tmp_str = ''; $level = 0; for ($j = $i + 1; $j < count($m_texts); $j++) { $cmd_parts2 = explode($this->tag['delim'], $m_tags[$j], 2); $tmp_str .= $m_texts[$j]; /* IF subtag. */ if (! strcasecmp($this->cmd['if'], $cmd_parts2[0])) { $level++; } /* ELSE subtag. */ elseif (! $level && ! strcasecmp($this->cmd['else'], $cmd_parts2[0])) { if (! isset($ar_out[$ar_out_idx]['true'])) { $ar_out[$ar_out_idx]['true'] = $this->_string_transform($tmp_str); $tmp_str = ''; continue; } } /* ENDIF subtag. */ elseif (! strcasecmp($this->cmd['endif'], $cmd_parts2[0])) { if ($level) $level--; else break; } $tmp_str .= $this->tag['begin'] . $m_tags[$j] . $this->tag['end']; } if (isset($ar_out[$ar_out_idx]['true'])) $ar_out[$ar_out_idx]['false'] = $this->_string_transform($tmp_str); else $ar_out[$ar_out_idx]['true'] = $this->_string_transform($tmp_str); $i = $j; } /* Others tags. */ else { //$ar_out[$ar_out_idx] = array('key' => strtolower($m_tags[$i])); $ar_out[$ar_out_idx] = array('key' => $this->_start_explode($m_tags[$i])); } $ar_out_idx++; } } if ($debug && $ar_out_idx <= 1) print "_string_transform() DEBUG: ar_out_idx = $ar_out_idx
"; return $ar_out_idx > 1 ? $ar_out : $ar_out[0]; } function _generate_error($message = "unknown error") { return $this->cstr['begin'] . ' ' . $this->cstr['classname'] . ':' . ' ' . $message . ' ' . $this->cstr['end']; } } ?>