Skip to content

Commit 498cfaa

Browse files
committed
Merge branch '2.3-develop' into MC-3103-product-attribute-full-width
2 parents 8a2b9f8 + 6200e46 commit 498cfaa

File tree

65 files changed

+1040
-191
lines changed

Some content is hidden

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

65 files changed

+1040
-191
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ To learn more about issue gate labels click [here](https://github.com/magento/ma
5858

5959
<h2>Reporting security issues</h2>
6060

61-
To report security vulnerabilities in Magento software or web sites, please e-mail <a href="mailto:security@magento.com">security@magento.com</a>. Please do not report security issues using GitHub. Be sure to encrypt your e-mail with our <a href="https://info2.magento.com/rs/magentoenterprise/images/security_at_magento.asc">encryption key</a> if it includes sensitive information. Learn more about reporting security issues <a href="https://magento.com/security/reporting-magento-security-issue">here</a>.
61+
To report security vulnerabilities in Magento software or web sites, please create a Bugcrowd researcher account <a href="https://bugcrowd.com/magento">there</a> to submit and follow-up your issue. Learn more about reporting security issues <a href="https://magento.com/security/reporting-magento-security-issue">here</a>.
6262

6363
Stay up-to-date on the latest security news and patches for Magento by signing up for <a href="https://magento.com/security/sign-up">Security Alert Notifications</a>.
6464

app/code/Magento/Authorizenet/Model/Directpost.php

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -814,10 +814,14 @@ protected function declineOrder(\Magento\Sales\Model\Order $order, $message = ''
814814
{
815815
try {
816816
$response = $this->getResponse();
817-
if ($voidPayment && $response->getXTransId() && strtoupper($response->getXType())
818-
== self::REQUEST_TYPE_AUTH_ONLY
817+
if ($voidPayment
818+
&& $response->getXTransId()
819+
&& strtoupper($response->getXType()) == self::REQUEST_TYPE_AUTH_ONLY
819820
) {
820-
$order->getPayment()->setTransactionId(null)->setParentTransactionId($response->getXTransId())->void();
821+
$order->getPayment()
822+
->setTransactionId(null)
823+
->setParentTransactionId($response->getXTransId())
824+
->void($response);
821825
}
822826
$order->registerCancellation($message)->save();
823827
} catch (\Exception $e) {

app/code/Magento/Backend/view/adminhtml/ui_component/design_config_form.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@
9292
</select>
9393
</formElements>
9494
</field>
95-
<actionDelete template="Magento_Backend/dynamic-rows/cells/action-delete" sortOrder="50">
95+
<actionDelete template="Magento_Backend/dynamic-rows/cells/action-delete">
9696
<argument name="data" xsi:type="array">
9797
<item name="config" xsi:type="array">
9898
<item name="fit" xsi:type="boolean">false</item>
Lines changed: 211 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,211 @@
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\Captcha\Test\Unit\Observer;
9+
10+
use Magento\Captcha\Model\DefaultModel as CaptchaModel;
11+
use Magento\Captcha\Observer\CheckGuestCheckoutObserver;
12+
use Magento\Captcha\Helper\Data as CaptchaDataHelper;
13+
use Magento\Framework\App\Action\Action;
14+
use Magento\Framework\App\ActionFlag;
15+
use Magento\Captcha\Observer\CaptchaStringResolver;
16+
use Magento\Checkout\Model\Type\Onepage;
17+
use Magento\Framework\App\Request\Http;
18+
use Magento\Framework\App\Response\Http as HttpResponse;
19+
use Magento\Framework\Event\Observer;
20+
use Magento\Framework\Json\Helper\Data as JsonHelper;
21+
use Magento\Framework\TestFramework\Unit\Helper\ObjectManager;
22+
use Magento\Quote\Model\Quote;
23+
24+
/**
25+
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
26+
*/
27+
class CheckGuestCheckoutObserverTest extends \PHPUnit\Framework\TestCase
28+
{
29+
const FORM_ID = 'guest_checkout';
30+
31+
/**
32+
* @var CheckGuestCheckoutObserver
33+
*/
34+
private $checkGuestCheckoutObserver;
35+
36+
/**
37+
* @var ObjectManager
38+
*/
39+
private $objectManager;
40+
41+
/**
42+
* @var Observer
43+
*/
44+
private $observer;
45+
46+
/**
47+
* @var HttpResponse|\PHPUnit_Framework_MockObject_MockObject
48+
*/
49+
private $responseMock;
50+
51+
/**
52+
* @var HttpResponse|\PHPUnit_Framework_MockObject_MockObject
53+
*/
54+
private $requestMock;
55+
56+
/**
57+
* @var ActionFlag|\PHPUnit_Framework_MockObject_MockObject
58+
*/
59+
private $actionFlagMock;
60+
61+
/**
62+
* @var CaptchaStringResolver|\PHPUnit_Framework_MockObject_MockObject
63+
*/
64+
private $captchaStringResolverMock;
65+
66+
/**
67+
* @var JsonHelper|\PHPUnit_Framework_MockObject_MockObject
68+
*/
69+
private $jsonHelperMock;
70+
71+
/**
72+
* @var CaptchaModel|\PHPUnit_Framework_MockObject_MockObject
73+
*/
74+
private $captchaModelMock;
75+
76+
/**
77+
* @var Quote|\PHPUnit_Framework_MockObject_MockObject
78+
*/
79+
private $quoteModelMock;
80+
81+
/**
82+
* @var Action|\PHPUnit_Framework_MockObject_MockObject
83+
*/
84+
private $controllerMock;
85+
86+
protected function setUp()
87+
{
88+
$onepageModelTypeMock = $this->createMock(Onepage::class);
89+
$captchaHelperMock = $this->createMock(CaptchaDataHelper::class);
90+
$this->objectManager = new ObjectManager($this);
91+
$this->actionFlagMock = $this->createMock(ActionFlag::class);
92+
$this->captchaStringResolverMock = $this->createMock(CaptchaStringResolver::class);
93+
$this->captchaModelMock = $this->createMock(CaptchaModel::class);
94+
$this->quoteModelMock = $this->createMock(Quote::class);
95+
$this->controllerMock = $this->createMock(Action::class);
96+
$this->requestMock = $this->createMock(Http::class);
97+
$this->responseMock = $this->createMock(HttpResponse::class);
98+
$this->observer = new Observer(['controller_action' => $this->controllerMock]);
99+
$this->jsonHelperMock = $this->createMock(JsonHelper::class);
100+
101+
$this->checkGuestCheckoutObserver = $this->objectManager->getObject(
102+
CheckGuestCheckoutObserver::class,
103+
[
104+
'helper' => $captchaHelperMock,
105+
'actionFlag' => $this->actionFlagMock,
106+
'captchaStringResolver' => $this->captchaStringResolverMock,
107+
'typeOnepage' => $onepageModelTypeMock,
108+
'jsonHelper' => $this->jsonHelperMock
109+
]
110+
);
111+
112+
$captchaHelperMock->expects($this->once())
113+
->method('getCaptcha')
114+
->with(self::FORM_ID)
115+
->willReturn($this->captchaModelMock);
116+
$onepageModelTypeMock->expects($this->once())
117+
->method('getQuote')
118+
->willReturn($this->quoteModelMock);
119+
}
120+
121+
public function testCheckGuestCheckoutForRegister()
122+
{
123+
$this->quoteModelMock->expects($this->once())
124+
->method('getCheckoutMethod')
125+
->willReturn(Onepage::METHOD_REGISTER);
126+
$this->captchaModelMock->expects($this->never())
127+
->method('isRequired');
128+
129+
$this->checkGuestCheckoutObserver->execute($this->observer);
130+
}
131+
132+
public function testCheckGuestCheckoutWithNoCaptchaRequired()
133+
{
134+
$this->quoteModelMock->expects($this->once())
135+
->method('getCheckoutMethod')
136+
->willReturn(Onepage::METHOD_GUEST);
137+
$this->captchaModelMock->expects($this->once())
138+
->method('isRequired')
139+
->willReturn(false);
140+
$this->captchaModelMock->expects($this->never())
141+
->method('isCorrect');
142+
143+
$this->checkGuestCheckoutObserver->execute($this->observer);
144+
}
145+
146+
public function testCheckGuestCheckoutWithIncorrectCaptcha()
147+
{
148+
$captchaValue = 'some_word';
149+
$encodedJsonValue = '{}';
150+
151+
$this->quoteModelMock->expects($this->once())
152+
->method('getCheckoutMethod')
153+
->willReturn(Onepage::METHOD_GUEST);
154+
$this->captchaModelMock->expects($this->once())
155+
->method('isRequired')
156+
->willReturn(true);
157+
$this->controllerMock->expects($this->once())
158+
->method('getRequest')
159+
->willReturn($this->requestMock);
160+
$this->controllerMock->expects($this->once())
161+
->method('getResponse')
162+
->willReturn($this->responseMock);
163+
$this->controllerMock->expects($this->once())
164+
->method('getResponse')
165+
->willReturn($this->responseMock);
166+
$this->captchaStringResolverMock->expects($this->once())
167+
->method('resolve')
168+
->with($this->requestMock, self::FORM_ID)
169+
->willReturn($captchaValue);
170+
$this->captchaModelMock->expects($this->once())
171+
->method('isCorrect')
172+
->with($captchaValue)
173+
->willReturn(false);
174+
$this->actionFlagMock->expects($this->once())
175+
->method('set')
176+
->with('', Action::FLAG_NO_DISPATCH, true);
177+
$this->jsonHelperMock->expects($this->once())
178+
->method('jsonEncode')
179+
->willReturn($encodedJsonValue);
180+
$this->responseMock->expects($this->once())
181+
->method('representJson')
182+
->with($encodedJsonValue);
183+
184+
$this->checkGuestCheckoutObserver->execute($this->observer);
185+
}
186+
187+
public function testCheckGuestCheckoutWithCorrectCaptcha()
188+
{
189+
$this->quoteModelMock->expects($this->once())
190+
->method('getCheckoutMethod')
191+
->willReturn(Onepage::METHOD_GUEST);
192+
$this->captchaModelMock->expects($this->once())
193+
->method('isRequired')
194+
->willReturn(true);
195+
$this->controllerMock->expects($this->once())
196+
->method('getRequest')
197+
->willReturn($this->requestMock);
198+
$this->captchaStringResolverMock->expects($this->once())
199+
->method('resolve')
200+
->with($this->requestMock, self::FORM_ID)
201+
->willReturn('some_word');
202+
$this->captchaModelMock->expects($this->once())
203+
->method('isCorrect')
204+
->with('some_word')
205+
->willReturn(true);
206+
$this->actionFlagMock->expects($this->never())
207+
->method('set');
208+
209+
$this->checkGuestCheckoutObserver->execute($this->observer);
210+
}
211+
}

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

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
use Magento\Catalog\Api\Data\ProductCustomOptionInterface;
1010
use Magento\Catalog\Api\Data\ProductCustomOptionValuesInterface;
11+
use Magento\Catalog\Api\Data\ProductCustomOptionValuesInterfaceFactory;
1112
use Magento\Catalog\Api\Data\ProductInterface;
1213
use Magento\Catalog\Model\Product;
1314
use Magento\Catalog\Model\ResourceModel\Product\Option\Value\Collection;
@@ -102,6 +103,11 @@ class Option extends AbstractExtensibleModel implements ProductCustomOptionInter
102103
*/
103104
private $metadataPool;
104105

106+
/**
107+
* @var ProductCustomOptionValuesInterfaceFactory
108+
*/
109+
private $customOptionValuesFactory;
110+
105111
/**
106112
* @param \Magento\Framework\Model\Context $context
107113
* @param \Magento\Framework\Registry $registry
@@ -114,6 +120,7 @@ class Option extends AbstractExtensibleModel implements ProductCustomOptionInter
114120
* @param \Magento\Framework\Model\ResourceModel\AbstractResource $resource
115121
* @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection
116122
* @param array $data
123+
* @param ProductCustomOptionValuesInterfaceFactory|null $customOptionValuesFactory
117124
* @SuppressWarnings(PHPMD.ExcessiveParameterList)
118125
*/
119126
public function __construct(
@@ -127,12 +134,16 @@ public function __construct(
127134
Option\Validator\Pool $validatorPool,
128135
\Magento\Framework\Model\ResourceModel\AbstractResource $resource = null,
129136
\Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null,
130-
array $data = []
137+
array $data = [],
138+
ProductCustomOptionValuesInterfaceFactory $customOptionValuesFactory = null
131139
) {
132140
$this->productOptionValue = $productOptionValue;
133141
$this->optionTypeFactory = $optionFactory;
134142
$this->validatorPool = $validatorPool;
135143
$this->string = $string;
144+
$this->customOptionValuesFactory = $customOptionValuesFactory ?:
145+
\Magento\Framework\App\ObjectManager::getInstance()->get(ProductCustomOptionValuesInterfaceFactory::class);
146+
136147
parent::__construct(
137148
$context,
138149
$registry,
@@ -390,20 +401,21 @@ public function beforeSave()
390401
*/
391402
public function afterSave()
392403
{
393-
$this->getValueInstance()->unsetValues();
394404
$values = $this->getValues() ?: $this->getData('values');
395405
if (is_array($values)) {
396406
foreach ($values as $value) {
397-
if ($value instanceof \Magento\Catalog\Api\Data\ProductCustomOptionValuesInterface) {
407+
if ($value instanceof ProductCustomOptionValuesInterface) {
398408
$data = $value->getData();
399409
} else {
400410
$data = $value;
401411
}
402-
$this->getValueInstance()->addValue($data);
403-
}
404412

405-
$this->getValueInstance()->setOption($this)->saveValues();
406-
} elseif ($this->getGroupByType($this->getType()) == self::OPTION_GROUP_SELECT) {
413+
$this->customOptionValuesFactory->create()
414+
->addValue($data)
415+
->setOption($this)
416+
->saveValues();
417+
}
418+
} elseif ($this->getGroupByType($this->getType()) === self::OPTION_GROUP_SELECT) {
407419
throw new LocalizedException(__('Select type options required values rows.'));
408420
}
409421

@@ -804,7 +816,7 @@ public function setImageSizeY($imageSizeY)
804816
}
805817

806818
/**
807-
* @param \Magento\Catalog\Api\Data\ProductCustomOptionValuesInterface[] $values
819+
* @param ProductCustomOptionValuesInterface[] $values
808820
* @return $this
809821
*/
810822
public function setValues(array $values = null)

app/code/Magento/Catalog/Model/Product/Option/Type/Text.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ public function validateUserValue($values)
8484
*/
8585
public function prepareForCart()
8686
{
87-
if ($this->getIsValid() && strlen($this->getUserValue()) > 0) {
87+
if ($this->getIsValid() && ($this->getUserValue() !== '')) {
8888
return $this->getUserValue();
8989
} else {
9090
return null;

app/code/Magento/Catalog/Model/Product/Option/Value.php

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ class Value extends AbstractModel implements \Magento\Catalog\Api\Data\ProductCu
7676
* @param \Magento\Framework\Model\ResourceModel\AbstractResource $resource
7777
* @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection
7878
* @param array $data
79+
* @param CustomOptionPriceCalculator|null $customOptionPriceCalculator
7980
*/
8081
public function __construct(
8182
\Magento\Framework\Model\Context $context,
@@ -89,6 +90,7 @@ public function __construct(
8990
$this->_valueCollectionFactory = $valueCollectionFactory;
9091
$this->customOptionPriceCalculator = $customOptionPriceCalculator
9192
?? \Magento\Framework\App\ObjectManager::getInstance()->get(CustomOptionPriceCalculator::class);
93+
9294
parent::__construct(
9395
$context,
9496
$registry,
@@ -201,19 +203,15 @@ public function getProduct()
201203
*/
202204
public function saveValues()
203205
{
206+
$option = $this->getOption();
207+
204208
foreach ($this->getValues() as $value) {
205209
$this->isDeleted(false);
206-
$this->setData(
207-
$value
208-
)->setData(
209-
'option_id',
210-
$this->getOption()->getId()
211-
)->setData(
212-
'store_id',
213-
$this->getOption()->getStoreId()
214-
);
215-
216-
if ($this->getData('is_delete') == '1') {
210+
$this->setData($value)
211+
->setData('option_id', $option->getId())
212+
->setData('store_id', $option->getStoreId());
213+
214+
if ((bool) $this->getData('is_delete') === true) {
217215
if ($this->getId()) {
218216
$this->deleteValues($this->getId());
219217
$this->delete();
@@ -222,7 +220,7 @@ public function saveValues()
222220
$this->save();
223221
}
224222
}
225-
//eof foreach()
223+
226224
return $this;
227225
}
228226

0 commit comments

Comments
 (0)