Skip to content

Commit e6a91dc

Browse files
committed
Merge remote-tracking branch 'mainline/2.3-develop' into PB-48
2 parents 8e61d95 + cc599e5 commit e6a91dc

File tree

32 files changed

+638
-114
lines changed

32 files changed

+638
-114
lines changed

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

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ public function containsValue($entityType, $entity, $attributeCode, $storeId)
8181
if ((int)$storeId === Store::DEFAULT_STORE_ID) {
8282
return false;
8383
}
84-
if ($this->attributesValues === null) {
84+
if (!isset($this->attributesValues[$storeId])) {
8585
$this->initAttributeValues($entityType, $entity, (int)$storeId);
8686
}
8787

@@ -110,6 +110,8 @@ public function getDefaultValues($entityType, $entity)
110110
}
111111

112112
/**
113+
* Init attribute values.
114+
*
113115
* @param string $entityType
114116
* @param \Magento\Catalog\Model\AbstractModel $entity
115117
* @param int $storeId
@@ -158,6 +160,8 @@ private function initAttributeValues($entityType, $entity, $storeId)
158160
}
159161

160162
/**
163+
* Returns entity attributes.
164+
*
161165
* @param string $entityType
162166
* @return \Magento\Eav\Api\Data\AttributeInterface[]
163167
*/

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

Lines changed: 21 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,9 @@
66
namespace Magento\Catalog\Model\Product;
77

88
use Magento\Catalog\Api\Data\ProductInterface;
9+
use Magento\Catalog\Model\Attribute\ScopeOverriddenValue;
910
use Magento\Catalog\Model\Product;
11+
use Magento\Catalog\Model\ProductFactory;
1012

1113
/**
1214
* Catalog product copier.
@@ -28,25 +30,32 @@ class Copier
2830
protected $copyConstructor;
2931

3032
/**
31-
* @var \Magento\Catalog\Model\ProductFactory
33+
* @var ProductFactory
3234
*/
3335
protected $productFactory;
3436

3537
/**
3638
* @var \Magento\Framework\EntityManager\MetadataPool
3739
*/
3840
protected $metadataPool;
41+
/**
42+
* @var ScopeOverriddenValue
43+
*/
44+
private $scopeOverriddenValue;
3945

4046
/**
4147
* @param CopyConstructorInterface $copyConstructor
42-
* @param \Magento\Catalog\Model\ProductFactory $productFactory
48+
* @param ProductFactory $productFactory
49+
* @param ScopeOverriddenValue $scopeOverriddenValue
4350
*/
4451
public function __construct(
4552
CopyConstructorInterface $copyConstructor,
46-
\Magento\Catalog\Model\ProductFactory $productFactory
53+
ProductFactory $productFactory,
54+
ScopeOverriddenValue $scopeOverriddenValue
4755
) {
4856
$this->productFactory = $productFactory;
4957
$this->copyConstructor = $copyConstructor;
58+
$this->scopeOverriddenValue = $scopeOverriddenValue;
5059
}
5160

5261
/**
@@ -121,19 +130,20 @@ private function setStoresUrl(Product $product, Product $duplicate) : void
121130
$storeIds = $duplicate->getStoreIds();
122131
$productId = $product->getId();
123132
$productResource = $product->getResource();
124-
$defaultUrlKey = $productResource->getAttributeRawValue(
125-
$productId,
126-
'url_key',
127-
\Magento\Store\Model\Store::DEFAULT_STORE_ID
128-
);
129133
$duplicate->setData('save_rewrites_history', false);
130134
foreach ($storeIds as $storeId) {
135+
$useDefault = !$this->scopeOverriddenValue->containsValue(
136+
ProductInterface::class,
137+
$product,
138+
'url_key',
139+
$storeId
140+
);
141+
if ($useDefault) {
142+
continue;
143+
}
131144
$isDuplicateSaved = false;
132145
$duplicate->setStoreId($storeId);
133146
$urlKey = $productResource->getAttributeRawValue($productId, 'url_key', $storeId);
134-
if ($urlKey === $defaultUrlKey) {
135-
continue;
136-
}
137147
do {
138148
$urlKey = $this->modifyUrl($urlKey);
139149
$duplicate->setUrlKey($urlKey);

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

Lines changed: 28 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
namespace Magento\Catalog\Test\Unit\Model\Product;
77

88
use Magento\Catalog\Api\Data\ProductInterface;
9+
use Magento\Catalog\Model\Attribute\ScopeOverriddenValue;
910
use Magento\Catalog\Model\Product;
1011
use Magento\Catalog\Model\Product\Copier;
1112

@@ -46,6 +47,11 @@ class CopierTest extends \PHPUnit\Framework\TestCase
4647
*/
4748
protected $metadata;
4849

