Skip to content

Commit a7b3356

Browse files
committed
Merge remote-tracking branch 'mainline/develop' into MAGETWO-69383
2 parents df1d483 + d844e31 commit a7b3356

File tree

71 files changed

+2488
-948
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

71 files changed

+2488
-948
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,3 +66,4 @@ atlassian*
6666
!/vendor/.htaccess
6767
/generated/*
6868
!/generated/.htaccess
69+
.DS_Store

.travis.yml

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,19 +22,22 @@ env:
2222
- MAGENTO_HOST_NAME="magento2.travis"
2323
matrix:
2424
- TEST_SUITE=unit
25+
- TEST_SUITE=static
26+
- TEST_SUITE=js GRUNT_COMMAND=spec
27+
- TEST_SUITE=js GRUNT_COMMAND=static
2528
- TEST_SUITE=integration INTEGRATION_INDEX=1
2629
- TEST_SUITE=integration INTEGRATION_INDEX=2
2730
- TEST_SUITE=integration INTEGRATION_INDEX=3
28-
- TEST_SUITE=static
29-
- TEST_SUITE=js
3031
- TEST_SUITE=functional ACCEPTANCE_INDEX=1
3132
- TEST_SUITE=functional ACCEPTANCE_INDEX=2
3233
matrix:
3334
exclude:
3435
- php: 7.0
3536
env: TEST_SUITE=static
3637
- php: 7.0
37-
env: TEST_SUITE=js
38+
env: TEST_SUITE=js GRUNT_COMMAND=spec
39+
- php: 7.0
40+
env: TEST_SUITE=js GRUNT_COMMAND=static
3841
- php: 7.0
3942
env: TEST_SUITE=functional ACCEPTANCE_INDEX=1
4043
- php: 7.0
@@ -49,4 +52,11 @@ cache:
4952
before_install: ./dev/travis/before_install.sh
5053
install: composer install --no-interaction --prefer-dist
5154
before_script: ./dev/travis/before_script.sh
52-
script: ./dev/travis/script.sh
55+
script:
56+
# Set arguments for variants of phpunit based tests; '|| true' prevents failing script when leading test fails
57+
- test $TEST_SUITE = "static" && TEST_FILTER='--filter "Magento\\Test\\Php\\LiveCodeTest"' || true
58+
- test $TEST_SUITE = "functional" && TEST_FILTER='dev/tests/functional/testsuites/Magento/Mtf/TestSuite/InjectableTests.php' || true
59+
60+
# The scripts for grunt/phpunit type tests
61+
- if [ $TEST_SUITE != "js" ]; then phpunit -c dev/tests/$TEST_SUITE $TEST_FILTER; fi
62+
- if [ $TEST_SUITE == "js" ]; then grunt $GRUNT_COMMAND; fi

CONTRIBUTING.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,3 +29,8 @@ If you are a new GitHub user, we recommend that you create your own [free github
2929
3. Create and test your work.
3030
4. Fork the Magento 2 repository according to [Fork a repository instructions](http://devdocs.magento.com/guides/v2.0/contributor-guide/contributing.html#fork) and when you are ready to send us a pull request – follow [Create a pull request instructions](http://devdocs.magento.com/guides/v2.0/contributor-guide/contributing.html#pull_request).
3131
5. Once your contribution is received, Magento 2 development team will review the contribution and collaborate with you as needed to improve the quality of the contribution.
32+
33+
## Code of Conduct
34+
35+
Please note that this project is released with a Contributor Code of Conduct. We expect you to agree to its terms when participating in this project.
36+
The full text is available in the repository [Wiki](https://github.com/magento/magento2/wiki/Magento-Code-of-Conduct).

app/code/Magento/Catalog/Controller/Adminhtml/Product/Save.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,7 @@ public function execute()
144144
$this->messageManager->addSuccess(__('You duplicated the product.'));
145145
}
146146
} catch (\Magento\Framework\Exception\LocalizedException $e) {
147+
$this->_objectManager->get(\Psr\Log\LoggerInterface::class)->critical($e);
147148
$this->messageManager->addError($e->getMessage());
148149
$this->getDataPersistor()->set('catalog_product', $data);
149150
$redirectBack = $productId ? true : 'new';

app/code/Magento/Catalog/Model/Product.php

Lines changed: 69 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2509,13 +2509,15 @@ public function setTypeId($typeId)
25092509
/**
25102510
* {@inheritdoc}
25112511
*
2512-
* @return \Magento\Catalog\Api\Data\ProductExtensionInterface|null
2512+
* @return \Magento\Catalog\Api\Data\ProductExtensionInterface
25132513
*/
25142514
public function getExtensionAttributes()
25152515
{
25162516
$extensionAttributes = $this->_getExtensionAttributes();
2517-
if (!$extensionAttributes) {
2518-
return $this->extensionAttributesFactory->create(\Magento\Catalog\Api\Data\ProductInterface::class);
2517+
if (null === $extensionAttributes) {
2518+
/** @var \Magento\Catalog\Api\Data\ProductExtensionInterface $extensionAttributes */
2519+
$extensionAttributes = $this->extensionAttributesFactory->create(ProductInterface::class);
2520+
$this->setExtensionAttributes($extensionAttributes);
25192521
}
25202522
return $extensionAttributes;
25212523
}
@@ -2639,4 +2641,68 @@ public function setAssociatedProductIds(array $productIds)
26392641
$this->getExtensionAttributes()->setConfigurableProductLinks($productIds);
26402642
return $this;
26412643
}
2644+
2645+
/**
2646+
* Get quantity and stock status data
2647+
*
2648+
* @return array|null
2649+
*
2650+
* @deprecated as Product model shouldn't be responsible for stock status
2651+
* @see StockItemInterface when you want to change the stock data
2652+
* @see StockStatusInterface when you want to read the stock data for representation layer (storefront)
2653+
* @see StockItemRepositoryInterface::save as extension point for customization of saving process
2654+
*/
2655+
public function getQuantityAndStockStatus()
2656+
{
2657+
return $this->getData('quantity_and_stock_status');
2658+
}
2659+
2660+
/**
2661+
* Set quantity and stock status data
2662+
*
2663+
* @param array $quantityAndStockStatusData
2664+
* @return $this
2665+
*
2666+
* @deprecated as Product model shouldn't be responsible for stock status
2667+
* @see StockItemInterface when you want to change the stock data
2668+
* @see StockStatusInterface when you want to read the stock data for representation layer (storefront)
2669+
* @see StockItemRepositoryInterface::save as extension point for customization of saving process
2670+
*/
2671+
public function setQuantityAndStockStatus($quantityAndStockStatusData)
2672+
{
2673+
$this->setData('quantity_and_stock_status', $quantityAndStockStatusData);
2674+
return $this;
2675+
}
2676+
2677+
/**
2678+
* Get stock data
2679+
*
2680+
* @return array|null
2681+
*
2682+
* @deprecated as Product model shouldn't be responsible for stock status
2683+
* @see StockItemInterface when you want to change the stock data
2684+
* @see StockStatusInterface when you want to read the stock data for representation layer (storefront)
2685+
* @see StockItemRepositoryInterface::save as extension point for customization of saving process
2686+
*/
2687+
public function getStockData()
2688+
{
2689+
return $this->getData('stock_data');
2690+
}
2691+
2692+
/**
2693+
* Set stock data
2694+
*
2695+
* @param array $stockData
2696+
* @return $this
2697+
*
2698+
* @deprecated as Product model shouldn't be responsible for stock status
2699+
* @see StockItemInterface when you want to change the stock data
2700+
* @see StockStatusInterface when you want to read the stock data for representation layer (storefront)
2701+
* @see StockItemRepositoryInterface::save as extension point for customization of saving process
2702+
*/
2703+
public function setStockData($stockData)
2704+
{
2705+
$this->setData('stock_data', $stockData);
2706+
return $this;
2707+
}
26422708
}

