8
8
9
9
namespace Magento \WebapiAsync \Controller \Rest \Asynchronous ;
10
10
11
+ use Magento \Framework \Api \SimpleDataObjectConverter ;
11
12
use Magento \Framework \App \ObjectManager ;
12
13
use Magento \Framework \Exception \AuthorizationException ;
13
14
use Magento \Framework \Exception \InputException ;
14
15
use Magento \Framework \Exception \LocalizedException ;
16
+ use Magento \Framework \Reflection \MethodsMap ;
15
17
use Magento \Framework \Webapi \Exception ;
16
18
use Magento \Framework \Webapi \Rest \Request as RestRequest ;
17
19
use Magento \Framework \Webapi \ServiceInputProcessor ;
@@ -61,6 +63,11 @@ class InputParamsResolver
61
63
*/
62
64
private $ inputArraySizeLimitValue ;
63
65
66
+ /**
67
+ * @var MethodsMap
68
+ */
69
+ private $ methodsMap ;
70
+
64
71
/**
65
72
* Initialize dependencies.
66
73
*
@@ -72,6 +79,7 @@ class InputParamsResolver
72
79
* @param WebapiInputParamsResolver $inputParamsResolver
73
80
* @param bool $isBulk
74
81
* @param InputArraySizeLimitValue|null $inputArraySizeLimitValue
82
+ * @param MethodsMap|null $methodsMap
75
83
*/
76
84
public function __construct (
77
85
RestRequest $ request ,
@@ -81,7 +89,8 @@ public function __construct(
81
89
RequestValidator $ requestValidator ,
82
90
WebapiInputParamsResolver $ inputParamsResolver ,
83
91
bool $ isBulk = false ,
84
- ?InputArraySizeLimitValue $ inputArraySizeLimitValue = null
92
+ ?InputArraySizeLimitValue $ inputArraySizeLimitValue = null ,
93
+ ?MethodsMap $ methodsMap = null
85
94
) {
86
95
$ this ->request = $ request ;
87
96
$ this ->paramsOverrider = $ paramsOverrider ;
@@ -92,6 +101,8 @@ public function __construct(
92
101
$ this ->isBulk = $ isBulk ;
93
102
$ this ->inputArraySizeLimitValue = $ inputArraySizeLimitValue ?? ObjectManager::getInstance ()
94
103
->get (InputArraySizeLimitValue::class);
104
+ $ this ->methodsMap = $ methodsMap ?? ObjectManager::getInstance ()
105
+ ->get (MethodsMap::class);
95
106
}
96
107
97
108
/**
@@ -120,6 +131,12 @@ public function resolve()
120
131
$ this ->inputArraySizeLimitValue ->set ($ route ->getInputArraySizeLimit ());
121
132
122
133
foreach ($ inputData as $ key => $ singleEntityParams ) {
134
+ if (!is_array ($ singleEntityParams )) {
135
+ continue ;
136
+ }
137
+
138
+ $ this ->validateParameters ($ routeServiceClass , $ routeServiceMethod , array_keys ($ route ->getParameters ()));
139
+
123
140
$ webapiResolvedParams [$ key ] = $ this ->resolveBulkItemParams (
124
141
$ singleEntityParams ,
125
142
$ routeServiceClass ,
@@ -147,7 +164,18 @@ public function getInputData()
147
164
$ requestBodyParams = $ this ->request ->getBodyParams ();
148
165
$ inputData = array_merge ($ requestBodyParams , $ inputData );
149
166
}
150
- return $ inputData ;
167
+
168
+ return array_map (function ($ singleEntityParams ) {
169
+ if (is_array ($ singleEntityParams )) {
170
+ $ singleEntityParams = $ this ->filterInputData ($ singleEntityParams );
171
+ $ singleEntityParams = $ this ->paramsOverrider ->override (
172
+ $ singleEntityParams ,
173
+ $ this ->getRoute ()->getParameters ()
174
+ );
175
+ }
176
+
177
+ return $ singleEntityParams ;
178
+ }, $ inputData );
151
179
}
152
180
153
181
/**
@@ -180,4 +208,63 @@ private function resolveBulkItemParams(array $inputData, string $serviceClass, s
180
208
{
181
209
return $ this ->serviceInputProcessor ->process ($ serviceClass , $ serviceMethod , $ inputData );
182
210
}
211
+
212
+ /**
213
+ * Validates InputData
214
+ *
215
+ * @param array $inputData
216
+ * @return array
217
+ */
218
+ private function filterInputData (array $ inputData ): array
219
+ {
220
+ $ result = [];
221
+
222
+ $ data = array_filter ($ inputData , function ($ k ) use (&$ result ) {
223
+ $ key = is_string ($ k ) ? strtolower (str_replace ('_ ' , "" , $ k )) : $ k ;
224
+ return !isset ($ result [$ key ]) && ($ result [$ key ] = true );
225
+ }, ARRAY_FILTER_USE_KEY );
226
+
227
+ return array_map (function ($ value ) {
228
+ return is_array ($ value ) ? $ this ->filterInputData ($ value ) : $ value ;
229
+ }, $ data );
230
+ }
231
+
232
+ /**
233
+ * Validate that parameters are really used in the current request.
234
+ *
235
+ * @param string $serviceClassName
236
+ * @param string $serviceMethodName
237
+ * @param array $paramOverriders
238
+ */
239
+ private function validateParameters (
240
+ string $ serviceClassName ,
241
+ string $ serviceMethodName ,
242
+ array $ paramOverriders
243
+ ): void {
244
+ $ methodParams = $ this ->methodsMap ->getMethodParams ($ serviceClassName , $ serviceMethodName );
245
+ foreach ($ paramOverriders as $ key => $ param ) {
246
+ $ arrayKeys = explode ('. ' , $ param ?? '' );
247
+ $ value = array_shift ($ arrayKeys );
248
+
249
+ foreach ($ methodParams as $ serviceMethodParam ) {
250
+ $ serviceMethodParamName = $ serviceMethodParam [MethodsMap::METHOD_META_NAME ];
251
+ $ serviceMethodType = $ serviceMethodParam [MethodsMap::METHOD_META_TYPE ];
252
+
253
+ $ camelCaseValue = SimpleDataObjectConverter::snakeCaseToCamelCase ($ value );
254
+ if ($ serviceMethodParamName === $ value || $ serviceMethodParamName === $ camelCaseValue ) {
255
+ if (count ($ arrayKeys ) > 0 ) {
256
+ $ camelCaseKey = SimpleDataObjectConverter::snakeCaseToCamelCase ('set_ ' . $ arrayKeys [0 ]);
257
+ $ this ->validateParameters ($ serviceMethodType , $ camelCaseKey , [implode ('. ' , $ arrayKeys )]);
258
+ }
259
+ unset($ paramOverriders [$ key ]);
260
+ break ;
261
+ }
262
+ }
263
+ }
264
+ if (!empty ($ paramOverriders )) {
265
+ $ message = 'The current request does not expect the next parameters: '
266
+ . implode (', ' , $ paramOverriders );
267
+ throw new \UnexpectedValueException (__ ($ message )->__toString ());
268
+ }
269
+ }
183
270
}
0 commit comments