PageRenderTime 39ms CodeModel.GetById 10ms RepoModel.GetById 0ms app.codeStats 0ms

/src/lib/taglib.php

http://prails.googlecode.com/
PHP | 193 lines | 151 code | 20 blank | 22 comment | 22 complexity | 5c6be6d9ab5ff05af61c07a9f61073c0 MD5 | raw file
Possible License(s): GPL-3.0, LGPL-2.1
  1. <?php
  2. /**
  3. PRails Web Framework
  4. Copyright (C) 2010 Robert Kunze
  5. This program is free software: you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation, either version 3 of the License, or
  8. (at your option) any later version.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with this program. If not, see <http://www.gnu.org/licenses/>.
  15. */
  16. /**
  17. * This class implements the framework's tag lib base engine
  18. *
  19. * @author RoQ
  20. */
  21. class TagLib {
  22. private $tagLibDir = "lib/tags/";
  23. private $allowedPrefixes = Array("c");
  24. private $tagMatch = Array();
  25. private $unclosedPos = Array();
  26. private $depth = 0;
  27. private $html = "";
  28. private $template = "";
  29. public function TagLib($template = "") {
  30. $this->template = $template;
  31. }
  32. public function compile($html, $allowedDepth = 0) {
  33. $this->html = $html;
  34. $this->match($html);
  35. foreach ($this->tagMatch as $tag=>$arr_tag) {
  36. foreach ($arr_tag as $entry) {
  37. if ($entry["depth"] > $allowedDepth) continue;
  38. $rc = new TagLib();
  39. if (strlen($entry["body"]) > 0) {
  40. $entry["body"] = $rc->compile($entry["body"], $allowedDepth);
  41. }
  42. $content = $this->loadTagLib($tag, $entry);
  43. $html = str_replace($entry["match"], $content, $html);
  44. }
  45. }
  46. $html = $this->makeAllVars($html);
  47. $html = str_replace(Array('<%', '%>', "<@", "@>"), Array("<?", "?>", "<?", "?>"), $html);
  48. $html = $this->integrate($html);
  49. return $html;
  50. }
  51. private function loadTagLib($name, $tag) {
  52. $path = $this->tagLibDir.$name.".tag";
  53. if (!file_exists($path)) {
  54. $path = $this->tagLibDir."custom/".$name.".tag";
  55. if (!file_exists($path)) {
  56. $path = $this->tagLibDir."custom/".$name.((int)$_SESSION["builder"]["user_id"]).".tag";
  57. }
  58. }
  59. ob_start();
  60. require($path);
  61. $content = ob_get_contents();
  62. ob_end_clean();
  63. $content = str_replace(Array("@>", "<@", "%>", "<%"), Array("?>", "<?", "?>", "<?"), $content);
  64. return $content;
  65. }
  66. private function makeAllVars($buffer) {
  67. preg_match_all("/(#|@)([a-zA-Z_0-9]+[.][.A-Za-z0-9_]*[a-zA-Z0-9]*)(\[([a-zA-Z0-9]+)\](\[([^\]]+)\])?)?/", $buffer, $arr_matches);
  68. foreach ($arr_matches[2] as $key => $str_match) {
  69. $toClose = false;
  70. preg_match_all('/<!--\[noeval\]-->.*<!--\[\/noeval\]-->/sU', $buffer, $arr_test);
  71. $found = false;
  72. foreach ($arr_test[0] as $test) {
  73. $found = $found || (strpos($test, $arr_matches[0][$key]) !== false);
  74. }
  75. if ($found) continue;
  76. $parts = explode(".", $str_match);
  77. if (strlen($arr_matches[4][$key]) > 0) {
  78. if (file_exists("lib/tags/".$arr_matches[4][$key].".var")) {
  79. ob_start();
  80. $var["name"] = $arr_matches[4][$key];
  81. $var["modifier"] = $arr_matches[6][$key];
  82. require("lib/tags/".$arr_matches[4][$key].".var");
  83. $str_param = ob_get_clean();
  84. $toClose = $var["close"];
  85. } else
  86. {
  87. $str_param = "(" . $arr_matches[4][$key] . ")\$arr_param";
  88. }
  89. } else {
  90. $str_param = "\$arr_param";
  91. }
  92. foreach ($parts as $part) {
  93. if (is_numeric($part)) {
  94. $str_param .= "[" . $part . "]";
  95. } else {
  96. $str_param .= "[\"" . $part . "\"]";
  97. }
  98. }
  99. if ($toClose) $str_param .= ")";
  100. if ($arr_matches[1][$key] == "@") {
  101. $buffer = str_replace($arr_matches[0][$key], $str_param, $buffer);
  102. } else {
  103. $buffer = str_replace($arr_matches[0][$key], "<"."?=".$str_param."?".">", $buffer);
  104. }
  105. }
  106. return $buffer;
  107. }
  108. private function makeVar($var) {
  109. return str_replace(".", "\"][\"", $var);
  110. }
  111. private function match($html) {
  112. $pattern = '@<(/)?(\w+):(\w+)(\s*|(\s+[a-zA-Z0-9\-_]+=(?:"[^"]*"|\'[^\']*\')\s*)+)(/)?>@usix';
  113. preg_match_all($pattern, $html = trim($html), $m, PREG_OFFSET_CAPTURE | PREG_SET_ORDER);
  114. foreach ($m as $set) {
  115. if (in_array($set[2][0], $this->allowedPrefixes)) {
  116. if ($set[1][1] >= 0) {
  117. $this->endTag($set[3][0], $set[0][1], strlen(trim($set[0][0])));
  118. } else {
  119. $this->startTag($set[3][0], $this->getAttribs($set[4][0]), $set[0][1], strlen(trim($set[0][0])));
  120. if ($set[6][1] > 0) {
  121. $this->endTag($set[3][0], $set[0][1], strlen(trim($set[0][0])));
  122. }
  123. }
  124. }
  125. }
  126. }
  127. private function startTag($tagName, $attributes, $startPos, $len) {
  128. $cur = count($this->tagMatch[$tagName]);
  129. if (!is_array($this->unclosedPos[$tagName])) {
  130. $this->unclosedPos[$tagName] = Array();
  131. }
  132. $this->tagMatch[$tagName][$cur]["attributes"] = $attributes;
  133. $this->tagMatch[$tagName][$cur]["startPos"] = $startPos;
  134. $this->tagMatch[$tagName][$cur]["startLen"] = $len;
  135. $this->tagMatch[$tagName][$cur]["depth"] = $this->depth;
  136. array_push($this->unclosedPos[$tagName], $cur);
  137. $this->depth++;
  138. }
  139. private function endTag($tagName, $endPos, $len) {
  140. $pos = array_pop($this->unclosedPos[$tagName]);
  141. $this->tagMatch[$tagName][$pos]["endPos"] = $endPos;
  142. $this->tagMatch[$tagName][$pos]["endLen"] = $len;
  143. $this->tagMatch[$tagName][$pos]["body"] = $this->getBody($this->tagMatch[$tagName][$pos]);
  144. $this->tagMatch[$tagName][$pos]["match"] = $this->getMatch($this->tagMatch[$tagName][$pos]);
  145. $this->depth--;
  146. }
  147. private function getAttribs($content) {
  148. $arr_attributes = Array();
  149. $pattern = '@\s*([a-zA-Z0-9\-_]+)=(?:"([^"]*)"|\'([^\']*)\')\s*@usix';
  150. preg_match_all($pattern, $content=trim($content), $m, PREG_OFFSET_CAPTURE | PREG_SET_ORDER);
  151. foreach ($m as $set) {
  152. $arr_attributes[$set[1][0]] = $set[2][0];
  153. }
  154. return $arr_attributes;
  155. }
  156. private function getBody($tag) {
  157. if ($tag["startPos"] < $tag["endPos"]) {
  158. return trim(substr($this->html, $tag["startPos"] + $tag["startLen"], $tag["endPos"] - ($tag["startPos"] + $tag["startLen"])));
  159. } else {
  160. return "";
  161. }
  162. }
  163. private function getMatch($tag) {
  164. return trim(substr($this->html, $tag["startPos"], ($tag["endPos"] + $tag["endLen"]) - $tag["startPos"]));
  165. }
  166. private function integrate($content) {
  167. return preg_replace('@(<\?[^=]([^?]|\?[^>])+)\?>\s*<\?([^=])@usix', "\\1\\3", $content);
  168. }
  169. }
  170. ?>