Skip to content

Commit 88225a7

Browse files
author
Joan He
committed
Merge remote-tracking branch 'upstream/develop' into develop
2 parents 5fdd20b + 8e256d4 commit 88225a7

File tree

51 files changed

+1116
-225
lines changed

Some content is hidden

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

51 files changed

+1116
-225
lines changed

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ class Converter
1919
protected function indexBySku(array $products)
2020
{
2121
$converted = [];
22-
foreach($products as $product) {
22+
foreach ($products as $product) {
2323
$converted[$product->getSku()] = $product;
2424
}
2525
return $converted;
@@ -34,7 +34,7 @@ public function convertLinksToGroupedArray($entity)
3434
$basicData = $entity->getProductLinks();
3535
$associatedProducts = $entity->getTypeInstance()->getAssociatedProducts($entity);
3636
$associatedProducts = $this->indexBySku($associatedProducts);
37-
37+
$linksAsArray = [];
3838
/** @var \Magento\Catalog\Api\Data\ProductLinkInterface $link */
3939
foreach ($basicData as $link) {
4040
$info = $link->getData();
@@ -46,4 +46,4 @@ public function convertLinksToGroupedArray($entity)
4646
}
4747
return $linksAsArray;
4848
}
49-
}
49+
}

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

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,16 @@ class Resolver
1717
*/
1818
protected $links = null;
1919

20+
/**
21+
* Resolver constructor.
22+
* @param \Magento\Framework\App\RequestInterface $request
23+
*/
2024
public function __construct(
2125
\Magento\Framework\App\RequestInterface $request
2226
) {
2327
$this->request = $request;
2428
}
2529

