Skip to content

Commit a207cb1

Browse files
[Magento Community Engineering] Community Contributions - 2.3-develop
- merged latest code from mainline branch
2 parents 3cda561 + c227666 commit a207cb1

File tree

19 files changed

+790
-30
lines changed

19 files changed

+790
-30
lines changed
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
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\Braintree\Plugin;
9+
10+
use Magento\Quote\Model\QuoteManagement;
11+
use Magento\Quote\Api\CartManagementInterface;
12+
use Magento\Quote\Model\Quote;
13+
14+
/**
15+
* Plugin for QuoteManagement to disable quote address validation
16+
*/
17+
class DisableQuoteAddressValidation
18+
{
19+
/**
20+
* Disable quote address validation before submit order
21+
*
22+
* @param QuoteManagement $subject
23+
* @param Quote $quote
24+
* @param array $orderData
25+
* @return array
26+
* @throws \Exception
27+
* @throws \Magento\Framework\Exception\LocalizedException
28+
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
29+
*/
30+
public function beforeSubmit(
31+
QuoteManagement $subject,
32+
Quote $quote,
33+
$orderData = []
34+
) {
35+
if ($quote->getPayment()->getMethod() == 'braintree_paypal' &&
36+
$quote->getCheckoutMethod() == CartManagementInterface::METHOD_GUEST) {
37+
$billingAddress = $quote->getBillingAddress();
38+
$billingAddress->setShouldIgnoreValidation(true);
39+
$quote->setBillingAddress($billingAddress);
40+
}
41+
return [$quote, $orderData];
42+
}
43+
}

app/code/Magento/Braintree/etc/di.xml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -627,4 +627,7 @@
627627
<type name="Magento\Quote\Api\CartManagementInterface">
628628
<plugin name="order_cancellation" type="Magento\Braintree\Plugin\OrderCancellation"/>
629629
</type>
630+
<type name="Magento\Quote\Model\QuoteManagement">
631+
<plugin name="disable_quote_address_validation" type="Magento\Braintree\Plugin\DisableQuoteAddressValidation"/>
632+
</type>
630633
</config>

