Security update for permissions_by_term
[yaffs-website] / vendor / behat / behat / src / Behat / Behat / HelperContainer / BuiltInServiceContainer.php
1 <?php
2
3 /*
4  * This file is part of the Behat.
5  * (c) Konstantin Kudryashov <ever.zet@gmail.com>
6  *
7  * For the full copyright and license information, please view the LICENSE
8  * file that was distributed with this source code.
9  */
10
11 namespace Behat\Behat\HelperContainer;
12
13 use Behat\Behat\HelperContainer\Exception\ServiceNotFoundException;
14 use Behat\Behat\HelperContainer\Exception\WrongServicesConfigurationException;
15 use Interop\Container\ContainerInterface;
16 use ReflectionClass;
17 use ReflectionMethod;
18
19 /**
20  * Built-in service container.
21  *
22  * @author Konstantin Kudryashov <ever.zet@gmail.com>
23  */
24 final class BuiltInServiceContainer implements ContainerInterface
25 {
26     /**
27      * @var array
28      */
29     private $schema;
30     /**
31      * @var array
32      */
33     private $instances;
34
35     /**
36      * Initialises container using provided service configuration.
37      *
38      * @param array $schema
39      */
40     public function __construct(array $schema)
41     {
42         $this->schema = $schema;
43     }
44
45     /**
46      * {@inheritdoc}
47      */
48     public function has($id)
49     {
50         return array_key_exists($id, $this->schema);
51     }
52
53     /**
54      * {@inheritdoc}
55      */
56     public function get($id)
57     {
58         if (!$this->has($id)) {
59             throw new ServiceNotFoundException(
60                 sprintf('Service with id `%s` was not defined inside the `services` setting`.', $id),
61                 $id
62             );
63         }
64
65         return $this->instances[$id] = isset($this->instances[$id]) ? $this->instances[$id] : $this->createInstance($id);
66     }
67
68     /**
69      * Creates an instance of given service.
70      *
71      * @param string $id
72      *
73      * @return mixed
74      */
75     private function createInstance($id)
76     {
77         $schema = $this->getAndValidateServiceSchema($id);
78
79         $reflection = new ReflectionClass($schema['class']);
80         $arguments = $schema['arguments'];
81
82         if ($factoryMethod = $this->getAndValidateFactoryMethod($reflection, $schema)) {
83             return $factoryMethod->invokeArgs(null, $arguments);
84         }
85
86         return $reflection->newInstanceArgs($arguments);
87     }
88
89     /**
90      * Gets and validates a service configuration for a service with given ID.
91      *
92      * @param string $id
93      *
94      * @throws WrongServicesConfigurationException
95      *
96      * @return array|string
97      */
98     private function getAndValidateServiceSchema($id)
99     {
100         $schema = $this->schema[$id];
101
102         if (null === $schema) {
103             $schema = array('class' => $id);
104         }
105
106         if (is_string($schema)) {
107             $schema = array('class' => $schema);
108         }
109
110         $schema['class'] = $this->getAndValidateClass($id, $schema);
111         $schema['arguments'] = $this->getAndValidateArguments($schema);
112
113         return $schema;
114     }
115
116     /**
117      * Gets and validates a class from schema.
118      *
119      * @param string       $id
120      * @param string|array $schema
121      *
122      * @return string
123      */
124     private function getAndValidateClass($id, array $schema)
125     {
126         if (!isset($schema['class'])) {
127             $schema['class'] = $id;
128         }
129
130         return $schema['class'];
131     }
132
133     /**
134      * Gets and validates arguments from schema.
135      *
136      * @param array $schema
137      *
138      * @return array
139      */
140     private function getAndValidateArguments(array $schema)
141     {
142         return isset($schema['arguments']) ? (array)$schema['arguments'] : array();
143     }
144
145     /**
146      * Gets and validates a factory method.
147      *
148      * @param ReflectionClass $reflection
149      * @param array           $schema
150      *
151      * @return null|ReflectionMethod
152      */
153     private function getAndValidateFactoryMethod(ReflectionClass $reflection, array $schema)
154     {
155         if (!isset($schema['factory_method'])) {
156             return null;
157         }
158
159         $factoryMethod = $schema['factory_method'];
160         $this->assertFactoryMethodExists($reflection, $factoryMethod);
161         $method = $reflection->getMethod($factoryMethod);
162         $this->assertFactoryMethodIsStatic($method);
163
164         return $method;
165     }
166
167     /**
168      * Checks if factory method exists.
169      *
170      * @param ReflectionClass $class
171      * @param string          $methodName
172      *
173      * @throws WrongServicesConfigurationException
174      */
175     private function assertFactoryMethodExists(ReflectionClass $class, $methodName)
176     {
177         if (!$class->hasMethod($methodName)) {
178             throw new WrongServicesConfigurationException(sprintf(
179                 'Factory method `%s::%s` does not exist.',
180                 $class->getName(),
181                 $methodName
182             ));
183         }
184     }
185
186     /**
187      * Checks if factory method is static.
188      *
189      * @param ReflectionMethod $method
190      *
191      * @throws WrongServicesConfigurationException
192      */
193     private function assertFactoryMethodIsStatic(ReflectionMethod $method)
194     {
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(),
199                 $method->getName()
200             ));
201         }
202     }
203 }