1
1
<?php
2
2
/**
3
- * Copyright © Magento, Inc. All rights reserved.
3
+ * Copyright 2025 Adobe
4
+ * All rights reserved.
4
5
* See COPYING.txt for license details.
5
6
*/
6
7
7
8
declare (strict_types=1 );
8
9
9
10
namespace Magento \WebapiAsync \Controller \Rest \Asynchronous ;
10
11
12
+ use Magento \Framework \Api \SimpleDataObjectConverter ;
11
13
use Magento \Framework \App \ObjectManager ;
12
14
use Magento \Framework \Exception \AuthorizationException ;
13
15
use Magento \Framework \Exception \InputException ;
14
16
use Magento \Framework \Exception \LocalizedException ;
17
+ use Magento \Framework \Reflection \MethodsMap ;
15
18
use Magento \Framework \Webapi \Exception ;
16
19
use Magento \Framework \Webapi \Rest \Request as RestRequest ;
17
20
use Magento \Framework \Webapi \ServiceInputProcessor ;
24
27
25
28
/**
26
29
* This class is responsible for retrieving resolved input data
30
+ *
31
+ * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
27
32
*/
28
33
class InputParamsResolver
29
34
{
@@ -61,6 +66,11 @@ class InputParamsResolver
61
66
*/
62
67
private $ inputArraySizeLimitValue ;
63
68
69
+ /**
70
+ * @var MethodsMap
71
+ */
72
+ private $ methodsMap ;
73
+
64
74
/**
65
75
* Initialize dependencies.
66
76
*
@@ -72,6 +82,7 @@ class InputParamsResolver
72
82
* @param WebapiInputParamsResolver $inputParamsResolver
73
83
* @param bool $isBulk
74
84
* @param InputArraySizeLimitValue|null $inputArraySizeLimitValue
85
+ * @param MethodsMap|null $methodsMap
75
86
*/
76
87
public function __construct (
77
88
RestRequest $ request ,
@@ -81,7 +92,8 @@ public function __construct(
81
92
RequestValidator $ requestValidator ,
82
93
WebapiInputParamsResolver $ inputParamsResolver ,
83
94
bool $ isBulk = false ,
84
- ?InputArraySizeLimitValue $ inputArraySizeLimitValue = null
95
+ ?InputArraySizeLimitValue $ inputArraySizeLimitValue = null ,
96
+ ?MethodsMap $ methodsMap = null
85
97
) {
86
98
$ this ->request = $ request ;
87
99
$ this ->paramsOverrider = $ paramsOverrider ;
@@ -92,6 +104,8 @@ public function __construct(
92
104
$ this ->isBulk = $ isBulk ;
93
105
$ this ->inputArraySizeLimitValue = $ inputArraySizeLimitValue ?? ObjectManager::getInstance ()
94
106
->get (InputArraySizeLimitValue::class);
107
+ $ this ->methodsMap = $ methodsMap ?? ObjectManager::getInstance ()
108
+ ->get (MethodsMap::class);
95
109
}
96
110
97
111
/**
@@ -119,6 +133,8 @@ public function resolve()
119
133
$ routeServiceMethod = $ route ->getServiceMethod ();
120
134
$ this ->inputArraySizeLimitValue ->set ($ route ->getInputArraySizeLimit ());
121
135
136
+ $ this ->validateParameters ($ routeServiceClass , $ routeServiceMethod , array_keys ($ route ->getParameters ()));
137
+
122
138
foreach ($ inputData as $ key => $ singleEntityParams ) {
123
139
if (!is_array ($ singleEntityParams )) {
124
140
continue ;
@@ -147,11 +163,22 @@ public function getInputData()
147
163
$ inputData = $ this ->request ->getRequestData ();
148
164
149
165
$ httpMethod = $ this ->request ->getHttpMethod ();
150
- if ($ httpMethod == RestRequest::HTTP_METHOD_DELETE ) {
166
+ if ($ httpMethod === RestRequest::HTTP_METHOD_DELETE ) {
151
167
$ requestBodyParams = $ this ->request ->getBodyParams ();
152
168
$ inputData = array_merge ($ requestBodyParams , $ inputData );
153
169
}
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 );
155
182
}
156
183
157
184
/**
@@ -184,4 +211,64 @@ private function resolveBulkItemParams(array $inputData, string $serviceClass, s
184
211
{
185
212
return $ this ->serviceInputProcessor ->process ($ serviceClass , $ serviceMethod , $ inputData );
186
213
}
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
+ }
187
274
}
0 commit comments