diff --git a/app/code/Magento/Bundle/Model/Product/Price.php b/app/code/Magento/Bundle/Model/Product/Price.php index d7dd23bc8931e46a74cc4eb728eaa4858522fa0d..73902761e14a527539f29719f6ba7dc30cdc726c 100644 --- a/app/code/Magento/Bundle/Model/Product/Price.php +++ b/app/code/Magento/Bundle/Model/Product/Price.php @@ -118,9 +118,8 @@ class Price extends \Magento\Catalog\Model\Product\Type\Price { $price = 0.0; if ($product->hasCustomOptions()) { - $customOption = $product->getCustomOption('bundle_selection_ids'); - if ($customOption) { - $selectionIds = unserialize($customOption->getValue()); + $selectionIds = $this->getBundleSelectionIds($product); + if ($selectionIds) { $selections = $product->getTypeInstance()->getSelectionsByIds($selectionIds, $product); $selections->addTierPriceData(); $this->_eventManager->dispatch( @@ -145,6 +144,24 @@ class Price extends \Magento\Catalog\Model\Product\Type\Price return $price; } + /** + * Retrieve array of bundle selection IDs + * + * @param \Magento\Catalog\Model\Product $product + * @return array + */ + protected function getBundleSelectionIds(\Magento\Catalog\Model\Product $product) + { + $customOption = $product->getCustomOption('bundle_selection_ids'); + if ($customOption) { + $selectionIds = unserialize($customOption->getValue()); + if (!empty($selectionIds) && is_array($selectionIds)) { + return $selectionIds; + } + } + return []; + } + /** * Get product final price * diff --git a/app/code/Magento/Bundle/Test/Unit/Model/Product/PriceTest.php b/app/code/Magento/Bundle/Test/Unit/Model/Product/PriceTest.php index 226418b97aed883cabefb2c24e889633c15a5cf0..887d772ea403248fba1ae574e3f5864d0a00fe6b 100644 --- a/app/code/Magento/Bundle/Test/Unit/Model/Product/PriceTest.php +++ b/app/code/Magento/Bundle/Test/Unit/Model/Product/PriceTest.php @@ -146,4 +146,121 @@ class PriceTest extends \PHPUnit_Framework_TestCase [10, 100, 1, true, 10], ]; } + + public function testGetTotalBundleItemsPriceWithNoCustomOptions() + { + $productMock = $this->getMockBuilder('Magento\Catalog\Model\Product') + ->disableOriginalConstructor() + ->getMock(); + + $productMock->expects($this->once()) + ->method('hasCustomOptions') + ->willReturn(false); + + $this->assertEquals(0, $this->model->getTotalBundleItemsPrice($productMock)); + } + + /** + * @param string|null $value + * @dataProvider dataProviderWithEmptyOptions + */ + public function testGetTotalBundleItemsPriceWithEmptyOptions($value) + { + $dataObjectMock = $this->getMockBuilder('Magento\Framework\DataObject') + ->setMethods(['getValue']) + ->disableOriginalConstructor() + ->getMock(); + + $productMock = $this->getMockBuilder('Magento\Catalog\Model\Product') + ->disableOriginalConstructor() + ->getMock(); + + $productMock->expects($this->once()) + ->method('hasCustomOptions') + ->willReturn(true); + $productMock->expects($this->once()) + ->method('getCustomOption') + ->with('bundle_selection_ids') + ->willReturn($dataObjectMock); + + $dataObjectMock->expects($this->once()) + ->method('getValue') + ->willReturn($value); + + $this->assertEquals(0, $this->model->getTotalBundleItemsPrice($productMock)); + } + + /** + * @return array + */ + public function dataProviderWithEmptyOptions() + { + return [ + ['a:0:{}'], + [''], + [null], + ]; + } + + public function testGetTotalBundleItemsPriceWithNoItems() + { + $storeId = 1; + + $dataObjectMock = $this->getMockBuilder('Magento\Framework\DataObject') + ->setMethods(['getValue']) + ->disableOriginalConstructor() + ->getMock(); + + $productMock = $this->getMockBuilder('Magento\Catalog\Model\Product') + ->disableOriginalConstructor() + ->getMock(); + + $productTypeMock = $this->getMockBuilder('Magento\Bundle\Model\Product\Type') + ->disableOriginalConstructor() + ->getMock(); + + $selectionsMock = $this->getMockBuilder('Magento\Bundle\Model\ResourceModel\Selection\Collection') + ->disableOriginalConstructor() + ->getMock(); + + $productMock->expects($this->once()) + ->method('hasCustomOptions') + ->willReturn(true); + $productMock->expects($this->once()) + ->method('getCustomOption') + ->with('bundle_selection_ids') + ->willReturn($dataObjectMock); + $productMock->expects($this->once()) + ->method('getTypeInstance') + ->willReturn($productTypeMock); + $productMock->expects($this->once()) + ->method('getStoreId') + ->willReturn($storeId); + + $dataObjectMock->expects($this->once()) + ->method('getValue') + ->willReturn('a:1:{i:0;s:1:"1";}'); + + $productTypeMock->expects($this->once()) + ->method('getSelectionsByIds') + ->with([1], $productMock) + ->willReturn($selectionsMock); + + $selectionsMock->expects($this->once()) + ->method('addTierPriceData') + ->willReturnSelf(); + $selectionsMock->expects($this->once()) + ->method('getItems') + ->willReturn([]); + + $this->eventManagerMock->expects($this->once()) + ->method('dispatch') + ->with( + 'prepare_catalog_product_collection_prices', + ['collection' => $selectionsMock, 'store_id' => $storeId] + ) + ->willReturnSelf(); + + $this->assertEquals(0, $this->model->getTotalBundleItemsPrice($productMock)); + } }