diff --git a/lib/internal/Magento/Framework/Data/Collection.php b/lib/internal/Magento/Framework/Data/Collection.php index 916f5c294762c..03ab3a7193f9b 100644 --- a/lib/internal/Magento/Framework/Data/Collection.php +++ b/lib/internal/Magento/Framework/Data/Collection.php @@ -515,17 +515,29 @@ public function walk($callback, array $args = []) } /** - * @param string|array $objMethod + * Call method or callback on each item in the collection. + * + * @param string|array|\Closure $objMethod * @param array $args * @return void */ public function each($objMethod, $args = []) { - foreach ($args->_items as $k => $item) { - $args->_items[$k] = call_user_func($objMethod, $item); + if ($objMethod instanceof \Closure) { + foreach ($this->getItems() as $item) { + $objMethod($item, ...$args); + } + } elseif (is_array($objMethod)) { + foreach ($this->getItems() as $item) { + call_user_func($objMethod, $item, ...$args); + } + } else { + foreach ($this->getItems() as $item) { + $item->$objMethod(...$args); + } } } - + /** * Setting data for all collection items * diff --git a/lib/internal/Magento/Framework/Data/Test/Unit/CollectionTest.php b/lib/internal/Magento/Framework/Data/Test/Unit/CollectionTest.php index 7705cf35c7e9b..cafb0a284beb9 100644 --- a/lib/internal/Magento/Framework/Data/Test/Unit/CollectionTest.php +++ b/lib/internal/Magento/Framework/Data/Test/Unit/CollectionTest.php @@ -173,4 +173,85 @@ public function testPossibleFlowWithItem() $this->_model->removeAllItems(); $this->assertEquals([], $this->_model->getItems()); } + + public function testEachCallsMethodOnEachItemWithNoArgs() + { + for ($i = 0; $i < 3; $i++) { + $item = $this->getMock(\Magento\Framework\DataObject::class, ['testCallback']); + $item->expects($this->once())->method('testCallback')->with(); + $this->_model->addItem($item); + } + $this->_model->each('testCallback'); + } + + public function testEachCallsMethodOnEachItemWithArgs() + { + for ($i = 0; $i < 3; $i++) { + $item = $this->getMock(\Magento\Framework\DataObject::class, ['testCallback']); + $item->expects($this->once())->method('testCallback')->with('a', 'b', 'c'); + $this->_model->addItem($item); + } + $this->_model->each('testCallback', ['a', 'b', 'c']); + } + + public function testCallsClosureWithEachItemAndNoArgs() + { + for ($i = 0; $i < 3; $i++) { + $item = $this->getMock(\Magento\Framework\DataObject::class, ['testCallback']); + $item->expects($this->once())->method('testCallback')->with(); + $this->_model->addItem($item); + } + $this->_model->each(function ($item) { + $item->testCallback(); + }); + } + + public function testCallsClosureWithEachItemAndArgs() + { + for ($i = 0; $i < 3; $i++) { + $item = $this->getMock(\Magento\Framework\DataObject::class, ['testItemCallback']); + $item->expects($this->once())->method('testItemCallback')->with('a', 'b', 'c'); + $this->_model->addItem($item); + } + $this->_model->each(function ($item, ...$args) { + $item->testItemCallback(...$args); + }, ['a', 'b', 'c']); + } + + public function testCallsCallableArrayWithEachItemNoArgs() + { + $mockCallbackObject = $this->getMockBuilder('DummyEachCallbackInstance') + ->setMethods(['testObjCallback']) + ->getMock(); + $mockCallbackObject->method('testObjCallback')->willReturnCallback(function ($item, ...$args) { + $item->testItemCallback(...$args); + }); + + for ($i = 0; $i < 3; $i++) { + $item = $this->getMock(\Magento\Framework\DataObject::class, ['testItemCallback']); + $item->expects($this->once())->method('testItemCallback')->with(); + $this->_model->addItem($item); + } + + $this->_model->each([$mockCallbackObject, 'testObjCallback']); + } + + public function testCallsCallableArrayWithEachItemAndArgs() + { + $mockCallbackObject = $this->getMockBuilder('DummyEachCallbackInstance') + ->setMethods(['testObjCallback']) + ->getMock(); + $mockCallbackObject->method('testObjCallback')->willReturnCallback(function ($item, ...$args) { + $item->testItemCallback(...$args); + }); + + for ($i = 0; $i < 3; $i++) { + $item = $this->getMock(\Magento\Framework\DataObject::class, ['testItemCallback']); + $item->expects($this->once())->method('testItemCallback')->with('a', 'b', 'c'); + $this->_model->addItem($item); + } + + $callback = [$mockCallbackObject, 'testObjCallback']; + $this->_model->each($callback, ['a', 'b', 'c']); + } }