ContextServiceEnvironmentHandler::__construct()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 5
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 2
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\Context\Environment\Handler;
15
16
use Behat\Behat\Context\Context;
17
use Behat\Behat\Context\Initializer\ContextInitializer;
18
use Behat\Testwork\Environment\Environment;
19
use Behat\Testwork\Environment\Exception\EnvironmentIsolationException;
20
use Behat\Testwork\Environment\Handler\EnvironmentHandler;
21
use Behat\Testwork\Suite\Exception\SuiteConfigurationException;
22
use Behat\Testwork\Suite\Suite;
23
use FriendsOfBehat\ContextServiceExtension\Context\ContextRegistry;
24
use FriendsOfBehat\ContextServiceExtension\Context\Environment\InitialisedContextServiceEnvironment;
25
use FriendsOfBehat\ContextServiceExtension\Context\Environment\UninitialisedContextServiceEnvironment;
26
use Symfony\Component\DependencyInjection\ContainerInterface;
27
28
/**
29
 * @internal
30
 */
31
final class ContextServiceEnvironmentHandler implements EnvironmentHandler
32
{
33
    /**
34
     * @var ContainerInterface
35
     */
36
    private $container;
37
38
    /**
39
     * @var ContextRegistry
40
     */
41
    private $contextRegistry;
42
43
    /**
44
     * @var ContextInitializer[]
45
     */
46
    private $contextInitializers = [];
47
48
    /**
49
     * @param ContainerInterface $container
50
     * @param ContextRegistry $contextRegistry
51
     */
52
    public function __construct(ContainerInterface $container, ContextRegistry $contextRegistry)
53
    {
54
        $this->container = $container;
55
        $this->contextRegistry = $contextRegistry;
56
    }
57
58
    /**
59
     * {@inheritdoc}
60
     */
61
    public function supportsSuite(Suite $suite): bool
62
    {
63
        return $suite->hasSetting('contexts_services');
64
    }
65
66
    /**
67
     * {@inheritdoc}
68
     */
69
    public function buildEnvironment(Suite $suite): Environment
70
    {
71
        $environment = new UninitialisedContextServiceEnvironment($suite);
72
        foreach ($this->getSuiteContextsServices($suite) as $serviceId) {
73
            $environment->registerContextService($serviceId, $this->contextRegistry->getClass($serviceId));
74
        }
75
76
        return $environment;
77
    }
78
79
    /**
80
     * {@inheritdoc}
81
     */
82
    public function supportsEnvironmentAndSubject(Environment $environment, $testSubject = null): bool
83
    {
84
        return $environment instanceof UninitialisedContextServiceEnvironment;
85
    }
86
87
    /**
88
     * {@inheritdoc}
89
     *
90
     * @throws EnvironmentIsolationException
91
     */
92
    public function isolateEnvironment(Environment $uninitializedEnvironment, $testSubject = null): Environment
93
    {
94
        /** @var UninitialisedContextServiceEnvironment $uninitializedEnvironment */
95
        $this->assertEnvironmentCanBeIsolated($uninitializedEnvironment, $testSubject);
96
97
        $environment = new InitialisedContextServiceEnvironment($uninitializedEnvironment->getSuite());
98
        foreach ($uninitializedEnvironment->getContextServices() as $serviceId) {
99
            /** @var Context $context */
100
            $context = $this->container->get($serviceId);
101
            $this->initializeInstance($context);
102
            $environment->registerContext($context);
103
        }
104
105
        return $environment;
106
    }
107
108
    /**
109
     * @param Suite $suite
110
     *
111
     * @return string[]
112
     *
113
     * @throws SuiteConfigurationException If "contexts_services" setting is not an array
114
     */
115
    private function getSuiteContextsServices(Suite $suite): array
116
    {
117
        $contextsServices = $suite->getSetting('contexts_services');
118
119
        if (!is_array($contextsServices)) {
120
            throw new SuiteConfigurationException(sprintf(
121
                '"contexts_services" setting of the "%s" suite is expected to be an array, %s given.',
122
                $suite->getName(),
123
                gettype($contextsServices)
124
            ), $suite->getName());
125
        }
126
127
        return $contextsServices;
128
    }
129
130
    /**
131
     * @param Environment $uninitializedEnvironment
132
     * @param mixed $testSubject
133
     *
134
     * @throws EnvironmentIsolationException
135
     */
136
    private function assertEnvironmentCanBeIsolated(Environment $uninitializedEnvironment, $testSubject): void
137
    {
138
        if (!$this->supportsEnvironmentAndSubject($uninitializedEnvironment, $testSubject)) {
139
            throw new EnvironmentIsolationException(sprintf(
140
                '"%s" does not support isolation of "%s" environment.',
141
                static::class,
142
                get_class($uninitializedEnvironment)
143
            ), $uninitializedEnvironment);
144
        }
145
    }
146
147
    /**
148
     * Initializes context class and returns new context instance.
149
     *
150
     * @param Context $context
151
     */
152
    private function initializeInstance(Context $context)
153
    {
154
        foreach ($this->contextInitializers as $initializer) {
155
            $initializer->initializeContext($context);
156
        }
157
    }
158
159
    /**
160
     * Registers context initializer.
161
     *
162
     * @param ContextInitializer $initializer
163
     */
164
    public function registerContextInitializer(ContextInitializer $initializer)
165
    {
166
        $this->contextInitializers[] = $initializer;
167
    }
168
}
169