Skip to content
This repository was archived by the owner on Apr 29, 2019. It is now read-only.

Commit 53a8966

Browse files
author
Lysenko Olexandr
authored
Merge pull request #3405 from magento-chaika/chaika_november
[Chaika] Bugfixes
2 parents 2a389b0 + 9c5ade5 commit 53a8966

File tree

6 files changed

+241
-54
lines changed

6 files changed

+241
-54
lines changed

app/code/Magento/Checkout/view/frontend/web/js/model/shipping-rates-validator.js

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,6 @@ define([
3535
var checkoutConfig = window.checkoutConfig,
3636
validators = [],
3737
observedElements = [],
38-
postcodeElement = null,
3938
postcodeElementName = 'postcode';
4039

4140
validators.push(defaultValidator);
@@ -79,7 +78,11 @@ define([
7978
}
8079

8180
$.each(elements, function (index, field) {
82-
uiRegistry.async(formPath + '.' + field)(self.doElementBinding.bind(self));
81+
var elementBinding = self.doElementBinding.bind(self),
82+
fullPath = formPath + '.' + field,
83+
func = uiRegistry.async(fullPath);
84+
85+
func(elementBinding);
8386
});
8487
},
8588

@@ -101,7 +104,6 @@ define([
101104

102105
if (element.index === postcodeElementName) {
103106
this.bindHandler(element, delay);
104-
postcodeElement = element;
105107
}
106108
},
107109

@@ -136,7 +138,7 @@ define([
136138
if (!formPopUpState.isVisible()) {
137139
clearTimeout(self.validateAddressTimeout);
138140
self.validateAddressTimeout = setTimeout(function () {
139-
self.postcodeValidation();
141+
self.postcodeValidation(element);
140142
self.validateFields();
141143
}, delay);
142144
}
@@ -148,7 +150,7 @@ define([
148150
/**
149151
* @return {*}
150152
*/
151-
postcodeValidation: function () {
153+
postcodeValidation: function (postcodeElement) {
152154
var countryId = $('select[name="country_id"]').val(),
153155
validationResult,
154156
warnMessage;
@@ -178,8 +180,8 @@ define([
178180
*/
179181
validateFields: function () {
180182
var addressFlat = addressConverter.formDataProviderToFlatData(
181-
this.collectObservedData(),
182-
'shippingAddress'
183+
this.collectObservedData(),
184+
'shippingAddress'
183185
),
184186
address;
185187

app/code/Magento/Checkout/view/frontend/web/js/view/billing-address.js

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,8 @@ define([
1717
'Magento_Customer/js/customer-data',
1818
'Magento_Checkout/js/action/set-billing-address',
1919
'Magento_Ui/js/model/messageList',
20-
'mage/translate'
20+
'mage/translate',
21+
'Magento_Checkout/js/model/shipping-rates-validator'
2122
],
2223
function (
2324
ko,
@@ -33,7 +34,8 @@ function (
3334
customerData,
3435
setBillingAddressAction,
3536
globalMessageList,
36-
$t
37+
$t,
38+
shippingRatesValidator
3739
) {
3840
'use strict';
3941

@@ -71,6 +73,7 @@ function (
7173
quote.paymentMethod.subscribe(function () {
7274
checkoutDataResolver.resolveBillingAddress();
7375
}, this);
76+
shippingRatesValidator.initFields(this.get('name') + '.form-fields');
7477
},
7578

7679
/**

app/code/Magento/ConfigurableProduct/Model/Product/Configuration/Item/ItemProductResolver.php

Lines changed: 33 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -13,16 +13,17 @@
1313
use Magento\Catalog\Model\Product\Configuration\Item\ItemResolverInterface;
1414
use Magento\Framework\App\Config\ScopeConfigInterface;
1515
use Magento\Catalog\Model\Product;
16+
use Magento\Store\Model\ScopeInterface;
1617

1718
/**
18-
* {@inheritdoc}
19+
* Resolves the product from a configured item.
1920
*/
2021
class ItemProductResolver implements ItemResolverInterface
2122
{
2223
/**
2324
* Path in config to the setting which defines if parent or child product should be used to generate a thumbnail.
2425
*/
25-
const CONFIG_THUMBNAIL_SOURCE = 'checkout/cart/configurable_product_image';
26+
public const CONFIG_THUMBNAIL_SOURCE = 'checkout/cart/configurable_product_image';
2627

2728
/**
2829
* @var ScopeConfigInterface
@@ -38,27 +39,21 @@ public function __construct(ScopeConfigInterface $scopeConfig)
3839
}
3940

4041
/**
41-
* {@inheritdoc}
42+
* Get the final product from a configured item by product type and selection.
43+
*
44+
* @param ItemInterface $item
45+
* @return ProductInterface
4246
*/
43-
public function getFinalProduct(ItemInterface $item) : ProductInterface
47+
public function getFinalProduct(ItemInterface $item): ProductInterface
4448
{
4549
/**
4650
* Show parent product thumbnail if it must be always shown according to the related setting in system config
4751
* or if child thumbnail is not available.
4852
*/
49-
$parentProduct = $item->getProduct();
50-
$finalProduct = $parentProduct;
53+
$finalProduct = $item->getProduct();
5154
$childProduct = $this->getChildProduct($item);
52-
if ($childProduct !== $parentProduct) {
53-
$configValue = $this->scopeConfig->getValue(
54-
self::CONFIG_THUMBNAIL_SOURCE,
55-
\Magento\Store\Model\ScopeInterface::SCOPE_STORE
56-
);
57-
$childThumb = $childProduct->getData('thumbnail');
58-
$finalProduct =
59-
($configValue == Thumbnail::OPTION_USE_PARENT_IMAGE) || (!$childThumb || $childThumb == 'no_selection')
60-
? $parentProduct
61-
: $childProduct;
55+
if ($childProduct !== null && $this->isUseChildProduct($childProduct)) {
56+
$finalProduct = $childProduct;
6257
}
6358
return $finalProduct;
6459
}
@@ -67,15 +62,30 @@ public function getFinalProduct(ItemInterface $item) : ProductInterface
6762
* Get item configurable child product.
6863
*
6964
* @param ItemInterface $item
70-
* @return Product
65+
* @return Product | null
7166
*/
72-
private function getChildProduct(ItemInterface $item) : Product
67+
private function getChildProduct(ItemInterface $item): ?Product
7368
{
69+
/** @var \Magento\Quote\Model\Quote\Item\Option $option */
7470
$option = $item->getOptionByCode('simple_product');
75-
$product = $item->getProduct();
76-
if ($option) {
77-
$product = $option->getProduct();
78-
}
79-
return $product;
71+
return $option ? $option->getProduct() : null;
72+
}
73+
74+
/**
75+
* Is need to use child product
76+
*
77+
* @param Product $childProduct
78+
* @return bool
79+
*/
80+
private function isUseChildProduct(Product $childProduct): bool
81+
{
82+
$configValue = $this->scopeConfig->getValue(
83+
self::CONFIG_THUMBNAIL_SOURCE,
84+
ScopeInterface::SCOPE_STORE
85+
);
86+
$childThumb = $childProduct->getData('thumbnail');
87+
return $configValue !== Thumbnail::OPTION_USE_PARENT_IMAGE
88+
&& $childThumb !== null
89+
&& $childThumb !== 'no_selection';
8090
}
8191
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
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\ConfigurableProduct\Test\Unit\Model\Product\Configuration\Item;
9+
10+
use Magento\Catalog\Model\Config\Source\Product\Thumbnail;
11+
use Magento\Catalog\Model\Product;
12+
use Magento\Catalog\Model\Product\Configuration\Item\ItemInterface;
13+
use Magento\Catalog\Model\Product\Configuration\Item\Option\OptionInterface;
14+
use Magento\ConfigurableProduct\Model\Product\Configuration\Item\ItemProductResolver;
15+
use Magento\Framework\App\Config\ScopeConfigInterface;
16+
use Magento\Quote\Model\Quote\Item\Option;
17+
use PHPUnit\Framework\MockObject\MockObject;
18+
use PHPUnit\Framework\TestCase;
19+
20+
class ItemProductResolverTest extends TestCase
21+
{
22+
/** @var ItemProductResolver */
23+
private $model;
24+
/** @var ItemInterface | MockObject */
25+
private $item;
26+
/** @var Product | MockObject */
27+
private $parentProduct;
28+
/** @var ScopeConfigInterface | MockObject */
29+
private $scopeConfig;
30+
/** @var OptionInterface | MockObject */
31+
private $option;
32+
/** @var Product | MockObject */
33+
private $childProduct;
34+
35+
/**
36+
* Set up method
37+
*/
38+
protected function setUp()
39+
{
40+
parent::setUp();
41+
42+
$this->scopeConfig = $this->getMockBuilder(ScopeConfigInterface::class)
43+
->disableOriginalConstructor()
44+
->getMock();
45+
46+
$this->parentProduct = $this->getMockBuilder(Product::class)
47+
->disableOriginalConstructor()
48+
->getMock();
49+
$this->parentProduct
50+
->method('getSku')
51+
->willReturn('parent_product');
52+
53+
$this->childProduct = $this->getMockBuilder(Product::class)
54+
->disableOriginalConstructor()
55+
->getMock();
56+
$this->childProduct
57+
->method('getSku')
58+
->willReturn('child_product');
59+
60+
$this->option = $this->getMockBuilder(Option::class)
61+
->disableOriginalConstructor()
62+
->getMock();
63+
64+
$this->option
65+
->method('getProduct')
66+
->willReturn($this->childProduct);
67+
68+
$this->item = $this->getMockBuilder(ItemInterface::class)
69+
->disableOriginalConstructor()
70+
->getMock();
71+
72+
$this->item
73+
->expects($this->once())
74+
->method('getProduct')
75+
->willReturn($this->parentProduct);
76+
77+
$this->model = new ItemProductResolver($this->scopeConfig);
78+
}
79+
80+
/**
81+
* Test for deleted child product from configurable product
82+
*/
83+
public function testGetFinalProductChildIsNull(): void
84+
{
85+
$this->scopeConfig->expects($this->never())->method('getValue');
86+
$this->childProduct->expects($this->never())->method('getData');
87+
88+
$this->item->expects($this->once())
89+
->method('getOptionByCode')
90+
->willReturn(null);
91+
92+
$finalProduct = $this->model->getFinalProduct($this->item);
93+
$this->assertEquals(
94+
$this->parentProduct->getSku(),
95+
$finalProduct->getSku()
96+
);
97+
}
98+
99+
/**
100+
* Tests child product from configurable product
101+
*
102+
* @dataProvider provideScopeConfig
103+
* @param string $expectedSku
104+
* @param string $scopeValue
105+
* @param string | null $thumbnail
106+
*/
107+
public function testGetFinalProductChild($expectedSku, $scopeValue, $thumbnail): void
108+
{
109+
$this->item->expects($this->once())
110+
->method('getOptionByCode')
111+
->willReturn($this->option);
112+
113+
$this->childProduct
114+
->expects($this->once())
115+
->method('getData')
116+
->willReturn($thumbnail);
117+
118+
$this->scopeConfig->expects($this->once())
119+
->method('getValue')
120+
->willReturn($scopeValue);
121+
122+
$finalProduct = $this->model->getFinalProduct($this->item);
123+
$this->assertEquals($expectedSku, $finalProduct->getSku());
124+
}
125+
126+
/**
127+
* Dataprovider for scope test
128+
* @return array
129+
*/
130+
public function provideScopeConfig(): array
131+
{
132+
return [
133+
['child_product', Thumbnail::OPTION_USE_OWN_IMAGE, 'thumbnail'],
134+
['parent_product', Thumbnail::OPTION_USE_PARENT_IMAGE, 'thumbnail'],
135+
136+
['parent_product', Thumbnail::OPTION_USE_OWN_IMAGE, null],
137+
['parent_product', Thumbnail::OPTION_USE_OWN_IMAGE, 'no_selection'],
138+
139+
['parent_product', Thumbnail::OPTION_USE_PARENT_IMAGE, null],
140+
['parent_product', Thumbnail::OPTION_USE_PARENT_IMAGE, 'no_selection'],
141+
];
142+
}
143+
}

app/code/Magento/Integration/Plugin/Model/AdminUser.php

Lines changed: 5 additions & 3 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+
67
namespace Magento\Integration\Plugin\Model;
78

89
use Magento\Integration\Model\AdminTokenService;
@@ -31,14 +32,15 @@ public function __construct(
3132
*
3233
* @param \Magento\User\Model\User $subject
3334
* @param \Magento\Framework\DataObject $object
34-
* @return $this
35+
* @return \Magento\User\Model\User
36+
* @throws \Magento\Framework\Exception\LocalizedException
3537
*/
3638
public function afterSave(
3739
\Magento\User\Model\User $subject,
3840
\Magento\Framework\DataObject $object
39-
) {
41+
): \Magento\User\Model\User {
4042
$isActive = $object->getIsActive();
41-
if (isset($isActive) && $isActive == 0) {
43+
if ($isActive !== null && $isActive == 0) {
4244
$this->adminTokenService->revokeAdminAccessToken($object->getId());
4345
}
4446
return $subject;

0 commit comments

Comments
 (0)