Security update for permissions_by_term
[yaffs-website] / vendor / behat / mink-extension / src / Behat / MinkExtension / ServiceContainer / MinkExtension.php
1 <?php
2
3 /*
4  * This file is part of the Behat MinkExtension.
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\MinkExtension\ServiceContainer;
12
13 use Behat\Behat\Context\ServiceContainer\ContextExtension;
14 use Behat\MinkExtension\ServiceContainer\Driver\BrowserStackFactory;
15 use Behat\MinkExtension\ServiceContainer\Driver\DriverFactory;
16 use Behat\MinkExtension\ServiceContainer\Driver\GoutteFactory;
17 use Behat\MinkExtension\ServiceContainer\Driver\SahiFactory;
18 use Behat\MinkExtension\ServiceContainer\Driver\SauceLabsFactory;
19 use Behat\MinkExtension\ServiceContainer\Driver\Selenium2Factory;
20 use Behat\MinkExtension\ServiceContainer\Driver\SeleniumFactory;
21 use Behat\MinkExtension\ServiceContainer\Driver\ZombieFactory;
22 use Behat\Testwork\EventDispatcher\ServiceContainer\EventDispatcherExtension;
23 use Behat\Testwork\ServiceContainer\Exception\ProcessingException;
24 use Behat\Testwork\ServiceContainer\Extension as ExtensionInterface;
25 use Behat\Testwork\ServiceContainer\ExtensionManager;
26 use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition;
27 use Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
28 use Symfony\Component\DependencyInjection\ContainerBuilder;
29 use Symfony\Component\DependencyInjection\Definition;
30 use Symfony\Component\DependencyInjection\Reference;
31
32 /**
33  * Mink extension for Behat class.
34  *
35  * @author Konstantin Kudryashov <ever.zet@gmail.com>
36  * @author Christophe Coevoet <stof@notk.org>
37  */
38 class MinkExtension implements ExtensionInterface
39 {
40     const MINK_ID = 'mink';
41     const SELECTORS_HANDLER_ID = 'mink.selectors_handler';
42
43     const SELECTOR_TAG = 'mink.selector';
44
45     /**
46      * @var DriverFactory[]
47      */
48     private $driverFactories = array();
49
50     public function __construct()
51     {
52         $this->registerDriverFactory(new GoutteFactory());
53         $this->registerDriverFactory(new SahiFactory());
54         $this->registerDriverFactory(new SeleniumFactory());
55         $this->registerDriverFactory(new Selenium2Factory());
56         $this->registerDriverFactory(new SauceLabsFactory());
57         $this->registerDriverFactory(new BrowserStackFactory());
58         $this->registerDriverFactory(new ZombieFactory());
59     }
60
61     public function registerDriverFactory(DriverFactory $driverFactory)
62     {
63         $this->driverFactories[$driverFactory->getDriverName()] = $driverFactory;
64     }
65
66     /**
67      * {@inheritDoc}
68      */
69     public function load(ContainerBuilder $container, array $config)
70     {
71         if (isset($config['mink_loader'])) {
72             $basePath = $container->getParameter('paths.base');
73
74             if (file_exists($basePath.DIRECTORY_SEPARATOR.$config['mink_loader'])) {
75                 require($basePath.DIRECTORY_SEPARATOR.$config['mink_loader']);
76             } else {
77                 require($config['mink_loader']);
78             }
79         }
80
81         $this->loadMink($container);
82         $this->loadContextInitializer($container);
83         $this->loadSelectorsHandler($container);
84         $this->loadSessions($container, $config);
85         $this->loadSessionsListener($container);
86
87         if ($config['show_auto']) {
88             $this->loadFailureShowListener($container);
89         }
90
91         unset($config['sessions']);
92
93         $container->setParameter('mink.parameters', $config);
94         $container->setParameter('mink.base_url', $config['base_url']);
95         $container->setParameter('mink.browser_name', $config['browser_name']);
96     }
97
98     /**
99      * {@inheritDoc}
100      */
101     public function configure(ArrayNodeDefinition $builder)
102     {
103         // Rewrite keys to define a shortcut way without allowing conflicts with real keys
104         $renamedKeys = array_diff(
105             array_keys($this->driverFactories),
106             array('mink_loader', 'base_url', 'files_path', 'show_auto', 'show_cmd', 'show_tmp_dir', 'default_session', 'javascript_session', 'browser_name', 'sessions')
107         );
108
109         $builder
110             ->beforeNormalization()
111                 ->always()
112                 ->then(function ($v) use ($renamedKeys) {
113                     foreach ($renamedKeys as $driverType) {
114                         if (!array_key_exists($driverType, $v) || isset($v['sessions'][$driverType])) {
115                             continue;
116                         }
117
118                         $v['sessions'][$driverType][$driverType] = $v[$driverType];
119                         unset($v[$driverType]);
120                     }
121
122                     return $v;
123                 })
124             ->end()
125             ->addDefaultsIfNotSet()
126             ->children()
127                 ->scalarNode('mink_loader')->defaultNull()->end()
128                 ->scalarNode('base_url')->defaultNull()->end()
129                 ->scalarNode('files_path')->defaultNull()->end()
130                 ->booleanNode('show_auto')->defaultFalse()->end()
131                 ->scalarNode('show_cmd')->defaultNull()->end()
132                 ->scalarNode('show_tmp_dir')->defaultValue(sys_get_temp_dir())->end()
133                 ->scalarNode('default_session')->defaultNull()->info('Defaults to the first non-javascript session if any, or the first session otherwise')->end()
134                 ->scalarNode('javascript_session')->defaultNull()->info('Defaults to the first javascript session if any')->end()
135                 ->scalarNode('browser_name')->defaultValue('firefox')->end()
136             ->end()
137         ->end();
138
139         /** @var ArrayNodeDefinition $sessionsBuilder */
140         $sessionsBuilder = $builder
141             ->children()
142                 ->arrayNode('sessions')
143                     ->isRequired()
144                     ->requiresAtLeastOneElement()
145                     ->useAttributeAsKey('name')
146                     ->prototype('array')
147         ;
148
149         foreach ($this->driverFactories as $factory) {
150             $factoryNode = $sessionsBuilder->children()->arrayNode($factory->getDriverName())->canBeUnset();
151
152             $factory->configure($factoryNode);
153         }
154
155         $sessionsBuilder
156             ->validate()
157                 ->ifTrue(function ($v) {return count($v) > 1;})
158                 ->thenInvalid('You cannot set multiple driver types for the same session')
159             ->end()
160             ->validate()
161                 ->ifTrue(function ($v) {return count($v) === 0;})
162                 ->thenInvalid('You must set a driver definition for the session.')
163             ->end()
164         ;
165     }
166
167     /**
168      * {@inheritDoc}
169      */
170     public function getConfigKey()
171     {
172         return 'mink';
173     }
174
175     /**
176      * {@inheritdoc}
177      */
178     public function initialize(ExtensionManager $extensionManager)
179     {
180     }
181
182     /**
183      * {@inheritDoc}
184      */
185     public function process(ContainerBuilder $container)
186     {
187         $this->processSelectors($container);
188     }
189
190     private function loadMink(ContainerBuilder $container)
191     {
192         $container->setDefinition(self::MINK_ID, new Definition('Behat\Mink\Mink'));
193     }
194
195     private function loadContextInitializer(ContainerBuilder $container)
196     {
197         $definition = new Definition('Behat\MinkExtension\Context\Initializer\MinkAwareInitializer', array(
198             new Reference(self::MINK_ID),
199             '%mink.parameters%',
200         ));
201         $definition->addTag(ContextExtension::INITIALIZER_TAG, array('priority' => 0));
202         $container->setDefinition('mink.context_initializer', $definition);
203     }
204
205     private function loadSelectorsHandler(ContainerBuilder $container)
206     {
207         $container->setDefinition(self::SELECTORS_HANDLER_ID, new Definition('Behat\Mink\Selector\SelectorsHandler'));
208
209         $cssSelectorDefinition = new Definition('Behat\Mink\Selector\CssSelector');
210         $cssSelectorDefinition->addTag(self::SELECTOR_TAG, array('alias' => 'css'));
211         $container->setDefinition(self::SELECTOR_TAG . '.css', $cssSelectorDefinition);
212
213         $namedSelectorDefinition = new Definition('Behat\Mink\Selector\NamedSelector');
214         $namedSelectorDefinition->addTag(self::SELECTOR_TAG, array('alias' => 'named'));
215         $container->setDefinition(self::SELECTOR_TAG . '.named', $namedSelectorDefinition);
216     }
217
218     private function loadSessions(ContainerBuilder $container, array $config)
219     {
220         $defaultSession = $config['default_session'];
221         $javascriptSession = $config['javascript_session'];
222         $javascriptSessions = $nonJavascriptSessions = array();
223
224         $minkDefinition = $container->getDefinition(self::MINK_ID);
225
226         foreach ($config['sessions'] as $name => $session) {
227             $driver = key($session);
228             $factory = $this->driverFactories[$driver];
229
230             $definition = new Definition('Behat\Mink\Session', array(
231                 $factory->buildDriver($session[$driver]),
232                 new Reference(self::SELECTORS_HANDLER_ID),
233             ));
234             $minkDefinition->addMethodCall('registerSession', array($name, $definition));
235
236             if ($factory->supportsJavascript()) {
237                 $javascriptSessions[] = $name;
238             } else {
239                 $nonJavascriptSessions[] = $name;
240             }
241         }
242
243         if (null === $javascriptSession && !empty($javascriptSessions)) {
244             $javascriptSession = $javascriptSessions[0];
245         } elseif (null !== $javascriptSession && !in_array($javascriptSession, $javascriptSessions)) {
246             throw new InvalidConfigurationException(sprintf(
247                 'The javascript session must be one of the enabled javascript sessions (%s), but got %s',
248                 json_encode($javascriptSessions),
249                 $javascriptSession
250             ));
251         }
252
253         if (null === $defaultSession) {
254             $defaultSession = !empty($nonJavascriptSessions) ? $nonJavascriptSessions[0] : $javascriptSessions[0];
255         } elseif (!isset($config['sessions'][$defaultSession])) {
256             throw new InvalidConfigurationException(sprintf('The default session must be one of the enabled sessions, but got %s', $defaultSession));
257         }
258
259         $container->setParameter('mink.default_session', $defaultSession);
260         $container->setParameter('mink.javascript_session', $javascriptSession);
261         $container->setParameter('mink.available_javascript_sessions', $javascriptSessions);
262     }
263
264     private function loadSessionsListener(ContainerBuilder $container)
265     {
266         $definition = new Definition('Behat\MinkExtension\Listener\SessionsListener', array(
267             new Reference(self::MINK_ID),
268             '%mink.default_session%',
269             '%mink.javascript_session%',
270             '%mink.available_javascript_sessions%',
271         ));
272         $definition->addTag(EventDispatcherExtension::SUBSCRIBER_TAG, array('priority' => 0));
273         $container->setDefinition('mink.listener.sessions', $definition);
274     }
275
276     private function loadFailureShowListener(ContainerBuilder $container)
277     {
278         $definition = new Definition('Behat\MinkExtension\Listener\FailureShowListener', array(
279             new Reference(self::MINK_ID),
280             '%mink.parameters%',
281         ));
282         $definition->addTag(EventDispatcherExtension::SUBSCRIBER_TAG, array('priority' => 0));
283         $container->setDefinition('mink.listener.failure_show', $definition);
284     }
285
286     private function processSelectors(ContainerBuilder $container)
287     {
288         $handlerDefinition = $container->getDefinition(self::SELECTORS_HANDLER_ID);
289
290         foreach ($container->findTaggedServiceIds(self::SELECTOR_TAG) as $id => $tags) {
291             foreach ($tags as $tag) {
292                 if (!isset($tag['alias'])) {
293                     throw new ProcessingException(sprintf(
294                         'All `%s` tags should have an `alias` attribute, but `%s` service has none.',
295                         $tag,
296                         $id
297                     ));
298                 }
299                 $handlerDefinition->addMethodCall(
300                     'registerSelector', array($tag['alias'], new Reference($id))
301                 );
302             }
303         }
304     }
305 }