Skip to content

Commit 48e8ec6

Browse files
author
Yu Tang
committed
Merge branch 'FearlessKiwis-MAGETWO-28252-catalog-inventory-integration-api' into develop
2 parents 3726867 + 512ac7f commit 48e8ec6

File tree

9 files changed

+849
-7
lines changed

9 files changed

+849
-7
lines changed

app/code/Magento/CatalogInventory/Api/Data/StockItemInterface.php

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ interface StockItemInterface extends ExtensibleDataInterface
5555
const CUSTOMER_GROUP_ID = 'customer_group_id';
5656

5757
/**
58-
* @return int
58+
* @return int|null
5959
*/
6060
public function getItemId();
6161

@@ -66,7 +66,7 @@ public function getItemId();
6666
public function setItemId($itemId);
6767

6868
/**
69-
* @return int
69+
* @return int|null
7070
*/
7171
public function getProductId();
7272

@@ -79,7 +79,7 @@ public function setProductId($productId);
7979
/**
8080
* Retrieve Website Id
8181
*
82-
* @return int
82+
* @return int|null
8383
*/
8484
public function getWebsiteId();
8585

@@ -94,7 +94,7 @@ public function setWebsiteId($websiteId);
9494
/**
9595
* Retrieve stock identifier
9696
*
97-
* @return int
97+
* @return int|null
9898
*/
9999
public function getStockId();
100100

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
<?php
2+
/**
3+
*
4+
* Copyright © 2015 Magento. All rights reserved.
5+
* See COPYING.txt for license details.
6+
*/
7+
8+
namespace Magento\CatalogInventory\Model\Plugin;
9+
10+
class AfterProductLoad
11+
{
12+
/**
13+
* @var \Magento\CatalogInventory\Api\StockRegistryInterface
14+
*/
15+
protected $stockRegistry;
16+
17+
/**
18+
* @var \Magento\Catalog\Api\Data\ProductExtensionFactory
19+
*/
20+
protected $productExtensionFactory;
21+
22+
/**
23+
* @param \Magento\CatalogInventory\Api\StockRegistryInterface $stockRegistry
24+
* @param \Magento\Catalog\Api\Data\ProductExtensionFactory $productExtensionFactory
25+
*/
26+
public function __construct(
27+
\Magento\CatalogInventory\Api\StockRegistryInterface $stockRegistry,
28+
\Magento\Catalog\Api\Data\ProductExtensionFactory $productExtensionFactory
29+
) {
30+
$this->stockRegistry = $stockRegistry;
31+
$this->productExtensionFactory = $productExtensionFactory;
32+
}
33+
34+
/**
35+
* Add stock item information to the product's extension attributes
36+
*
37+
* @param \Magento\Catalog\Model\Product $product
38+
* @return \Magento\Catalog\Model\Product
39+
*/
40+
public function afterLoad(\Magento\Catalog\Model\Product $product)
41+
{
42+
$productExtension = $product->getExtensionAttributes();
43+
if ($productExtension === null) {
44+
$productExtension = $this->productExtensionFactory->create();
45+
}
46+
// stockItem := \Magento\CatalogInventory\Api\Data\StockItemInterface
47+
$productExtension->setStockItem($this->stockRegistry->getStockItem($product->getId()));
48+
$product->setExtensionAttributes($productExtension);
49+
return $product;
50+
}
51+
}
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
<?php
2+
/**
3+
*
4+
* Copyright © 2015 Magento. All rights reserved.
5+
* See COPYING.txt for license details.
6+
*/
7+
8+
namespace Magento\CatalogInventory\Model\Plugin;
9+
10+
class AroundProductRepositorySave
11+
{
12+
/**
13+
* @var \Magento\CatalogInventory\Api\StockRegistryInterface
14+
*/
15+
protected $stockRegistry;
16+
17+
/**
18+
* @var \Magento\Store\Model\StoreManagerInterface
19+
*/
20+
protected $storeManager;
21+
22+
/**
23+
* @param \Magento\CatalogInventory\Api\StockRegistryInterface $stockRegistry
24+
* @param \Magento\Store\Model\StoreManagerInterface $storeManager
25+
*/
26+
public function __construct(
27+
\Magento\CatalogInventory\Api\StockRegistryInterface $stockRegistry,
28+
\Magento\Store\Model\StoreManagerInterface $storeManager
29+
) {
30+
$this->stockRegistry = $stockRegistry;
31+
$this->storeManager = $storeManager;
32+
}
33+
34+
/**
35+
* @param \Magento\Catalog\Api\ProductRepositoryInterface $subject
36+
* @param callable $proceed
37+
* @param \Magento\Catalog\Api\Data\ProductInterface $product
38+
* @param bool $saveOptions
39+
* @return \Magento\Catalog\Api\Data\ProductInterface
40+
* @throws \Magento\Framework\Exception\CouldNotSaveException
41+
*/
42+
public function aroundSave(
43+
\Magento\Catalog\Api\ProductRepositoryInterface $subject,
44+
\Closure $proceed,
45+
\Magento\Catalog\Api\Data\ProductInterface $product,
46+
$saveOptions = false
47+
) {
48+
/** @var \Magento\Catalog\Api\Data\ProductInterface $result */
49+
$result = $proceed($product, $saveOptions);
50+
51+
/* @var \Magento\CatalogInventory\Api\Data\StockItemInterface $stockItem */
52+
$stockItem = $this->getStockItemToBeUpdated($product);
53+
if ($stockItem == null) {
54+
return $result;
55+
}
56+
57+
// set fields that the customer should not care about
58+
$stockItem->setProductId($result->getId());
59+
$stockItem->setWebsiteId($this->storeManager->getStore($result->getStoreId())->getWebsiteId());
60+
61+
$this->stockRegistry->updateStockItemBySku($result->getSku(), $stockItem);
62+
63+
// since we just saved a portion of the product, force a reload of it before returning it
64+
return $subject->get($result->getSku(), false, $result->getStoreId(), true);
65+
}
66+
67+
/**
68+
* Return the stock item that needs to be updated.
69+
* If the stock item does not need to be updated, return null.
70+
*
71+
* @param \Magento\Catalog\Api\Data\ProductInterface $product
72+
* @return \Magento\CatalogInventory\Api\Data\StockItemInterface|null
73+
*/
74+
protected function getStockItemToBeUpdated($product)
75+
{
76+
// from the API, all the data we care about will exist as extension attributes of the original product
77+
$extendedAttributes = $product->getExtensionAttributes();
78+
if ($extendedAttributes !== null) {
79+
$stockItem = $extendedAttributes->getStockItem();
80+
if ($stockItem != null) {
81+
return $stockItem;
82+
}
83+
}
84+
85+
// we have no new stock item information to update, however we need to ensure that the product does have some
86+
// stock item information present. On a newly created product, it will not have any stock item info.
87+
$stockItem = $this->stockRegistry->getStockItem($product->getId());
88+
if ($stockItem->getItemId() != null) {
89+
// we already have stock item info, so we return null since nothing more needs to be updated
90+
return null;
91+
}
92+
93+
return $stockItem;
94+
}
95+
}

