f1c80bc20951e8e8bbd3d0df01733afc94b06227
[GitHub/WoltLab/WCF.git] /
1 <?php
2
3 declare(strict_types=1);
4
5 namespace CuyZ\Valinor\Mapper\Object\Factory;
6
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;
16 use DateTime;
17 use DateTimeImmutable;
18
19 use function array_filter;
20 use function count;
21
22 /** @internal */
23 final class DateTimeObjectBuilderFactory implements ObjectBuilderFactory
24 {
25 public function __construct(
26 private ObjectBuilderFactory $delegate,
27 /** @var non-empty-array<non-empty-string> */
28 private array $supportedDateFormats,
29 private FunctionDefinitionRepository $functionDefinitionRepository
30 ) {}
31
32 public function for(ClassDefinition $class): array
33 {
34 $className = $class->name();
35
36 $builders = $this->delegate->for($class);
37
38 if ($className !== DateTime::class && $className !== DateTimeImmutable::class) {
39 return $builders;
40 }
41
42 // Remove `DateTime` & `DateTimeImmutable` native constructors
43 $builders = array_filter($builders, fn (ObjectBuilder $builder) => ! $builder instanceof NativeConstructorObjectBuilder);
44
45 $buildersWithOneArgument = array_filter($builders, fn (ObjectBuilder $builder) => count($builder->describeArguments()) === 1);
46
47 if (count($buildersWithOneArgument) === 0 || $this->supportedDateFormats !== Settings::DEFAULT_SUPPORTED_DATETIME_FORMATS) {
48 $builders[] = $this->internalDateTimeBuilder($class->type());
49 }
50
51 return $builders;
52 }
53
54 private function internalDateTimeBuilder(ClassType $type): FunctionObjectBuilder
55 {
56 $constructor = new DateTimeFormatConstructor(...$this->supportedDateFormats);
57 $function = new FunctionObject($this->functionDefinitionRepository->for($constructor), $constructor);
58
59 return new FunctionObjectBuilder($function, $type);
60 }
61 }