Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
82.14% covered (warning)
82.14%
46 / 56
66.67% covered (warning)
66.67%
6 / 9
CRAP
0.00% covered (danger)
0.00%
0 / 1
UnionTypeMetadata
82.14% covered (warning)
82.14%
46 / 56
66.67% covered (warning)
66.67%
6 / 9
37.83
0.00% covered (danger)
0.00%
0 / 1
 __construct
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 toClass
83.33% covered (warning)
83.33%
10 / 12
0.00% covered (danger)
0.00%
0 / 1
5.12
 toSkipNull
100.00% covered (success)
100.00%
8 / 8
100.00% covered (success)
100.00%
1 / 1
5
 getTypes
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getHashmap
57.14% covered (warning)
57.14%
4 / 7
0.00% covered (danger)
0.00%
0 / 1
5.26
 getRequiredFields
0.00% covered (danger)
0.00%
0 / 5
0.00% covered (danger)
0.00%
0 / 1
12
 toScalarType
100.00% covered (success)
100.00%
10 / 10
100.00% covered (success)
100.00%
1 / 1
6
 getArrayItemType
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
4
 getValueOptions
100.00% covered (success)
100.00%
7 / 7
100.00% covered (success)
100.00%
1 / 1
3
1<?php
2namespace Apie\Core\Metadata;
3
4use Apie\Core\Context\ApieContext;
5use Apie\Core\Context\MetadataFieldHashmap;
6use Apie\Core\Enums\ScalarType;
7use Apie\Core\Lists\StringList;
8use Apie\Core\Lists\ValueOptionList;
9use Apie\Core\Metadata\Fields\OptionalField;
10use ReflectionClass;
11
12class UnionTypeMetadata implements NullableMetadataInterface
13{
14    /**
15     * @var MetadataInterface[] $metadata
16     */
17    private array $metadata;
18
19    public function __construct(MetadataInterface... $metadata)
20    {
21        $this->metadata = $metadata;
22    }
23
24    public function toClass(): ?ReflectionClass
25    {
26        $first = true;
27        $class = null;
28        foreach ($this->metadata as $metadata) {
29            $current = $metadata->toClass();
30            if (null === $current) {
31                return null;
32            }
33            if ($first) {
34                $class = $metadata->toClass();
35                $first = false;
36            }
37            if ($current->name !== $class->name) {
38                return null;
39            }
40        }
41        return null;
42    }
43
44    public function toSkipNull(): MetadataInterface
45    {
46        $metadata = [];
47        foreach ($this->metadata as $submetadata) {
48            if ($submetadata instanceof ScalarMetadata && $submetadata->toScalarType() === ScalarType::NULLVALUE) {
49                continue;
50            }
51            $metadata[] = $submetadata;
52        }
53        if (count($metadata) === 1) {
54            return $metadata[0];
55        }
56        return new UnionTypeMetadata(...$metadata);
57    }
58
59    /**
60     * @return MetadataInterface[]
61     */
62    public function getTypes(): array
63    {
64        return $this->metadata;
65    }
66
67    public function getHashmap(): MetadataFieldHashmap
68    {
69        $map = [];
70        foreach ($this->metadata as $objectData) {
71            foreach ($objectData->getHashmap() as $key => $value) {
72                if (isset($map[$key])) {
73                    $value = new OptionalField($value, $map[$key]);
74                }
75                $map[$key] = $value;
76            }
77        }
78        return new MetadataFieldHashmap($map);
79    }
80    
81    public function getRequiredFields(): StringList
82    {
83        $requiredFields = [];
84        foreach ($this->metadata as $objectData) {
85            $required = $objectData->getRequiredFields()->toArray();
86            $requiredFields[] = array_combine($required, $required);
87        }
88        return new StringList($requiredFields ? array_intersect_key(...$requiredFields) : []);
89    }
90
91    public function toScalarType(bool $ignoreNull = false): ScalarType
92    {
93        $current = null;
94        foreach ($this->metadata as $objectData) {
95            $type = $objectData->toScalarType($ignoreNull);
96            if ($ignoreNull && $type === ScalarType::NULLVALUE) {
97                continue;
98            }
99            if ($current === null) {
100                $current = $type;
101            } elseif ($type !== $current) {
102                return ScalarType::MIXED;
103            }
104        }
105        return $current ?? ScalarType::MIXED;
106    }
107
108    public function getArrayItemType(): ?MetadataInterface
109    {
110        foreach ($this->metadata as $objectData) {
111            $arrayPrototype = $objectData->getArrayItemType();
112            if (!isset($arrayType) || $arrayType === $arrayPrototype) {
113                $arrayType = $arrayPrototype;
114            }
115        }
116        return $arrayType ?? null;
117    }
118
119    public function getValueOptions(ApieContext $context, bool $runtimeFilter = false): ?ValueOptionList
120    {
121        $result = [];
122        foreach ($this->metadata as $objectData) {
123            $valueOptions = $objectData->getValueOptions($context, $runtimeFilter);
124            if ($valueOptions === null) {
125                return null;
126            }
127            $result = [...$result, ...$valueOptions];
128        }
129        return new ValueOptionList($result);
130    }
131}