app/code/Magento/CatalogInventory/Model/StockRegistry.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515

1616
/**
1717
* Class StockRegistry
18+
*
19+
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
1820
*/
1921
class StockRegistry implements StockRegistryInterface
2022
{
@@ -185,9 +187,7 @@ public function updateStockItemBySku($productSku, \Magento\CatalogInventory\Api\
185187
$origStockItem = $this->getStockItem($productId, $websiteId);
186188
$data = $stockItem->getData();
187189
if ($origStockItem->getItemId()) {
188-
if (isset($data['item_id'])) {
189-
unset($data['item_id']);
190-
}
190+
unset($data['item_id']);
191191
}
192192
$origStockItem->addData($data);
193193
$origStockItem->setProductId($productId);
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
<?php
2+
/**
3+
*
4+
* Copyright © 2015 Magento. All rights reserved.
5+
* See COPYING.txt for license details.
6+
*/
7+
8+
// @codingStandardsIgnoreFile
9+
10+
namespace Magento\CatalogInventory\Test\Unit\Model\Plugin;
11+
12+
class AfterProductLoadTest extends \PHPUnit_Framework_TestCase
13+
{
14+
/**
15+
* @var \Magento\CatalogInventory\Model\Plugin\AfterProductLoad
16+
*/
17+
protected $plugin;
18+
19+
/**
20+
* @var \Magento\Catalog\Api\Data\ProductInterface|\PHPUnit_Framework_MockObject_MockObject
21+
*/
22+
protected $productMock;
23+
24+
/**
25+
* @var \Magento\Catalog\Api\Data\ProductExtensionFactory|\PHPUnit_Framework_MockObject_MockObject
26+
*/
27+
protected $productExtensionFactoryMock;
28+
29+
/**
30+
* @var \Magento\Catalog\Api\Data\ProductExtension|\PHPUnit_Framework_MockObject_MockObject
31+
*/
32+
protected $productExtensionMock;
33+
34+
protected function setUp()
35+
{
36+
$stockRegistryMock = $this->getMock('\Magento\CatalogInventory\Api\StockRegistryInterface');
37+
$this->productExtensionFactoryMock = $this->getMockBuilder('\Magento\Catalog\Api\Data\ProductExtensionFactory')
38+
->disableOriginalConstructor()
39+
->getMock();
40+
41+
$this->plugin = new \Magento\CatalogInventory\Model\Plugin\AfterProductLoad(
42+
$stockRegistryMock,
43+
$this->productExtensionFactoryMock
44+
);
45+
46+
$productId = 5494;
47+
$stockItemMock = $this->getMock('\Magento\CatalogInventory\Api\Data\StockItemInterface');
48+
49+
$stockRegistryMock->expects($this->once())
50+
->method('getStockItem')
51+
->with($productId)
52+
->willReturn($stockItemMock);
53+
54+
$this->productExtensionMock = $this->getMockBuilder('\Magento\Catalog\Api\Data\ProductExtension')
55+
->setMethods(['setStockItem'])
56+
->getMock();
57+
$this->productExtensionMock->expects($this->once())
58+
->method('setStockItem')
59+
->with($stockItemMock)
60+
->willReturnSelf();
61+
62+
$this->productMock = $this->getMockBuilder('\Magento\Catalog\Model\Product')
63+
->disableOriginalConstructor()
64+
->getMock();
65+
$this->productMock->expects($this->once())
66+
->method('setExtensionAttributes')
67+
->with($this->productExtensionMock)
68+
->willReturnSelf();
69+
$this->productMock->expects(($this->once()))
70+
->method('getId')
71+
->will($this->returnValue($productId));
72+
}
73+
74+
public function testAfterLoad()
75+
{
76+
// test when extension attributes are not (yet) present in the product
77+
$this->productMock->expects($this->once())
78+
->method('getExtensionAttributes')
79+
->willReturn(null);
80+
$this->productExtensionFactoryMock->expects($this->once())
81+
->method('create')
82+
->willReturn($this->productExtensionMock);
83+
84+
$this->assertEquals(
85+
$this->productMock,
86+
$this->plugin->afterLoad($this->productMock)
87+
);
88+
}
89+
90+
public function testAfterLoadWithExistingExtensionAttributes()
91+
{
92+
// test when extension attributes already exist
93+
$this->productMock->expects($this->once())
94+
->method('getExtensionAttributes')
95+
->willReturn($this->productExtensionMock);
96+
$this->productExtensionFactoryMock->expects($this->never())
97+
->method('create');
98+
99+
$this->assertEquals(
100+
$this->productMock,
101+
$this->plugin->afterLoad($this->productMock)
102+
);
103+
}
104+
}

0 commit comments

Comments
 (0)