Skip to content

Commit e2e86b1

Browse files
Merge remote-tracking branch '39669/fix-for-issue-39236' into aprilcomprs
2 parents 2f5b3d5 + 715d107 commit e2e86b1

File tree

4 files changed

+145
-22
lines changed

4 files changed

+145
-22
lines changed

app/code/Magento/Checkout/Model/Sidebar.php

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<?php
22
/**
3-
* Copyright © Magento, Inc. All rights reserved.
4-
* See COPYING.txt for license details.
3+
* Copyright 2015 Adobe
4+
* All Rights Reserved.
55
*/
66
namespace Magento\Checkout\Model;
77

@@ -10,6 +10,7 @@
1010
use Magento\Framework\Exception\LocalizedException;
1111
use Magento\Framework\Filter\LocalizedToNormalized;
1212
use Magento\Framework\Locale\ResolverInterface;
13+
use Magento\Framework\NumberFormatter;
1314
use Magento\Quote\Api\Data\CartItemInterface;
1415
use Magento\Quote\Model\Quote\Address\Total;
1516

@@ -129,8 +130,12 @@ public function updateQuoteItem($itemId, $itemQty)
129130
protected function normalize($itemQty)
130131
{
131132
if ($itemQty) {
133+
if (is_string($itemQty) && str_contains($itemQty, ',')) {
134+
$itemQty = (double)str_replace(',', '.', $itemQty);
135+
}
136+
132137
$filter = new LocalizedToNormalized(
133-
['locale' => $this->resolver->getLocale()]
138+
['locale' => $this->resolver->getLocale(), 'decimal_style' => NumberFormatter::DECIMAL]
134139
);
135140
return $filter->filter((string)$itemQty);
136141
}

app/code/Magento/Checkout/Test/Unit/Model/SidebarTest.php

Lines changed: 33 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<?php
22
/**
3-
* Copyright © Magento, Inc. All rights reserved.
4-
* See COPYING.txt for license details.
3+
* Copyright 2015 Adobe
4+
* All Rights Reserved.
55
*/
66
declare(strict_types=1);
77

@@ -140,19 +140,29 @@ public function testRemoveQuoteItem()
140140
$this->assertEquals($this->sidebar, $this->sidebar->removeQuoteItem($itemId));
141141
}
142142

143-
public function testUpdateQuoteItem()
144-
{
145-
$itemId = 1;
146-
$itemQty = 2;
147-
143+
/**
144+
* @param string $locale
145+
* @param int|string $itemId
146+
* @param int|string|float $expectedItemQty
147+
* @param int|string|float $itemQty
148+
*
149+
* @dataProvider dataProviderUpdateQuoteItem
150+
*/
151+
public function testUpdateQuoteItem(
152+
string $locale,
153+
int|string $itemId,
154+
int|string|float $expectedItemQty,
155+
int|string|float $itemQty
156+
) {
148157
$this->resolverMock->expects($this->once())
149158
->method('getLocale')
150-
->willReturn('en');
159+
->willReturn($locale);
151160

152161
$this->cartMock->expects($this->once())
153162
->method('updateItems')
154-
->with([$itemId => ['qty' => $itemQty]])
163+
->with([$itemId => ['qty' => $expectedItemQty]])
155164
->willReturnSelf();
165+
156166
$this->cartMock->expects($this->once())
157167
->method('save')
158168
->willReturnSelf();
@@ -178,4 +188,18 @@ public function testUpdateQuoteItemWithZeroQty()
178188

179189
$this->assertEquals($this->sidebar, $this->sidebar->updateQuoteItem($itemId, $itemQty));
180190
}
191+
192+
/**
193+
* @return array
194+
*/
195+
public static function dataProviderUpdateQuoteItem(): array
196+
{
197+
return [
198+
//locale, itemId, expectedItemQty, ItemQty
199+
[ 'en_US', 1, 2, 2],
200+
[ 'en_US', 1, 0.5, 0.5],
201+
[ 'en_US', 1,"0.5","0.5"],
202+
[ 'nl_NL', 1,"0.5","0,5"]
203+
];
204+
}
181205
}

lib/internal/Magento/Framework/Filter/LocalizedToNormalized.php

Lines changed: 22 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
<?php
22
/**
3-
* Copyright © Magento, Inc. All rights reserved.
4-
* See COPYING.txt for license details.
3+
* Copyright 2011 Adobe
4+
* All Rights Reserved.
55
*/
6+
67
namespace Magento\Framework\Filter;
78