50+
/**
51+
* @var ScopeOverriddenValue|\PHPUnit_Framework_MockObject_MockObject
52+
*/
53+
private $scopeOverriddenValue;
54+
4955
protected function setUp()
5056
{
5157
$this->copyConstructorMock = $this->createMock(\Magento\Catalog\Model\Product\CopyConstructorInterface::class);
@@ -59,6 +65,7 @@ protected function setUp()
5965
$this->optionRepositoryMock;
6066
$this->productMock = $this->createMock(Product::class);
6167
$this->productMock->expects($this->any())->method('getEntityId')->willReturn(1);
68+
$this->scopeOverriddenValue = $this->createMock(ScopeOverriddenValue::class);
6269

6370
$this->metadata = $this->getMockBuilder(\Magento\Framework\EntityManager\EntityMetadata::class)
6471
->disableOriginalConstructor()
@@ -67,15 +74,20 @@ protected function setUp()
6774
->disableOriginalConstructor()
6875
->getMock();
6976
$metadataPool->expects($this->any())->method('getMetadata')->willReturn($this->metadata);
77+
7078
$this->_model = new Copier(
7179
$this->copyConstructorMock,
72-
$this->productFactoryMock
80+
$this->productFactoryMock,
81+
$this->scopeOverriddenValue
7382
);
7483

75-
$this->setProperties($this->_model, [
76-
'optionRepository' => $this->optionRepositoryMock,
77-
'metadataPool' => $metadataPool,
78-
]);
84+
$this->setProperties(
85+
$this->_model,
86+
[
87+
'optionRepository' => $this->optionRepositoryMock,
88+
'metadataPool' => $metadataPool,
89+
]
90+
);
7991
}
8092

8193
/**
@@ -103,10 +115,12 @@ public function testCopy()
103115
];
104116
$this->productMock->expects($this->atLeastOnce())->method('getWebsiteIds');
105117
$this->productMock->expects($this->atLeastOnce())->method('getCategoryIds');
106-
$this->productMock->expects($this->any())->method('getData')->willReturnMap([
107-
['', null, $productData],
108-
['linkField', null, '1'],
109-
]);
118+
$this->productMock->expects($this->any())->method('getData')->willReturnMap(
119+
[
120+
['', null, $productData],
121+
['linkField', null, '1'],
122+
]
123+
);
110124

111125
$entityMock = $this->getMockForAbstractClass(
112126
\Magento\Eav\Model\Entity\AbstractEntity::class,
@@ -191,9 +205,11 @@ public function testCopy()
191205

192206
$this->metadata->expects($this->any())->method('getLinkField')->willReturn('linkField');
193207

194-
$duplicateMock->expects($this->any())->method('getData')->willReturnMap([
195-
['linkField', null, '2'],
196-
]);
208+
$duplicateMock->expects($this->any())->method('getData')->willReturnMap(
209+
[
210+
['linkField', null, '2'],
211+
]
212+
);
197213
$this->optionRepositoryMock->expects($this->once())
198214
->method('duplicate')
199215
->with($this->productMock, $duplicateMock);
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
declare(strict_types=1);
7+
8+
namespace Magento\CatalogSearch\Test\Unit\Ui\DataProvider\Product;
9+
10+
use Magento\Framework\TestFramework\Unit\Helper\ObjectManager as ObjectManagerHelper;
11+
use Magento\CatalogSearch\Model\ResourceModel\Search\Collection as SearchCollection;
12+
use Magento\Framework\Data\Collection;
13+
use Magento\CatalogSearch\Ui\DataProvider\Product\AddFulltextFilterToCollection;
14+
15+
class AddFulltextFilterToCollectionTest extends \PHPUnit\Framework\TestCase
16+
{
17+
/**
18+
* @var SearchCollection|\PHPUnit_Framework_MockObject_MockObject
19+
*/
20+
private $searchCollection;
21+
22+
/**
23+
* @var Collection|\PHPUnit_Framework_MockObject_MockObject
24+
*/
25+
private $collection;
26+
27+
/**
28+
* @var ObjectManagerHelper
29+
*/
30+
private $objectManager;
31+
32+
/**
33+
* @var AddFulltextFilterToCollection
34+
*/
35+
private $model;
36+
37+
protected function setUp()
38+
{
39+
$this->objectManager = new ObjectManagerHelper($this);
40+
41+
$this->searchCollection = $this->getMockBuilder(SearchCollection::class)
42+
->setMethods(['addBackendSearchFilter', 'load', 'getAllIds'])
43+
->disableOriginalConstructor()
44+
->getMock();
45+
$this->searchCollection->expects($this->any())
46+
->method('load')
47+
->willReturnSelf();
48+
$this->collection = $this->getMockBuilder(Collection::class)
49+
->setMethods(['addIdFilter'])
50+
->disableOriginalConstructor()
51+
->getMock();
52+
53+
$this->model = $this->objectManager->getObject(
54+
AddFulltextFilterToCollection::class,
55+
[
56+
'searchCollection' => $this->searchCollection
57+
]
58+
);
59+
}
60+
61+
public function testAddFilter()
62+
{
63+
$this->searchCollection->expects($this->once())
64+
->method('addBackendSearchFilter')
65+
->with('test');
66+
$this->searchCollection->expects($this->once())
67+
->method('getAllIds')
68+
->willReturn([]);
69+
$this->collection->expects($this->once())
70+
->method('addIdFilter')
71+
->with(-1);
72+
$this->model->addFilter($this->collection, 'test', ['fulltext' => 'test']);
73+
}
74+
}

