Completed
Pull Request — master (#692)
by Renan
02:25
created

attachServiceToAllConnections()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 17
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 17
rs 9.4285
c 0
b 0
f 0
cc 3
eloc 9
nc 3
nop 2
1
<?php
2
3
namespace Doctrine\Bundle\DoctrineBundle\DependencyInjection\Compiler;
4
5
use Doctrine\DBAL\Logging\SQLLogger;
6
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
7
use Symfony\Component\DependencyInjection\ContainerBuilder;
8
use Symfony\Component\DependencyInjection\Definition;
9
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
10
use Symfony\Component\DependencyInjection\Reference;
11
12
final class DoctrineDBALLoggerPass implements CompilerPassInterface
13
{
14
    private const TAG_NAME = 'doctrine.dbal.logger';
15
    private const BASE_CHAIN_NAME = 'doctrine.dbal.logger.chain';
16
17
    public function process(ContainerBuilder $container)
18
    {
19
        $serviceList = $container->findTaggedServiceIds(self::TAG_NAME, true);
20
        $serviceList = array_keys($serviceList);
21
22
        foreach ($serviceList as $serviceId) {
23
            $this->ensureIsValidServiceDefinition($container, $serviceId);
24
            $this->attachServiceToAllConnections($container, $serviceId);
25
        }
26
    }
27
28
    private function ensureIsValidServiceDefinition(ContainerBuilder $container, string $serviceId): void
29
    {
30
        $serviceDefinition = $container->getDefinition($serviceId);
31
32
        $serviceClass = $container->getParameterBag()->resolveValue(
33
            $serviceDefinition->getClass()
34
        );
35
        $reflectionClass = $container->getReflectionClass($serviceClass);
36
37
        if (!$reflectionClass) {
38
            throw new InvalidArgumentException(sprintf(
39
                'Class "%s" used for service "%s" cannot be found.',
40
                $serviceClass,
41
                $serviceId
42
            ));
43
        }
44
45
        if (!$reflectionClass->implementsInterface(SQLLogger::class)) {
46
            throw new InvalidArgumentException(sprintf(
47
                'The service "%s" tagged "%s" must implement "%s".',
48
                $serviceId,
49
                self::TAG_NAME,
50
                SQLLogger::class
51
            ));
52
        }
53
54
        if ($reflectionClass->isAbstract()) {
55
            throw new InvalidArgumentException(sprintf(
56
                'The service "%s" tagged "%s" cannot be abstract.',
57
                $serviceId,
58
                self::TAG_NAME
59
            ));
60
        }
61
    }
62
63
    private function attachServiceToAllConnections(ContainerBuilder $container, string $serviceId): void
64
    {
65
        $serviceReference = new Reference($serviceId);
66
67
        $connectionList = $container->getParameter('doctrine.connections');
68
69
        foreach ($connectionList as $connectionName => $connectionId) {
70
            $chainId = self::BASE_CHAIN_NAME . '.' . $connectionName;
71
72
            if (!$container->hasDefinition($chainId)) {
73
                $this->createEmptyChain($container, $chainId, $connectionId);
74
            }
75
76
            $chainDefinition = $container->getDefinition($chainId);
77
            $chainDefinition->addMethodCall('addLogger', array($serviceReference));
78
        }
79
    }
80
81
    private function createEmptyChain(ContainerBuilder $container, string $chainId, string $connectionId): void
82
    {
83
        $chainReference = new Reference($chainId);
84
85
        $container->setDefinition($chainId, new Definition(self::BASE_CHAIN_NAME));
86
87
        $configurationDefinition = $container->getDefinition($connectionId . '.configuration');
88
        $configurationDefinition->addMethodCall('setSQLLogger', array($chainReference));
89
    }
90
}
91