PageRenderTime 56ms CodeModel.GetById 29ms RepoModel.GetById 1ms app.codeStats 0ms

/lib/eztemplate/classes/eztemplatecompiledloop.php

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