app/code/Magento/CatalogSearch/Ui/DataProvider/Product/AddFulltextFilterToCollection.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,10 @@ public function addFilter(Collection $collection, $field, $condition = null)
4040
if (isset($condition['fulltext']) && (string)$condition['fulltext'] !== '') {
4141
$this->searchCollection->addBackendSearchFilter($condition['fulltext']);
4242
$productIds = $this->searchCollection->load()->getAllIds();
43+
if (empty($productIds)) {
44+
//add dummy id to prevent returning full unfiltered collection
45+
$productIds = -1;
46+
}
4347
$collection->addIdFilter($productIds);
4448
}
4549
}

app/code/Magento/Checkout/view/frontend/web/js/view/form/element/email.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,10 @@ define([
185185
* @returns {Boolean} - initial visibility state.
186186
*/
187187
resolveInitialPasswordVisibility: function () {
188+
if (checkoutData.getInputFieldEmailValue() !== '' && checkoutData.getCheckedEmailValue() === '') {
189+
return true;
190+
}
191+
188192
if (checkoutData.getInputFieldEmailValue() !== '') {
189193
return checkoutData.getInputFieldEmailValue() === checkoutData.getCheckedEmailValue();
190194
}

app/code/Magento/CustomerGraphQl/Model/Customer/Address/CreateCustomerAddress.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,10 @@ public function __construct(
6767
*/
6868
public function execute(int $customerId, array $data): AddressInterface
6969
{
70+
// It is needed because AddressInterface has country_id field.
71+
if (isset($data['country_code'])) {
72+
$data['country_id'] = $data['country_code'];
73+
}
7074
$this->validateData($data);
7175

7276
/** @var AddressInterface $address */

app/code/Magento/CustomerGraphQl/Model/Customer/Address/ExtractCustomerAddressData.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,10 @@ public function execute(AddressInterface $address): array
127127

128128
$addressData['customer_id'] = null;
129129

130+
if (isset($addressData['country_id'])) {
131+
$addressData['country_code'] = $addressData['country_id'];
132+
}
133+
130134
return $addressData;
131135
}
132136
}

app/code/Magento/CustomerGraphQl/Model/Customer/Address/UpdateCustomerAddress.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,9 @@ public function __construct(
6666
*/
6767
public function execute(AddressInterface $address, array $data): void
6868
{
69+
if (isset($data['country_code'])) {
70+
$data['country_id'] = $data['country_code'];
71+
}
6972
$this->validateData($data);
7073

7174
$filteredData = array_diff_key($data, array_flip($this->restrictedKeys));

app/code/Magento/CustomerGraphQl/etc/schema.graphqls

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,8 @@ input CustomerAddressInput {
2828
city: String @doc(description: "The city or town")
2929
region: CustomerAddressRegionInput @doc(description: "An object containing the region name, region code, and region ID")
3030
postcode: String @doc(description: "The customer's ZIP or postal code")
31-
country_id: CountryCodeEnum @doc(description: "The customer's country")
31+
country_id: CountryCodeEnum @doc(description: "Deprecated: use `country_code` instead.")
32+
country_code: CountryCodeEnum @doc(description: "The customer's country")
3233
default_shipping: Boolean @doc(description: "Indicates whether the address is the default shipping address")
3334
default_billing: Boolean @doc(description: "Indicates whether the address is the default billing address")
3435
fax: String @doc(description: "The fax number")
@@ -102,7 +103,8 @@ type CustomerAddress @doc(description: "CustomerAddress contains detailed inform
102103
customer_id: Int @doc(description: "The customer ID") @deprecated(reason: "customer_id is not needed as part of CustomerAddress, address ID (id) is unique identifier for the addresses.")
103104
region: CustomerAddressRegion @doc(description: "An object containing the region name, region code, and region ID")
104105
region_id: Int @deprecated(reason: "Region ID is excessive on storefront and region code should suffice for all scenarios")
105-
country_id: String @doc(description: "The customer's country")
106+
country_id: String @doc(description: "The customer's country") @deprecated(reason: "Use `country_code` instead.")
107+
country_code: CountryCodeEnum @doc(description: "The customer's country")
106108
street: [String] @doc(description: "An array of strings that define the street number and name")
107109
company: String @doc(description: "The customer's company")
108110
telephone: String @doc(description: "The telephone number")

0 commit comments

Comments
 (0)