26-
2730
/**
2831
* Get stored value.
2932
* Fallback to request if none.
@@ -42,6 +45,7 @@ public function getLinks()
4245
* Override link data from request
4346
*
4447
* @param array|null $links
48+
* @return void
4549
*/
4650
public function override($links)
4751
{

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
use Magento\Framework\Api\ImageProcessorInterface;
1616
use Magento\Framework\Api\SortOrder;
1717
use Magento\Framework\Exception\InputException;
18+
use Magento\Framework\Exception\LocalizedException;
1819
use Magento\Framework\Exception\NoSuchEntityException;
1920
use Magento\Framework\Exception\StateException;
2021
use Magento\Framework\Exception\ValidatorException;
@@ -546,6 +547,8 @@ public function save(\Magento\Catalog\Api\Data\ProductInterface $product, $saveO
546547
);
547548
} catch (ValidatorException $e) {
548549
throw new CouldNotSaveException(__($e->getMessage()));
550+
} catch (LocalizedException $e) {
551+
throw $e;
549552
} catch (\Exception $e) {
550553
throw new \Magento\Framework\Exception\CouldNotSaveException(__('Unable to save product'));
551554
}
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
<?php
2+
/**
3+
* Copyright © 2016 Magento. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
namespace Magento\Catalog\Test\Unit\Model\Product\Link;
7+
8+
use Magento\Catalog\Model\Product\Link\Converter;
9+
10+
class ConverterTest extends \PHPUnit_Framework_TestCase
11+
{
12+
/**
13+
* @var Converter
14+
*/
15+
protected $converter;
16+
17+
protected function setUp()
18+
{
19+
$this->converter = new Converter();
20+
}
21+
22+
public function testConvertLinksToGroupedArray()
23+
{
24+
$linkedProductSku = 'linkedProductSample';
25+
$linkedProductId = '2016';
26+
$linkType = 'associated';
27+
$linkMock = $this->getMockBuilder(\Magento\Catalog\Api\Data\ProductLinkInterface::class)
28+
->disableOriginalConstructor()
29+
->setMethods(['getData', 'getLinkType', 'getLinkedProductSku', 'getExtensionAttributes'])
30+
->getMockForAbstractClass();
31+
$basicData = [$linkMock];
32+
$linkedProductMock = $this->getMockBuilder(\Magento\Catalog\Model\Product::class)
33+
->disableOriginalConstructor()
34+
->getMock();
35+
$associatedProducts = [$linkedProductSku => $linkedProductMock];
36+
$info = [100, 300, 500];
37+
$infoFinal = [100, 300, 500, 'id' => $linkedProductId, 'qty' => 33];
38+
$linksAsArray = [$linkType => [$infoFinal]];
39+
40+
$typeMock = $this->getMockBuilder(\Magento\Catalog\Model\Product\Type\AbstractType::class)
41+
->setMethods(['getAssociatedProducts'])
42+
->disableOriginalConstructor()
43+
->getMockForAbstractClass();
44+
45+
$productMock = $this->getMockBuilder(\Magento\Catalog\Model\Product::class)
46+
->disableOriginalConstructor()
47+
->getMock();
48+
$productMock->expects($this->once())
49+
->method('getProductLinks')
50+
->willReturn($basicData);
51+
$productMock->expects($this->once())
52+
->method('getTypeInstance')
53+
->willReturn($typeMock);
54+
$typeMock->expects($this->once())
55+
->method('getAssociatedProducts')
56+
->with($productMock)
57+
->willReturn($associatedProducts);
58+
$linkedProductMock->expects($this->once())
59+
->method('getSku')
60+
->willReturn($linkedProductSku);
61+
$linkMock->expects($this->once())
62+
->method('getData')
63+
->willReturn($info);
64+
$linkMock->expects($this->exactly(2))
65+
->method('getLinkType')
66+
->willReturn($linkType);
67+
$linkMock->expects($this->once())
68+
->method('getLinkedProductSku')
69+
->willReturn($linkedProductSku);
70+
$linkedProductMock->expects($this->once())
71+
->method('getId')
72+
->willReturn($linkedProductId);
73+
$attributeMock = $this->getMockBuilder(\Magento\Framework\Api\ExtensionAttributesInterface::class)
74+
->setMethods(['__toArray'])
75+
->getMockForAbstractClass();
76+
$linkMock->expects($this->once())
77+
->method('getExtensionAttributes')
78+
->willReturn($attributeMock);
79+
$attributeMock->expects($this->once())
80+
->method('__toArray')
81+
->willReturn(['qty' => 33]);
82+
83+
$this->assertEquals($linksAsArray, $this->converter->convertLinksToGroupedArray($productMock));
84+
}
85+
}
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
<?php
2+
/**
3+
* Copyright © 2016 Magento. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
namespace Magento\Catalog\Test\Unit\Model\Product\Link;
7+
8+
use Magento\Catalog\Model\Product\Link\Resolver;
9+
10+
class ResolverTest extends \PHPUnit_Framework_TestCase
11+
{
12+
/**
13+
* @var \PHPUnit_Framework_MockObject_MockObject
14+
*/
15+
protected $requestMock;
16+
17+
/**
18+
* @var Resolver
19+
*/
20+
protected $resolver;
21+
22+
protected function setUp()
23+
{
24+
$this->requestMock = $this->getMockBuilder(\Magento\Framework\App\RequestInterface::class)
25+
->getMockForAbstractClass();
26+
27+
$this->resolver = new Resolver($this->requestMock);
28+
}
29+
30+
public function testGetLinksEmpty()
31+
{
32+
$someLinks = [1, 2, 3];
33+
$this->requestMock->expects($this->once())
34+
->method('getParam')
35+
->with('links', [])
36+
->willReturn($someLinks);
37+
$this->assertEquals($someLinks, $this->resolver->getLinks());
38+
39+
}
40+
41+
public function testGetLinksOverridden()
42+
{
43+
$overriddenLinks = [3, 5, 7];
44+
$this->requestMock->expects($this->never())
45+
->method('getParam');
46+
47+
$this->resolver->override($overriddenLinks);
48+
$this->assertEquals($overriddenLinks, $this->resolver->getLinks());
49+
50+
}
51+
}

app/code/Magento/Catalog/view/adminhtml/web/js/options.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,9 @@ define([
137137
}
138138
};
139139

