PageRenderTime 59ms CodeModel.GetById 31ms RepoModel.GetById 1ms app.codeStats 0ms

/lib/eztemplate/classes/eztemplatecompiledloop.php

https://github.com/lserwatka/ezpublish
PHP | 310 lines | 196 code | 36 blank | 78 comment | 20 complexity | c05c95a6a374a0ccafa26de6e4882bda MD5 | raw file
  1. <?php
  2. //
  3. // Definition of eZTemplateCompiledLoop class
  4. //
  5. // Created on: <17-Mar-2005 11:26:59 vs>
  6. //
  7. // ## BEGIN COPYRIGHT, LICENSE AND WARRANTY NOTICE ##
  8. // SOFTWARE NAME: eZ Publish
  9. // SOFTWARE RELEASE: 4.1.x
  10. // COPYRIGHT NOTICE: Copyright (C) 1999-2010 eZ Systems AS
  11. // SOFTWARE LICENSE: GNU General Public License v2.0
  12. // NOTICE: >
  13. // This program is free software; you can redistribute it and/or
  14. // modify it under the terms of version 2.0 of the GNU General
  15. // Public License as published by the Free Software Foundation.
  16. //
  17. // This program is distributed in the hope that it will be useful,
  18. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  19. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  20. // GNU General Public License for more details.
  21. //
  22. // You should have received a copy of version 2.0 of the GNU General
  23. // Public License along with this program; if not, write to the Free
  24. // Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
  25. // MA 02110-1301, USA.
  26. //
  27. //
  28. // ## END COPYRIGHT, LICENSE AND WARRANTY NOTICE ##
  29. //
  30. /*!
  31. \class eZTemplateCompiledLoop eztemplatecompiledloop.php
  32. \ingroup eZTemplateFunctions
  33. \brief Common code for compiling the loop functions
  34. */
  35. class eZTemplateCompiledLoop
  36. {
  37. function eZTemplateCompiledLoop( $name, &$newNodes, $parameters, $nodePlacement, $uniqid,
  38. $node, $tpl, $privateData )
  39. {
  40. $this->Name = $name;
  41. $this->Parameters = $parameters;
  42. $this->NodePlacement = $nodePlacement;
  43. $this->UniqID = $uniqid;
  44. $this->NewNodes =& $newNodes;
  45. $this->Node = $node;
  46. $this->Tpl = $tpl;
  47. $this->PrivateData = $privateData;
  48. }
  49. /*!
  50. * Returns true if sequence has been specified for the loop in its parameters.
  51. */
  52. function hasSequence()
  53. {
  54. return isset( $this->Parameters['sequence_var'] );
  55. }
  56. /*!
  57. * Destroys PHP and template variables defined by the loop.
  58. */
  59. function cleanup()
  60. {
  61. if ( $this->hasSequence() )
  62. $this->destroySequenceVars();
  63. $this->NewNodes[] = eZTemplateNodeTool::createCodePieceNode( "\$skipDelimiter = false;" );
  64. }
  65. /*!
  66. \private
  67. */
  68. function destroySequenceVars()
  69. {
  70. $fName = $this->Name;
  71. $uniqid = $this->UniqID;
  72. $this->NewNodes[] = eZTemplateNodeTool::createVariableUnsetNode( "${fName}_sequence_array_$uniqid" );
  73. $this->NewNodes[] = eZTemplateNodeTool::createVariableUnsetNode( "${fName}_sequence_var_$uniqid" );
  74. $this->NewNodes[] = eZTemplateNodeTool::createVariableUnsetNode( $this->Parameters['sequence_var'][0][1] );
  75. }
  76. /*!
  77. * Create PHP and template variables representing sequence specified for the loop.
  78. */
  79. function createSequenceVars()
  80. {
  81. if ( !$this->hasSequence() )
  82. return;
  83. $fName = $this->Name;
  84. $uniqid = $this->UniqID;
  85. $this->NewNodes[] = eZTemplateNodeTool::createCodePieceNode( "// creating sequence variables for \{$fName} loop" );
  86. $this->NewNodes[] = eZTemplateNodeTool::createVariableNode( false,
  87. $this->Parameters['sequence_array'],
  88. $this->NodePlacement,
  89. array( 'treat-value-as-non-object' => true, 'text-result' => false ),
  90. "${fName}_sequence_array_$uniqid" );
  91. $this->NewNodes[] = eZTemplateNodeTool::createCodePieceNode( "\$${fName}_sequence_var_$uniqid = current( \$${fName}_sequence_array_$uniqid );\n" );
  92. }
  93. /*!
  94. * Export current sequence value to the template variable specified in loop parameters.
  95. */
  96. function setCurrentSequenceValue()
  97. {
  98. if ( !$this->hasSequence() )
  99. return;
  100. $fName = $this->Name;
  101. $uniqid = $this->UniqID;
  102. $seqVar = "${fName}_sequence_var_$uniqid";
  103. $this->NewNodes[] = eZTemplateNodeTool::createCodePieceNode( "// setting current sequence value" );
  104. $this->NewNodes[] = eZTemplateNodeTool::createVariableNode( false, $seqVar, $this->NodePlacement, array(),
  105. $this->Parameters['sequence_var'][0][1],
  106. false, true, true );
  107. }
  108. /*!
  109. * Increments loop sequence.
  110. */
  111. function iterateSequence()
  112. {
  113. if ( !$this->hasSequence() )
  114. return;
  115. $fName = $this->Name;
  116. $uniqid = $this->UniqID;
  117. $seqArray = "${fName}_sequence_array_$uniqid";
  118. $seqVar = "${fName}_sequence_var_$uniqid";
  119. $alterSeqValCode =
  120. "if ( ( \$$seqVar = next( \$$seqArray ) ) === false )\n" .
  121. "{\n" .
  122. " reset( \$$seqArray );\n" .
  123. " \$$seqVar = current( \$$seqArray );\n" .
  124. "}\n";
  125. $this->NewNodes[] = eZTemplateNodeTool::createCodePieceNode( "// sequence iteration" );
  126. $this->NewNodes[] = eZTemplateNodeTool::createCodePieceNode( $alterSeqValCode );
  127. }
  128. /*
  129. * Compiles loop children (=code residing between start and end tags of the loop).
  130. * Besides, does special handling of {break}, {continue}, {skip} and {delimiter} functions.
  131. * \return true if the caller loop should break, false otherwise
  132. */
  133. function processChildren()
  134. {
  135. // process the loop body
  136. $children = eZTemplateNodeTool::extractFunctionNodeChildren( $this->Node );
  137. $transformedChildren = eZTemplateCompiler::processNodeTransformationNodes( $this->Tpl, $this->Node, $children, $this->PrivateData );
  138. $childrenNodes = array();
  139. $delimiter = null;
  140. if ( is_array( $transformedChildren ) )
  141. {
  142. foreach ( $transformedChildren as $child )
  143. {
  144. if ( $child[0] == eZTemplate::NODE_FUNCTION ) // check child type
  145. {
  146. $childFunctionName = $child[2];
  147. if ( $childFunctionName == 'delimiter' )
  148. {
  149. // save delimiter for it to be processed below
  150. $delimiter = $child;
  151. continue;
  152. }
  153. elseif ( $childFunctionName == 'break' )
  154. {
  155. $childrenNodes[] = eZTemplateNodeTool::createCodePieceNode( "break;\n" );
  156. continue;
  157. }
  158. elseif ( $childFunctionName == 'continue' )
  159. {
  160. $childrenNodes[] = eZTemplateNodeTool::createCodePieceNode( "continue;\n" );
  161. continue;
  162. }
  163. elseif ( $childFunctionName == 'skip' )
  164. {
  165. $childrenNodes[] = eZTemplateNodeTool::createCodePieceNode( "\$skipDelimiter = true;\ncontinue;\n" );
  166. continue;
  167. }
  168. }
  169. $childrenNodes[] = $child;
  170. }
  171. }
  172. if ( $delimiter ) // if delimiter is specified
  173. {
  174. $delimiterNodes = eZTemplateNodeTool::extractNodes( $children,
  175. array( 'match' => array( 'type' => 'equal',
  176. 'matches' => array( array( 'match-keys' => array( 0 ),
  177. 'match-with' => eZTemplate::NODE_FUNCTION ),
  178. array( 'match-keys' => array( 2 ),
  179. 'match-with' => 'delimiter' ) ) ) ) );
  180. $delimiterNode = false;
  181. if ( count( $delimiterNodes ) > 0 )
  182. $delimiterNode = $delimiterNodes[0];
  183. $delimiterChildren = eZTemplateNodeTool::extractFunctionNodeChildren( $delimiterNode );
  184. $delimiterParameters = eZTemplateNodeTool::extractFunctionNodeParameters( $delimiterNode );
  185. $checkModulo = array();
  186. $checkModuloEnd = array();
  187. $delemiterModuloValue = array();
  188. if ( isset( $delimiterParameters['modulo'] ) )
  189. {
  190. switch ( $this->Name )
  191. {
  192. case 'foreach':
  193. {
  194. $delimiterModulo = $delimiterParameters['modulo'];
  195. $delimiterModulo = eZTemplateCompiler::processElementTransformationList( $this->Tpl, $delimiterModulo, $delimiterModulo, $this->PrivateData );
  196. // Get unique index
  197. $currentIndex = "\$fe_i_$this->UniqID";
  198. if ( eZTemplateNodeTool::isStaticElement( $delimiterModulo ) )
  199. {
  200. $moduloValue = (int)eZTemplateNodeTool::elementStaticValue( $delimiterModulo );
  201. $matchCode = "( ( $currentIndex ) % $moduloValue ) == 0";
  202. }
  203. else
  204. {
  205. $delemiterModuloValue[] = eZTemplateNodeTool::createVariableNode( false, $delimiterModulo, eZTemplateNodeTool::extractFunctionNodePlacement( $this->Node ),
  206. array( 'spacing' => 0 ), 'moduloValue' );
  207. $matchCode = "( ( $currentIndex ) % \$moduloValue ) == 0";
  208. }
  209. $checkModulo[] = eZTemplateNodeTool::createCodePieceNode( "if ( $matchCode ) // Check modulo\n{" );
  210. $checkModulo[] = eZTemplateNodeTool::createSpacingIncreaseNode( 4 );
  211. $checkModuloEnd[] = eZTemplateNodeTool::createSpacingDecreaseNode( 4 );
  212. $checkModuloEnd[] = eZTemplateNodeTool::createCodePieceNode( "}\n" );
  213. }
  214. }
  215. }
  216. $delimiterNodes = array();
  217. $delimiterNodes[] = eZTemplateNodeTool::createCodePieceNode( "if ( \$skipDelimiter )\n" .
  218. " \$skipDelimiter = false;\n" .
  219. "else\n" .
  220. "{ // delimiter begins" );
  221. $delimiterNodes[] = eZTemplateNodeTool::createSpacingIncreaseNode();
  222. if ( is_array( $delimiter[1] ) ) // if delimiter has children
  223. {
  224. // If modulo is specified
  225. $delimiterNodes = array_merge( $delimiterNodes, $checkModulo );
  226. foreach ( $delimiter[1] as $delimiterChild )
  227. $delimiterNodes[] = $delimiterChild;
  228. // Set end of checking for modulo
  229. $delimiterNodes = array_merge( $delimiterNodes, $checkModuloEnd );
  230. }
  231. $delimiterNodes[] = eZTemplateNodeTool::createSpacingDecreaseNode();
  232. $delimiterNodes[] = eZTemplateNodeTool::createCodePieceNode( "} // delimiter ends\n" );
  233. // we place its code right before other loop children,
  234. // if delemiter and modulo are specified and value of modulo is not static
  235. // $delemiterModuloValue is initialization of variable
  236. // we should place initialization of moduloValue before checking for delimiter
  237. $childrenNodes = array_merge( $delemiterModuloValue, $delimiterNodes, $childrenNodes );
  238. }
  239. $this->NewNodes = array_merge( $this->NewNodes, $childrenNodes );
  240. }
  241. /*!
  242. * Generates loop body.
  243. */
  244. function processBody()
  245. {
  246. // export current sequence value to the specified template variable <$sequence_var>
  247. $this->setCurrentSequenceValue();
  248. // process the loop body
  249. $this->processChildren();
  250. $this->iterateSequence();
  251. }
  252. /*!
  253. * create PHP and template variables needed for the loop.
  254. */
  255. function initVars()
  256. {
  257. // initialize delimiter processing
  258. $this->NewNodes[] = eZTemplateNodeTool::createCodePieceNode( "\$skipDelimiter = true;" );
  259. // initialize sequence
  260. $this->createSequenceVars();
  261. }
  262. ///
  263. /// \privatesection
  264. ///
  265. public $Name;
  266. public $Parameters;
  267. public $NodePlacement;
  268. public $UniqID;
  269. public $NewNodes;
  270. public $Node;
  271. public $Tpl;
  272. public $PrivateData;
  273. }
  274. ?>