app/code/Magento/Catalog/Model/Product/Attribute/Backend/Stock.php

Lines changed: 5 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,17 @@
33
* Copyright © Magento, Inc. All rights reserved.
44
* See COPYING.txt for license details.
55
*/
6-
76
namespace Magento\Catalog\Model\Product\Attribute\Backend;
87

98
use Magento\Catalog\Model\Product;
109

1110
/**
1211
* Quantity and Stock Status attribute processing
12+
*
13+
* @deprecated as this attribute should be removed
14+
* @see StockItemInterface when you want to change the stock data
15+
* @see StockStatusInterface when you want to read the stock data for representation layer (storefront)
16+
* @see StockItemRepositoryInterface::save as extension point for customization of saving process
1317
*/
1418
class Stock extends \Magento\Eav\Model\Entity\Attribute\Backend\AbstractBackend
1519
{
@@ -47,25 +51,6 @@ public function afterLoad($object)
4751
return parent::afterLoad($object);
4852
}
4953

50-
/**
51-
* Prepare inventory data from custom attribute
52-
*
53-
* @param Product $object
54-
* @return void
55-
*/
56-
public function beforeSave($object)
57-
{
58-
$stockData = $object->getData($this->getAttribute()->getAttributeCode());
59-
if (isset($stockData['qty']) && $stockData['qty'] === '') {
60-
$stockData['qty'] = null;
61-
}
62-
if ($object->getStockData() !== null && $stockData !== null) {
63-
$object->setStockData(array_replace((array)$object->getStockData(), (array)$stockData));
64-
}
65-
$object->unsetData($this->getAttribute()->getAttributeCode());
66-
parent::beforeSave($object);
67-
}
68-
6954
/**
7055
* Validate
7156
*

app/code/Magento/Catalog/Model/Product/Copier.php

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,9 @@ public function copy(\Magento\Catalog\Model\Product $product)
5959

6060
/** @var \Magento\Catalog\Model\Product $duplicate */
6161
$duplicate = $this->productFactory->create();
62-
$duplicate->setData($product->getData());
62+
$productData = $product->getData();
63+
$productData = $this->removeStockItem($productData);
64+
$duplicate->setData($productData);
6365
$duplicate->setOptions([]);
6466
$duplicate->setIsDuplicate(true);
6567
$duplicate->setOriginalLinkId($product->getData($metadata->getLinkField()));
@@ -116,4 +118,21 @@ private function getMetadataPool()
116118
}
117119
return $this->metadataPool;
118120
}
121+
122+
/**
123+
* Remove stock item
124+
*
125+
* @param array $productData
126+
* @return array
127+
*/
128+
private function removeStockItem(array $productData)
129+
{
130+
if (isset($productData[ProductInterface::EXTENSION_ATTRIBUTES_KEY])) {
131+
$extensionAttributes = $productData[ProductInterface::EXTENSION_ATTRIBUTES_KEY];
132+
if (null !== $extensionAttributes->getStockItem()) {
133+
$extensionAttributes->setData('stock_item', null);
134+
}
135+
}
136+
return $productData;
137+
}
119138
}

