Skip to content

Commit a992110

Browse files
authored
Merge branch '2.4.8-beta2-develop' into ACP2E-3476-2.4.8-beta2
2 parents d90dc53 + 22a4ba2 commit a992110

File tree

6 files changed

+121
-234
lines changed

6 files changed

+121
-234
lines changed

app/code/Magento/Customer/Plugin/AsyncRequestCustomerGroupAuthorization.php

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
<?php
22
/**
3-
* Copyright © Magento, Inc. All rights reserved.
3+
* Copyright 2025 Adobe
4+
* All rights reserved.
45
* See COPYING.txt for license details.
56
*/
67

@@ -9,7 +10,6 @@
910
namespace Magento\Customer\Plugin;
1011

1112
use Magento\Customer\Api\Data\CustomerInterface;
12-
use Magento\Framework\App\ObjectManager;
1313
use Magento\Framework\AuthorizationInterface;
1414
use Magento\Framework\Exception\AuthorizationException;
1515
use Magento\AsynchronousOperations\Model\MassSchedule;
@@ -60,6 +60,11 @@ public function beforePublishMass(
6060
string $groupId = null,
6161
string $userId = null
6262
) {
63+
// only apply the plugin on account create.
64+
if ($topic !== 'async.magento.customer.api.accountmanagementinterface.createaccount.post') {
65+
return;
66+
}
67+
6368
foreach ($entitiesArray as $entityParams) {
6469
foreach ($entityParams as $entity) {
6570
if ($entity instanceof CustomerInterface) {

app/code/Magento/Quote/etc/webapi.xml

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
<?xml version="1.0"?>
22
<!--
33
/**
4-
* Copyright © Magento, Inc. All rights reserved.
4+
* Copyright 2025 Adobe
5+
* All rights reserved.
56
* See COPYING.txt for license details.
67
*/
78
-->
@@ -98,6 +99,9 @@
9899
<resources>
99100
<resource ref="self" />
100101
</resources>
102+
<data>
103+
<parameter name="customerId" force="true">%customer_id%</parameter>
104+
</data>
101105
</route>
102106
<route url="/V1/guest-carts/:cartId/order" method="PUT">
103107
<service class="Magento\Quote\Api\GuestCartManagementInterface" method="placeOrder"/>

app/code/Magento/WebapiAsync/Controller/Rest/Asynchronous/InputParamsResolver.php

Lines changed: 91 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,20 @@
11
<?php
22
/**
3-
* Copyright © Magento, Inc. All rights reserved.
3+
* Copyright 2025 Adobe
4+
* All rights reserved.
45
* See COPYING.txt for license details.
56
*/
67

78
declare(strict_types=1);
89

910
namespace Magento\WebapiAsync\Controller\Rest\Asynchronous;
1011

12+
use Magento\Framework\Api\SimpleDataObjectConverter;
1113
use Magento\Framework\App\ObjectManager;
1214
use Magento\Framework\Exception\AuthorizationException;
1315
use Magento\Framework\Exception\InputException;
1416
use Magento\Framework\Exception\LocalizedException;
17+
use Magento\Framework\Reflection\MethodsMap;
1518
use Magento\Framework\Webapi\Exception;
1619
use Magento\Framework\Webapi\Rest\Request as RestRequest;
1720
use Magento\Framework\Webapi\ServiceInputProcessor;
@@ -24,6 +27,8 @@
2427

2528
/**
2629
* This class is responsible for retrieving resolved input data
30+
*
31+
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
2732
*/
2833
class InputParamsResolver
2934
{
@@ -61,6 +66,11 @@ class InputParamsResolver
6166
*/
6267
private $inputArraySizeLimitValue;
6368

69+
/**
70+
* @var MethodsMap
71+
*/
72+
private $methodsMap;
73+
6474
/**
6575
* Initialize dependencies.
6676
*
@@ -72,6 +82,7 @@ class InputParamsResolver
7282
* @param WebapiInputParamsResolver $inputParamsResolver
7383
* @param bool $isBulk
7484
* @param InputArraySizeLimitValue|null $inputArraySizeLimitValue
85+
* @param MethodsMap|null $methodsMap
7586
*/
7687
public function __construct(
7788
RestRequest $request,
@@ -81,7 +92,8 @@ public function __construct(
8192
RequestValidator $requestValidator,
8293
WebapiInputParamsResolver $inputParamsResolver,
8394
bool $isBulk = false,
84-
?InputArraySizeLimitValue $inputArraySizeLimitValue = null
95+
?InputArraySizeLimitValue $inputArraySizeLimitValue = null,
96+
?MethodsMap $methodsMap = null
8597
) {
8698
$this->request = $request;
8799
$this->paramsOverrider = $paramsOverrider;
@@ -92,6 +104,8 @@ public function __construct(
92104
$this->isBulk = $isBulk;
93105
$this->inputArraySizeLimitValue = $inputArraySizeLimitValue ?? ObjectManager::getInstance()
94106
->get(InputArraySizeLimitValue::class);
107+
$this->methodsMap = $methodsMap ?? ObjectManager::getInstance()
108+
->get(MethodsMap::class);
95109
}
96110

97111
/**
@@ -119,6 +133,8 @@ public function resolve()
119133
$routeServiceMethod = $route->getServiceMethod();
120134
$this->inputArraySizeLimitValue->set($route->getInputArraySizeLimit());
121135

136+
$this->validateParameters($routeServiceClass, $routeServiceMethod, array_keys($route->getParameters()));
137+
122138
foreach ($inputData as $key => $singleEntityParams) {
123139
if (!is_array($singleEntityParams)) {
124140
continue;
@@ -147,11 +163,22 @@ public function getInputData()
147163
$inputData = $this->request->getRequestData();
148164

149165
$httpMethod = $this->request->getHttpMethod();
150-
if ($httpMethod == RestRequest::HTTP_METHOD_DELETE) {
166+
if ($httpMethod === RestRequest::HTTP_METHOD_DELETE) {
151167
$requestBodyParams = $this->request->getBodyParams();
152168
$inputData = array_merge($requestBodyParams, $inputData);
153169
}
154-
return $inputData;
170+
171+
return array_map(function ($singleEntityParams) {
172+
if (is_array($singleEntityParams)) {
173+
$singleEntityParams = $this->filterInputData($singleEntityParams);
174+
$singleEntityParams = $this->paramsOverrider->override(
175+
$singleEntityParams,
176+
$this->getRoute()->getParameters()
177+
);
178+
}
179+
180+
return $singleEntityParams;
181+
}, $inputData);
155182
}
156183

157184
/**
@@ -184,4 +211,64 @@ private function resolveBulkItemParams(array $inputData, string $serviceClass, s
184211
{
185212
return $this->serviceInputProcessor->process($serviceClass, $serviceMethod, $inputData);
186213
}
214+
215+
/**
216+
* Validates InputData
217+
*
218+
* @param array $inputData
219+
* @return array
220+
*/
221+
private function filterInputData(array $inputData): array
222+
{
223+
$result = [];
224+
225+
$data = array_filter($inputData, function ($k) use (&$result) {
226+
$key = is_string($k) ? strtolower(str_replace('_', "", $k)) : $k;
227+
return !isset($result[$key]) && ($result[$key] = true);
228+
}, ARRAY_FILTER_USE_KEY);
229+
230+
return array_map(function ($value) {
231+
return is_array($value) ? $this->filterInputData($value) : $value;
232+
}, $data);
233+
}
234+
235+
/**
236+
* Validate that parameters are really used in the current request.
237+
*
238+
* @param string $serviceClassName
239+
* @param string $serviceMethodName
240+
* @param array $paramOverriders
241+
*/
242+
private function validateParameters(
243+
string $serviceClassName,
244+
string $serviceMethodName,
245+
array $paramOverriders
246+
): void {
247+
$methodParams = $this->methodsMap->getMethodParams($serviceClassName, $serviceMethodName);
248+
foreach ($paramOverriders as $key => $param) {
249+
$arrayKeys = explode('.', $param ?? '');
250+
$value = array_shift($arrayKeys);
251+
252+
foreach ($methodParams as $serviceMethodParam) {
253+
$serviceMethodParamName = $serviceMethodParam[MethodsMap::METHOD_META_NAME];
254+
$serviceMethodType = $serviceMethodParam[MethodsMap::METHOD_META_TYPE];
255+
256+
$camelCaseValue = SimpleDataObjectConverter::snakeCaseToCamelCase($value);
257+
if ($serviceMethodParamName === $value || $serviceMethodParamName === $camelCaseValue) {
258+
if (count($arrayKeys) > 0) {
259+
$camelCaseKey = SimpleDataObjectConverter::snakeCaseToCamelCase('set_' . $arrayKeys[0]);
260+
$this->validateParameters($serviceMethodType, $camelCaseKey, [implode('.', $arrayKeys)]);
261+
}
262+
unset($paramOverriders[$key]);
263+
break;
264+
}
265+
}
266+
}
267+
268+
if (!empty($paramOverriders)) {
269+
$message = 'The current request does not expect the next parameters: '
270+
. implode(', ', $paramOverriders);
271+
throw new \UnexpectedValueException(__($message)->__toString());
272+
}
273+
}
187274
}

app/code/Magento/WebapiAsync/Controller/Rest/AsynchronousRequestProcessor.php

Lines changed: 15 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
<?php
22
/**
3-
* Copyright © Magento, Inc. All rights reserved.
3+
* Copyright 2025 Adobe
4+
* All rights reserved.
45
* See COPYING.txt for license details.
56
*/
67

@@ -9,6 +10,10 @@
910
namespace Magento\WebapiAsync\Controller\Rest;
1011

1112
use Magento\Framework\Exception\BulkException;
13+
use Magento\Framework\Exception\InputException;
14+
use Magento\Framework\Exception\LocalizedException;
15+
use Magento\Framework\Webapi\Exception;
16+
use Magento\Framework\Webapi\Rest\Request;
1217
use Magento\Webapi\Controller\Rest\RequestProcessorInterface;
1318
use Magento\Framework\Webapi\Rest\Response as RestResponse;
1419
use Magento\WebapiAsync\Controller\Rest\Asynchronous\InputParamsResolver;
@@ -17,8 +22,6 @@
1722
use Magento\Framework\Reflection\DataObjectProcessor;
1823
use Magento\AsynchronousOperations\Api\Data\AsyncResponseInterfaceFactory;
1924
use Magento\AsynchronousOperations\Api\Data\AsyncResponseInterface;
20-
use Magento\Framework\Webapi\Rest\Request;
21-
use Magento\Framework\Webapi\Exception;
2225

2326
/**
2427
* Responsible for dispatching single and bulk requests.
@@ -121,13 +124,15 @@ public function process(Request $request)
121124
}
122125

123126
/**
124-
* Get topic name from webapi_async_config services config array by route url and http method
125-
*
126-
* @param \Magento\Framework\Webapi\Rest\Request $request
127+
* Get Topic Name
127128
*
129+
* @param Request $request
128130
* @return string
131+
* @throws InputException
132+
* @throws LocalizedException
133+
* @throws Exception
129134
*/
130-
private function getTopicName($request)
135+
private function getTopicName(Request $request): string
131136
{
132137
$route = $this->inputParamsResolver->getRoute();
133138

@@ -147,49 +152,22 @@ public function canProcess(Request $request)
147152
}
148153

149154
if (preg_match($this->processorPath, $request->getPathInfo()) === 1) {
150-
return $this->checkSelfResourceRequest($request);
155+
return true;
151156
}
152-
153157
return false;
154158
}
155159

156160
/**
157-
* Check if current request is bulk request
161+
* To check if it is bulk
158162
*
159163
* @param Request $request
160164
* @return bool
161165
*/
162-
public function isBulk(Request $request)
166+
public function isBulk(Request $request): bool
163167
{
164168
if (preg_match(self::BULK_PROCESSOR_PATH, $request->getPathInfo()) === 1) {
165169
return true;
166170
}
167171
return false;
168172
}
169-
170-
/**
171-
* Check if current request is self resource request
172-
*
173-
* @param Request $request
174-
* @return bool
175-
*
176-
* @throws Exception
177-
*/
178-
private function checkSelfResourceRequest(Request $request): bool
179-
{
180-
$path = preg_replace($this->processorPath, "$1", $request->getPathInfo());
181-
$request->setPathInfo(
182-
$path
183-
);
184-
185-
$route = $this->inputParamsResolver->getRoute();
186-
$aclResources = $route->getAclResources();
187-
188-
// We do not process self resource requests asynchronously
189-
if (in_array('self', $aclResources, true)) {
190-
return false;
191-
}
192-
193-
return true;
194-
}
195173
}

0 commit comments

Comments
 (0)