Skip to content

Commit 82901ad

Browse files
committed
Merge remote-tracking branch 'mainline/2.3-develop' into RE-develop
2 parents 00f985b + 6c69054 commit 82901ad

File tree

70 files changed

+1316
-228
lines changed

Some content is hidden

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

70 files changed

+1316
-228
lines changed

app/code/Magento/Backend/Controller/Adminhtml/System/Store/DeleteStorePost.php

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,6 @@ public function execute()
3737
try {
3838
$model->delete();
3939

40-
$this->_eventManager->dispatch('store_delete', ['store' => $model]);
41-
4240
$this->messageManager->addSuccess(__('You deleted the store view.'));
4341
return $redirectResult->setPath('adminhtml/*/');
4442
} catch (\Magento\Framework\Exception\LocalizedException $e) {

app/code/Magento/Backend/Controller/Adminhtml/System/Store/Save.php

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,6 @@ private function processWebsiteSave($postData)
4646
*/
4747
private function processStoreSave($postData)
4848
{
49-
$eventName = 'store_edit';
5049
/** @var \Magento\Store\Model\Store $storeModel */
5150
$storeModel = $this->_objectManager->create(\Magento\Store\Model\Store::class);
5251
$postData['store']['name'] = $this->filterManager->removeTags($postData['store']['name']);
@@ -56,7 +55,6 @@ private function processStoreSave($postData)
5655
$storeModel->setData($postData['store']);
5756
if ($postData['store']['store_id'] == '') {
5857
$storeModel->setId(null);
59-
$eventName = 'store_add';
6058
}
6159
$groupModel = $this->_objectManager->create(
6260
\Magento\Store\Model\Group::class
@@ -70,8 +68,6 @@ private function processStoreSave($postData)
7068
);
7169
}
7270
$storeModel->save();
73-
$this->_objectManager->get(\Magento\Store\Model\StoreManager::class)->reinitStores();
74-
$this->_eventManager->dispatch($eventName, ['store' => $storeModel]);
7571
$this->messageManager->addSuccess(__('You saved the store view.'));
7672

7773
return $postData;
@@ -102,7 +98,6 @@ private function processGroupSave($postData)
10298
);
10399
}
104100
$groupModel->save();
105-
$this->_eventManager->dispatch('store_group_save', ['group' => $groupModel]);
106101
$this->messageManager->addSuccess(__('You saved the store.'));
107102

108103
return $postData;