app/code/Magento/Catalog/Model/ProductRepository.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -634,7 +634,7 @@ public function save(\Magento\Catalog\Api\Data\ProductInterface $product, $saveO
634634
} catch (LocalizedException $e) {
635635
throw $e;
636636
} catch (\Exception $e) {
637-
throw new \Magento\Framework\Exception\CouldNotSaveException(__('Unable to save product'));
637+
throw new \Magento\Framework\Exception\CouldNotSaveException(__('Unable to save product'), $e);
638638
}
639639
unset($this->instances[$product->getSku()]);
640640
unset($this->instancesById[$product->getId()]);

app/code/Magento/Catalog/Test/Unit/Model/Product/Attribute/Backend/StockTest.php

Lines changed: 0 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -74,68 +74,4 @@ public function testAfterLoad()
7474
$this->assertEquals(1, $data[self::ATTRIBUTE_NAME]['is_in_stock']);
7575
$this->assertEquals(5, $data[self::ATTRIBUTE_NAME]['qty']);
7676
}
77-
78-
public function testBeforeSave()
79-
{
80-
$object = new \Magento\Framework\DataObject(
81-
[
82-
self::ATTRIBUTE_NAME => ['is_in_stock' => 1, 'qty' => 5],
83-
'stock_data' => ['is_in_stock' => 2, 'qty' => 2],
84-
]
85-
);
86-
$stockData = $object->getStockData();
87-
$this->assertEquals(2, $stockData['is_in_stock']);
88-
$this->assertEquals(2, $stockData['qty']);
89-
$this->assertNotEmpty($object->getData(self::ATTRIBUTE_NAME));
90-
91-
$this->model->beforeSave($object);
92-
93-
$stockData = $object->getStockData();
94-
$this->assertEquals(1, $stockData['is_in_stock']);
95-
$this->assertEquals(5, $stockData['qty']);
96-
$this->assertNull($object->getData(self::ATTRIBUTE_NAME));
97-
}
98-
99-
public function testBeforeSaveQtyIsEmpty()
100-
{
101-
$object = new \Magento\Framework\DataObject(
102-
[
103-
self::ATTRIBUTE_NAME => ['is_in_stock' => 1, 'qty' => ''],
104-
'stock_data' => ['is_in_stock' => 2, 'qty' => ''],
105-
]
106-
);
107-
108-
$this->model->beforeSave($object);
109-
110-
$stockData = $object->getStockData();
111-
$this->assertNull($stockData['qty']);
112-
}
113-
114-
public function testBeforeSaveQtyIsZero()
115-
{
116-
$object = new \Magento\Framework\DataObject(
117-
[
118-
self::ATTRIBUTE_NAME => ['is_in_stock' => 1, 'qty' => 0],
119-
'stock_data' => ['is_in_stock' => 2, 'qty' => 0],
120-
]
121-
);
122-
123-
$this->model->beforeSave($object);
124-
125-
$stockData = $object->getStockData();
126-
$this->assertEquals(0, $stockData['qty']);
127-
}
128-
129-
public function testBeforeSaveNoStockData()
130-
{
131-
$object = new \Magento\Framework\DataObject(
132-
[
133-
self::ATTRIBUTE_NAME => ['is_in_stock' => 1, 'qty' => 0]
134-
]
135-
);
136-
137-
$this->model->beforeSave($object);
138-
$this->assertNull($object->getStockData());
139-
$this->assertNull($object->getData(self::ATTRIBUTE_NAME));
140-
}
14177
}