89
use Exception;
@@ -17,9 +18,10 @@ class LocalizedToNormalized implements FilterInterface
1718
* @var array
1819
*/
1920
protected $_options = [
20-
'locale' => null,
21+
'locale' => null,
2122
'date_format' => null,
22-
'precision' => null
23+
'precision' => null,
24+
'decimal_style' => null
2325
];
2426

2527
/**
@@ -60,14 +62,25 @@ public function setOptions(?array $options = null)
6062
*
6163
* Normalizes the given input
6264
*
63-
* @param string $value Value to normalized
65+
* @param string $value Value to normalized
6466
* @return string|array The normalized value
6567
*/
6668
public function filter($value)
6769
{
6870
if (is_numeric($value)) {
69-
$numberParse = new NumberParse($this->_options['locale'], NumberFormatter::PATTERN_DECIMAL);
70-
return (string) $numberParse->filter($value);
71+
72+
if (filter_var($value, FILTER_VALIDATE_INT) !== false) {
73+
$value = (int)$value;
74+
} elseif (filter_var($value, FILTER_VALIDATE_FLOAT) !== false) {
75+
$value = (float)$value;
76+
}
77+
$numberParse = new NumberParse(
78+
$this->_options['locale'],
79+
empty($this->_options['decimal_style'])
80+
? NumberFormatter::PATTERN_DECIMAL
81+
: $this->_options['decimal_style']
82+
);
83+
return (string)$numberParse->filter($value);
7184
} elseif ($this->_options['date_format'] === null && strpos($value, ':') !== false) {
7285
$formatter = new IntlDateFormatter(
7386
$this->_options['locale'],
@@ -144,7 +157,7 @@ private function parseDate($date)
144157
$parse[$month] = 'M';
145158
}
146159
if ($year !== false) {
147-
$parse[$year] = 'y';
160+
$parse[$year] = 'y';
148161
}
149162
preg_match_all('/\d+/u', $date, $splitted);
150163
$split = false;
@@ -184,7 +197,7 @@ private function parseDate($date)
184197
}
185198
if ($split === false) {
186199
if (count($splitted[0]) > $cnt) {
187-
$result['year'] = $splitted[0][$cnt];
200+
$result['year'] = $splitted[0][$cnt];
188201
}
189202
} else {
190203
$result['year'] = iconv_substr($splitted[0][0], $split, $length);
@@ -193,7 +206,6 @@ private function parseDate($date)
193206
}
194207
++$cnt;
195208
}
196-
197209
return $result;
198210
}
199211
}
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
<?php
2+
/**
3+
* Copyright 2025 Adobe
4+
* All Rights Reserved.
5+
*/
6+
declare(strict_types=1);
7+
8+
namespace Magento\Framework\Filter\Test\Unit;
9+
10+
use Magento\Framework\Filter\LocalizedToNormalized;
11+
use PHPUnit\Framework\TestCase;
12+
use NumberFormatter;
13+
14+
class LocalizedToNormalizedTest extends TestCase
15+
{
16+
17+
/**
18+
* @param string $value
19+
* @param array $options
20+
* @param string|array $expectedValues
21+
*
22+
* @dataProvider localizedToNormalizedDataProvider
23+
*/
24+
public function testLocalizedToNormalized(string $value, array $options, string|array $expectedValue)
25+
{
26+
$filter = new LocalizedToNormalized($options);
27+
$this->assertEquals($expectedValue, $filter->filter($value));
28+
}
29+
30+
/**
31+
* @return array
32+
*/
33+
public static function localizedToNormalizedDataProvider(): array
34+
{
35+
return [
36+
'1' => [
37+
"0.5",
38+
[
39+
'locale' => 'nl',
40+
'date_format' => null,
41+
'precision' => null,
42+
'decimal_style' => null
43+
],
44+
"0.5"
45+
],
46+
'2' => [
47+
"0.5",
48+
[
49+
'locale' => 'en',
50+
'date_format' => null,
51+
'precision' => null,
52+
'decimal_style' => NumberFormatter::PATTERN_DECIMAL
53+
],
54+
"0.5"
55+
],
56+
'3' => [
57+
"2",
58+
[
59+
'locale' => 'en',
60+
'date_format' => null,
61+
'precision' => null
62+
],
63+
"2"
64+
],
65+
'4' => [
66+
'2014-03-30',
67+
[
68+
'locale' => 'en',
69+
'date_format' => 'Y-M-d',
70+
'precision' => null
71+
],
72+
[
73+
"date_format" => "Y-M-d",
74+
"locale" => "en",
75+
"year" => "2014",
76+
"month" => "03",
77+
"day" => "30",
78+
]
79+
]
80+
];
81+
}
82+
}

0 commit comments

Comments
 (0)