forked from doctrine/DoctrineBundle
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathRegisterDbalTypePass.php
More file actions
102 lines (83 loc) · 3.84 KB
/
RegisterDbalTypePass.php
File metadata and controls
102 lines (83 loc) · 3.84 KB
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
<?php
declare(strict_types=1);
namespace Doctrine\Bundle\DoctrineBundle\DependencyInjection\Compiler;
use Doctrine\Bundle\DoctrineBundle\Attribute\AsDbalType;
use Doctrine\DBAL\Types\Type;
use ReflectionClass;
use Symfony\Component\DependencyInjection\ChildDefinition;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
use function is_subclass_of;
use function method_exists;
use function sprintf;
/** @internal */
final class RegisterDbalTypePass implements CompilerPassInterface
{
private const string TAG = 'doctrine.dbal.type';
/**
* @param ReflectionClass<T> $reflector
*
* @template T of ReflectionClass
*/
public static function autoconfigureFromAttribute(ChildDefinition $definition, AsDbalType $type, ReflectionClass $reflector): void
{
$attributes = [
'type_name' => $type->name ?? $reflector->name,
];
// Determine if the version of symfony/dependency-injection is >= 7.3
/** @phpstan-ignore function.alreadyNarrowedType */
if (method_exists($definition, 'addResourceTag')) {
$definition->addResourceTag(self::TAG, $attributes);
} else {
// Needed to keep compatibility with symfony/dependency-injection < 7.3
$definition->addTag(self::TAG, $attributes)
->addTag('container.excluded', ['source' => sprintf('by tag "%s"', self::TAG)]);
}
}
public function process(ContainerBuilder $container): void
{
$types = $container->getParameter('doctrine.dbal.connection_factory.types');
foreach ($this->findTaggedResourceIds($container) as $id => $tags) {
foreach ($tags as $tag) {
$class = $container->getDefinition($id)->getClass();
if (! $class) {
throw new InvalidArgumentException(sprintf('The definition of "%s" must define its class.', $id));
}
if (! is_subclass_of($class, Type::class)) {
throw new InvalidArgumentException(sprintf('The "%s" class must extends "%s".', $class, Type::class));
}
$types[$tag['type_name'] ?? $id] = ['class' => $class];
}
}
$container->setParameter('doctrine.dbal.connection_factory.types', $types);
}
/** @return array<string, array<array{type_name?: string}>> */
private function findTaggedResourceIds(ContainerBuilder $container): array
{
// Determine if the version of symfony/dependency-injection is >= 7.3
/** @phpstan-ignore function.alreadyNarrowedType */
if (method_exists($container, 'findTaggedResourceIds')) {
return $container->findTaggedResourceIds(self::TAG);
}
// Needed to keep compatibility with symfony/dependency-injection < 7.3
$tags = [];
foreach ($container->getDefinitions() as $id => $definition) {
if (! $definition->hasTag(self::TAG)) {
continue;
}
if (! $definition->hasTag('container.excluded')) {
throw new InvalidArgumentException(sprintf('The resource "%s" tagged "%s" is missing the "container.excluded" tag.', $id, self::TAG));
}
$class = $container->getParameterBag()->resolveValue($definition->getClass());
if (! $class || $definition->isAbstract()) {
throw new InvalidArgumentException(sprintf('The resource "%s" tagged "%s" must have a class and not be abstract.', $id, self::TAG));
}
if ($definition->getClass() !== $class) {
$definition->setClass($class);
}
$tags[$id] = $definition->getTag(self::TAG);
}
return $tags;
}
}