app/code/Magento/Catalog/Test/Unit/Model/Product/CopierTest.php

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,12 @@
55
*/
66
namespace Magento\Catalog\Test\Unit\Model\Product;
77

8+
use Magento\Catalog\Api\Data\ProductInterface;
89
use \Magento\Catalog\Model\Product\Copier;
910

11+
/**
12+
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
13+
*/
1014
class CopierTest extends \PHPUnit_Framework_TestCase
1115
{
1216
/**
@@ -80,10 +84,28 @@ protected function setUp()
8084

8185
public function testCopy()
8286
{
87+
$stockItem = $this->getMockBuilder(\Magento\CatalogInventory\Api\Data\StockItemInterface::class)
88+
->getMock();
89+
$extensionAttributes = $this->getMockBuilder(\Magento\Catalog\Api\Data\ProductExtension::class)
90+
->setMethods(['getStockItem', 'setData'])
91+
->getMock();
92+
$extensionAttributes
93+
->expects($this->once())
94+
->method('getStockItem')
95+
->willReturn($stockItem);
96+
$extensionAttributes
97+
->expects($this->once())
98+
->method('setData')
99+
->with('stock_item', null);
100+
101+
$productData = [
102+
'product data' => ['product data'],
103+
ProductInterface::EXTENSION_ATTRIBUTES_KEY => $extensionAttributes,
104+
];
83105
$this->productMock->expects($this->atLeastOnce())->method('getWebsiteIds');
84106
$this->productMock->expects($this->atLeastOnce())->method('getCategoryIds');
85107
$this->productMock->expects($this->any())->method('getData')->willReturnMap([
86-
['', null, 'product data'],
108+
['', null, $productData],
87109
['linkField', null, '1'],
88110
]);
89111

@@ -135,7 +157,7 @@ public function testCopy()
135157
)->with(
136158
\Magento\Store\Model\Store::DEFAULT_STORE_ID
137159
);
138-
$duplicateMock->expects($this->once())->method('setData')->with('product data');
160+
$duplicateMock->expects($this->once())->method('setData')->with($productData);
139161
$this->copyConstructorMock->expects($this->once())->method('build')->with($this->productMock, $duplicateMock);
140162
$duplicateMock->expects($this->once())->method('getUrlKey')->willReturn('urk-key-1');
141163
$duplicateMock->expects($this->once())->method('setUrlKey')->with('urk-key-2');

0 commit comments

Comments
 (0)