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 ;
24
26
25
27
/**
26
28
* This class is responsible for retrieving resolved input data
29
+ *
30
+ * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
27
31
*/
28
32
class InputParamsResolver
29
33
{
@@ -61,6 +65,11 @@ class InputParamsResolver
61
65
*/
62
66
private $ inputArraySizeLimitValue ;
63
67
68
+ /**
69
+ * @var MethodsMap
70
+ */
71
+ private $ methodsMap ;
72
+
64
73
/**
65
74
* Initialize dependencies.
66
75
*
@@ -72,6 +81,7 @@ class InputParamsResolver
72
81
* @param WebapiInputParamsResolver $inputParamsResolver
73
82
* @param bool $isBulk
74
83
* @param InputArraySizeLimitValue|null $inputArraySizeLimitValue
84
+ * @param MethodsMap|null $methodsMap
75
85
*/
76
86
public function __construct (
77
87
RestRequest $ request ,
@@ -81,7 +91,8 @@ public function __construct(
81
91
RequestValidator $ requestValidator ,
82
92
WebapiInputParamsResolver $ inputParamsResolver ,
83
93
bool $ isBulk = false ,
84
- ?InputArraySizeLimitValue $ inputArraySizeLimitValue = null
94
+ ?InputArraySizeLimitValue $ inputArraySizeLimitValue = null ,
95
+ ?MethodsMap $ methodsMap = null
85
96
) {
86
97
$ this ->request = $ request ;
87
98
$ this ->paramsOverrider = $ paramsOverrider ;
@@ -92,6 +103,8 @@ public function __construct(
92
103
$ this ->isBulk = $ isBulk ;
93
104
$ this ->inputArraySizeLimitValue = $ inputArraySizeLimitValue ?? ObjectManager::getInstance ()
94
105
->get (InputArraySizeLimitValue::class);
106
+ $ this ->methodsMap = $ methodsMap ?? ObjectManager::getInstance ()
107
+ ->get (MethodsMap::class);
95
108
}
96
109
97
110
/**
@@ -119,7 +132,13 @@ public function resolve()
119
132
$ routeServiceMethod = $ route ->getServiceMethod ();
120
133
$ this ->inputArraySizeLimitValue ->set ($ route ->getInputArraySizeLimit ());
121
134
135
+ $ this ->validateParameters ($ routeServiceClass , $ routeServiceMethod , array_keys ($ route ->getParameters ()));
136
+
122
137
foreach ($ inputData as $ key => $ singleEntityParams ) {
138
+ if (!is_array ($ singleEntityParams )) {
139
+ continue ;
140
+ }
141
+
123
142
$ webapiResolvedParams [$ key ] = $ this ->resolveBulkItemParams (
124
143
$ singleEntityParams ,
125
144
$ routeServiceClass ,
@@ -143,11 +162,22 @@ public function getInputData()
143
162
$ inputData = $ this ->request ->getRequestData ();
144
163
145
164
$ httpMethod = $ this ->request ->getHttpMethod ();
146
- if ($ httpMethod == RestRequest::HTTP_METHOD_DELETE ) {
165
+ if ($ httpMethod === RestRequest::HTTP_METHOD_DELETE ) {
147
166
$ requestBodyParams = $ this ->request ->getBodyParams ();
148
167
$ inputData = array_merge ($ requestBodyParams , $ inputData );
149
168
}
150
- return $ inputData ;
169
+
170
+ return array_map (function ($ singleEntityParams ) {
171
+ if (is_array ($ singleEntityParams )) {
172
+ $ singleEntityParams = $ this ->filterInputData ($ singleEntityParams );
173
+ $ singleEntityParams = $ this ->paramsOverrider ->override (
174
+ $ singleEntityParams ,
175
+ $ this ->getRoute ()->getParameters ()
176
+ );
177
+ }
178
+
179
+ return $ singleEntityParams ;
180
+ }, $ inputData );
151
181
}
152
182
153
183
/**
@@ -180,4 +210,64 @@ private function resolveBulkItemParams(array $inputData, string $serviceClass, s
180
210
{
181
211
return $ this ->serviceInputProcessor ->process ($ serviceClass , $ serviceMethod , $ inputData );
182
212
}
213
+
214
+ /**
215
+ * Validates InputData
216
+ *
217
+ * @param array $inputData
218
+ * @return array
219
+ */
220
+ private function filterInputData (array $ inputData ): array
221
+ {
222
+ $ result = [];
223
+
224
+ $ data = array_filter ($ inputData , function ($ k ) use (&$ result ) {
225
+ $ key = is_string ($ k ) ? strtolower (str_replace ('_ ' , "" , $ k )) : $ k ;
226
+ return !isset ($ result [$ key ]) && ($ result [$ key ] = true );
227
+ }, ARRAY_FILTER_USE_KEY );
228
+
229
+ return array_map (function ($ value ) {
230
+ return is_array ($ value ) ? $ this ->filterInputData ($ value ) : $ value ;
231
+ }, $ data );
232
+ }
233
+
234
+ /**
235
+ * Validate that parameters are really used in the current request.
236
+ *
237
+ * @param string $serviceClassName
238
+ * @param string $serviceMethodName
239
+ * @param array $paramOverriders
240
+ */
241
+ private function validateParameters (
242
+ string $ serviceClassName ,
243
+ string $ serviceMethodName ,
244
+ array $ paramOverriders
245
+ ): void {
246
+ $ methodParams = $ this ->methodsMap ->getMethodParams ($ serviceClassName , $ serviceMethodName );
247
+ foreach ($ paramOverriders as $ key => $ param ) {
248
+ $ arrayKeys = explode ('. ' , $ param ?? '' );
249
+ $ value = array_shift ($ arrayKeys );
250
+
251
+ foreach ($ methodParams as $ serviceMethodParam ) {
252
+ $ serviceMethodParamName = $ serviceMethodParam [MethodsMap::METHOD_META_NAME ];
253
+ $ serviceMethodType = $ serviceMethodParam [MethodsMap::METHOD_META_TYPE ];
254
+
255
+ $ camelCaseValue = SimpleDataObjectConverter::snakeCaseToCamelCase ($ value );
256
+ if ($ serviceMethodParamName === $ value || $ serviceMethodParamName === $ camelCaseValue ) {
257
+ if (count ($ arrayKeys ) > 0 ) {
258
+ $ camelCaseKey = SimpleDataObjectConverter::snakeCaseToCamelCase ('set_ ' . $ arrayKeys [0 ]);
259
+ $ this ->validateParameters ($ serviceMethodType , $ camelCaseKey , [implode ('. ' , $ arrayKeys )]);
260
+ }
261
+ unset($ paramOverriders [$ key ]);
262
+ break ;
263
+ }
264
+ }
265
+ }
266
+
267
+ if (!empty ($ paramOverriders )) {
268
+ $ message = 'The current request does not expect the next parameters: '
269
+ . implode (', ' , $ paramOverriders );
270
+ throw new \UnexpectedValueException (__ ($ message )->__toString ());
271
+ }
272
+ }
183
273
}
0 commit comments