@@ -208,6 +208,7 @@ private static function propertyAliasesToFlat(array $aliases, $parent = null): a
208208 return $ result ;
209209 }
210210
211+
211212 /**
212213 * @param array $data
213214 * @param array $mapping
@@ -228,64 +229,59 @@ protected static function buildMap(array $data, array $mapping, $parent = null)
228229
229230 $ originalKey = $ mapping ['flat ' ][$ pKey ]['key ' ];
230231 $ type = $ mapping ['flat ' ][$ pKey ]['type ' ];
232+ $ schema = $ mapping ['flat ' ][$ pKey ];
231233
232- // Cast to Type.
233234 switch ($ type ) {
234- case MappingFieldType::TEXT :
235- case MappingFieldType::KEYWORD :
235+ default :
236236 if (\is_array ($ value )) {
237237 foreach ($ value as $ k => $ v ) {
238- $ value [$ k ] = ( string ) $ v ;
238+ $ value [$ k ] = self :: cast ( $ v , $ type ) ;
239239 }
240240 } else {
241- $ value = (string ) $ value ;
242- }
243- break ;
244-
245- case MappingFieldType::SHORT :
246- case MappingFieldType::INTEGER :
247- $ value = (int ) $ value ;
248- break ;
249-
250- case MappingFieldType::LONG :
251- case MappingFieldType::DOUBLE :
252- $ value = (double ) $ value ;
253- break ;
254-
255- case MappingFieldType::SCALED_FLOAT :
256- case MappingFieldType::HALF_FLOAT :
257- case MappingFieldType::FLOAT :
258- $ value = (float ) $ value ;
259- break ;
260-
261- case MappingFieldType::BOOLEAN :
262- $ value = \filter_var ($ value , FILTER_VALIDATE_BOOLEAN );
263- break ;
264-
265- case MappingFieldType::DATE :
266- if (empty ($ value ) == true || $ value == '0000-00-00 ' ) {
267- $ value = null ;
241+ $ value = self ::cast ($ value , $ type );
268242 }
269243 break ;
270244
271245 case MappingFieldType::OBJECT :
272246 case MappingFieldType::NESTED :
273- // Check if $value is associative.
274- if (\is_array (\current ($ value ))) {
247+ $ newValue = [];
248+
249+ if (! self ::isAssociative ($ value , false )) {
275250 foreach ($ value as $ k => $ v ) {
276- $ nestedPKey = $ pKey ;
251+ if (\is_array ($ v )) {
252+ $ newValue [] = self ::buildMap ($ v , $ mapping , $ pKey );
253+ }
254+ }
255+ } else {
256+ foreach (\array_keys ($ schema ['map ' ]) as $ map ) {
257+ if (! isset ($ mapping ['flat ' ][$ pKey . '. ' . $ map ])) {
258+ continue ;
259+ }
277260
278- if (isset ( $ mapping [ ' flat ' ][ $ pKey . ' . ' . $ k ] )) {
279- $ nestedPKey = ( $ pKey . ' . ' . $ k ) ;
261+ if (! \array_key_exists ( $ map , $ value )) {
262+ continue ;
280263 }
281264
282- $ value [$ k ] = self ::buildMap ($ v , $ mapping , $ nestedPKey );
265+ if (\is_array ($ value [$ map ]) && self ::isAssociative ($ value [$ map ])) {
266+ $ newValue [$ map ] = self ::buildMap (
267+ $ value [$ map ],
268+ $ mapping ,
269+ ($ pKey . '. ' . $ map )
270+ );
271+ } else {
272+ $ newValue [$ map ] = self ::buildMap (
273+ [$ map => $ value [$ map ]],
274+ $ mapping ,
275+ ($ pKey )
276+ )[$ map ];
277+ }
283278 }
284- } else {
285- $ value = self ::buildMap ($ value , $ mapping , $ pKey );
286279 }
280+
281+ $ value = $ newValue ;
282+
287283 break ;
288- }//end switch
284+ }
289285
290286 $ result [$ originalKey ] = $ value ;
291287 }//end foreach
@@ -297,4 +293,87 @@ protected static function buildMap(array $data, array $mapping, $parent = null)
297293 return $ result ;
298294 }
299295
296+ /**
297+ * @param mixed $value
298+ * @param string $type
299+ *
300+ * @return mixed
301+ */
302+ protected static function cast ($ value , $ type )
303+ {
304+ switch ($ type ) {
305+ case MappingFieldType::TEXT :
306+ case MappingFieldType::KEYWORD :
307+ $ value = (string ) $ value ;
308+ break ;
309+
310+ case MappingFieldType::SHORT :
311+ case MappingFieldType::INTEGER :
312+ $ value = (int ) $ value ;
313+ break ;
314+
315+ case MappingFieldType::LONG :
316+ case MappingFieldType::DOUBLE :
317+ $ value = (double ) $ value ;
318+ break ;
319+
320+ case MappingFieldType::SCALED_FLOAT :
321+ case MappingFieldType::HALF_FLOAT :
322+ case MappingFieldType::FLOAT :
323+ $ value = (float ) $ value ;
324+ break ;
325+
326+ case MappingFieldType::BOOLEAN :
327+ $ value = \filter_var ($ value , FILTER_VALIDATE_BOOLEAN );
328+ break ;
329+
330+ case MappingFieldType::DATE :
331+ if (empty ($ value ) == true || $ value == '0000-00-00 ' ) {
332+ $ value = null ;
333+ }
334+ break ;
335+ }
336+
337+ return $ value ;
338+ }
339+
340+ /**
341+ * Returns a value indicating whether the given array is an associative array.
342+ *
343+ * An array is associative if all its keys are strings. If `$allStrings` is false,
344+ * then an array will be treated as associative if at least one of its keys is a string.
345+ *
346+ * Note that an empty array will NOT be considered associative.
347+ *
348+ * @param array $array the array being checked
349+ * @param bool $allStrings whether the array keys must be all strings in order for
350+ * the array to be treated as associative.
351+ *
352+ * @return bool whether the array is associative
353+ */
354+ protected static function isAssociative (array $ array , bool $ allStrings = true ): bool
355+ {
356+ if (! \is_array ($ array ) || empty ($ array )) {
357+ return false ;
358+ }
359+
360+ if ($ allStrings ) {
361+ foreach ($ array as $ key => $ value ) {
362+ if (! \is_string ($ key )) {
363+ return false ;
364+ }
365+ }
366+
367+ return true ;
368+ }
369+
370+ foreach ($ array as $ key => $ value ) {
371+ if (\is_string ($ key )) {
372+ return true ;
373+ }
374+ }
375+
376+ return false ;
377+ }
378+
300379}
0 commit comments