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\HelperContainer;
13 use Behat\Behat\HelperContainer\Exception\ServiceNotFoundException;
14 use Behat\Behat\HelperContainer\Exception\WrongServicesConfigurationException;
15 use Interop\Container\ContainerInterface;
20 * Built-in service container.
22 * @author Konstantin Kudryashov <ever.zet@gmail.com>
24 final class BuiltInServiceContainer implements ContainerInterface
36 * Initialises container using provided service configuration.
38 * @param array $schema
40 public function __construct(array $schema)
42 $this->schema = $schema;
48 public function has($id)
50 return array_key_exists($id, $this->schema);
56 public function get($id)
58 if (!$this->has($id)) {
59 throw new ServiceNotFoundException(
60 sprintf('Service with id `%s` was not defined inside the `services` setting`.', $id),
65 return $this->instances[$id] = isset($this->instances[$id]) ? $this->instances[$id] : $this->createInstance($id);
69 * Creates an instance of given service.
75 private function createInstance($id)
77 $schema = $this->getAndValidateServiceSchema($id);
79 $reflection = new ReflectionClass($schema['class']);
80 $arguments = $schema['arguments'];
82 if ($factoryMethod = $this->getAndValidateFactoryMethod($reflection, $schema)) {
83 return $factoryMethod->invokeArgs(null, $arguments);
86 return $reflection->newInstanceArgs($arguments);
90 * Gets and validates a service configuration for a service with given ID.
94 * @throws WrongServicesConfigurationException
96 * @return array|string
98 private function getAndValidateServiceSchema($id)
100 $schema = $this->schema[$id];
102 if (null === $schema) {
103 $schema = array('class' => $id);
106 if (is_string($schema)) {
107 $schema = array('class' => $schema);
110 $schema['class'] = $this->getAndValidateClass($id, $schema);
111 $schema['arguments'] = $this->getAndValidateArguments($schema);
117 * Gets and validates a class from schema.
120 * @param string|array $schema
124 private function getAndValidateClass($id, array $schema)
126 if (!isset($schema['class'])) {
127 $schema['class'] = $id;
130 return $schema['class'];
134 * Gets and validates arguments from schema.
136 * @param array $schema
140 private function getAndValidateArguments(array $schema)
142 return isset($schema['arguments']) ? (array)$schema['arguments'] : array();
146 * Gets and validates a factory method.
148 * @param ReflectionClass $reflection
149 * @param array $schema
151 * @return null|ReflectionMethod
153 private function getAndValidateFactoryMethod(ReflectionClass $reflection, array $schema)
155 if (!isset($schema['factory_method'])) {
159 $factoryMethod = $schema['factory_method'];
160 $this->assertFactoryMethodExists($reflection, $factoryMethod);
161 $method = $reflection->getMethod($factoryMethod);
162 $this->assertFactoryMethodIsStatic($method);
168 * Checks if factory method exists.
170 * @param ReflectionClass $class
171 * @param string $methodName
173 * @throws WrongServicesConfigurationException
175 private function assertFactoryMethodExists(ReflectionClass $class, $methodName)
177 if (!$class->hasMethod($methodName)) {
178 throw new WrongServicesConfigurationException(sprintf(
179 'Factory method `%s::%s` does not exist.',
187 * Checks if factory method is static.
189 * @param ReflectionMethod $method
191 * @throws WrongServicesConfigurationException
193 private function assertFactoryMethodIsStatic(ReflectionMethod $method)
195 if (!$method->isStatic()) {
196 throw new WrongServicesConfigurationException(sprintf(
197 'Service factory methods must be static, but `%s::%s` is not.',
198 $method->getDeclaringClass()->getName(),