3 declare(strict_types=1);
5 namespace CuyZ\Valinor\Mapper\Object\Factory;
7 use CuyZ\Valinor\Definition\ClassDefinition;
8 use CuyZ\Valinor\Definition\FunctionObject;
9 use CuyZ\Valinor\Definition\Repository\FunctionDefinitionRepository;
10 use CuyZ\Valinor\Mapper\Object\FunctionObjectBuilder;
11 use CuyZ\Valinor\Mapper\Object\NativeConstructorObjectBuilder;
12 use CuyZ\Valinor\Mapper\Object\ObjectBuilder;
13 use CuyZ\Valinor\Mapper\Tree\Message\MessageBuilder;
14 use CuyZ\Valinor\Type\ClassType;
18 use function array_filter;
22 final class DateTimeZoneObjectBuilderFactory implements ObjectBuilderFactory
24 private ObjectBuilderFactory $delegate;
26 private FunctionDefinitionRepository $functionDefinitionRepository;
28 public function __construct(ObjectBuilderFactory $delegate, FunctionDefinitionRepository $functionDefinitionRepository)
30 $this->delegate = $delegate;
31 $this->functionDefinitionRepository = $functionDefinitionRepository;
34 public function for(ClassDefinition $class): array
36 $builders = $this->delegate->for($class);
38 if ($class->name() !== DateTimeZone::class) {
42 // Remove `DateTimeZone` native constructors
43 $builders = array_filter($builders, fn (ObjectBuilder $builder) => ! $builder instanceof NativeConstructorObjectBuilder);
45 $useDefaultBuilder = true;
47 foreach ($builders as $builder) {
48 if (count($builder->describeArguments()) === 1) {
49 $useDefaultBuilder = false;
50 // @infection-ignore-all
55 if ($useDefaultBuilder) {
56 // @infection-ignore-all / Ignore memoization
57 $builders[] = $this->defaultBuilder($class->type());
63 private function defaultBuilder(ClassType $type): FunctionObjectBuilder
65 $constructor = function (string $timezone) {
67 return new DateTimeZone($timezone);
69 throw MessageBuilder::newError('Value {source_value} is not a valid timezone.')->build();
73 $function = new FunctionObject($this->functionDefinitionRepository->for($constructor), $constructor);
75 return new FunctionObjectBuilder($function, $type);