HamlNode.php 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253
  1. <?php
  2. /* SVN FILE: $Id: HamlNode.php 92 2010-05-20 17:42:59Z chris.l.yates $ */
  3. /**
  4. * HamlNode class file.
  5. * @author Chris Yates <chris.l.yates@gmail.com>
  6. * @copyright Copyright (c) 2010 PBM Web Development
  7. * @license http://phamlp.googlecode.com/files/license.txt
  8. * @package PHamlP
  9. * @subpackage Haml.tree
  10. */
  11. require_once('HamlRootNode.php');
  12. require_once('HamlCommentNode.php');
  13. require_once('HamlDoctypeNode.php');
  14. require_once('HamlElementNode.php');
  15. require_once('HamlFilterNode.php');
  16. require_once('HamlHelperNode.php');
  17. require_once('HamlCodeBlockNode.php');
  18. require_once('HamlNodeExceptions.php');
  19. /**
  20. * HamlNode class.
  21. * Base class for all Haml nodes.
  22. * @package PHamlP
  23. * @subpackage Haml.tree
  24. */
  25. class HamlNode {
  26. /**
  27. * @var HamlNode root node of this node
  28. */
  29. protected $root;
  30. /**
  31. * @var HamlNode parent of this node
  32. */
  33. protected $parent;
  34. /**
  35. * @var array children of this node
  36. */
  37. protected $children = array();
  38. /**
  39. * @var array source line token
  40. */
  41. public $token;
  42. /**
  43. * @var boolean whether to show the output in the browser for debug
  44. */
  45. public $showOutput;
  46. /**
  47. * @var boolean whether to show the source in the browser for debug
  48. */
  49. public $showSource;
  50. /**
  51. * @var string content to render
  52. */
  53. public $content;
  54. /**
  55. * @var string output buffer
  56. */
  57. protected $output;
  58. /**
  59. * @var HamlRenderer Renderer object
  60. */
  61. private $_r;
  62. /**
  63. * @var array Options
  64. */
  65. private $_o;
  66. public function __construct($content, $parent) {
  67. $this->content = $content;
  68. if (!is_null($parent)) { // $parent === null for "else" code blocks
  69. $this->parent = $parent;
  70. $this->root = $parent->root;
  71. $parent->children[] = $this;
  72. }
  73. }
  74. /**
  75. * Getter.
  76. * @param string name of property to get
  77. * @return mixed return value of getter function
  78. */
  79. public function __get($name) {
  80. $getter = 'get' . ucfirst($name);
  81. if (method_exists($this, $getter)) {
  82. return $this->$getter();
  83. }
  84. throw new HamlNodeException('No getter function for {what}', array('{what}'=>$name));
  85. }
  86. /**
  87. * Setter.
  88. * @param string name of property to set
  89. * @return mixed value of property
  90. * @return HamlNode this node
  91. */
  92. public function __set($name, $value) {
  93. $setter = 'set' . ucfirst($name);
  94. if (method_exists($this, $setter)) {
  95. $this->$setter($value);
  96. return $this;
  97. }
  98. throw new HamlNodeException('No setter function for {what}', array('{what}'=>$name));
  99. }
  100. /**
  101. * Return a value indicating if this node has a parent
  102. * @return array the node's parent
  103. */
  104. public function hasParent() {
  105. return !empty($this->parent);
  106. }
  107. /**
  108. * Returns the node's content and that of its child nodes
  109. * @param integer the indent level. This is to allow properly indented output
  110. * that filters (e.g. Sass) may need.
  111. * @return string the node's content and that of its child nodes
  112. */
  113. public function getContent($indentLevel = 0) {
  114. $output = str_repeat(' ', 2 * $indentLevel++) . $this->content . "\n";
  115. foreach ($this->children as $child) {
  116. $output .= $child->getContent($indentLevel);
  117. } // foreach
  118. return $output;
  119. }
  120. /**
  121. * Returns the node's parent
  122. * @return array the node's parent
  123. */
  124. public function getParent() {
  125. return $this->parent;
  126. }
  127. /**
  128. * Returns a value indicating if this node has children
  129. * @return boolean true if the node has children, false if not
  130. */
  131. public function hasChildren() {
  132. return !empty($this->children);
  133. }
  134. /**
  135. * Returns the node's children
  136. * @return array the node's children
  137. */
  138. public function getChildren() {
  139. return $this->children;
  140. }
  141. /**
  142. * Returns the last child node of this node.
  143. * @return HamlNode the last child node of this node
  144. */
  145. public function getLastChild() {
  146. return $this->children[count($this->children) - 1];
  147. }
  148. /**
  149. * Returns the indent level of this node.
  150. * @return integer the indent level of this node
  151. */
  152. private function getLevel() {
  153. return $this->token['level'];
  154. }
  155. /**
  156. * Sets the indent level of this node.
  157. * Used during rendering to give correct indentation.
  158. * @param integer the indent level of this node
  159. * @return HamlNode this node
  160. */
  161. private function setLevel($level) {
  162. $this->token['level'] = $level;
  163. return $this;
  164. }
  165. /**
  166. * Returns the source for this node
  167. * @return string the source for this node
  168. */
  169. private function getSource() {
  170. return $this->token[HamlParser::HAML_SOURCE];
  171. }
  172. /**
  173. * Returns the source for this node
  174. * @return string the source for this node
  175. */
  176. private function getLine() {
  177. return $this->token['line'];
  178. }
  179. /**
  180. * Returns the filename for this node
  181. * @return string the filename for this node
  182. */
  183. private function getFilename() {
  184. return $this->token['filename'];
  185. }
  186. /**
  187. * Returns the options.
  188. * @return array the options
  189. */
  190. public function getOptions() {
  191. if (empty($this->_o)) {
  192. $this->_r = $this->root->options;
  193. }
  194. return $this->_o;
  195. }
  196. /**
  197. * Returns the renderer.
  198. * @return HamlRenderer the rendered
  199. */
  200. public function getRenderer() {
  201. if (empty($this->_r)) {
  202. $this->_r = $this->root->renderer;
  203. }
  204. return $this->_r;
  205. }
  206. public function render() {
  207. $output = $this->renderer->renderContent($this);
  208. foreach ($this->children as $child) {
  209. $output .= $child->render();
  210. } // foreach
  211. return $this->debug($output);
  212. }
  213. protected function debug($output) {
  214. $output = ($this->showSource ? $this->showSource($output) : $output);
  215. return ($this->showOutput && $this->line['indentLevel'] == 0 ?
  216. nl2br(str_replace(' ', '&nbsp;', htmlspecialchars($output))) :
  217. $output);
  218. }
  219. /**
  220. * Adds a comment with source debug information for the current line to the output.
  221. * The debug information is:
  222. * + source file (relative to the application path)
  223. * + line number
  224. * + indent level
  225. * + source code
  226. * @param array source line(s) that generated the ouput
  227. */
  228. protected function showSource($output) {
  229. return "<!--\n ({$this->line['file']} {$this->line['number']}:{$this->line['indentLevel']})\n {$this->line[HamlParser::HAML_SOURCE]}\n-->\n$output";
  230. }
  231. }