Skip to content

Commit 65c9a58

Browse files
🔃 [EngCom] Public Pull Requests - 2.2-develop
Accepted Public Pull Requests: - #19422: Fix for incorrectly escapeHtml'd JSON in commit b8f78cc (by @insanityinside) - #19427: [Backport] Adding integration tests for wrong captcha (by @eduard13) - #19426: [Backport] Fixing the customer subscribing from different stores (by @eduard13) - #19398: [Backport-2.2] Code generation improvement for php 7.1 (by @swnsma) - #19014: [Backport] #17813 - Huge "product_data_storage" in localStorage hangs the shop (by @omiroshnichenko) Fixed GitHub Issues: - #19172: Newsletter subscription does not set the correct store_id if already subscribed. Not Fixed in 2.3-dev (reported by @bbmxxc) has been fixed in #19426 by @eduard13 in 2.2-develop branch Related commits: 1. b8fc202 - #15505: Interceptor class methods do not support nullable return types (reported by @jsamhall) has been fixed in #19398 by @swnsma in 2.2-develop branch Related commits: 1. 8b900d4 2. f674bad 3. 541ce18 4. d33db64 5. c0c0a37 6. 3e7f0eb 7. d7efcca 8. d249036 9. 87ab26f 10. 41c8da0 11. f0758f3 12. a33f89d - #17813: Huge "product_data_storage" in localStorage hangs the shop (reported by @krzksz) has been fixed in #19014 by @omiroshnichenko in 2.2-develop branch Related commits: 1. 57a85b8
2 parents 899e950 + 972dadb commit 65c9a58

File tree

20 files changed

+984
-86
lines changed

20 files changed

+984
-86
lines changed

app/code/Magento/Catalog/view/frontend/web/js/product/storage/data-storage.js

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,21 @@ define([
3434
};
3535
}
3636

