Security update for permissions_by_term
[yaffs-website] / vendor / behat / behat / src / Behat / Behat / HelperContainer / Argument / ServicesResolverFactory.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\Argument;
12
13 use Behat\Behat\Context\Argument\ArgumentResolver;
14 use Behat\Behat\HelperContainer\Environment\ServiceContainerEnvironment;
15 use Behat\Behat\Context\Argument\ArgumentResolverFactory;
16 use Behat\Behat\Context\Argument\SuiteScopedResolverFactory;
17 use Behat\Behat\HelperContainer\BuiltInServiceContainer;
18 use Behat\Behat\HelperContainer\Exception\WrongContainerClassException;
19 use Behat\Behat\HelperContainer\Exception\WrongServicesConfigurationException;
20 use Behat\Behat\HelperContainer\ServiceContainer\HelperContainerExtension;
21 use Behat\Testwork\Environment\Environment;
22 use Behat\Testwork\Suite\Suite;
23 use Psr\Container\ContainerInterface;
24 use Symfony\Component\DependencyInjection\TaggedContainerInterface;
25
26 /**
27  * Generates ServiceContainer argument resolvers based on suite's `services` setting.
28  *
29  * @see ContextEnvironmentHandler
30  *
31  * @author Konstantin Kudryashov <ever.zet@gmail.com>
32  */
33 final class ServicesResolverFactory implements SuiteScopedResolverFactory, ArgumentResolverFactory
34 {
35     /**
36      * @var TaggedContainerInterface
37      */
38     private $container;
39
40     /**
41      * Initialises factory.
42      *
43      * @param TaggedContainerInterface $container
44      */
45     public function __construct(TaggedContainerInterface $container)
46     {
47         $this->container = $container;
48     }
49
50     /**
51      * {@inheritdoc}
52      *
53      * @deprecated as part of SuiteScopedResolverFactory deprecation. Would be removed in 4.0
54      *
55      * @throws WrongServicesConfigurationException
56      * @throws WrongContainerClassException
57      */
58     public function generateArgumentResolvers(Suite $suite)
59     {
60         @trigger_error(
61             'SuiteScopedResolverFactory::generateArgumentResolvers() was deprecated and will be removed in 4.0',
62             E_USER_DEPRECATED
63         );
64
65         if (!$suite->hasSetting('services')) {
66             return array();
67         }
68
69         $container = $this->createContainer($suite->getSetting('services'));
70
71         return $this->createResolvers($container, false);
72     }
73
74     /**
75      * {@inheritdoc}
76      *
77      * @throws WrongServicesConfigurationException
78      * @throws WrongContainerClassException
79      */
80     public function createArgumentResolvers(Environment $environment)
81     {
82         $suite = $environment->getSuite();
83
84         if (!$suite->hasSetting('services')) {
85             return array();
86         }
87
88         $container = $this->createContainer($suite->getSetting('services'));
89         $autowire = $suite->hasSetting('autowire') && $suite->getSetting('autowire');
90
91         if ($environment instanceof ServiceContainerEnvironment) {
92             $environment->setServiceContainer($container);
93         }
94
95         return $this->createResolvers($container, $autowire);
96     }
97
98     /**
99      * Creates container from the setting passed.
100      *
101      * @param string $settings
102      *
103      * @return mixed
104      *
105      * @throws WrongServicesConfigurationException
106      */
107     private function createContainer($settings)
108     {
109         if (is_string($settings)) {
110             return $this->createContainerFromString($settings);
111         }
112
113         if (is_array($settings)) {
114             return $this->createContainerFromArray($settings);
115         }
116
117         throw new WrongServicesConfigurationException(
118             sprintf('`services` must be either string or an array, but `%s` given.', gettype($settings))
119         );
120     }
121
122     /**
123      * Creates custom container using class/constructor given.
124      *
125      * @param string $settings
126      *
127      * @return mixed
128      *
129      * @throws WrongServicesConfigurationException
130      */
131     private function createContainerFromString($settings)
132     {
133         if (0 === mb_strpos($settings, '@')) {
134             return $this->loadContainerFromContainer(mb_substr($settings, 1));
135         }
136
137         return $this->createContainerFromClassSpec($settings);
138     }
139
140     /**
141      * Creates built-in service container with provided settings.
142      *
143      * @param array $settings
144      *
145      * @return BuiltInServiceContainer
146      */
147     private function createContainerFromArray(array $settings)
148     {
149         return new BuiltInServiceContainer($settings);
150     }
151
152     /**
153      * Loads container from string.
154      *
155      * @param string $name
156      *
157      * @return mixed
158      *
159      * @throws WrongServicesConfigurationException
160      */
161     private function loadContainerFromContainer($name)
162     {
163         $services = $this->container->findTaggedServiceIds(HelperContainerExtension::HELPER_CONTAINER_TAG);
164
165         if (!array_key_exists($name, $services)) {
166             throw new WrongServicesConfigurationException(
167                 sprintf('Service container `@%s` was not found.', $name)
168             );
169         }
170
171         return $this->container->get($name);
172     }
173
174     /**
175      * Creates container from string-based class spec.
176      *
177      * @param string $classSpec
178      *
179      * @return mixed
180      */
181     private function createContainerFromClassSpec($classSpec)
182     {
183         $constructor = explode('::', $classSpec);
184
185         if (2 === count($constructor)) {
186             return call_user_func($constructor);
187         }
188
189         return new $constructor[0];
190     }
191
192     /**
193      * Checks if container implements the correct interface and creates resolver using it.
194      *
195      * @param mixed $container
196      * @param bool  $autowire
197      *
198      * @return ArgumentResolver[]
199      *
200      * @throws WrongContainerClassException
201      */
202     private function createResolvers($container, $autowire)
203     {
204         if (!$container instanceof ContainerInterface) {
205             throw new WrongContainerClassException(
206                 sprintf(
207                     'Service container is expected to implement `Psr\Container\ContainerInterface`, but `%s` does not.',
208                     get_class($container)
209                 ),
210                 get_class($container)
211             );
212         }
213
214         if ($autowire) {
215             return array(new ServicesResolver($container), new AutowiringResolver($container));
216         }
217
218         return array(new ServicesResolver($container));
219     }
220 }