Skip to content

Commit 4991339

Browse files
Merge branch '2.4-develop' into spartans_pr_21042025
2 parents db48078 + 5660c9c commit 4991339

File tree

28 files changed

+1670
-225
lines changed

28 files changed

+1670
-225
lines changed

.github/app-projects-boards-automation.config.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,7 @@ automations:
219219
- ['merged', 'eq', true]
220220
actions:
221221
- moveTo: [23, 'Recently Merged'] #['Pull Requests Dashboard', 'Recently Merged']
222+
- moveTo: [22, 'Recently Merged'] #['Community Dashboard', 'Recently Merged']
222223

223224
# 18. Whenever a pull request is closed:
224225
# a. it must be removed from the "Pull Requests Dashboard" project

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,10 @@
135135
<index referenceId="CATALOG_PRODUCT_ENTITY_INT_ATTRIBUTE_ID" indexType="btree">
136136
<column name="attribute_id"/>
137137
</index>
138+
<index referenceId="CATALOG_PRODUCT_ENTITY_INT_ATTRIBUTE_ID_ENTITY_ID" indexType="btree">
139+
<column name="attribute_id"/>
140+
<column name="entity_id"/>
141+
</index>
138142
<index referenceId="CATALOG_PRODUCT_ENTITY_INT_STORE_ID" indexType="btree">
139143
<column name="store_id"/>
140144
</index>

app/code/Magento/Catalog/etc/db_schema_whitelist.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@
6969
},
7070
"index": {
7171
"CATALOG_PRODUCT_ENTITY_INT_ATTRIBUTE_ID": true,
72+
"CATALOG_PRODUCT_ENTITY_INT_ATTRIBUTE_ID_ENTITY_ID": true,
7273
"CATALOG_PRODUCT_ENTITY_INT_STORE_ID": true,
7374
"CATALOG_PRODUCT_ENTITY_INT_ATTRIBUTE_ID_STORE_ID_VALUE": true
7475
},

app/code/Magento/CatalogInventoryGraphQl/Model/Resolver/QuantityResolver.php

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

88
namespace Magento\CatalogInventoryGraphQl\Model\Resolver;
99

1010
use Magento\Catalog\Api\ProductRepositoryInterface;
1111
use Magento\Catalog\Model\Product;
12-
use Magento\CatalogInventory\Model\StockState;
1312
use Magento\CatalogInventory\Model\Config\Source\NotAvailableMessage;
1413
use Magento\Framework\App\Config\ScopeConfigInterface;
1514
use Magento\Framework\Exception\LocalizedException;
@@ -36,16 +35,16 @@ class QuantityResolver implements ResolverInterface
3635
private const CONFIG_PATH_NOT_AVAILABLE_MESSAGE = "cataloginventory/options/not_available_message";
3736

3837
/**
38+
* QuantityResolver Constructor
39+
*
3940
* @param ProductRepositoryInterface $productRepositoryInterface
4041
* @param ScopeConfigInterface $scopeConfig
41-
* @param StockState $stockState
4242
* @param ProductStock $productStock
4343
*/
4444
public function __construct(
4545
private readonly ProductRepositoryInterface $productRepositoryInterface,
4646
private readonly ScopeConfigInterface $scopeConfig,
47-
private readonly StockState $stockState,
48-
private readonly ProductStock $productStock,
47+
private readonly ProductStock $productStock
4948
) {
5049
}
5150

@@ -69,7 +68,7 @@ public function resolve(
6968
}
7069

7170
if (isset($value['cart_item']) && $value['cart_item'] instanceof Item) {
72-
return $this->productStock->getProductAvailableStock($value['cart_item']);
71+
return $this->productStock->getSaleableQtyByCartItem($value['cart_item'], null);
7372
}
7473

7574
if (!isset($value['model'])) {
@@ -82,6 +81,7 @@ public function resolve(
8281
if ($product->getTypeId() === self::PRODUCT_TYPE_CONFIGURABLE) {
8382
$product = $this->productRepositoryInterface->get($product->getSku());
8483
}
85-
return $this->stockState->getStockQty($product->getId());
84+
85+
return $this->productStock->getSaleableQty($product, null);
8686
}
8787
}

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
}

app/code/Magento/PageCache/Model/App/Request/Http/IdentifierForSave.php

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,14 +46,38 @@ public function getValue()
4646
{
4747
$pattern = $this->identifier->getMarketingParameterPatterns();
4848
$replace = array_fill(0, count($pattern), '');
49+
$url = preg_replace($pattern, $replace, (string)$this->request->getUriString());
50+
list($baseUrl, $query) = $this->reconstructUrl($url);
4951
$data = [
5052
$this->request->isSecure(),
51-
preg_replace($pattern, $replace, (string)$this->request->getUriString()),
53+
$baseUrl,
54+
$query,
5255
$this->context->getVaryString()
5356
];
5457

5558
$data = $this->identifierStoreReader->getPageTagsWithStoreCacheTags($data);
56-
5759
return sha1($this->serializer->serialize($data));
5860
}
61+
62+
/**
63+
* Reconstruct url and sort query
64+
*
65+
* @param string $url
66+
* @return array
67+
*/
68+
private function reconstructUrl(string $url): array
69+
{
70+
if (empty($url)) {
71+
return [$url, ''];
72+
}
73+
$baseUrl = strtok($url, '?');
74+
$query = $this->request->getUri()->getQueryAsArray();
75+
if (!empty($query)) {
76+
ksort($query);
77+
$query = http_build_query($query);
78+
} else {
79+
$query = '';
80+
}
81+
return [$baseUrl, $query];
82+
}
5983
}

