Completed
Pull Request — master (#15)
by Gorka
06:18
created

ContextServiceExtension::loadContextInitializers()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 10
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 10
rs 9.4285
c 0
b 0
f 0
cc 2
eloc 5
nc 2
nop 1
1
<?php
2
3
declare(strict_types=1);
4
5
/*
6
 * This file is part of the ContextServiceExtension package.
7
 *
8
 * (c) Kamil Kokot <[email protected]>
9
 *
10
 * For the full copyright and license information, please view the LICENSE
11
 * file that was distributed with this source code.
12
 */
13
14
namespace FriendsOfBehat\ContextServiceExtension\ServiceContainer;
15
16
use Behat\Behat\Context\ServiceContainer\ContextExtension;
17
use Behat\Testwork\Environment\ServiceContainer\EnvironmentExtension;
18
use Behat\Testwork\EventDispatcher\ServiceContainer\EventDispatcherExtension;
19
use Behat\Testwork\ServiceContainer\Extension;
20
use Behat\Testwork\ServiceContainer\ExtensionManager;
21
use FriendsOfBehat\ContextServiceExtension\Context\ContextRegistry;
22
use FriendsOfBehat\ContextServiceExtension\Context\Environment\Handler\ContextServiceEnvironmentHandler;
23
use FriendsOfBehat\ContextServiceExtension\Listener\ScenarioContainerResetter;
24
use FriendsOfBehat\ContextServiceExtension\ServiceContainer\Scenario\ContainerFactory;
25
use FriendsOfBehat\ContextServiceExtension\ServiceContainer\Scenario\ContextRegistryPass;
26
use FriendsOfBehat\CrossContainerExtension\CrossContainerProcessor;
27
use FriendsOfBehat\CrossContainerExtension\ServiceContainer\CrossContainerExtension;
28
use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition;
29
use Symfony\Component\DependencyInjection\ContainerBuilder;
30
use Symfony\Component\DependencyInjection\Definition;
31
use Symfony\Component\DependencyInjection\Reference;
32
33
/**
34
 * @internal
35
 */
36
final class ContextServiceExtension implements Extension
37
{
38
    /**
39
     * @var CrossContainerProcessor|null
40
     */
41
    private $crossContainerProcessor;
42
43
    /**
44
     * {@inheritdoc}
45
     */
46
    public function getConfigKey(): string
47
    {
48
        return 'fob_context_service';
49
    }
50
51
    /**
52
     * {@inheritdoc}
53
     */
54
    public function initialize(ExtensionManager $extensionManager): void
55
    {
56
        /** @var CrossContainerExtension|null $crossContainerExtension */
57
        $crossContainerExtension = $extensionManager->getExtension('fob_cross_container');
58
        if (null !== $crossContainerExtension) {
59
            $this->crossContainerProcessor = $crossContainerExtension->getCrossContainerProcessor();
60
        }
61
    }
62
63
    /**
64
     * {@inheritdoc}
65
     */
66
    public function configure(ArrayNodeDefinition $builder): void
67
    {
68
        $builder
69
            ->children()
70
                ->arrayNode('imports')
71
                    ->performNoDeepMerging()
72
                    ->prototype('scalar')->end()
73
                ->end()
74
            ->end()
75
        ;
76
    }
77
78
    /**
79
     * {@inheritdoc}
80
     */
81
    public function load(ContainerBuilder $container, array $config): void
82
    {
83
        $this->loadContextRegistry($container);
84
        $this->loadScenarioServiceContainer($container, $config);
85
        $this->loadEnvironmentHandler($container);
86
        $this->loadContextInitializers($container);
87
    }
88
89
    /**
90
     * {@inheritdoc}
91
     */
92
    public function process(ContainerBuilder $container): void
93
    {
94
        /** @var ContainerBuilder $scenarioContainer */
95
        $scenarioContainer = $container->get('fob_context_service.service_container.scenario');
96
97
        if (null !== $this->crossContainerProcessor) {
98
            $this->crossContainerProcessor->process($scenarioContainer);
99
        }
100
101
        $scenarioContainer->addCompilerPass(new ContextRegistryPass($container->getDefinition('fob_context_service.context_registry')));
102
        $scenarioContainer->compile();
103
    }
104
105
    /**
106
     * @param ContainerBuilder $container
107
     */
108
    private function loadContextRegistry(ContainerBuilder $container): void
109
    {
110
        $container->setDefinition('fob_context_service.context_registry', (new Definition(ContextRegistry::class))->setPublic(false));
111
    }
112
113
    /**
114
     * @param ContainerBuilder $container
115
     * @param array $config
116
     */
117
    private function loadScenarioServiceContainer(ContainerBuilder $container, array $config): void
118
    {
119
        $container->set(
120
            'fob_context_service.service_container.scenario',
121
            (new ContainerFactory())->createContainer($container->getParameter('paths.base'), $config['imports'])
122
        );
123
124
        $definition = new Definition(ScenarioContainerResetter::class, [
125
            new Reference('fob_context_service.service_container.scenario'),
126
        ]);
127
        $definition->addTag(EventDispatcherExtension::SUBSCRIBER_TAG);
128
        $container->setDefinition('fob_context_service.service_container.scenario.resetter', $definition);
129
    }
130
131
    /**
132
     * @param ContainerBuilder $container
133
     */
134
    private function loadEnvironmentHandler(ContainerBuilder $container): void
135
    {
136
        $definition = new Definition(ContextServiceEnvironmentHandler::class, [
137
            new Reference('fob_context_service.service_container.scenario'),
138
            new Reference('fob_context_service.context_registry'),
139
        ]);
140
        $definition->addTag(EnvironmentExtension::HANDLER_TAG, ['priority' => 128]);
141
142
        $container->setDefinition('fob_context_service.environment_handler.context_service', $definition);
143
    }
144
145
    /**
146
     * @param ContainerBuilder $container
147
     */
148
    private function loadContextInitializers(ContainerBuilder $container)
149
    {
150
        $references = $container->findTaggedServiceIds(ContextExtension::INITIALIZER_TAG);
151
152
        $definition = $container->getDefinition('fob_context_service.environment_handler.context_service');
153
154
        foreach ($references as $serviceId => $tags) {
155
            $definition->addMethodCall('registerContextInitializer', [$container->getDefinition($serviceId)]);
156
        }
157
    }
158
}
159