app/code/Magento/Catalog/Block/Product/ProductList/Toolbar.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -196,7 +196,7 @@ public function setCollection($collection)
196196
$this->_collection->addAttributeToSort(
197197
$this->getCurrentOrder(),
198198
$this->getCurrentDirection()
199-
)->addAttributeToSort('entity_id', $this->getCurrentDirection());
199+
);
200200
} else {
201201
$this->_collection->setOrder($this->getCurrentOrder(), $this->getCurrentDirection());
202202
}

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

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,9 @@ private function handleImageRemoveError($postData, $productId)
216216
/**
217217
* Do copying data to stores
218218
*
219+
* If the 'copy_from' field is not specified in the input data,
220+
* the store fallback mechanism will automatically take the admin store's default value.
221+
*
219222
* @param array $data
220223
* @param int $productId
221224
* @return void
@@ -227,15 +230,17 @@ protected function copyToStores($data, $productId)
227230
if (isset($data['product']['website_ids'][$websiteId])
228231
&& (bool)$data['product']['website_ids'][$websiteId]) {
229232
foreach ($group as $store) {
230-
$copyFrom = (isset($store['copy_from'])) ? $store['copy_from'] : 0;
231-
$copyTo = (isset($store['copy_to'])) ? $store['copy_to'] : 0;
232-
if ($copyTo) {
233-
$this->_objectManager->create(\Magento\Catalog\Model\Product::class)
234-
->setStoreId($copyFrom)
235-
->load($productId)
236-
->setStoreId($copyTo)
237-
->setCopyFromView(true)
238-
->save();
233+
if (isset($store['copy_from'])) {
234+
$copyFrom = $store['copy_from'];
235+
$copyTo = (isset($store['copy_to'])) ? $store['copy_to'] : 0;
236+
if ($copyTo) {
237+
$this->_objectManager->create(\Magento\Catalog\Model\Product::class)
238+
->setStoreId($copyFrom)
239+
->load($productId)
240+
->setStoreId($copyTo)
241+
->setCopyFromView(true)
242+
->save();
243+
}
239244
}
240245
}
241246
}

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

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -141,19 +141,17 @@ public function deleteEntity(\Magento\Framework\Model\AbstractModel $object)
141141
->getMetadata(ProductInterface::class)
142142
->getLinkField();
143143

144-
$select = $this->getConnection()->select()->from(
145-
$attribute->getEntity()->getEntityTable(),
146-
$linkField
147-
)->where(
148-
'attribute_set_id = ?',
149-
$result['attribute_set_id']
150-
);
144+
$backendLinkField = $attribute->getBackend()->getEntityIdField();
151145

152-
$clearCondition = [
153-
'attribute_id =?' => $attribute->getId(),
154-
$linkField . ' IN (?)' => $select,
155-
];
156-
$this->getConnection()->delete($backendTable, $clearCondition);
146+
$select = $this->getConnection()->select()
147+
->from(['b' => $backendTable])
148+
->join(
149+
['e' => $attribute->getEntity()->getEntityTable()],
150+
"b.$backendLinkField = e.$linkField"
151+
)->where('b.attribute_id = ?', $attribute->getId())
152+
->where('e.attribute_set_id = ?', $result['attribute_set_id']);
153+
154+
$this->getConnection()->query($select->deleteFromSelect('b'));
157155
}
158156
}
159157

Lines changed: 230 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,230 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
7+
declare(strict_types=1);
8+
9+
namespace Magento\Catalog\Test\Unit\Model\ResourceModel;
10+
11+
use Magento\Catalog\Api\Data\ProductInterface;
12+
use Magento\Catalog\Model\ResourceModel\Attribute;
13+
use Magento\Eav\Model\Entity\Attribute\AbstractAttribute;
14+
use Magento\Eav\Model\ResourceModel\Entity\Type;
15+
use Magento\Framework\App\ResourceConnection;
16+
use Magento\Framework\EntityManager\EntityMetadataInterface;
17+
use Magento\Framework\Model\ResourceModel\Db\Context;
18+
use Magento\Framework\DB\Adapter\AdapterInterface as Adapter;
19+
use Magento\ResourceConnections\DB\Select;
20+
use Magento\Store\Model\StoreManagerInterface;
21+
use Magento\Catalog\Model\Attribute\LockValidatorInterface;
22+
use Magento\Framework\Model\AbstractModel;
23+
use Magento\Framework\EntityManager\MetadataPool;
24+
25+
/**
26+
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
27+
*/
28+
class AttributeTest extends \PHPUnit\Framework\TestCase
29+
{
30+
/**
31+
* @var Select|\PHPUnit_Framework_MockObject_MockObject
32+
*/
33+
private $selectMock;
34+
35+
/**
36+
* @var Adapter|\PHPUnit_Framework_MockObject_MockObject
37+
*/
38+
private $connectionMock;
39+
40+
/**
41+
* @var ResourceConnection|\PHPUnit_Framework_MockObject_MockObject
42+
*/
43+
private $resourceMock;
44+
45+
/**
46+
* @var StoreManagerInterface|\PHPUnit_Framework_MockObject_MockObject
47+
*/
48+
private $storeManagerMock;
49+
50+
/**
51+
* @var Context|\PHPUnit_Framework_MockObject_MockObject
52+
*/
53+
private $contextMock;
54+
55+
/**
56+
* @var \Magento\Eav\Model\ResourceModel\Entity\Type|\PHPUnit_Framework_MockObject_MockObject
57+
*/
58+
private $eavEntityTypeMock;
59+
60+
/**
61+
* @var \Magento\Eav\Model\Config|\PHPUnit_Framework_MockObject_MockObject
62+
*/
63+
private $eavConfigMock;
64+
65+
/**
66+
* @var LockValidatorInterface|\PHPUnit_Framework_MockObject_MockObject
67+
*/
68+
private $lockValidatorMock;
69+
70+
/**
71+
* @var EntityMetadataInterface|\PHPUnit_Framework_MockObject_MockObject
72+
*/
73+
private $entityMetaDataInterfaceMock;
74+
75+
/**
76+
* @inheritDoc
77+
*/
78+
protected function setUp()
79+
{
80+
$this->selectMock = $this->getMockBuilder(Select::class)
81+
->disableOriginalConstructor()
82+
->setMethods(['from', 'where', 'join', 'deleteFromSelect'])
83+
->getMock();
84+
85+
$this->connectionMock = $this->getMockBuilder(Adapter::class)->getMockForAbstractClass();
86+
$this->connectionMock->expects($this->once())->method('select')->willReturn($this->selectMock);
87+
$this->connectionMock->expects($this->once())->method('query')->willReturn($this->selectMock);
88+
$this->connectionMock->expects($this->once())->method('delete')->willReturn($this->selectMock);
89+
$this->selectMock->expects($this->once())->method('from')->willReturnSelf();
90+
$this->selectMock->expects($this->once())->method('join')->willReturnSelf();
91+
$this->selectMock->expects($this->any())->method('where')->willReturnSelf();
92+
$this->selectMock->expects($this->any())->method('deleteFromSelect')->willReturnSelf();
93+
94+
$this->resourceMock = $this->getMockBuilder(ResourceConnection::class)
95+
->disableOriginalConstructor()
96+
->setMethods(['delete', 'getConnection'])
97+
->getMock();
98+
99+
$this->contextMock = $this->getMockBuilder(Context::class)->disableOriginalConstructor()->getMock();
100+
$this->storeManagerMock = $this->getMockBuilder(StoreManagerInterface::class)->getMock();
101+
$this->eavEntityTypeMock = $this->getMockBuilder(Type::class)
102+
->disableOriginalConstructor()
103+
->getMock();
104+
$this->eavConfigMock = $this->getMockBuilder(\Magento\Eav\Model\Config::class)
105+
->disableOriginalConstructor()
106+
->setMethods(['getAttribute'])
107+
->getMock();
108+
$this->lockValidatorMock = $this->getMockBuilder(LockValidatorInterface::class)
109+
->disableOriginalConstructor()
110+
->setMethods(['validate'])
111+
->getMock();
112+
$this->entityMetaDataInterfaceMock = $this->getMockBuilder(EntityMetadataInterface::class)
113+
->disableOriginalConstructor()
114+
->getMock();
115+
}
116+
117+
/**
118+
* Sets object non-public property.
119+
*
120+
* @param mixed $object
121+
* @param string $propertyName
122+
* @param mixed $value
123+
*
124+
* @return void
125+
*/
126+
private function setObjectProperty($object, string $propertyName, $value) : void
127+
{
128+
$reflectionClass = new \ReflectionClass($object);
129+
$reflectionProperty = $reflectionClass->getProperty($propertyName);
130+
$reflectionProperty->setAccessible(true);
131+
$reflectionProperty->setValue($object, $value);
132+
}
133+
134+
/**
135+
* @return void
136+
*/
137+
public function testDeleteEntity() : void
138+
{
139+
$entityAttributeId = 196;
140+
$entityTypeId = 4;
141+
$result = [
142+
'entity_attribute_id' => 196,
143+
'entity_type_id' => 4,
144+
'attribute_set_id'=> 4,
145+
'attribute_group_id' => 7,
146+
'attribute_id' => 177,
147+
'sort_order' => 3,
148+
];
149+
150+
$backendTableName = 'weee_tax';
151+
$backendFieldName = 'value_id';
152+
153+
$attributeModel = $this->getMockBuilder(Attribute::class)
154+
->setMethods(['getEntityAttribute', 'getMetadataPool', 'getConnection', 'getTable'])
155+
->setConstructorArgs([
156+
$this->contextMock,
157+
$this->storeManagerMock,
158+
$this->eavEntityTypeMock,
159+
$this->eavConfigMock,
160+
$this->lockValidatorMock,
161+
null,
162+
])->getMock();
163+
$attributeModel->expects($this->any())
164+
->method('getEntityAttribute')
165+
->with($entityAttributeId)
166+
->willReturn($result);
167+
$metadataPoolMock = $this->getMockBuilder(MetadataPool::class)
168+
->disableOriginalConstructor()
169+
->setMethods(['getMetadata'])
170+
->getMock();
171+
172+
$this->setObjectProperty($attributeModel, 'metadataPool', $metadataPoolMock);
173+
174+
$eavAttributeMock = $this->getMockBuilder(\Magento\Eav\Model\Entity\Attribute\AbstractAttribute::class)
175+
->disableOriginalConstructor()
176+
->getMock();
177+
178+
$eavAttributeMock->expects($this->any())->method('getId')->willReturn($result['attribute_id']);
179+
180+
$this->eavConfigMock->expects($this->any())
181+
->method('getAttribute')
182+
->with($entityTypeId, $result['attribute_id'])
183+
->willReturn($eavAttributeMock);
184+
185+
$abstractModelMock = $this->getMockBuilder(AbstractModel::class)
186+
->disableOriginalConstructor()
187+
->setMethods(['getEntityAttributeId','getEntityTypeId'])
188+
->getMockForAbstractClass();
189+
$abstractModelMock->expects($this->any())->method('getEntityAttributeId')->willReturn($entityAttributeId);
190+
$abstractModelMock->expects($this->any())->method('getEntityTypeId')->willReturn($entityTypeId);
191+
192+
$this->lockValidatorMock->expects($this->any())
193+
->method('validate')
194+
->with($eavAttributeMock, $result['attribute_set_id'])
195+
->willReturn(true);
196+
197+
$backendModelMock = $this->getMockBuilder(AbstractBackend::class)
198+
->disableOriginalConstructor()
199+
->setMethods(['getBackend', 'getTable', 'getEntityIdField'])
200+
->getMock();
201+
202+
$abstractAttributeMock = $this->getMockBuilder(AbstractAttribute::class)
203+
->disableOriginalConstructor()
204+
->setMethods(['getEntity'])
205+
->getMockForAbstractClass();
206+
207+
$eavAttributeMock->expects($this->any())->method('getBackend')->willReturn($backendModelMock);
208+
$eavAttributeMock->expects($this->any())->method('getEntity')->willReturn($abstractAttributeMock);
209+
210+
$backendModelMock->expects($this->any())->method('getTable')->willReturn($backendTableName);
211+
$backendModelMock->expects($this->once())->method('getEntityIdField')->willReturn($backendFieldName);
212+
213+
$metadataPoolMock->expects($this->any())
214+
->method('getMetadata')
215+
->with(ProductInterface::class)
216+
->willReturn($this->entityMetaDataInterfaceMock);
217+
218+
$this->entityMetaDataInterfaceMock->expects($this->any())
219+
->method('getLinkField')
220+
->willReturn('row_id');
221+
222+
$attributeModel->expects($this->any())->method('getConnection')->willReturn($this->connectionMock);
223+
$attributeModel->expects($this->any())
224+
->method('getTable')
225+
->with('eav_entity_attribute')
226+
->willReturn('eav_entity_attribute');
227+
228+
$attributeModel->deleteEntity($abstractModelMock);
229+
}
230+
}

0 commit comments

Comments
 (0)