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
78declare (strict_types=1 );
89
910namespace Magento \WebapiAsync \Controller \Rest \Asynchronous ;
1011
12+ use Magento \Framework \Api \SimpleDataObjectConverter ;
1113use Magento \Framework \App \ObjectManager ;
1214use Magento \Framework \Exception \AuthorizationException ;
1315use Magento \Framework \Exception \InputException ;
1416use Magento \Framework \Exception \LocalizedException ;
17+ use Magento \Framework \Reflection \MethodsMap ;
1518use Magento \Framework \Webapi \Exception ;
1619use Magento \Framework \Webapi \Rest \Request as RestRequest ;
1720use Magento \Framework \Webapi \ServiceInputProcessor ;
2427
2528/**
2629 * This class is responsible for retrieving resolved input data
30+ *
31+ * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
2732 */
2833class 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}
0 commit comments