ReplaceIterator.php 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  1. <?php
  2. /**
  3. * CakePHP(tm) : Rapid Development Framework (https://cakephp.org)
  4. * Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
  5. *
  6. * Licensed under The MIT License
  7. * For full copyright and license information, please see the LICENSE.txt
  8. * Redistributions of files must retain the above copyright notice.
  9. *
  10. * @copyright Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
  11. * @link https://cakephp.org CakePHP(tm) Project
  12. * @since 3.0.0
  13. * @license https://opensource.org/licenses/mit-license.php MIT License
  14. */
  15. namespace Cake\Collection\Iterator;
  16. use ArrayIterator;
  17. use Cake\Collection\Collection;
  18. use Cake\Collection\CollectionInterface;
  19. /**
  20. * Creates an iterator from another iterator that will modify each of the values
  21. * by converting them using a callback function.
  22. */
  23. class ReplaceIterator extends Collection
  24. {
  25. /**
  26. * The callback function to be used to transform values
  27. *
  28. * @var callable
  29. */
  30. protected $_callback;
  31. /**
  32. * A reference to the internal iterator this object is wrapping.
  33. *
  34. * @var \Iterator
  35. */
  36. protected $_innerIterator;
  37. /**
  38. * Creates an iterator from another iterator that will modify each of the values
  39. * by converting them using a callback function.
  40. *
  41. * Each time the callback is executed it will receive the value of the element
  42. * in the current iteration, the key of the element and the passed $items iterator
  43. * as arguments, in that order.
  44. *
  45. * @param array|\Traversable $items The items to be filtered.
  46. * @param callable $callback Callback.
  47. */
  48. public function __construct($items, callable $callback)
  49. {
  50. $this->_callback = $callback;
  51. parent::__construct($items);
  52. $this->_innerIterator = $this->getInnerIterator();
  53. }
  54. /**
  55. * Returns the value returned by the callback after passing the current value in
  56. * the iteration
  57. *
  58. * @return mixed
  59. */
  60. public function current()
  61. {
  62. $callback = $this->_callback;
  63. return $callback(parent::current(), $this->key(), $this->_innerIterator);
  64. }
  65. /**
  66. * {@inheritDoc}
  67. *
  68. * We perform here some strictness analysis so that the
  69. * iterator logic is bypassed entirely.
  70. *
  71. * @return \Iterator
  72. */
  73. public function unwrap()
  74. {
  75. $iterator = $this->_innerIterator;
  76. if ($iterator instanceof CollectionInterface) {
  77. $iterator = $iterator->unwrap();
  78. }
  79. if (get_class($iterator) !== ArrayIterator::class) {
  80. return $this;
  81. }
  82. // ArrayIterator can be traversed strictly.
  83. // Let's do that for performance gains
  84. $callback = $this->_callback;
  85. $res = [];
  86. foreach ($iterator as $k => $v) {
  87. $res[$k] = $callback($v, $k, $iterator);
  88. }
  89. return new ArrayIterator($res);
  90. }
  91. }