app/code/Magento/Braintree/view/frontend/web/js/view/payment/method-renderer/paypal.js

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -187,17 +187,17 @@ define([
187187
*/
188188
setBillingAddress: function (customer, address) {
189189
var billingAddress = {
190-
street: [address.streetAddress],
191-
city: address.locality,
190+
street: [address.line1],
191+
city: address.city,
192192
postcode: address.postalCode,
193-
countryId: address.countryCodeAlpha2,
193+
countryId: address.countryCode,
194194
email: customer.email,
195195
firstname: customer.firstName,
196196
lastname: customer.lastName,
197-
telephone: customer.phone
197+
telephone: customer.phone,
198+
regionCode: address.state
198199
};
199200

200-
billingAddress['region_code'] = address.region;
201201
billingAddress = createBillingAddress(billingAddress);
202202
quote.billingAddress(billingAddress);
203203
},
@@ -209,10 +209,12 @@ define([
209209
beforePlaceOrder: function (payload) {
210210
this.setPaymentPayload(payload);
211211

212-
if ((this.isRequiredBillingAddress() || quote.billingAddress() === null) &&
213-
typeof payload.details.billingAddress !== 'undefined'
214-
) {
215-
this.setBillingAddress(payload.details, payload.details.billingAddress);
212+
if (this.isRequiredBillingAddress() || quote.billingAddress() === null) {
213+
if (typeof payload.details.billingAddress !== 'undefined') {
214+
this.setBillingAddress(payload.details, payload.details.billingAddress);
215+
} else {
216+
this.setBillingAddress(payload.details, payload.details.shippingAddress);
217+
}
216218
}
217219

218220
if (this.isSkipOrderReview()) {

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,7 @@ class Category extends \Magento\Catalog\Model\AbstractModel implements
131131
'page_layout',
132132
'custom_layout_update',
133133
'custom_apply_to_products',
134+
'custom_use_parent_settings',
134135
];
135136

136137
/**
@@ -331,9 +332,11 @@ protected function getCustomAttributesCodes()
331332
* @throws \Magento\Framework\Exception\LocalizedException
332333
* @return \Magento\Catalog\Model\ResourceModel\Category
333334
* @deprecated because resource models should be used directly
335+
* phpcs:disable Generic.CodeAnalysis.UselessOverridingMethod
334336
*/
335337
protected function _getResource()
336338
{
339+
//phpcs:enable Generic.CodeAnalysis.UselessOverridingMethod
337340
return parent::_getResource();
338341
}
339342
// phpcs:enable
Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
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\Catalog\Observer;
9+
10+
use Magento\Framework\Event\Observer;
11+
use Magento\Framework\Event\ObserverInterface;
12+
13+
/**
14+
* Observer for invalidating cache on catalog category design change
15+
*/
16+
class InvalidateCacheOnCategoryDesignChange implements ObserverInterface
17+
{
18+
/**
19+
* @var \Magento\Framework\App\Cache\TypeListInterface
20+
*/
21+
private $cacheTypeList;
22+
23+
/**
24+
* @var \Magento\Framework\App\Config\ScopeConfigInterface
25+
*/
26+
private $scopeConfig;
27+
28+
/**
29+
* @param \Magento\Framework\App\Cache\TypeListInterface $cacheTypeList
30+
* @param \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig
31+
*/
32+
public function __construct(
33+
\Magento\Framework\App\Cache\TypeListInterface $cacheTypeList,
34+
\Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig
35+
) {
36+
$this->cacheTypeList = $cacheTypeList;
37+
$this->scopeConfig = $scopeConfig;
38+
}
39+
40+
/**
41+
* Get default category design attribute values
42+
*
43+
* @return array
44+
*/
45+
private function getDefaultAttributeValues()
46+
{
47+
return [
48+
'custom_apply_to_products' => '0',
49+
'custom_use_parent_settings' => '0',
50+
'page_layout' => $this->scopeConfig->getValue(
51+
'web/default_layouts/default_category_layout',
52+
\Magento\Store\Model\ScopeInterface::SCOPE_STORE
53+
)
54+
];
55+
}
56+
57+
/**
58+
* Invalidate cache on category design attribute value changed
59+
*
60+
* @param \Magento\Framework\Event\Observer $observer
61+
*/
62+
public function execute(Observer $observer)
63+
{
64+
$category = $observer->getEvent()->getEntity();
65+
if (!$category->isObjectNew()) {
66+
foreach ($category->getDesignAttributes() as $designAttribute) {
67+
if ($this->isCategoryAttributeChanged($designAttribute->getAttributeCode(), $category)) {
68+
$this->cacheTypeList->invalidate(
69+
[
70+
\Magento\PageCache\Model\Cache\Type::TYPE_IDENTIFIER,
71+
\Magento\Framework\App\Cache\Type\Layout::TYPE_IDENTIFIER
72+
]
73+
);
74+
break;
75+
}
76+
}
77+
}
78+
}
79+
80+
/**
81+
* Check if category attribute changed
82+
*
83+
* @param string $attributeCode
84+
* @param \Magento\Catalog\Api\Data\CategoryInterface $category
85+
* @return bool
86+
*/
87+
private function isCategoryAttributeChanged($attributeCode, $category)
88+
{
89+
if (!array_key_exists($attributeCode, $category->getOrigData())) {
90+
$defaultValue = $this->getDefaultAttributeValues()[$attributeCode] ?? null;
91+
if ($category->getData($attributeCode) !== $defaultValue) {
92+
return true;
93+
}
94+
} else {
95+
if ($category->dataHasChangedFor($attributeCode)) {
96+
return true;
97+
}
98+
}
99+
100+
return false;
101+
}
102+
}
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!--
3+
/**
4+
* Copyright © Magento, Inc. All rights reserved.
5+
* See COPYING.txt for license details.
6+
*/
7+
-->
8+
9+
<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
10+
xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd">
11+
<test name="DisplayRefreshCacheAfterChangingCategoryPageLayoutTest">
12+
<annotations>
13+
<features value="Catalog"/>
14+
<title value="'Refresh cache' admin notification is displayed when changing category page layout"/>
15+
<description value="'Refresh cache' message is not displayed when changing category page layout"/>
16+
<severity value="MAJOR"/>
17+
<testCaseId value="MC-17031"/>
18+
<useCaseId value="MAGETWO-45666"/>
19+
<group value="catalog"/>
20+
</annotations>
21+
<before>
22+
<!-- Create category, flush cache and log in -->
23+
<comment userInput="Create category, flush cache and log in" stepKey="createCategoryAndLogIn"/>
24+
<createData entity="SimpleSubCategory" stepKey="simpleCategory"/>
25+
<actionGroup ref="LoginAsAdmin" stepKey="logInAsAdmin"/>
26+
<magentoCLI command="cache:flush" stepKey="flushCache"/>
27+
</before>
28+
<after>
29+
<!-- Delete category and log out -->
30+
<comment userInput="Delete category and log out" stepKey="deleteCategoryAndLogOut"/>
31+
<deleteData createDataKey="simpleCategory" stepKey="deleteCategory"/>
32+
<actionGroup ref="logout" stepKey="logOutFromAdmin"/>
33+
<magentoCLI command="cache:flush" stepKey="flushCache"/>
34+
</after>
35+
<!-- Navigate to category details page -->
36+
<comment userInput="Navigate to category details page" stepKey="navigateToAdminCategoryPage"/>
37+
<actionGroup ref="goToAdminCategoryPageById" stepKey="goToAdminCategoryPage">
38+
<argument name="id" value="$$simpleCategory.id$$"/>
39+
</actionGroup>
40+
<!-- Open design tab and set layout -->
41+
<comment userInput="Open design tab and set layout" stepKey="setLayoutAndSave"/>
42+
<click selector="{{CategoryDesignSection.DesignTab}}" stepKey="clickOnDesignTab"/>
43+
<waitForElementVisible selector="{{CategoryDesignSection.LayoutDropdown}}" stepKey="waitForLayoutDropDown" />
44+
<selectOption selector="{{CategoryDesignSection.LayoutDropdown}}" userInput="2 columns with right bar" stepKey="selectAnOption" />
45+
<click selector="{{ContentManagementSection.Save}}" stepKey="clickSaveConfig" />
46+
<waitForPageLoad stepKey="waitSaveToApply"/>
47+
<!-- See if warning message displays -->
48+
<comment userInput="See if warning message displays" stepKey="checkWarningMessagePresence"/>
49+
<see selector="{{AdminMessagesSection.warningMessage}}" userInput="Please go to Cache Management and refresh cache types" stepKey="seeWarningMessage"/>
50+
</test>
51+
</tests>

app/code/Magento/Catalog/etc/events.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
</event>
2727
<event name="magento_catalog_api_data_categoryinterface_save_after">
2828
<observer name="legacy_category_save_after" instance="Magento\Framework\EntityManager\Observer\AfterEntitySave" />
29+
<observer name="invalidate_cache_on_category_design_change" instance="Magento\Catalog\Observer\InvalidateCacheOnCategoryDesignChange" />
2930
</event>
3031
<event name="magento_catalog_api_data_categoryinterface_delete_before">
3132
<observer name="legacy_category_delete_before" instance="Magento\Framework\EntityManager\Observer\BeforeEntityDelete" />
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!--
3+
/**
4+
* Copyright © Magento, Inc. All rights reserved.
5+
* See COPYING.txt for license details.
6+
*/
7+
-->
8+
<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
9+
xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd">
10+
<actionGroup name="LoginToPayPalPaymentAccount">
11+
<arguments>
12+
<argument name="userName" type="string" defaultValue="{{Payer.buyerEmail}}"/>
13+
<argument name="password" type="string" defaultValue="{{Payer.buyerPassword}"/>
14+
</arguments>
15+
<fillField selector="{{PayPalPaymentSection.email}}" userInput="{{userName}}" stepKey="fillEmail"/>
16+
<click selector="{{PayPalPaymentSection.nextButton}}" stepKey="clickNext"/>
17+
<waitForElementVisible selector="{{PayPalPaymentSection.password}}" stepKey="waitForPasswordField"/>
18+
<fillField selector="{{PayPalPaymentSection.password}}" userInput="{{password}}" stepKey="fillPassword"/>
19+
<click selector="{{PayPalPaymentSection.loginBtn}}" stepKey="clickLogin"/>
20+
<waitForPageLoad stepKey="waitForLoginPageLoad"/>
21+
<click selector="{{PayPalPaymentSection.continueButton}}" stepKey="clickContinue"/>
22+
</actionGroup>
23+
</actionGroups>

app/code/Magento/Paypal/Test/Mftf/Section/PayPalExpressCheckoutConfigSection.xml

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,9 @@
4545
<element name="color" type="text" selector=".paypal-button-color-{{color}}" parameterized="true"/>
4646
</section>
4747
<section name="CheckoutPaymentSection">
48+
<element name="email" type="input" selector="#checkout-customer-email"/>
49+
<element name="payPalPaymentBraintree" type="radio" selector="#braintree_paypal"/>
50+
<element name="payPalFrame" type="iframe" selector="//iframe[contains(@class, 'zoid-component-frame zoid-visible')]" timeout="5"/>
4851
<element name="PayPalPaymentRadio" type="radio" selector="input#paypal_express.radio" timeout="30"/>
4952
<element name="PayPalBtn" type="radio" selector=".paypal-button.paypal-button-number-0" timeout="30"/>
5053
</section>
@@ -58,5 +61,7 @@
5861
<element name="cartIcon" type="text" selector="#transactionCart"/>
5962
<element name="itemName" type="text" selector="//span[@title='{{productName}}']" parameterized="true"/>
6063
<element name="PayPalSubmitBtn" type="text" selector="//input[@type='submit']"/>
64+
<element name="nextButton" type="button" selector="#btnNext"/>
65+
<element name="continueButton" type="button" selector=".continueButton"/>
6166
</section>
62-
</sections>
67+
</sections>

app/code/Magento/Sales/Model/OrderRepository.php

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
* Copyright © Magento, Inc. All rights reserved.
44
* See COPYING.txt for license details.
55
*/
6+
declare(strict_types=1);
67

78
namespace Magento\Sales\Model;
89

@@ -247,8 +248,11 @@ public function deleteById($id)
247248
/**
248249
* Perform persist operations for one entity
249250
*
250-
* @param \Magento\Sales\Api\Data\OrderInterface $entity
251-
* @return \Magento\Sales\Api\Data\OrderInterface
251+
* @param OrderInterface $entity
252+
* @return OrderInterface
253+
* @throws InputException
254+
* @throws NoSuchEntityException
255+
* @throws \Magento\Framework\Exception\AlreadyExistsException
252256
*/
253257
public function save(\Magento\Sales\Api\Data\OrderInterface $entity)
254258
{
@@ -262,6 +266,7 @@ public function save(\Magento\Sales\Api\Data\OrderInterface $entity)
262266
$entity->setShippingMethod($shipping->getMethod());
263267
}
264268
}
269+
265270
$this->metadata->getMapper()->save($entity);
266271
$this->registry[$entity->getEntityId()] = $entity;
267272
return $this->registry[$entity->getEntityId()];

app/code/Magento/Sales/Model/ResourceModel/EntityAbstract.php

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
* Copyright © Magento, Inc. All rights reserved.
44
* See COPYING.txt for license details.
55
*/
6+
declare(strict_types=1);
7+
68
namespace Magento\Sales\Model\ResourceModel;
79

810
use Magento\Framework\Model\ResourceModel\Db\VersionControl\AbstractDb;
@@ -14,6 +16,7 @@
1416
/**
1517
* Abstract sales entity provides to its children knowledge about eventPrefix and eventObject
1618
*
19+
* phpcs:disable Magento2.Classes.AbstractApi
1720
* @api
1821
* @SuppressWarnings(PHPMD.NumberOfChildren)
1922
* @since 100.0.2
@@ -96,6 +99,7 @@ public function saveAttribute(\Magento\Framework\Model\AbstractModel $object, $a
9699

97100
/**
98101
* Prepares data for saving and removes update time (if exists).
102+
*
99103
* This prevents saving same update time on each entity update.
100104
*
101105
* @param \Magento\Framework\Model\AbstractModel $object
@@ -114,6 +118,7 @@ protected function _prepareDataForSave(\Magento\Framework\Model\AbstractModel $o
114118

115119
/**
116120
* Perform actions before object save
121+
*
117122
* Perform actions before object save, calculate next sequence value for increment Id
118123
*
119124
* @param \Magento\Framework\Model\AbstractModel|\Magento\Framework\DataObject $object
@@ -122,7 +127,7 @@ protected function _prepareDataForSave(\Magento\Framework\Model\AbstractModel $o
122127
protected function _beforeSave(\Magento\Framework\Model\AbstractModel $object)
123128
{
124129
/** @var \Magento\Sales\Model\AbstractModel $object */
125-
if ($object instanceof EntityInterface && $object->getIncrementId() == null) {
130+
if ($object instanceof EntityInterface && $object->getEntityId() == null && $object->getIncrementId() == null) {
126131
$store = $object->getStore();
127132
$storeId = $store->getId();
128133
if ($storeId === null) {

0 commit comments

Comments
 (0)