-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathObjectRegistry.php
125 lines (103 loc) · 3.7 KB
/
ObjectRegistry.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
<?php
/*
* This file is part of the Klipper package.
*
* (c) François Pluchino <[email protected]>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Klipper\Component\DefaultValue;
use Klipper\Component\DefaultValue\Exception\ExceptionInterface;
use Klipper\Component\DefaultValue\Exception\UnexpectedTypeException;
use Klipper\Component\DefaultValue\Extension\Core\Type\DefaultType;
/**
* The central registry of the Object Default Value component.
*
* @author François Pluchino <[email protected]>
*/
class ObjectRegistry implements ObjectRegistryInterface
{
/**
* @var ObjectExtensionInterface[]
*/
protected array $extensions = [];
protected array $types = [];
protected ResolvedObjectTypeFactoryInterface $resolvedTypeFactory;
/**
* @param ObjectExtensionInterface[] $extensions An array of ObjectExtensionInterface
* @param ResolvedObjectTypeFactoryInterface $resolvedTypeFactory The factory for resolved object default value types
*
* @throws UnexpectedTypeException if any extension does not implement ObjectExtensionInterface
*/
public function __construct(
array $extensions,
ResolvedObjectTypeFactoryInterface $resolvedTypeFactory
) {
foreach ($extensions as $extension) {
if (!$extension instanceof ObjectExtensionInterface) {
throw new UnexpectedTypeException($extension, 'Klipper\Component\DefaultValue\ObjectExtensionInterface');
}
}
$this->extensions = $extensions;
$this->resolvedTypeFactory = $resolvedTypeFactory;
}
public function getType(string $classname): ResolvedObjectTypeInterface
{
if (!isset($this->types[$classname])) {
/** @var ObjectTypeInterface $type */
$type = null;
foreach ($this->extensions as $extension) {
/** @var ObjectExtensionInterface $extension */
if ($extension->hasType($classname)) {
$type = $extension->getType($classname);
break;
}
}
// fallback to default type
if (!$type) {
$type = new DefaultType($classname);
}
$this->resolveAndAddType($type);
}
return $this->types[$classname];
}
public function hasType(string $classname): bool
{
if (isset($this->types[$classname])) {
return true;
}
try {
$this->getType($classname);
} catch (ExceptionInterface $e) {
return false;
}
return true;
}
public function getExtensions(): iterable
{
return $this->extensions;
}
/**
* Wraps a type into a ResolvedObjectTypeInterface implementation and connects
* it with its parent type.
*
* @param ObjectTypeInterface $type The type to resolve
*/
private function resolveAndAddType(ObjectTypeInterface $type): void
{
$parentType = $type->getParent();
$typeExtensions = [];
foreach ($this->extensions as $extension) {
/** @var ObjectExtensionInterface $extension */
$typeExtensions = array_merge(
$typeExtensions,
$extension->getTypeExtensions('default'),
$extension->getTypeExtensions($type->getClass())
);
}
$parent = $parentType ? $this->getType($parentType) : null;
$rType = $this->resolvedTypeFactory->createResolvedType($type, $typeExtensions, $parent);
$this->types[$type->getClass()] = $rType;
}
}