/lib/ezc/Template/src/parsers/interfaces/tree_output.php

https://bitbucket.org/ericsagnes/ezpublish-multisite · PHP · 300 lines · 144 code · 13 blank · 143 comment · 16 complexity · 9ca045ada3e60914af0ade8bbaa837c6 MD5 · raw file

  1. <?php
  2. /**
  3. * File containing the ezcTemplateTreeOutput abstract class
  4. *
  5. * @package Template
  6. * @version //autogen//
  7. * @copyright Copyright (C) 2005-2010 eZ Systems AS. All rights reserved.
  8. * @license http://ez.no/licenses/new_bsd New BSD License
  9. * @access private
  10. */
  11. /**
  12. * Iterates the given tree and outputs the result as text.
  13. *
  14. * This class must be extended and combined with a visitor (e.g. ezcTemplateTstNodeVisitor)
  15. * to create a specific tree visitor for outputting the tree structure.
  16. *
  17. * This class has some abstract functions which must be implemented by the
  18. * extending class, they are used to gain more detailed information about tree
  19. * nodes.
  20. *
  21. * For instance the array:
  22. * <code>
  23. * array( 'name' => 'foo',
  24. * 'type' => 'bar',
  25. * 'isEnabled' => true );
  26. * </code>
  27. * will become:
  28. * <code>
  29. * |-- name: "foo"
  30. * |-- type: "bar"
  31. * `-- isEnabled: true
  32. * </code>
  33. *
  34. * It can also handle arrays and objects which will be output recursively.
  35. * For objects it will output the properties if it is an instance of $this->nodeClass
  36. * by calling outputNode() while array is output by calling outputArray().
  37. * All other objects will be cast to a string and output.
  38. *
  39. * Outputting an array with array:
  40. * <code>
  41. * array( 'children' => array( 'foo', 'bar' ) );
  42. * </code>
  43. * will become:
  44. * <code>
  45. * `-- children: array[2]
  46. * |-- "foo"
  47. * `-- "bar"
  48. * </code>
  49. *
  50. * Outputting an array with objects:
  51. * <code>
  52. * array( 'children' => array( new ezcTemplateLiteralTstNode( 5 ),
  53. * new ezcTemplateTextBlockTstNode( "line1\nline2" ) ) );
  54. * </code>
  55. * will become:
  56. * <code>
  57. * `-- children: array[2]
  58. * |-- <Literal> @ 1:0->2:0
  59. * | `-- value: 5
  60. * `-- <TextBlock> @ 2:0->3:0
  61. * "line1" . "\n" .
  62. * "line2"
  63. * </code>
  64. *
  65. * @package Template
  66. * @version //autogen//
  67. * @access private
  68. */
  69. abstract class ezcTemplateTreeOutput
  70. {
  71. /**
  72. * The result of the node output.
  73. * @var string $text
  74. */
  75. public $text;
  76. /**
  77. * The name of the class which all nodes inherit from.
  78. * @var string
  79. */
  80. public $nodeClass;
  81. /**
  82. * The regex (preg style) used to extract the name from the class name.
  83. * @see extractNodeName() uses this variable.
  84. * @var string
  85. */
  86. public $nodeClassRegex;
  87. /**
  88. * Initialize the output class with the name of the node class and the regular expression to extract short names.
  89. *
  90. * @param string $nodeClass
  91. * @param string $nodeClassRegex
  92. */
  93. public function __construct( $nodeClass, $nodeClassRegex = '' )
  94. {
  95. $this->text = '';
  96. $this->nodeClass = $nodeClass;
  97. $this->nodeClassRegex = $nodeClassRegex;
  98. }
  99. /**
  100. * Extracts the name of the node and returns it as a string.
  101. *
  102. * Note: Reimplement this to handle the node properly.
  103. *
  104. * @param Object $node The node to examine.
  105. * @return string
  106. */
  107. protected function extractNodeName( $node )
  108. {
  109. return preg_replace( $this->nodeClassRegex, '$1', get_class( $node ) );
  110. }
  111. /**
  112. * Extracts position data from the specified node and set in the out parameters.
  113. *
  114. * Note: Reimplement this to handle the node properly.
  115. *
  116. * @param Object $node The node to examine.
  117. * @param int $startLine The starting line for the node.
  118. * @param int $startColumn The starting column for the node.
  119. * @param int $endLine The starting line for the node.
  120. * @param int $endColumn The starting column for the node.
  121. * @return bool True if the extraction was succesful.
  122. */
  123. abstract protected function extractNodePosition( $node, &$startLine, &$startColumn, &$endLine, &$endColumn );
  124. /**
  125. * Extracts the properties from the specified node and returns it as an array.
  126. *
  127. * Note: Reimplement this to handle the node properly.
  128. *
  129. * @param Object $node The node to examine.
  130. * @return array(name=>value)
  131. */
  132. abstract protected function extractNodeProperties( $node );
  133. /**
  134. * Outputs the contents of any node.
  135. *
  136. * Will display the name of the node, the position in the file and then output
  137. * all the properties.
  138. *
  139. * @param Object $node The node to output.
  140. * @return string
  141. * @see extractNodeName()
  142. * @see extractNodePosition()
  143. * @see extractNodeProperties()
  144. */
  145. protected function outputNode( $node )
  146. {
  147. $text = "<" . $this->extractNodeName( $node ) . ">";
  148. if ( $this->extractNodePosition( $node, $startLine, $startColumn,
  149. $endLine, $endColumn ) )
  150. {
  151. $text .= " @ " . $startLine . ":" . $startColumn . "->" .
  152. $endLine . ":" . $endColumn;
  153. }
  154. $text .= "\n";
  155. $properties = $this->extractNodeProperties( $node );
  156. $text .= $this->outputArray( $properties, true );
  157. return $text;
  158. }
  159. /**
  160. * Outputs the array as a tree structure (recursively).
  161. *
  162. * @param array $properties The array to output
  163. * @param bool $useKey If true then the keys of the array is displayed.
  164. * @return string
  165. */
  166. protected function outputArray( $properties, $useKey )
  167. {
  168. $text = '';
  169. $maxLen = 0;
  170. if ( $useKey )
  171. {
  172. foreach ( $properties as $name => $property )
  173. {
  174. $maxLen = max( strlen( $name ), $maxLen );
  175. }
  176. }
  177. $i = 0;
  178. foreach ( $properties as $name => $property )
  179. {
  180. if ( $i > 0 )
  181. {
  182. $text .= "\n";
  183. }
  184. $remainderWsText = '';
  185. $remainder = $maxLen - strlen( $name );
  186. if ( $useKey && $remainder > 0 )
  187. {
  188. $remainderWsText = str_repeat( ' ', $remainder );
  189. }
  190. $suffix = '';
  191. if ( $useKey )
  192. {
  193. $suffix = $name . $remainderWsText . ': ';
  194. }
  195. if ( $i == count( $properties ) - 1 )
  196. {
  197. $text .= '`-- ' . $suffix;
  198. $prefix = ' ';
  199. }
  200. else
  201. {
  202. $text .= '|-- ' . $suffix;
  203. $prefix = '| ';
  204. }
  205. // if $textBlock contains a string it will be display in between
  206. // properties using $prefix for each line.
  207. $textBlock = false;
  208. if ( is_object( $property ) )
  209. {
  210. if ( $property instanceof $this->nodeClass )
  211. {
  212. $textBlock = $this->outputNode( $property, true );
  213. }
  214. else
  215. {
  216. $text .= (string)$property;
  217. }
  218. }
  219. elseif ( is_array( $property ) )
  220. {
  221. $text .= "array[" . count( $property ) . "]";
  222. $textBlock = $this->outputArray( $property, false );
  223. }
  224. elseif ( is_string( $property ) )
  225. {
  226. if ( strpos( $property, "\n" ) === false )
  227. {
  228. $line = self::outputString( $property );
  229. $text .= "\"{$line}\"";
  230. }
  231. else
  232. {
  233. $lines = explode( "\n", $property );
  234. foreach ( $lines as $offset => $line )
  235. {
  236. if ( $offset > 0 )
  237. $textBlock .= " . \"\\n\" .\n";
  238. $line = self::outputString( $line );
  239. $textBlock .= "\"{$line}\"";
  240. }
  241. }
  242. }
  243. else
  244. {
  245. $text .= var_export( $property, true );
  246. }
  247. if ( $textBlock !== false )
  248. {
  249. // Split into lines and output each with the $prefix value in front.
  250. $lines = explode( "\n", $textBlock );
  251. $start = 0;
  252. if ( $useKey )
  253. {
  254. $text .= "\n";
  255. }
  256. else
  257. {
  258. $start = 1;
  259. $text .= $lines[0] . "\n";
  260. }
  261. $linesCount = count( $lines );
  262. for ( $line = $start; $line < $linesCount; ++$line )
  263. {
  264. if ( $line > $start )
  265. $text .= "\n";
  266. $text .= $prefix . $lines[$line];
  267. }
  268. }
  269. ++$i;
  270. }
  271. return $text;
  272. }
  273. /**
  274. * Outputs the string by escaping special characters making them readable.
  275. *
  276. * The special characters are: \n, \r, \t, \b, \" and '
  277. * @param string $str The string to output.
  278. * @return string
  279. */
  280. protected static function outputString( $str )
  281. {
  282. return str_replace( array( "\n", "\r", "\t", "\b", "\"", "'" ),
  283. array( "\\n", "\\r", "\\t", "\\b", "\\\"", "\\'" ),
  284. $str );
  285. }
  286. }
  287. ?>