Completed
Push — master ( d7bbda...0e324f )
by Kamil
06:08
created

resolveDefinition()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 6
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 3
nc 1
nop 2
1
<?php
2
3
namespace FriendsOfBehat\CrossContainerExtension;
4
5
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
6
use Symfony\Component\DependencyInjection\ContainerBuilder;
7
use Symfony\Component\DependencyInjection\Definition;
8
use Symfony\Component\DependencyInjection\Reference;
9
10
final class ResolveCrossContainerReferencesPass implements CompilerPassInterface
11
{
12
    /**
13
     * @var ContainerAccessor[]
14
     */
15
    private $containerAccessors;
16
17
    /**
18
     * @param ContainerAccessor[] $containerAccessors
19
     */
20
    public function __construct(array $containerAccessors)
21
    {
22
        $this->containerAccessors = $containerAccessors;
23
    }
24
25
    /**
26
     * {@inheritdoc}
27
     */
28
    public function process(ContainerBuilder $container)
29
    {
30
        $definitions = $container->getDefinitions();
31
        foreach ($definitions as $definition) {
32
            $this->resolveDefinition($container, $definition);
33
        }
34
35
        foreach ($this->containerAccessors as $containerIdentifier => $containerAccessor) {
36
            foreach ($containerAccessor->getParameters() as $name => $value) {
37
                $container->setParameter(sprintf('__%s__.%s', $containerIdentifier, $name), $value);
38
            }
39
        }
40
    }
41
42
    /**
43
     * @param ContainerBuilder $container
44
     * @param Definition $definition
45
     *
46
     * @return Definition
47
     */
48
    private function resolveDefinition(ContainerBuilder $container, Definition $definition)
49
    {
50
        $definition->setArguments($this->resolveArguments($container, $definition->getArguments()));
51
52
        return $definition;
53
    }
54
55
    /**
56
     * @param ContainerBuilder $container
57
     * @param array $arguments
58
     *
59
     * @return array
60
     */
61
    private function resolveArguments(ContainerBuilder $container, array $arguments)
62
    {
63
        return array_map(function ($argument) use ($container) {
64
            return $this->resolveArgument($container, $argument);
65
        }, $arguments);
66
    }
67
68
    /**
69
     * @param ContainerBuilder $container
70
     * @param mixed $argument
71
     *
72
     * @return mixed
73
     */
74
    private function resolveArgument(ContainerBuilder $container, $argument)
75
    {
76
        if ($argument instanceof Definition) {
77
            return $this->resolveDefinition($container, $argument);
78
        }
79
80
        if ($argument instanceof Reference) {
81
            return $this->resolveReference($container, $argument);
82
        }
83
84
        if (is_array($argument)) {
85
            return $this->resolveArguments($container, $argument);
86
        }
87
88
        return $argument;
89
    }
90
91
    /**
92
     * @param ContainerBuilder $container
93
     * @param Reference $reference
94
     *
95
     * @return Definition|Reference
96
     */
97
    private function resolveReference(ContainerBuilder $container, Reference $reference)
98
    {
99
        $containerIdentifier = preg_replace('/^__([^_]+)__\..+$/', '$1', (string) $reference);
100
101
        if (null === $containerIdentifier) {
102
            return $reference;
103
        }
104
105
        if (!isset($this->containerAccessors[$containerIdentifier])) {
106
            return $reference;
107
        }
108
109
        $containerAccessorIdentifier = sprintf('__%s__', $containerIdentifier);
110
111
        if (!$container->has($containerAccessorIdentifier)) {
112
            $container->set($containerAccessorIdentifier, $this->containerAccessors[$containerIdentifier]);
113
        }
114
115
        $serviceIdentifier = preg_replace('/^__[^_]+__\.(.+)$/', '$1', (string) $reference);
116
117
        $definition = new Definition(null, [$serviceIdentifier]);
118
        $definition->setFactory([new Reference($containerAccessorIdentifier), 'getService']);
119
120
        return $definition;
121
    }
122
}
123