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\Library\Settings;
11 use CuyZ\Valinor\Mapper\Object\DateTimeFormatConstructor;
12 use CuyZ\Valinor\Mapper\Object\FunctionObjectBuilder;
13 use CuyZ\Valinor\Mapper\Object\NativeConstructorObjectBuilder;
14 use CuyZ\Valinor\Mapper\Object\ObjectBuilder;
15 use CuyZ\Valinor\Type\ClassType;
17 use DateTimeImmutable;
19 use function array_filter;
23 final class DateTimeObjectBuilderFactory implements ObjectBuilderFactory
25 public function __construct(
26 private ObjectBuilderFactory $delegate,
27 /** @var non-empty-array<non-empty-string> */
28 private array $supportedDateFormats,
29 private FunctionDefinitionRepository $functionDefinitionRepository
32 public function for(ClassDefinition $class): array
34 $className = $class->name();
36 $builders = $this->delegate->for($class);
38 if ($className !== DateTime::class && $className !== DateTimeImmutable::class) {
42 // Remove `DateTime` & `DateTimeImmutable` native constructors
43 $builders = array_filter($builders, fn (ObjectBuilder $builder) => ! $builder instanceof NativeConstructorObjectBuilder);
45 $buildersWithOneArgument = array_filter($builders, fn (ObjectBuilder $builder) => count($builder->describeArguments()) === 1);
47 if (count($buildersWithOneArgument) === 0 || $this->supportedDateFormats !== Settings::DEFAULT_SUPPORTED_DATETIME_FORMATS) {
48 $builders[] = $this->internalDateTimeBuilder($class->type());
54 private function internalDateTimeBuilder(ClassType $type): FunctionObjectBuilder
56 $constructor = new DateTimeFormatConstructor(...$this->supportedDateFormats);
57 $function = new FunctionObject($this->functionDefinitionRepository->for($constructor), $constructor);
59 return new FunctionObjectBuilder($function, $type);