Skip to content

Commit 0373fde

Browse files
committed
Merge branch '2.3-develop' into MAGETWO-92985
2 parents 5487dfa + c41ffe5 commit 0373fde

File tree

70 files changed

+1628
-199
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

+1628
-199
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/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+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<?xml version="1.0"?>
2+
<!--
3+
/**
4+
* Copyright © Magento, Inc. All rights reserved.
5+
* See COPYING.txt for license details.
6+
*/
7+
-->
8+
<services xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
9+
xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_WebapiAsync:etc/webapi_async.xsd">
10+
<route url="async/bulk/V1/products/bySku" method="PUT" alias="async/bulk/V1/products"/>
11+
</services>

app/code/Magento/Customer/Model/Address/Validator/Country.php

Lines changed: 39 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77

88
use Magento\Customer\Model\Address\AbstractAddress;
99
use Magento\Customer\Model\Address\ValidatorInterface;
10+
use Magento\Framework\App\ObjectManager;
11+
use Magento\Store\Model\ScopeInterface;
1012

1113
/**
1214
* Address country and region validator.
@@ -18,13 +20,31 @@ class Country implements ValidatorInterface
1820
*/
1921
private $directoryData;
2022

23+
/**
24+
* @var \Magento\Directory\Model\AllowedCountries
25+
*/
26+
private $allowedCountriesReader;
27+
28+
/**
29+
* @var \Magento\Customer\Model\Config\Share
30+
*/
31+
private $shareConfig;
32+
2133
/**
2234
* @param \Magento\Directory\Helper\Data $directoryData
35+
* @param \Magento\Directory\Model\AllowedCountries|null $allowedCountriesReader
36+
* @param \Magento\Customer\Model\Config\Share|null $shareConfig
2337
*/
2438
public function __construct(
25-
\Magento\Directory\Helper\Data $directoryData
39+
\Magento\Directory\Helper\Data $directoryData,
40+
\Magento\Directory\Model\AllowedCountries $allowedCountriesReader = null,
41+
\Magento\Customer\Model\Config\Share $shareConfig = null
2642
) {
2743
$this->directoryData = $directoryData;
44+
$this->allowedCountriesReader = $allowedCountriesReader
45+
?: ObjectManager::getInstance()->get(\Magento\Directory\Model\AllowedCountries::class);
46+
$this->shareConfig = $shareConfig
47+
?: ObjectManager::getInstance()->get(\Magento\Customer\Model\Config\Share::class);
2848
}
2949

3050
/**
@@ -52,7 +72,7 @@ private function validateCountry(AbstractAddress $address)
5272
$errors = [];
5373
if (!\Zend_Validate::is($countryId, 'NotEmpty')) {
5474
$errors[] = __('"%fieldName" is required. Enter and try again.', ['fieldName' => 'countryId']);
55-
} elseif (!in_array($countryId, $this->directoryData->getCountryCollection()->getAllIds(), true)) {
75+
} elseif (!in_array($countryId, $this->getWebsiteAllowedCountries($address), true)) {
5676
//Checking if such country exists.
5777
$errors[] = __(
5878
'Invalid value of "%value" provided for the %fieldName field.',
@@ -97,4 +117,21 @@ private function validateRegion(AbstractAddress $address)
97117

98118
return $errors;
99119
}
120+
121+
/**
122+
* Return allowed counties per website.
123+
*
124+
* @param AbstractAddress $address
125+
* @return array
126+
*/
127+
private function getWebsiteAllowedCountries(AbstractAddress $address): array
128+
{
129+
$websiteId = null;
130+
131+
if (!$this->shareConfig->isGlobalScope()) {
132+
$websiteId = $address->getCustomer() ? $address->getCustomer()->getWebsiteId() : null;
133+
}
134+
135+
return $this->allowedCountriesReader->getAllowedCountries(ScopeInterface::SCOPE_WEBSITE, $websiteId);
136+
}
100137
}

0 commit comments

Comments
 (0)