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;
13 use Behat\Testwork\Argument\Validator;
14 use Behat\Behat\Context\Argument\ArgumentResolver;
15 use Behat\Behat\Context\Initializer\ContextInitializer;
16 use Behat\Testwork\Argument\ArgumentOrganiser;
20 * Instantiates contexts using registered argument resolvers and context initializers.
22 * @author Konstantin Kudryashov <ever.zet@gmail.com>
24 final class ContextFactory
27 * @var ArgumentOrganiser
29 private $argumentOrganiser;
31 * @var ArgumentResolver[]
33 private $argumentResolvers = array();
35 * @var ContextInitializer[]
37 private $contextInitializers = array();
44 * Initialises factory.
46 * @param ArgumentOrganiser $argumentOrganiser
48 public function __construct(ArgumentOrganiser $argumentOrganiser)
50 $this->argumentOrganiser = $argumentOrganiser;
51 $this->validator = new Validator();
55 * Registers context argument resolver.
57 * @param ArgumentResolver $resolver
59 public function registerArgumentResolver(ArgumentResolver $resolver)
61 $this->argumentResolvers[] = $resolver;
65 * Registers context initializer.
67 * @param ContextInitializer $initializer
69 public function registerContextInitializer(ContextInitializer $initializer)
71 $this->contextInitializers[] = $initializer;
75 * Creates and initializes context class.
77 * @param string $class
78 * @param array $arguments
79 * @param ArgumentResolver[] $singleUseResolvers
83 public function createContext($class, array $arguments = array(), array $singleUseResolvers = array())
85 $reflection = new ReflectionClass($class);
86 $resolvers = array_merge($singleUseResolvers, $this->argumentResolvers);
87 $resolvedArguments = $this->resolveArguments($reflection, $arguments, $resolvers);
88 $context = $this->createInstance($reflection, $resolvedArguments);
89 $this->initializeInstance($context);
95 * Resolves arguments for a specific class using registered argument resolvers.
97 * @param ReflectionClass $reflection
98 * @param array $arguments
99 * @param ArgumentResolver[] $resolvers
103 private function resolveArguments(ReflectionClass $reflection, array $arguments, array $resolvers)
105 $newArguments = $arguments;
107 foreach ($resolvers as $resolver) {
108 $newArguments = $resolver->resolveArguments($reflection, $newArguments);
111 if (!$reflection->hasMethod('__construct')) {
112 return $newArguments;
115 $constructor = $reflection->getConstructor();
116 $newArguments = $this->argumentOrganiser->organiseArguments($constructor, $newArguments);
117 $this->validator->validateArguments($constructor, $newArguments);
119 return $newArguments;
123 * Creates context instance.
125 * @param ReflectionClass $reflection
126 * @param array $arguments
130 private function createInstance(ReflectionClass $reflection, array $arguments)
132 if (count($arguments)) {
133 return $reflection->newInstanceArgs($arguments);
136 return $reflection->newInstance();
140 * Initializes context class and returns new context instance.
142 * @param Context $context
144 private function initializeInstance(Context $context)
146 foreach ($this->contextInitializers as $initializer) {
147 $initializer->initializeContext($context);