getActualType(); } if ($type instanceof AbstractList) { $innerType = $type->getValueType(); $result = []; foreach ($rawValue as $key => $value) { $result[$key] = self::resolveAnnotatedValue($innerType, $value); } return $result; } if ($type instanceof Generic) { $types = $type->getTypes(); $innerType = count($types) === 2 ? $types[1] : $types[0]; if (is_array($rawValue)) { $innerValues = []; foreach ($rawValue as $key => $value) { $innerValues[$key] = self::resolveAnnotatedValue($innerType, $value); } return array_key_exists(0, $rawValue) ? new ($type->getFqsen()->__toString())($innerValues) : App::makeWith($type->getFqsen()->__toString(), $innerValues); } $value = self::resolveAnnotatedValue($innerType, $rawValue); return new ($type->getFqsen()->__toString())($value); } if ($type instanceof Boolean) { return boolval($rawValue); } if ($type instanceof Float_) { return floatval($rawValue); } if ($type instanceof Integer) { return intval($rawValue); } if ($type instanceof Object_) { return self::make($type->getFqsen()->__toString(), $rawValue); } return $rawValue; } public static function resolveDeclaredTypeValue(ReflectionNamedType $parameter, mixed $rawValue): mixed { $type = $parameter->getName(); if (is_a($type, \BackedEnum::class, true)) { return $type::from($rawValue); } return match ($type) { 'string' => $rawValue, 'bool' => boolval($rawValue), 'int' => intval($rawValue), 'float' => floatval($rawValue), 'array' => $rawValue, default => self::make($type, $rawValue), }; } /** * @param array $input */ public static function make(string $class, array $input): object { $parameters = ReflectionHelper::getParametersMeta($class); $arguments = []; foreach ($parameters as $parameter) { $name = $parameter->reflection->getName(); $parameterArgs = empty($parameter->reflection->getAttributes(Flat::class)) ? ($input[$name] ?? null) : $input; if (is_null($parameterArgs)) { $arguments[$name] = $parameter->reflection->isDefaultValueAvailable() ? $parameter->reflection->getDefaultValue() : null; continue; } if ($caster = $parameter->reflection->getAttributes(CastWith::class)[0] ?? null) { $caster = $caster->newInstance()->class; $arguments[$name] = App::call("$caster@cast", ['data' => $parameterArgs]); continue; } $parameterClass = $parameter->reflection->getClass()?->getName(); $type = $parameter->tag?->getType(); if (empty($parameterClass) && $type instanceof Object_) { $parameterClass = $type->getFqsen()?->__toString(); } if (!empty($parameterClass) && $caster = config('dto.cast.' . $parameterClass, null)) { $arguments[$name] = App::call($caster, ['data' => $parameterArgs]); continue; } if (!is_null($type)) { $arguments[$name] = self::resolveAnnotatedValue($type, $parameterArgs); continue; } $reflectionType = $parameter->reflection->getType(); if ($reflectionType instanceof ReflectionNamedType) { $arguments[$name] = self::resolveDeclaredTypeValue($reflectionType, $parameterArgs); continue; } $arguments[$name] = $parameterArgs; } return new $class(...$arguments); } }