You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

smarty_internal_runtime_foreach.php 5.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  1. <?php
  2. /**
  3. * Foreach Runtime Methods count(), init(), restore()
  4. *
  5. * @package Smarty
  6. * @subpackage PluginsInternal
  7. * @author Uwe Tews
  8. *
  9. */
  10. class Smarty_Internal_Runtime_Foreach
  11. {
  12. /**
  13. * Stack of saved variables
  14. *
  15. * @var array
  16. */
  17. private $stack = array();
  18. /**
  19. * Init foreach loop
  20. * - save item and key variables, named foreach property data if defined
  21. * - init item and key variables, named foreach property data if required
  22. * - count total if required
  23. *
  24. * @param \Smarty_Internal_Template $tpl
  25. * @param mixed $from values to loop over
  26. * @param string $item variable name
  27. * @param bool $needTotal flag if we need to count values
  28. * @param null|string $key variable name
  29. * @param null|string $name of named foreach
  30. * @param array $properties of named foreach
  31. *
  32. * @return mixed $from
  33. */
  34. public function init(Smarty_Internal_Template $tpl, $from, $item, $needTotal = false, $key = null, $name = null,
  35. $properties = array())
  36. {
  37. $saveVars = array();
  38. $total = null;
  39. if (!is_array($from)) {
  40. if (is_object($from)) {
  41. $total = $this->count($from);
  42. } else {
  43. settype($from, 'array');
  44. }
  45. }
  46. if (!isset($total)) {
  47. $total = empty($from) ? 0 : (($needTotal || isset($properties[ 'total' ])) ? count($from) : 1);
  48. }
  49. if (isset($tpl->tpl_vars[ $item ])) {
  50. $saveVars[ 'item' ] = array($item,
  51. $tpl->tpl_vars[ $item ]);
  52. }
  53. $tpl->tpl_vars[ $item ] = new Smarty_Variable(null, $tpl->isRenderingCache);
  54. if ($total === 0) {
  55. $from = null;
  56. } else {
  57. if ($key) {
  58. if (isset($tpl->tpl_vars[ $key ])) {
  59. $saveVars[ 'key' ] = array($key,
  60. $tpl->tpl_vars[ $key ]);
  61. }
  62. $tpl->tpl_vars[ $key ] = new Smarty_Variable(null, $tpl->isRenderingCache);
  63. }
  64. }
  65. if ($needTotal) {
  66. $tpl->tpl_vars[ $item ]->total = $total;
  67. }
  68. if ($name) {
  69. $namedVar = "__smarty_foreach_{$name}";
  70. if (isset($tpl->tpl_vars[ $namedVar ])) {
  71. $saveVars[ 'named' ] = array($namedVar,
  72. $tpl->tpl_vars[ $namedVar ]);
  73. }
  74. $namedProp = array();
  75. if (isset($properties[ 'total' ])) {
  76. $namedProp[ 'total' ] = $total;
  77. }
  78. if (isset($properties[ 'iteration' ])) {
  79. $namedProp[ 'iteration' ] = 0;
  80. }
  81. if (isset($properties[ 'index' ])) {
  82. $namedProp[ 'index' ] = - 1;
  83. }
  84. if (isset($properties[ 'show' ])) {
  85. $namedProp[ 'show' ] = ($total > 0);
  86. }
  87. $tpl->tpl_vars[ $namedVar ] = new Smarty_Variable($namedProp);
  88. }
  89. $this->stack[] = $saveVars;
  90. return $from;
  91. }
  92. /**
  93. *
  94. * [util function] counts an array, arrayAccess/traversable or PDOStatement object
  95. *
  96. * @param mixed $value
  97. *
  98. * @return int the count for arrays and objects that implement countable, 1 for other objects that don't, and 0
  99. * for empty elements
  100. */
  101. public function count($value)
  102. {
  103. if ($value instanceof IteratorAggregate) {
  104. // Note: getIterator() returns a Traversable, not an Iterator
  105. // thus rewind() and valid() methods may not be present
  106. return iterator_count($value->getIterator());
  107. } elseif ($value instanceof Iterator) {
  108. return $value instanceof Generator ? 1 : iterator_count($value);
  109. } elseif ($value instanceof Countable) {
  110. return count($value);
  111. } elseif ($value instanceof PDOStatement) {
  112. return $value->rowCount();
  113. } elseif ($value instanceof Traversable) {
  114. return iterator_count($value);
  115. }
  116. return count((array) $value);
  117. }
  118. /**
  119. * Restore saved variables
  120. *
  121. * will be called by {break n} or {continue n} for the required number of levels
  122. *
  123. * @param \Smarty_Internal_Template $tpl
  124. * @param int $levels number of levels
  125. */
  126. public function restore(Smarty_Internal_Template $tpl, $levels = 1)
  127. {
  128. while ($levels) {
  129. $saveVars = array_pop($this->stack);
  130. if (!empty($saveVars)) {
  131. if (isset($saveVars[ 'item' ])) {
  132. $item = &$saveVars[ 'item' ];
  133. $tpl->tpl_vars[ $item[ 0 ] ]->value = $item[ 1 ]->value;
  134. }
  135. if (isset($saveVars[ 'key' ])) {
  136. $tpl->tpl_vars[ $saveVars[ 'key' ][ 0 ] ] = $saveVars[ 'key' ][ 1 ];
  137. }
  138. if (isset($saveVars[ 'named' ])) {
  139. $tpl->tpl_vars[ $saveVars[ 'named' ][ 0 ] ] = $saveVars[ 'named' ][ 1 ];
  140. }
  141. }
  142. $levels --;
  143. }
  144. }
  145. }