app/code/Magento/PageCache/Test/Unit/Model/App/Request/Http/IdentifierForSaveTest.php

Lines changed: 89 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77

88
namespace Magento\PageCache\Test\Unit\Model\App\Request\Http;
99

10+
use Laminas\Stdlib\Parameters;
11+
use Laminas\Uri\Http as HttpUri;
1012
use Magento\Framework\App\Http\Context;
1113
use Magento\Framework\App\ObjectManager;
1214
use Magento\Framework\App\PageCache\Identifier;
@@ -49,6 +51,9 @@ class IdentifierForSaveTest extends TestCase
4951
*/
5052
private $identifierStoreReader;
5153

54+
/** @var Parameters|MockObject */
55+
private $fileParams;
56+
5257
/**
5358
* @var Identifier
5459
*/
@@ -76,6 +81,7 @@ function ($value) {
7681
return json_encode($value);
7782
}
7883
);
84+
$this->fileParams = $this->createMock(Parameters::class);
7985

8086
$this->identifierStoreReader = $this->getMockBuilder(IdentifierStoreReader::class)
8187
->onlyMethods(['getPageTagsWithStoreCacheTags'])
@@ -120,10 +126,24 @@ public function testGetValue(): void
120126
->method('getUriString')
121127
->willReturn('http://example.com/path1/');
122128

129+
$this->requestMock->expects($this->any())
130+
->method('getQuery')
131+
->willReturn($this->fileParams);
132+
133+
$this->fileParams->expects($this->any())
134+
->method('toArray')
135+
->willReturn([]);
136+
123137
$this->contextMock->expects($this->any())
124138
->method('getVaryString')
125139
->willReturn(self::VARY);
126140

141+
$uri = $this->createMock(HttpUri::class);
142+
$uri->expects($this->any())->method('getQueryAsArray')->willReturn('');
143+
$this->requestMock->expects($this->any())
144+
->method('getUri')
145+
->willReturn($uri);
146+
127147
$this->identifierStoreReader->method('getPageTagsWithStoreCacheTags')->willReturnCallback(
128148
function ($value) {
129149
return $value;
@@ -136,6 +156,67 @@ function ($value) {
136156
[
137157
true,
138158
'http://example.com/path1/',
159+
'',
160+
self::VARY
161+
]
162+
)
163+
),
164+
$this->model->getValue()
165+
);
166+
}
167+
168+
/**
169+
* Test get identifier for save value with query parameters.
170+
*
171+
* @return void
172+
*/
173+
public function testGetValueWithQuery(): void
174+
{
175+
$this->requestMock->expects($this->any())
176+
->method('isSecure')
177+
->willReturn(true);
178+
179+
$this->requestMock->expects($this->any())
180+
->method('getUriString')
181+
->willReturn('http://example.com/path1/?b=2&a=1');
182+
183+
$this->requestMock->expects($this->any())
184+
->method('getQuery')
185+
->willReturn($this->fileParams);
186+
187+
$this->fileParams->expects($this->any())
188+
->method('toArray')
189+
->willReturn([
190+
'b' => 2,
191+
'a' => 1,
192+
]);
193+
194+
$this->contextMock->expects($this->any())
195+
->method('getVaryString')
196+
->willReturn(self::VARY);
197+
198+
$uri = $this->createMock(HttpUri::class);
199+
$uri->expects($this->any())->method('getQueryAsArray')->willReturn([
200+
'b' => 2,
201+
'a' => 1,
202+
]);
203+
$this->requestMock->expects($this->any())
204+
->method('getUri')
205+
->willReturn($uri);
206+
207+
$this->identifierStoreReader->method('getPageTagsWithStoreCacheTags')->willReturnCallback(
208+
function ($value) {
209+
return $value;
210+
}
211+
);
212+
213+
$this->assertEquals(
214+
sha1(
215+
json_encode(
216+
[
217+
true,
218+
'http://example.com/path1/',
219+
'a=1&b=2',
139220
self::VARY
140221
]
141222
)
@@ -167,18 +248,24 @@ public function testGetValueWithMarketingParameters(): void
167248
->method('getVaryString')
168249
->willReturn(self::VARY);
169250

251+
$uri = $this->createMock(HttpUri::class);
252+
$uri->expects($this->any())->method('getQueryAsArray')->willReturn(['abc' => '123']);
253+
$this->requestMock->expects($this->any())
254+
->method('getUri')
255+
->willReturn($uri);
256+
170257
$this->identifierStoreReader->method('getPageTagsWithStoreCacheTags')->willReturnCallback(
171258
function ($value) {
172259
return $value;
173260
}
174261
);
175-
176262
$this->assertEquals(
177263
sha1(
178264
json_encode(
179265
[
180266
true,
181-
'http://example.com/path1/?abc=123',
267+
'http://example.com/path1/',
268+
'abc=123',
182269
self::VARY
183270
]
184271
)

0 commit comments

Comments
 (0)