public function _typecastLoadField(Field $f, $value)
{
// work only on copied value not real one !!!
$v = is_object($value) ? clone $value : $value;
switch ($f->type) {
case 'integer':
$v = (int) $v;
break;
case 'float':
$v = (double) $v;
break;
case 'money':
$v = round($v, 4);
break;
case 'boolean':
if (isset($f->enum) && is_array($f->enum)) {
if (isset($f->enum[0]) && $v == $f->enum[0]) {
$v = false;
} elseif (isset($f->enum[1]) && $v == $f->enum[1]) {
$v = true;
} else {
$v = null;
}
} else {
$v = (bool) $v;
}
break;
case 'date':
case 'datetime':
case 'time':
$dt_class = isset($f->dateTimeClass) ? $f->dateTimeClass : 'DateTime';
$tz_class = isset($f->dateTimeZoneClass) ? $f->dateTimeZoneClass : 'DateTimeZone';
if (is_numeric($v)) {
$v = new $dt_class('@' . $v);
} elseif (is_string($v)) {
// ! symbol in date format is essential here to remove time part of DateTime - don't remove, this is not a bug
$format = ['date' => '+!Y-m-d', 'datetime' => 'Y-m-d H:i:s', 'time' => 'H:i:s'];
$format = $f->persist_format ?: $format[$f->type];
// datetime only - set from persisting timezone
if ($f->type == 'datetime' && isset($f->persist_timezone)) {
$v = $dt_class::createFromFormat($format, $v, new $tz_class($f->persist_timezone));
if ($v === false) {
throw new Exception(['Incorrectly formatted datetime', 'format' => $format, 'value' => $value, 'field' => $f]);
}
$v->setTimeZone(new $tz_class(date_default_timezone_get()));
} else {
$v = $dt_class::createFromFormat($format, $v);
if ($v === false) {
throw new Exception(['Incorrectly formatted date/time', 'format' => $format, 'value' => $value, 'field' => $f]);
}
}
// need to cast here because DateTime::createFromFormat returns DateTime object not $dt_class
// this is what Carbon::instance(DateTime $dt) method does for example
if ($dt_class != 'DateTime') {
$v = new $dt_class($v->format('Y-m-d H:i:s.u'), $v->getTimeZone());
}
}
break;
case 'array':
// don't decode if we already use some kind of serialization
$v = $f->serialize ? $v : json_decode($v, true);
break;
case 'object':
// don't decode if we already use some kind of serialization
$v = $f->serialize ? $v : json_decode($v, false);
break;
}
return $v;
}