4 * This file is part of the Behat.
5 * (c) Konstantin Kudryashov <ever.zet@gmail.com>
7 * For the full copyright and license information, please view the LICENSE
8 * file that was distributed with this source code.
11 namespace Behat\Behat\Context\Environment\Handler;
13 use Behat\Behat\Context\Argument\SuiteScopedResolverFactory;
14 use Behat\Behat\Context\Argument\SuiteScopedResolverFactoryAdapter;
15 use Behat\Behat\Context\Argument\ArgumentResolverFactory;
16 use Behat\Behat\Context\Argument\NullFactory;
17 use Behat\Behat\Context\ContextClass\ClassResolver;
18 use Behat\Behat\Context\ContextFactory;
19 use Behat\Behat\Context\Environment\InitializedContextEnvironment;
20 use Behat\Behat\Context\Environment\UninitializedContextEnvironment;
21 use Behat\Testwork\Environment\Environment;
22 use Behat\Testwork\Environment\Exception\EnvironmentIsolationException;
23 use Behat\Testwork\Environment\Handler\EnvironmentHandler;
24 use Behat\Testwork\Suite\Exception\SuiteConfigurationException;
25 use Behat\Testwork\Suite\Suite;
28 * Handles build and initialisation of the context-based environments.
32 * @author Konstantin Kudryashov <ever.zet@gmail.com>
34 final class ContextEnvironmentHandler implements EnvironmentHandler
39 private $contextFactory;
41 * @var ArgumentResolverFactory
43 private $resolverFactory;
45 * @var ClassResolver[]
47 private $classResolvers = array();
50 * Initializes handler.
52 * @param ContextFactory $factory
53 * @param ArgumentResolverFactory|SuiteScopedResolverFactory $resolverFactory
55 public function __construct(ContextFactory $factory, $resolverFactory = null)
57 $this->contextFactory = $factory;
59 if ($resolverFactory && !$resolverFactory instanceof ArgumentResolverFactory) {
60 $resolverFactory = new SuiteScopedResolverFactoryAdapter($resolverFactory);
63 $this->resolverFactory = $resolverFactory ?: new NullFactory();
67 * Registers context class resolver.
69 * @param ClassResolver $resolver
71 public function registerClassResolver(ClassResolver $resolver)
73 $this->classResolvers[] = $resolver;
79 public function supportsSuite(Suite $suite)
81 return $suite->hasSetting('contexts');
87 public function buildEnvironment(Suite $suite)
89 $environment = new UninitializedContextEnvironment($suite);
90 foreach ($this->getNormalizedContextSettings($suite) as $context) {
91 $environment->registerContextClass($this->resolveClass($context[0]), $context[1]);
100 public function supportsEnvironmentAndSubject(Environment $environment, $testSubject = null)
102 return $environment instanceof UninitializedContextEnvironment;
108 public function isolateEnvironment(Environment $uninitializedEnvironment, $testSubject = null)
110 if (!$uninitializedEnvironment instanceof UninitializedContextEnvironment) {
111 throw new EnvironmentIsolationException(sprintf(
112 'ContextEnvironmentHandler does not support isolation of `%s` environment.',
113 get_class($uninitializedEnvironment)
114 ), $uninitializedEnvironment);
117 $environment = new InitializedContextEnvironment($uninitializedEnvironment->getSuite());
118 $resolvers = $this->resolverFactory->createArgumentResolvers($environment);
120 foreach ($uninitializedEnvironment->getContextClassesWithArguments() as $class => $arguments) {
121 $context = $this->contextFactory->createContext($class, $arguments, $resolvers);
122 $environment->registerContext($context);
129 * Returns normalized suite context settings.
131 * @param Suite $suite
135 private function getNormalizedContextSettings(Suite $suite)
138 function ($context) {
140 $arguments = array();
142 if (is_array($context)) {
143 $class = current(array_keys($context));
144 $arguments = $context[$class];
147 return array($class, $arguments);
149 $this->getSuiteContexts($suite)
154 * Returns array of context classes configured for the provided suite.
156 * @param Suite $suite
160 * @throws SuiteConfigurationException If `contexts` setting is not an array
162 private function getSuiteContexts(Suite $suite)
164 if (!is_array($suite->getSetting('contexts'))) {
165 throw new SuiteConfigurationException(
166 sprintf('`contexts` setting of the "%s" suite is expected to be an array, %s given.',
168 gettype($suite->getSetting('contexts'))
174 return $suite->getSetting('contexts');
178 * Resolves class using registered class resolvers.
180 * @param string $class
184 private function resolveClass($class)
186 foreach ($this->classResolvers as $resolver) {
187 if ($resolver->supportsClass($class)) {
188 return $resolver->resolveClass($class);