37+
/**
38+
* Set data to localStorage with support check.
39+
*
40+
* @param {String} namespace
41+
* @param {Object} data
42+
*/
43+
function setLocalStorageItem(namespace, data) {
44+
try {
45+
window.localStorage.setItem(namespace, JSON.stringify(data));
46+
} catch (e) {
47+
console.warn('localStorage is unavailable - skipping local caching of product data');
48+
console.error(e);
49+
}
50+
}
51+
3752
return {
3853

3954
/**
@@ -118,7 +133,7 @@ define([
118133
if (_.isEmpty(data)) {
119134
this.localStorage.removeAll();
120135
} else {
121-
this.localStorage.set(data);
136+
setLocalStorageItem(this.namespace, data);
122137
}
123138
},
124139

app/code/Magento/Catalog/view/frontend/web/js/product/storage/ids-storage.js

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,21 @@ define([
1111
], function ($, _, ko, utils) {
1212
'use strict';
1313

14+
/**
15+
* Set data to localStorage with support check.
16+
*
17+
* @param {String} namespace
18+
* @param {Object} data
19+
*/
20+
function setLocalStorageItem(namespace, data) {
21+
try {
22+
window.localStorage.setItem(namespace, JSON.stringify(data));
23+
} catch (e) {
24+
console.warn('localStorage is unavailable - skipping local caching of product data');
25+
console.error(e);
26+
}
27+
}
28+
1429
return {
1530

1631
/**
@@ -94,11 +109,7 @@ define([
94109
* Initializes handler to "data" property update
95110
*/
96111
internalDataHandler: function (data) {
97-
var localStorage = this.localStorage.get();
98-
99-
if (!utils.compare(data, localStorage).equal) {
100-
this.localStorage.set(data);
101-
}
112+
setLocalStorageItem(this.namespace, data);
102113
},
103114

104115
/**

app/code/Magento/Catalog/view/frontend/web/js/product/storage/storage-service.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ define([
4747
* @param {*} data
4848
*/
4949
add: function (data) {
50-
if (!_.isEmpty(data) && !utils.compare(data, this.data()).equal) {
50+
if (!_.isEmpty(data)) {
5151
this.data(_.extend(utils.copy(this.data()), data));
5252
}
5353
},

app/code/Magento/Cms/view/adminhtml/templates/browser/content/uploader.phtml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ require([
108108
fileTypes: /^image\/(gif|jpeg|png)$/,
109109
maxFileSize: <?= (int) $block->getFileSizeService()->getMaxFileSize() ?> * 10
110110
},
111-
<?= $block->escapeHtml($resizeConfig) ?>,
111+
<?= /* @noEscape */ $resizeConfig ?>,
112112
{
113113
action: 'save'
114114
}]

app/code/Magento/Newsletter/Model/Plugin/CustomerPlugin.php

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,13 @@
66
namespace Magento\Newsletter\Model\Plugin;
77

88
use Magento\Customer\Api\CustomerRepositoryInterface as CustomerRepository;
9+
use Magento\Customer\Api\Data\CustomerExtensionInterface;
910
use Magento\Customer\Api\Data\CustomerInterface;
10-
use Magento\Newsletter\Model\SubscriberFactory;
1111
use Magento\Framework\Api\ExtensionAttributesFactory;
12-
use Magento\Newsletter\Model\ResourceModel\Subscriber;
13-
use Magento\Customer\Api\Data\CustomerExtensionInterface;
1412
use Magento\Framework\App\ObjectManager;
13+
use Magento\Newsletter\Model\ResourceModel\Subscriber;
14+
use Magento\Newsletter\Model\SubscriberFactory;
15+
use Magento\Store\Model\StoreManagerInterface;
1516

1617
class CustomerPlugin
1718
{
@@ -37,22 +38,30 @@ class CustomerPlugin
3738
*/
3839
private $customerSubscriptionStatus = [];
3940

41+
/**
42+
* @var StoreManagerInterface
43+
*/
44+
private $storeManager;
45+
4046
/**
4147
* Initialize dependencies.
4248
*
4349
* @param SubscriberFactory $subscriberFactory
4450
* @param ExtensionAttributesFactory|null $extensionFactory
4551
* @param Subscriber|null $subscriberResource
52+
* @param StoreManagerInterface|null $storeManager
4653
*/
4754
public function __construct(
4855
SubscriberFactory $subscriberFactory,
4956
ExtensionAttributesFactory $extensionFactory = null,
50-
Subscriber $subscriberResource = null
57+
Subscriber $subscriberResource = null,
58+
StoreManagerInterface $storeManager = null
5159
) {
5260
$this->subscriberFactory = $subscriberFactory;
5361
$this->extensionFactory = $extensionFactory
5462
?: ObjectManager::getInstance()->get(ExtensionAttributesFactory::class);
5563
$this->subscriberResource = $subscriberResource ?: ObjectManager::getInstance()->get(Subscriber::class);
64+
$this->storeManager = $storeManager ?: ObjectManager::getInstance()->get(StoreManagerInterface::class);
5665
}
5766

5867
/**
@@ -149,6 +158,8 @@ public function afterDelete(CustomerRepository $subject, $result, CustomerInterf
149158
public function afterGetById(CustomerRepository $subject, CustomerInterface $customer)
150159
{
151160
$extensionAttributes = $customer->getExtensionAttributes();
161+
$storeId = $this->storeManager->getStore()->getId();
162+
$customer->setStoreId($storeId);
152163
if ($extensionAttributes === null) {
153164
/** @var CustomerExtensionInterface $extensionAttributes */
154165
$extensionAttributes = $this->extensionFactory->create(CustomerInterface::class);

app/code/Magento/Newsletter/Test/Unit/Model/Plugin/CustomerPluginTest.php

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010
use Magento\Customer\Api\Data\CustomerExtensionInterface;
1111
use Magento\Framework\Api\ExtensionAttributesFactory;
1212
use Magento\Newsletter\Model\ResourceModel\Subscriber;
13+
use Magento\Store\Model\Store;
14+
use Magento\Store\Model\StoreManagerInterface;
1315

1416
class CustomerPluginTest extends \PHPUnit\Framework\TestCase
1517
{
@@ -53,6 +55,11 @@ class CustomerPluginTest extends \PHPUnit\Framework\TestCase
5355
*/
5456
private $customerMock;
5557

58+
/**
59+
* @var StoreManagerInterface|\PHPUnit_Framework_MockObject_MockObject
60+
*/
61+
private $storeManagerMock;
62+
5663
protected function setUp()
5764
{
5865
$this->subscriberFactory = $this->getMockBuilder(\Magento\Newsletter\Model\SubscriberFactory::class)
@@ -87,14 +94,17 @@ protected function setUp()
8794
->setMethods(["getExtensionAttributes"])
8895
->disableOriginalConstructor()
8996
->getMockForAbstractClass();
97+
$this->storeManagerMock = $this->createMock(StoreManagerInterface::class);
98+
9099
$this->subscriberFactory->expects($this->any())->method('create')->willReturn($this->subscriber);
91100
$this->objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this);
92101
$this->plugin = $this->objectManager->getObject(
93102
\Magento\Newsletter\Model\Plugin\CustomerPlugin::class,
94103
[
95104
'subscriberFactory' => $this->subscriberFactory,
96105
'extensionFactory' => $this->extensionFactoryMock,
97-
'subscriberResource' => $this->subscriberResourceMock
106+
'subscriberResource' => $this->subscriberResourceMock,
107+
'storeManager' => $this->storeManagerMock,
98108
]
99109
);
100110
}
@@ -198,6 +208,7 @@ public function testAfterGetByIdCreatesExtensionAttributesIfItIsNotSet(
198208
) {
199209
$subject = $this->createMock(\Magento\Customer\Api\CustomerRepositoryInterface::class);
200210
$subscriber = [$subscriberStatusKey => $subscriberStatusValue];
211+
$this->prepareStoreData();
201212
$this->extensionFactoryMock->expects($this->any())
202213
->method('create')
203214
->willReturn($this->customerExtensionMock);
@@ -223,6 +234,7 @@ public function testAfterGetByIdSetsIsSubscribedFlagIfItIsNotSet()
223234
{
224235
$subject = $this->createMock(\Magento\Customer\Api\CustomerRepositoryInterface::class);
225236
$subscriber = ['subscriber_id' => 1, 'subscriber_status' => 1];
237+
$this->prepareStoreData();
226238
$this->customerMock->expects($this->any())
227239
->method('getExtensionAttributes')
228240
->willReturn($this->customerExtensionMock);
@@ -255,4 +267,17 @@ public function afterGetByIdDataProvider()
255267
[null, null, false]
256268
];
257269
}
270+
271+
/**
272+
* Prepare store information
273+
*
274+
* @return void
275+
*/
276+
private function prepareStoreData()
277+
{
278+
$storeId = 1;
279+
$storeMock = $this->createMock(Store::class);
280+
$storeMock->expects($this->any())->method('getId')->willReturn($storeId);
281+
$this->storeManagerMock->expects($this->any())->method('getStore')->willReturn($storeMock);
282+
}
258283
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
namespace Magento\Captcha\Observer;
7+
8+
use Magento\Framework\Data\Form\FormKey;
9+
use Magento\Framework\Message\MessageInterface;
10+
use Magento\TestFramework\Request;
11+
use Magento\TestFramework\TestCase\AbstractController;
12+
13+
/**
14+
* Test captcha observer behavior
15+
*
16+
* @magentoAppArea frontend
17+
*/
18+
class CaseCheckOnFrontendUnsuccessfulMessageWhenCaptchaFailedTest extends AbstractController
19+
{
20+
/**
21+
* Test incorrect captcha on customer login page
22+
*
23+
* @magentoDbIsolation enabled
24+
* @magentoAppIsolation enabled
25+
* @magentoConfigFixture default_store customer/captcha/enable 1
26+
* @magentoConfigFixture default_store customer/captcha/forms user_login
27+
* @magentoConfigFixture default_store customer/captcha/mode always
28+
*/
29+
public function testLoginCheckUnsuccessfulMessageWhenCaptchaFailed()
30+
{
31+
/** @var FormKey $formKey */
32+
$formKey = $this->_objectManager->get(FormKey::class);
33+
$post = [
34+
'login' => [
35+
'username' => 'dummy@dummy.com',
36+
'password' => 'dummy_password1',
37+
],
38+
'captcha' => ['user_login' => 'wrong_captcha'],
39+
'form_key' => $formKey->getFormKey(),
40+
];
41+
42+
$this->prepareRequestData($post);
43+
44+
$this->dispatch('customer/account/loginPost');
45+
46+
$this->assertRedirect($this->stringContains('customer/account/login'));
47+
$this->assertSessionMessages(
48+
$this->equalTo(['Incorrect CAPTCHA']),
49+
MessageInterface::TYPE_ERROR
50+
);
51+
}
52+
53+
/**
54+
* Test incorrect captcha on customer forgot password page
55+
*
56+
* @codingStandardsIgnoreStart
57+
* @magentoConfigFixture current_store customer/password/limit_password_reset_requests_method 0
58+
* @magentoConfigFixture default_store customer/captcha/enable 1
59+
* @magentoConfigFixture default_store customer/captcha/forms user_forgotpassword
60+
* @magentoConfigFixture default_store customer/captcha/mode always
61+
*/
62+
public function testForgotPasswordCheckUnsuccessfulMessageWhenCaptchaFailed()
63+
{
64+
$post = ['email' => 'dummy@dummy.com'];
65+
$this->prepareRequestData($post);
66+
67+
$this->dispatch('customer/account/forgotPasswordPost');
68+
69+
$this->assertRedirect($this->stringContains('customer/account/forgotpassword'));
70+
$this->assertSessionMessages(
71+
$this->equalTo(['Incorrect CAPTCHA']),
72+
MessageInterface::TYPE_ERROR
73+
);
74+
}
75+
76+
/**
77+
* Test incorrect captcha on customer create account page
78+
*
79+
* @codingStandardsIgnoreStart
80+
* @magentoConfigFixture current_store customer/password/limit_password_reset_requests_method 0
81+
* @magentoConfigFixture default_store customer/captcha/enable 1
82+
* @magentoConfigFixture default_store customer/captcha/forms user_create
83+
* @magentoConfigFixture default_store customer/captcha/mode always
84+
*/
85+
public function testCreateAccountCheckUnsuccessfulMessageWhenCaptchaFailed()
86+
{
87+
/** @var FormKey $formKey */
88+
$formKey = $this->_objectManager->get(FormKey::class);
89+
$post = [
90+
'firstname' => 'Firstname',
91+
'lastname' => 'Lastname',
92+
'email' => 'dummy@dummy.com',
93+
'password' => 'TestPassword123',
94+
'password_confirmation' => 'TestPassword123',
95+
'captcha' => ['user_create' => 'wrong_captcha'],
96+
'form_key' => $formKey->getFormKey(),
97+
];
98+
$this->prepareRequestData($post);
99+
100+
$this->dispatch('customer/account/createPost');
101+
102+
$this->assertRedirect($this->stringContains('customer/account/create'));
103+
$this->assertSessionMessages(
104+
$this->equalTo(['Incorrect CAPTCHA']),
105+
MessageInterface::TYPE_ERROR
106+
);
107+
}
108+
109+
/**
110+
* @param array $postData
111+
* @return void
112+
*/
113+
private function prepareRequestData($postData)
114+
{
115+
$this->getRequest()->setMethod(Request::METHOD_POST);
116+
$this->getRequest()->setPostValue($postData);
117+
}
118+
}

0 commit comments

Comments
 (0)