48871ca9c77fcd7066c3cca06db1836d6d3129fc
[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\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;
15 use DateTimeZone;
16 use Exception;
17
18 use function array_filter;
19 use function count;
20
21 /** @internal */
22 final class DateTimeZoneObjectBuilderFactory implements ObjectBuilderFactory
23 {
24 private ObjectBuilderFactory $delegate;
25
26 private FunctionDefinitionRepository $functionDefinitionRepository;
27
28 public function __construct(ObjectBuilderFactory $delegate, FunctionDefinitionRepository $functionDefinitionRepository)
29 {
30 $this->delegate = $delegate;
31 $this->functionDefinitionRepository = $functionDefinitionRepository;
32 }
33
34 public function for(ClassDefinition $class): array
35 {
36 $builders = $this->delegate->for($class);
37
38 if ($class->name() !== DateTimeZone::class) {
39 return $builders;
40 }
41
42 // Remove `DateTimeZone` native constructors
43 $builders = array_filter($builders, fn (ObjectBuilder $builder) => ! $builder instanceof NativeConstructorObjectBuilder);
44
45 $useDefaultBuilder = true;
46
47 foreach ($builders as $builder) {
48 if (count($builder->describeArguments()) === 1) {
49 $useDefaultBuilder = false;
50 // @infection-ignore-all
51 break;
52 }
53 }
54
55 if ($useDefaultBuilder) {
56 // @infection-ignore-all / Ignore memoization
57 $builders[] = $this->defaultBuilder($class->type());
58 }
59
60 return $builders;
61 }
62
63 private function defaultBuilder(ClassType $type): FunctionObjectBuilder
64 {
65 $constructor = function (string $timezone) {
66 try {
67 return new DateTimeZone($timezone);
68 } catch (Exception) {
69 throw MessageBuilder::newError('Value {source_value} is not a valid timezone.')->build();
70 }
71 };
72
73 $function = new FunctionObject($this->functionDefinitionRepository->for($constructor), $constructor);
74
75 return new FunctionObjectBuilder($function, $type);
76 }
77 }