88
99namespace Magento \WebapiAsync \Controller \Rest \Asynchronous ;
1010
11+ use Magento \Framework \Api \SimpleDataObjectConverter ;
1112use Magento \Framework \App \ObjectManager ;
1213use Magento \Framework \Exception \AuthorizationException ;
1314use Magento \Framework \Exception \InputException ;
1415use Magento \Framework \Exception \LocalizedException ;
16+ use Magento \Framework \Reflection \MethodsMap ;
1517use Magento \Framework \Webapi \Exception ;
1618use Magento \Framework \Webapi \Rest \Request as RestRequest ;
1719use Magento \Framework \Webapi \ServiceInputProcessor ;
@@ -61,6 +63,11 @@ class InputParamsResolver
6163 */
6264 private $ inputArraySizeLimitValue ;
6365
66+ /**
67+ * @var MethodsMap
68+ */
69+ private $ methodsMap ;
70+
6471 /**
6572 * Initialize dependencies.
6673 *
@@ -72,6 +79,7 @@ class InputParamsResolver
7279 * @param WebapiInputParamsResolver $inputParamsResolver
7380 * @param bool $isBulk
7481 * @param InputArraySizeLimitValue|null $inputArraySizeLimitValue
82+ * @param MethodsMap|null $methodsMap
7583 */
7684 public function __construct (
7785 RestRequest $ request ,
@@ -81,7 +89,8 @@ public function __construct(
8189 RequestValidator $ requestValidator ,
8290 WebapiInputParamsResolver $ inputParamsResolver ,
8391 bool $ isBulk = false ,
84- ?InputArraySizeLimitValue $ inputArraySizeLimitValue = null
92+ ?InputArraySizeLimitValue $ inputArraySizeLimitValue = null ,
93+ ?MethodsMap $ methodsMap = null
8594 ) {
8695 $ this ->request = $ request ;
8796 $ this ->paramsOverrider = $ paramsOverrider ;
@@ -92,6 +101,8 @@ public function __construct(
92101 $ this ->isBulk = $ isBulk ;
93102 $ this ->inputArraySizeLimitValue = $ inputArraySizeLimitValue ?? ObjectManager::getInstance ()
94103 ->get (InputArraySizeLimitValue::class);
104+ $ this ->methodsMap = $ methodsMap ?? ObjectManager::getInstance ()
105+ ->get (MethodsMap::class);
95106 }
96107
97108 /**
@@ -120,6 +131,12 @@ public function resolve()
120131 $ this ->inputArraySizeLimitValue ->set ($ route ->getInputArraySizeLimit ());
121132
122133 foreach ($ inputData as $ key => $ singleEntityParams ) {
134+ if (!is_array ($ singleEntityParams )) {
135+ continue ;
136+ }
137+
138+ $ this ->validateParameters ($ routeServiceClass , $ routeServiceMethod , array_keys ($ route ->getParameters ()));
139+
123140 $ webapiResolvedParams [$ key ] = $ this ->resolveBulkItemParams (
124141 $ singleEntityParams ,
125142 $ routeServiceClass ,
@@ -147,7 +164,18 @@ public function getInputData()
147164 $ requestBodyParams = $ this ->request ->getBodyParams ();
148165 $ inputData = array_merge ($ requestBodyParams , $ inputData );
149166 }
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 );
151179 }
152180
153181 /**
@@ -180,4 +208,63 @@ private function resolveBulkItemParams(array $inputData, string $serviceClass, s
180208 {
181209 return $ this ->serviceInputProcessor ->process ($ serviceClass , $ serviceMethod , $ inputData );
182210 }
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+ }
183270}
0 commit comments