PageRenderTime 49ms CodeModel.GetById 25ms RepoModel.GetById 0ms app.codeStats 0ms

/includes/Opl/Opt/Instruction/Snippet.php

https://bitbucket.org/kandsten/hitta.sverok.se
PHP | 329 lines | 187 code | 28 blank | 114 comment | 15 complexity | 61fcaaf1d945084cfc6a959505afaba9 MD5 | raw file
Possible License(s): GPL-3.0, MIT
  1. <?php
  2. /*
  3. * OPEN POWER LIBS <http://www.invenzzia.org>
  4. *
  5. * This file is subject to the new BSD license that is bundled
  6. * with this package in the file LICENSE. It is also available through
  7. * WWW at this URL: <http://www.invenzzia.org/license/new-bsd>
  8. *
  9. * Copyright (c) Invenzzia Group <http://www.invenzzia.org>
  10. * and other contributors. See website for details.
  11. *
  12. * $Id: Snippet.php 272 2009-12-23 08:42:26Z zyxist $
  13. */
  14. /**
  15. * The snippet instruction processor.
  16. */
  17. class Opt_Instruction_Snippet extends Opt_Compiler_Processor
  18. {
  19. /**
  20. * The processor name required by the parent.
  21. * @internal
  22. * @var string
  23. */
  24. protected $_name = 'snippet';
  25. /**
  26. * The list of available snippets.
  27. * @internal
  28. * @var array
  29. */
  30. protected $_snippets = array();
  31. /**
  32. * The currently inserted snippet stack used for detecting the infinite recursion.
  33. * @internal
  34. * @var array
  35. */
  36. protected $_current = array();
  37. /**
  38. * Configures the instruction processor.
  39. *
  40. * @internal
  41. */
  42. public function configure()
  43. {
  44. $this->_addInstructions(array('opt:snippet', 'opt:insert', 'opt:parent'));
  45. $this->_addAttributes(array('opt:use'));
  46. } // end configure();
  47. /**
  48. * Resets the processor after the finished compilation and frees the
  49. * memory taken by the snippets.
  50. *
  51. * @internal
  52. */
  53. public function reset()
  54. {
  55. foreach($this->_snippets as &$snippetList)
  56. {
  57. foreach($snippetList as $snippet)
  58. {
  59. $snippet->dispose();
  60. }
  61. }
  62. $this->_snippets = array();
  63. $this->_current = array();
  64. } // end reset();
  65. /*
  66. public function processNode(Opt_Xml_Node $node)
  67. {
  68. $name = '_process'.ucfirst($node->getName());
  69. $this->$name($node);
  70. } // end processNode();
  71. public function postprocessNode(Opt_Xml_Node $node)
  72. {
  73. $name = '_postprocess'.ucfirst($node->getName());
  74. $this->$name($node);
  75. } // end postprocessNode();
  76. */
  77. /**
  78. * Processes the opt:use attribute.
  79. *
  80. * @internal
  81. * @param Opt_Xml_Node $node The node the attribute is added to
  82. * @param Opt_Xml_Attribute $attr The found attribute.
  83. */
  84. public function processAttribute(Opt_Xml_Node $node, Opt_Xml_Attribute $attr)
  85. {
  86. if(isset($this->_snippets[$attr->getValue()]))
  87. {
  88. array_push($this->_current, $attr->getValue());
  89. $snippet = &$this->_snippets[$attr->getValue()];
  90. // Move all the stuff to the fake node.
  91. if($node->hasChildren())
  92. {
  93. $newNode = new Opt_Xml_Element('opt:_');
  94. $newNode->moveChildren($node);
  95. $size = sizeof($snippet);
  96. $snippet[$size] = $newNode;
  97. $attr->set('snippetObj', $snippet);
  98. $attr->set('size', $size);
  99. }
  100. $node->removeChildren();
  101. // Process the snippets
  102. $node->set('escaping', $this->_compiler->get('escaping'));
  103. $this->_compiler->set('escaping', $snippet[0]->get('escaping'));
  104. foreach($snippet[0] as $subnode)
  105. {
  106. $node->appendChild(clone $subnode);
  107. }
  108. $node->set('call:use', $attr->getValue());
  109. $attr->set('postprocess', true);
  110. }
  111. } // end processAttribute();
  112. /**
  113. * A postprocessing routine for opt:use
  114. * @internal
  115. * @param Opt_Xml_Node $node
  116. * @param Opt_Xml_Attribute $attr
  117. */
  118. public function postprocessAttribute(Opt_Xml_Node $node, Opt_Xml_Attribute $attr)
  119. {
  120. if(!is_null($attr->get('size')))
  121. {
  122. $snippet = $attr->get('snippetObj');
  123. unset($snippet[$attr->get('size')]);
  124. }
  125. // Restore the original escaping state
  126. $this->_compiler->set('escaping', $node->get('escaping'));
  127. array_pop($this->_current);
  128. } // end postprocessAttribute();
  129. /**
  130. * Processes the opt:snippet element.
  131. * @internal
  132. * @param Opt_Xml_Element $node The found snippet.
  133. */
  134. public function _processSnippet(Opt_Xml_Element $node)
  135. {
  136. $params = array(
  137. 'name' => array(0 => self::REQUIRED, self::ID)
  138. );
  139. $this->_extractAttributes($node, $params);
  140. // Assign this snippet
  141. if(!isset($this->_snippets[$params['name']]))
  142. {
  143. $this->_snippets[$params['name']] = array(0 => $node);
  144. $current = 0;
  145. }
  146. else
  147. {
  148. $current = sizeof($this->_snippets[$params['name']]);
  149. $this->_snippets[$params['name']][] = $node;
  150. }
  151. if($node->getParent()->removeChild($node) == 0)
  152. {
  153. throw new Opl_Debug_Exception();
  154. }
  155. // Remember the template state of escaping for this snippet.
  156. // This is necessary to make per-template escaping work with
  157. // the inheritance.
  158. $node->set('escaping', $this->_compiler->get('escaping'));
  159. // Link "opt:parent" with the parent
  160. $parentTags = $node->getElementsByTagNameNS('opt', 'parent');
  161. foreach($parentTags as $parent)
  162. {
  163. $parent->set('snippetName', $params['name']);
  164. $parent->set('snippetId', $current + 1);
  165. }
  166. } // end _processSnippet();
  167. /**
  168. * Processes the opt:parent element.
  169. * @internal
  170. * @param Opt_Xml_Element $node The found element.
  171. */
  172. public function _processParent(Opt_Xml_Element $node)
  173. {
  174. $n = $node->get('snippetName');
  175. $i = $node->get('snippetId');
  176. // If there is a parent, append it here and execute.
  177. if(isset($this->_snippets[$n][$i]))
  178. {
  179. $node->set('escaping', $this->_compiler->get('escaping'));
  180. $node->set('single', false);
  181. $this->_compiler->set('escaping', $this->_snippets[$n][$i]->get('escaping'));
  182. $master = $node->getParent();
  183. foreach($this->_snippets[$n][$i] as $subnode)
  184. {
  185. $master->insertBefore($cloned = clone $subnode, $node);
  186. $this->_enqueue($cloned);
  187. }
  188. $master->removeChild($node);
  189. $node->set('postprocess', true);
  190. }
  191. } // end _processParent();
  192. /**
  193. * A postprocessing routine for opt:parent
  194. * @internal
  195. * @param Opt_Xml_Element $node The found element
  196. */
  197. public function _postprocessParent(Opt_Xml_Element $node)
  198. {
  199. $this->_compiler->set('escaping', $node->get('escaping'));
  200. } // end _postprocessParent();
  201. /**
  202. * Processes the opt:insert element.
  203. * @internal
  204. * @param Opt_Xml_Element $node The found element
  205. */
  206. public function _processInsert(Opt_Xml_Element $node)
  207. {
  208. // A support for the dynamically chosen part captured by opt:capture
  209. if($node->getAttribute('captured') !== NULL)
  210. {
  211. $params = array(
  212. 'captured' => array(0 => self::REQUIRED, self::EXPRESSION)
  213. );
  214. $this->_extractAttributes($node, $params);
  215. if($node->hasChildren())
  216. {
  217. $node->addBefore(Opt_Xml_Buffer::TAG_BEFORE, 'if(!isset(self::$_capture['.$params['captured'].'])){ ');
  218. $node->addAfter(Opt_Xml_Buffer::TAG_AFTER, '} else { echo self::$_capture['.$params['captured'].']; } ');
  219. $this->_process($node);
  220. }
  221. else
  222. {
  223. $node->addBefore(Opt_Xml_Buffer::TAG_BEFORE, 'if(isset(self::$_capture['.$params['captured'].'])){ echo self::$_capture['.$params['captured'].']; } ');
  224. }
  225. }
  226. else
  227. {
  228. // Snippet insertion
  229. $params = array(
  230. 'snippet' => array(0 => self::REQUIRED, self::ID),
  231. 'ignoredefault' => array(0 => self::OPTIONAL, self::BOOL, false)
  232. );
  233. $this->_extractAttributes($node, $params);
  234. if(in_array($params['snippet'], $this->_current))
  235. {
  236. array_push($this->_current, $params['snippet']);
  237. $err = new Opt_SnippetRecursion_Exception($params['snippet']);
  238. throw $err->setData($this->_current);
  239. }
  240. if(isset($this->_snippets[$params['snippet']]))
  241. {
  242. array_push($this->_current, $params['snippet']);
  243. $snippet = &$this->_snippets[$params['snippet']];
  244. // Move all the stuff to the fake node.
  245. if($node->hasChildren() && $params['ignoredefault'] == false)
  246. {
  247. $newNode = new Opt_Xml_Element('opt:_');
  248. $newNode->set('escaping', $this->_compiler->get('escaping'));
  249. $newNode->moveChildren($node);
  250. $size = sizeof($snippet);
  251. $snippet[$size] = $newNode;
  252. $node->set('insertSize', $size);
  253. }
  254. // We must do the cleaning for the inserted node.
  255. $node->removeChildren();
  256. // Process the snippets
  257. $node->set('escaping', $this->_compiler->get('escaping'));
  258. $this->_compiler->set('escaping', $snippet[0]->get('escaping'));
  259. foreach($snippet[0] as $subnode)
  260. {
  261. $node->appendChild(clone $subnode);
  262. }
  263. $this->_process($node);
  264. $node->set('insertSnippet', $params['snippet']);
  265. $node->set('postprocess', true);
  266. }
  267. else
  268. {
  269. // Processing the default content - snippet not found.
  270. $this->_process($node);
  271. }
  272. }
  273. } // end _processInsert();
  274. /**
  275. * Postprocesses the opt:insert element.
  276. * @internal
  277. * @param Opt_Xml_Element $node The found element.
  278. */
  279. public function _postprocessInsert(Opt_Xml_Element $node)
  280. {
  281. // Freeing the fake node, if necessary.
  282. if(!is_null($node->get('insertSize')))
  283. {
  284. $this->_snippets[$node->get('insertSnippet')][$node->get('insertSize')]->dispose();
  285. unset($this->_snippets[$node->get('insertSnippet')][$node->get('insertSize')]);
  286. }
  287. // Restore the original escaping state
  288. $this->_compiler->set('escaping', $node->get('escaping'));
  289. array_pop($this->_current);
  290. } // end _postprocessInsert();
  291. /**
  292. * Returns true, if the snippet with the given name is defined.
  293. * @param string $name The snippet name
  294. * @return boolean
  295. */
  296. public function isSnippet($name)
  297. {
  298. return isset($this->_snippets[$name]);
  299. } // end isSnippet();
  300. } // end Opt_Instruction_Snippet;