Skip to content
Browse files

Re-implementing Collection::insert using a special iterator class for

this job. Using Multiple iterator had too many shortcomings to actually
be useful.
  • Loading branch information...
1 parent d60d7f1 commit f91bec12ce3877cd4924a6f5dbcf319b8449f994 @lorenzo lorenzo committed
View
22 src/Collection/CollectionTrait.php
@@ -22,7 +22,7 @@
use Cake\Collection\Iterator\MapReduce;
use Cake\Collection\Iterator\ReplaceIterator;
use Cake\Collection\Iterator\SortIterator;
-use Cake\Collection\Iterator\SyncIterator;
+use Cake\Collection\Iterator\InsertIterator;
use LimitIterator;
/**
@@ -752,25 +752,7 @@ public function nest($idPath, $parentPath) {
}
public function insert($path, $values) {
- $iterator = new SyncIterator($this, new Collection($values));
- $collection = new Collection($iterator);
- $path = explode('.', $path);
- $target = array_pop($path);
-
- return $collection->map(function($values) use ($path, $target) {
- list($row, $insert) = $values;
- $pointer =& $row;
-
- foreach ($path as $step) {
- if (!isset($pointer[$step])) {
- return $row;
- }
- $pointer =& $pointer[$step];
- }
-
- $pointer[$target] = $insert;
- return $row;
- });
+ return new InsertIterator($this, $path, $values);
}
/**
View
132 src/Collection/Iterator/InsertIterator.php
@@ -0,0 +1,132 @@
+<?php
+/**
+ * CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
+ * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
+ *
+ * Licensed under The MIT License
+ * For full copyright and license information, please see the LICENSE.txt
+ * Redistributions of files must retain the above copyright notice.
+ *
+ * @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
+ * @link http://cakephp.org CakePHP(tm) Project
+ * @since CakePHP(tm) v 3.0.0
+ * @license MIT License (http://www.opensource.org/licenses/mit-license.php)
+ */
+namespace Cake\Collection\Iterator;
+
+use Cake\Collection\Collection;
+
+/**
+ * This iterator will insert values into a property of each of the records returned.
+ * The values to be inserted come out of another traversal object. This is useful
+ * when you have two separate collections and want to merge them toghether by placing
+ * each of the values from one collection into a property inside the other collection.
+ */
+class InsertIterator extends Collection {
+
+/**
+ * The collection from which to extract the values to be inserted
+ *
+ * @var \Cake\Collection\Collection
+ */
+ protected $_values;
+
+/**
+ * Holds whether the values colelction is still valid. (has more records)
+ *
+ * @var boolean
+ */
+ protected $_validValues = true;
+
+/**
+ * An array containing each of the properties to be traversed to reach the
+ * point where the values should be inserted.
+ *
+ * @var array
+ */
+ protected $_path;
+
+/**
+ * The property name to which values will be assigned
+ *
+ * @var string
+ */
+ protected $_target;
+
+/**
+ * Constructs a new collection that will dynamically add properties to it out of
+ * the values found in $values.
+ *
+ * @param array|\Traversable $into The target collection to which the values will
+ * be inserted at the specified path.
+ * @param string $path A dot separated list of properties that need to be traversed
+ * to insert the value into the target collection.
+ * @param array|\Traversable $values The source collection from which the values will
+ * be inserted at the specified path.
+ */
+ public function __construct($into, $path, $values) {
+ parent::__construct($into);
+
+ if (!($values instanceof Collection)) {
+ $values = new Collection($values);
+ }
+
+ $path = explode('.', $path);
+ $target = array_pop($path);
+ $this->_path = $path;
+ $this->_target = $target;
+ $this->_values = $values;
+ }
+
+/**
+ * Advances the cursor to the next record
+ *
+ * @return void
+ */
+ public function next() {
+ parent::next();
+ if ($this->_validValues) {
+ $this->_values->next();
+ }
+ $this->_validValues = $this->_values->valid();
+ }
+
+/**
+ * Returns the current element in the target collection after inserting
+ * the value from the source collection into the specified path.
+ *
+ * @return void
+ */
+
+ public function current() {
+ $row = parent::current();
+
+ if (!$this->_validValues) {
+ return $row;
+ }
+
+ $pointer =& $row;
+ foreach ($this->_path as $step) {
+ if (!isset($pointer[$step])) {
+ return $row;
+ }
+ $pointer =& $pointer[$step];
+ }
+
+ $pointer[$this->_target] = $this->_values->current();
+ return $row;
+ }
+
+/**
+ * Resets the collection pointer.
+ *
+ * @return void
+ */
+ public function rewind() {
+ parent::rewind();
+ $this->_values->rewind();
+ $this->_validValues = $this->_values->valid();
+ }
+
+}
+
View
34 src/Collection/Iterator/SyncIterator.php
@@ -1,34 +0,0 @@
-<?php
-/**
- * CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
- * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
- *
- * Licensed under The MIT License
- * For full copyright and license information, please see the LICENSE.txt
- * Redistributions of files must retain the above copyright notice.
- *
- * @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
- * @link http://cakephp.org CakePHP(tm) Project
- * @since CakePHP(tm) v 3.0.0
- * @license MIT License (http://www.opensource.org/licenses/mit-license.php)
- */
-namespace Cake\Collection\Iterator;
-
-use Iterator;
-use MultipleIterator;
-
-class SyncIterator extends MultipleIterator {
-
- public function __construct(Iterator $left, Iterator $right) {
- $flags = static::MIT_NEED_ANY|static::MIT_KEYS_NUMERIC;
- parent::__construct($flags);
- $this->attachIterator($left);
- $this->attachIterator($right);
- }
-
- public function key() {
- $key = parent::key();
- return $key[0];
- }
-
-}

0 comments on commit f91bec1

Please sign in to comment.
Something went wrong with that request. Please try again.