140-
Event.observe('add_new_option_button', 'click', attributeOption.add.bind(attributeOption, {}, true));
140+
if ($('add_new_option_button')) {
141+
Event.observe('add_new_option_button', 'click', attributeOption.add.bind(attributeOption, {}, true));
142+
}
141143
$('manage-options-panel').on('click', '.delete-option', function (event) {
142144
attributeOption.remove(event);
143145
});

app/code/Magento/CatalogSearch/Model/Indexer/Fulltext/Plugin/Product.php

Lines changed: 39 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -6,45 +6,58 @@
66

77
namespace Magento\CatalogSearch\Model\Indexer\Fulltext\Plugin;
88

9+
use Magento\Catalog\Model\ResourceModel\Product as ResourceProduct;
10+
use Magento\Framework\Model\AbstractModel;
11+
912
class Product extends AbstractPlugin
1013
{
1114
/**
1215
* Reindex on product save
1316
*
14-
* @param \Magento\Catalog\Model\ResourceModel\Product $productResource
17+
* @param ResourceProduct $productResource
1518
* @param \Closure $proceed
16-
* @param \Magento\Framework\Model\AbstractModel $product
17-
* @return \Magento\Catalog\Model\ResourceModel\Product
18-
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
19+
* @param AbstractModel $product
20+
* @return ResourceProduct
1921
*/
20-
public function aroundSave(
21-
\Magento\Catalog\Model\ResourceModel\Product $productResource,
22-
\Closure $proceed,
23-
\Magento\Framework\Model\AbstractModel $product
24-
) {
25-
$productResource->addCommitCallback(function () use ($product) {
26-
$this->reindexRow($product->getEntityId());
27-
});
28-
return $proceed($product);
22+
public function aroundSave(ResourceProduct $productResource, \Closure $proceed, AbstractModel $product)
23+
{
24+
return $this->addCommitCallback($productResource, $proceed, $product);
2925
}
3026

3127
/**
3228
* Reindex on product delete
3329
*
34-
* @param \Magento\Catalog\Model\ResourceModel\Product $productResource
30+
* @param ResourceProduct $productResource
3531
* @param \Closure $proceed
36-
* @param \Magento\Framework\Model\AbstractModel $product
37-
* @return \Magento\Catalog\Model\ResourceModel\Product
38-
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
32+
* @param AbstractModel $product
33+
* @return ResourceProduct
3934
*/
40-
public function aroundDelete(
41-
\Magento\Catalog\Model\ResourceModel\Product $productResource,
42-
\Closure $proceed,
43-
\Magento\Framework\Model\AbstractModel $product
44-
) {
45-
$productResource->addCommitCallback(function () use ($product) {
46-
$this->reindexRow($product->getEntityId());
47-
});
48-
return $proceed($product);
35+
public function aroundDelete(ResourceProduct $productResource, \Closure $proceed, AbstractModel $product)
36+
{
37+
return $this->addCommitCallback($productResource, $proceed, $product);
38+
}
39+
40+
/**
41+
* @param ResourceProduct $productResource
42+
* @param \Closure $proceed
43+
* @param AbstractModel $product
44+
* @return ResourceProduct
45+
* @throws \Exception
46+
*/
47+
private function addCommitCallback(ResourceProduct $productResource, \Closure $proceed, AbstractModel $product)
48+
{
49+
try {
50+
$productResource->beginTransaction();
51+
$result = $proceed($product);
52+
$productResource->addCommitCallback(function () use ($product) {
53+
$this->reindexRow($product->getEntityId());
54+
});
55+
$productResource->commit();
56+
} catch (\Exception $e) {
57+
$productResource->rollBack();
58+
throw $e;
59+
}
60+
61+
return $result;
4962
}
5063
}

app/code/Magento/CatalogSearch/Test/Unit/Model/Indexer/Fulltext/Plugin/ProductTest.php

Lines changed: 33 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -6,22 +6,28 @@
66

77
namespace Magento\CatalogSearch\Test\Unit\Model\Indexer\Fulltext\Plugin;
88

9+
use Magento\Catalog\Model\Product as ProductModel;
10+
use Magento\Catalog\Model\ResourceModel\Product as ProductResourceModel;
911
use \Magento\CatalogSearch\Model\Indexer\Fulltext\Plugin\Product;
12+
use Magento\Framework\DB\Adapter\AdapterInterface;
13+
use Magento\Framework\Indexer\IndexerInterface;
14+
use Magento\Framework\Indexer\IndexerRegistry;
15+
use Magento\Framework\TestFramework\Unit\Helper\ObjectManager;
1016

1117
class ProductTest extends \PHPUnit_Framework_TestCase
1218
{
1319
/**
14-
* @var \PHPUnit_Framework_MockObject_MockObject|\Magento\Framework\Indexer\IndexerInterface
20+
* @var \PHPUnit_Framework_MockObject_MockObject|IndexerInterface
1521
*/
1622
protected $indexerMock;
1723

1824
/**
19-
* @var \PHPUnit_Framework_MockObject_MockObject|\Magento\Catalog\Model\ResourceModel\Product
25+
* @var \PHPUnit_Framework_MockObject_MockObject|ProductResourceModel
2026
*/
2127
protected $subjectMock;
2228

2329
/**
24-
* @var \PHPUnit_Framework_MockObject_MockObject|\Magento\Catalog\Model\Product
30+
* @var \PHPUnit_Framework_MockObject_MockObject|ProductModel
2531
*/
2632
protected $productMock;
2733

@@ -31,7 +37,7 @@ class ProductTest extends \PHPUnit_Framework_TestCase
3137
protected $proceed;
3238

3339
/**
34-
* @var \Magento\Framework\Indexer\IndexerRegistry|\PHPUnit_Framework_MockObject_MockObject
40+
* @var IndexerRegistry|\PHPUnit_Framework_MockObject_MockObject
3541
*/
3642
protected $indexerRegistryMock;
3743

@@ -42,30 +48,34 @@ class ProductTest extends \PHPUnit_Framework_TestCase
4248

4349
protected function setUp()
4450
{
45-
$this->productMock = $this->getMock('Magento\Catalog\Model\Product', [], [], '', false);
46-
$this->subjectMock = $this->getMock('Magento\Catalog\Model\ResourceModel\Product', [], [], '', false);
47-
$this->indexerMock = $this->getMockForAbstractClass(
48-
'Magento\Framework\Indexer\IndexerInterface',
49-
[],
50-
'',
51-
false,
52-
false,
53-
true,
54-
['getId', 'getState', '__wakeup']
55-
);
56-
$this->indexerRegistryMock = $this->getMock(
57-
'Magento\Framework\Indexer\IndexerRegistry',
58-
['get'],
59-
[],
60-
'',
61-
false
62-
);
51+
$this->productMock = $this->getMockBuilder(ProductModel::class)
52+
->disableOriginalConstructor()
53+
->getMock();
54+
$this->subjectMock = $this->getMockBuilder(ProductResourceModel::class)
55+
->disableOriginalConstructor()
56+
->getMock();
57+
$connection = $this->getMockBuilder(AdapterInterface::class)
58+
->disableOriginalConstructor()
59+
->getMockForAbstractClass();
60+
$this->subjectMock->method('getConnection')->willReturn($connection);
61+
62+
$this->indexerMock = $this->getMockBuilder(IndexerInterface::class)
63+
->disableOriginalConstructor()
64+
->setMethods(['getId', 'getState', '__wakeup'])
65+
->getMockForAbstractClass();
66+
$this->indexerRegistryMock = $this->getMockBuilder(IndexerRegistry::class)
67+
->disableOriginalConstructor()
68+
->setMethods(['get'])
69+
->getMock();
6370

6471
$this->proceed = function () {
6572
return $this->subjectMock;
6673
};
6774

68-
$this->model = new Product($this->indexerRegistryMock);
75+
$this->model = (new ObjectManager($this))->getObject(
76+
Product::class,
77+
['indexerRegistry' => $this->indexerRegistryMock]
78+
);
6979
}
7080

7181
public function testAfterSaveNonScheduled()

0 commit comments

Comments
 (0)