Skip to content

Commit 0f30a4a

Browse files
author
Oleksii Korshenko
authored
MAGETWO-87151: [EngCom Team] Batch 7. Forwardports to 2.3-develop #1289
2 parents c1aca1f + 2a32fed commit 0f30a4a

File tree

26 files changed

+758
-47
lines changed

26 files changed

+758
-47
lines changed

app/code/Magento/Catalog/Model/Category/Link/SaveHandler.php

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,9 @@ private function mergeCategoryLinks($newCategoryPositions, $oldCategoryPositions
119119

120120
if ($key === false) {
121121
$result[] = $newCategoryPosition;
122-
} elseif ($oldCategoryPositions[$key]['position'] != $newCategoryPosition['position']) {
122+
} elseif (isset($oldCategoryPositions[$key])
123+
&& $oldCategoryPositions[$key]['position'] != $newCategoryPosition['position']
124+
) {
123125
$result[] = $newCategoryPositions[$key];
124126
unset($oldCategoryPositions[$key]);
125127
}

app/code/Magento/Catalog/Model/ResourceModel/Config.php

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -149,8 +149,7 @@ public function getAttributesUsedForSortBy()
149149
['main_table' => $this->getTable('eav_attribute')]
150150
)->join(
151151
['additional_table' => $this->getTable('catalog_eav_attribute')],
152-
'main_table.attribute_id = additional_table.attribute_id',
153-
[]
152+
'main_table.attribute_id = additional_table.attribute_id'
154153
)->joinLeft(
155154
['al' => $this->getTable('eav_attribute_label')],
156155
'al.attribute_id = main_table.attribute_id AND al.store_id = ' . $this->getStoreId(),

app/code/Magento/Catalog/Test/Unit/Model/Category/Link/SaveHandlerTest.php

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,21 @@ public function getCategoryDataProvider()
197197
],
198198
[], //affected category_ids
199199
],
200+
[
201+
[3], //model category_ids
202+
[
203+
['category_id' => 3, 'position' => 20],
204+
['category_id' => 4, 'position' => 30],
205+
], // dto category links
206+
[
207+
['category_id' => 3, 'position' => 10],
208+
],
209+
[
210+
['category_id' => 3, 'position' => 20],
211+
['category_id' => 4, 'position' => 30],
212+
],
213+
[3, 4], //affected category_ids
214+
],
200215
];
201216
}
202217

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
7+
namespace Magento\Catalog\Test\Unit\Model\ResourceModel;
8+
9+
use Magento\Framework\TestFramework\Unit\Helper\ObjectManager;
10+
11+
/**
12+
* Test for Magento\Catalog\Model\ResourceModel\Config
13+
*/
14+
class ConfigTest extends \PHPUnit\Framework\TestCase
15+
{
16+
/**
17+
* @var \Magento\Catalog\Model\ResourceModel\Config
18+
*/
19+
private $model;
20+
21+
/**
22+
* @var \PHPUnit_Framework_MockObject_MockObject
23+
*/
24+
private $resource;
25+
26+
/**
27+
* @var \PHPUnit_Framework_MockObject_MockObject
28+
*/
29+
private $storeManager;
30+
31+
/**
32+
* @var \PHPUnit_Framework_MockObject_MockObject
33+
*/
34+
private $eavConfig;
35+
36+
protected function setUp()
37+
{
38+
$objectManager = new ObjectManager($this);
39+
40+
$this->resource = $this->createMock(\Magento\Framework\App\ResourceConnection::class);
41+
$this->storeManager = $this->createMock(\Magento\Store\Model\StoreManagerInterface::class);
42+
$this->eavConfig = $this->createMock(\Magento\Eav\Model\Config::class);
43+
44+
$this->model = $objectManager->getObject(
45+
\Magento\Catalog\Model\ResourceModel\Config::class,
46+
[
47+
'resource' => $this->resource,
48+
'storeManager' => $this->storeManager,
49+
'eavConfig' => $this->eavConfig,
50+
]
51+
);
52+
53+
parent::setUp();
54+
}
55+
56+
public function testGetAttributesUsedForSortBy()
57+
{
58+
$expression = 'someExpression';
59+
$storeId = 1;
60+
$entityTypeId = 4;
61+
62+
$connectionMock = $this->createMock(\Magento\Framework\DB\Adapter\AdapterInterface::class);
63+
$selectMock = $this->createMock(\Magento\Framework\DB\Select::class);
64+
$storeMock = $this->createMock(\Magento\Store\Api\Data\StoreInterface::class);
65+
$entityTypeMock = $this->createMock(\Magento\Eav\Model\Entity\Type::class);
66+
67+
$this->resource->expects($this->atLeastOnce())->method('getConnection')->willReturn($connectionMock);
68+
69+
$connectionMock->expects($this->once())->method('getCheckSql')
70+
->with('al.value IS NULL', 'main_table.frontend_label', 'al.value')
71+
->willReturn($expression);
72+
$connectionMock->expects($this->atLeastOnce())->method('select')->willReturn($selectMock);
73+
74+
$this->resource->expects($this->exactly(3))->method('getTableName')->withConsecutive(
75+
['eav_attribute'],
76+
['catalog_eav_attribute'],
77+
['eav_attribute_label']
78+
)->willReturnOnConsecutiveCalls('eav_attribute', 'catalog_eav_attribute', 'eav_attribute_label');
79+
80+
$this->storeManager->expects($this->once())->method('getStore')->willReturn($storeMock);
81+
$storeMock->expects($this->once())->method('getId')->willReturn($storeId);
82+
83+
$this->eavConfig->expects($this->once())->method('getEntityType')->willReturn($entityTypeMock);
84+
$entityTypeMock->expects($this->once())->method('getId')->willReturn($entityTypeId);
85+
86+
$selectMock->expects($this->once())->method('from')
87+
->with(['main_table' => 'eav_attribute'])->willReturn($selectMock);
88+
$selectMock->expects($this->once())->method('join')->with(
89+
['additional_table' => 'catalog_eav_attribute'],
90+
'main_table.attribute_id = additional_table.attribute_id'
91+
)->willReturn($selectMock);
92+
$selectMock->expects($this->once())->method('joinLeft')
93+
->with(
94+
['al' => 'eav_attribute_label'],
95+
'al.attribute_id = main_table.attribute_id AND al.store_id = ' . $storeId,
96+
['store_label' => $expression]
97+
)->willReturn($selectMock);
98+
$selectMock->expects($this->exactly(2))->method('where')->withConsecutive(
99+
['main_table.entity_type_id = ?', $entityTypeId],
100+
['additional_table.used_for_sort_by = ?', 1]
101+
)->willReturn($selectMock);
102+
103+
$connectionMock->expects($this->once())->method('fetchAll')->with($selectMock);
104+
105+
$this->model->getAttributesUsedForSortBy();
106+
}
107+
}
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
7+
namespace Magento\CatalogInventory\Observer;
8+
9+
use Magento\Catalog\Model\Product;
10+
use Magento\Catalog\Model\ResourceModel\Product\Collection;
11+
use Magento\CatalogInventory\Api\StockConfigurationInterface;
12+
use Magento\CatalogInventory\Api\StockItemCriteriaInterfaceFactory;
13+
use Magento\CatalogInventory\Api\StockItemRepositoryInterface;
14+
use Magento\Framework\Event\Observer;
15+
use Magento\Framework\Event\ObserverInterface;
16+
17+
/**
18+
* Add Stock items to product collection.
19+
*/
20+
class AddStockItemsObserver implements ObserverInterface
21+
{
22+
/**
23+
* @var StockItemCriteriaInterfaceFactory
24+
*/
25+
private $criteriaInterfaceFactory;
26+
27+
/**
28+
* @var StockItemRepositoryInterface
29+
*/
30+
private $stockItemRepository;
31+
32+
/**
33+
* @var StockConfigurationInterface
34+
*/
35+
private $stockConfiguration;
36+
37+
/**
38+
* AddStockItemsObserver constructor.
39+
*
40+
* @param StockItemCriteriaInterfaceFactory $criteriaInterfaceFactory
41+
* @param StockItemRepositoryInterface $stockItemRepository
42+
* @param StockConfigurationInterface $stockConfiguration
43+
*/
44+
public function __construct(
45+
StockItemCriteriaInterfaceFactory $criteriaInterfaceFactory,
46+
StockItemRepositoryInterface $stockItemRepository,
47+
StockConfigurationInterface $stockConfiguration
48+
) {
49+
$this->criteriaInterfaceFactory = $criteriaInterfaceFactory;
50+
$this->stockItemRepository = $stockItemRepository;
51+
$this->stockConfiguration = $stockConfiguration;
52+
}
53+
54+
/**
55+
* Add stock items to products in collection.
56+
*
57+
* @param Observer $observer
58+
* @return void
59+
*/
60+
public function execute(Observer $observer)
61+
{
62+
/** @var Collection $productCollection */
63+
$productCollection = $observer->getData('collection');
64+
$productIds = array_keys($productCollection->getItems());
65+
$criteria = $this->criteriaInterfaceFactory->create();
66+
$criteria->setProductsFilter($productIds);
67+
$criteria->setScopeFilter($this->stockConfiguration->getDefaultScopeId());
68+
$stockItemCollection = $this->stockItemRepository->getList($criteria);
69+
foreach ($stockItemCollection->getItems() as $item) {
70+
/** @var Product $product */
71+
$product = $productCollection->getItemById($item->getProductId());
72+
$productExtension = $product->getExtensionAttributes();
73+
$productExtension->setStockItem($item);
74+
$product->setExtensionAttributes($productExtension);
75+
}
76+
}
77+
}
Lines changed: 165 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,165 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
7+
namespace Magento\CatalogInventory\Test\Unit\Observer;
8+
9+
use Magento\Catalog\Api\Data\ProductExtensionInterface;
10+
use Magento\Catalog\Model\Product;
11+
use Magento\Catalog\Model\ResourceModel\Product\Collection as ProductCollection;
12+
use Magento\CatalogInventory\Api\Data\StockItemCollectionInterface;
13+
use Magento\CatalogInventory\Api\Data\StockItemInterface;
14+
use Magento\CatalogInventory\Api\StockConfigurationInterface;
15+
use Magento\CatalogInventory\Api\StockItemCriteriaInterface;
16+
use Magento\CatalogInventory\Api\StockItemCriteriaInterfaceFactory;
17+
use Magento\CatalogInventory\Api\StockItemRepositoryInterface;
18+
use Magento\CatalogInventory\Observer\AddStockItemsObserver;
19+
use Magento\Framework\Event\Observer;
20+
use Magento\Framework\TestFramework\Unit\Helper\ObjectManager;
21+
use PHPUnit\Framework\TestCase;
22+
23+
class AddStockItemsObserverTest extends TestCase
24+
{
25+
/**
26+
* Test subject.
27+
*
28+
* @var AddStockItemsObserver
29+
*/
30+
private $subject;
31+
/**
32+
* @var StockItemCriteriaInterfaceFactory|\PHPUnit_Framework_MockObject_MockObject
33+
*/
34+
private $criteriaInterfaceFactoryMock;
35+
36+
/**
37+
* @var StockItemRepositoryInterface|\PHPUnit_Framework_MockObject_MockObject
38+
*/
39+
private $stockItemRepositoryMock;
40+
41+
/**
42+
* @var StockConfigurationInterface|\PHPUnit_Framework_MockObject_MockObject
43+
*/
44+
private $stockConfigurationMock;
45+
46+
/**
47+
* @inheritdoc
48+
*/
49+
protected function setUp()
50+
{
51+
$objectManager = new ObjectManager($this);
52+
$this->criteriaInterfaceFactoryMock = $this->getMockBuilder(StockItemCriteriaInterfaceFactory::class)
53+
->setMethods(['create'])
54+
->disableOriginalConstructor()
55+
->getMockForAbstractClass();
56+
$this->stockItemRepositoryMock = $this->getMockBuilder(StockItemRepositoryInterface::class)
57+
->setMethods(['getList'])
58+
->disableOriginalConstructor()
59+
->getMockForAbstractClass();
60+
$this->stockConfigurationMock = $this->getMockBuilder(StockConfigurationInterface::class)
61+
->setMethods(['getDefaultScopeId'])
62+
->disableOriginalConstructor()
63+
->getMockForAbstractClass();
64+
$this->subject = $objectManager->getObject(
65+
AddStockItemsObserver::class,
66+
[
67+
'criteriaInterfaceFactory' => $this->criteriaInterfaceFactoryMock,
68+
'stockItemRepository' => $this->stockItemRepositoryMock,
69+
'stockConfiguration' => $this->stockConfigurationMock
70+
]
71+
);
72+
}
73+
74+
/**
75+
* Test AddStockItemsObserver::execute() add stock item to product as extension attribute.
76+
*/
77+
public function testExecute()
78+
{
79+
$productId = 1;
80+
$defaultScopeId = 0;
81+
82+
$criteria = $this->getMockBuilder(StockItemCriteriaInterface::class)
83+
->setMethods(['setProductsFilter', 'setScopeFilter'])
84+
->disableOriginalConstructor()
85+
->getMockForAbstractClass();
86+
$criteria->expects(self::once())
87+
->method('setProductsFilter')
88+
->with(self::identicalTo([$productId]))
89+
->willReturn(true);
90+
$criteria->expects(self::once())
91+
->method('setScopeFilter')
92+
->with(self::identicalTo($defaultScopeId))
93+
->willReturn(true);
94+
95+
$this->criteriaInterfaceFactoryMock->expects(self::once())
96+
->method('create')
97+
->willReturn($criteria);
98+
$stockItemCollection = $this->getMockBuilder(StockItemCollectionInterface::class)
99+
->setMethods(['getItems'])
100+
->disableOriginalConstructor()
101+
->getMockForAbstractClass();
102+
$stockItem = $this->getMockBuilder(StockItemInterface::class)
103+
->setMethods(['getProductId'])
104+
->disableOriginalConstructor()
105+
->getMockForAbstractClass();
106+
$stockItem->expects(self::once())
107+
->method('getProductId')
108+
->willReturn($productId);
109+
110+
$stockItemCollection->expects(self::once())
111+
->method('getItems')
112+
->willReturn([$stockItem]);
113+
114+
$this->stockItemRepositoryMock->expects(self::once())
115+
->method('getList')
116+
->with(self::identicalTo($criteria))
117+
->willReturn($stockItemCollection);
118+
119+
$this->stockConfigurationMock->expects(self::once())
120+
->method('getDefaultScopeId')
121+
->willReturn($defaultScopeId);
122+
123+
$productExtension = $this->getMockBuilder(ProductExtensionInterface::class)
124+
->setMethods(['setStockItem'])
125+
->disableOriginalConstructor()
126+
->getMockForAbstractClass();
127+
$productExtension->expects(self::once())
128+
->method('setStockItem')
129+
->with(self::identicalTo($stockItem));
130+
131+
$product = $this->getMockBuilder(Product::class)
132+
->disableOriginalConstructor()
133+
->getMock();
134+
$product->expects(self::once())
135+
->method('getExtensionAttributes')
136+
->willReturn($productExtension);
137+
$product->expects(self::once())
138+
->method('setExtensionAttributes')
139+
->with(self::identicalTo($productExtension))
140+
->willReturnSelf();
141+
142+
/** @var ProductCollection|\PHPUnit_Framework_MockObject_MockObject $productCollection */
143+
$productCollection = $this->getMockBuilder(ProductCollection::class)
144+
->disableOriginalConstructor()
145+
->getMock();
146+
$productCollection->expects(self::once())
147+
->method('getItems')
148+
->willReturn([$productId => $product]);
149+
$productCollection->expects(self::once())
150+
->method('getItemById')
151+
->with(self::identicalTo($productId))
152+
->willReturn($product);
153+
154+
/** @var Observer|\PHPUnit_Framework_MockObject_MockObject $observer */
155+
$observer = $this->getMockBuilder(Observer::class)
156+
->disableOriginalConstructor()
157+
->getMock();
158+
$observer->expects(self::once())
159+
->method('getData')
160+
->with('collection')
161+
->willReturn($productCollection);
162+
163+
$this->subject->execute($observer);
164+
}
165+
}

0 commit comments

Comments
 (0)