Skip to content

Commit 7871094

Browse files
authored
Update DataMapper.php
1 parent f03c602 commit 7871094

File tree

1 file changed

+119
-40
lines changed

1 file changed

+119
-40
lines changed

src/DataMapper.php

Lines changed: 119 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)