+++ /dev/null
-<?php
-
-/*
- * This file is part of the Behat.
- * (c) Konstantin Kudryashov <ever.zet@gmail.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-namespace Behat\Behat\Gherkin\ServiceContainer;
-
-use Behat\Testwork\Cli\ServiceContainer\CliExtension;
-use Behat\Testwork\Filesystem\ServiceContainer\FilesystemExtension;
-use Behat\Testwork\ServiceContainer\Exception\ExtensionException;
-use Behat\Testwork\ServiceContainer\Extension;
-use Behat\Testwork\ServiceContainer\ExtensionManager;
-use Behat\Testwork\ServiceContainer\ServiceProcessor;
-use Behat\Testwork\Specification\ServiceContainer\SpecificationExtension;
-use Behat\Testwork\Suite\ServiceContainer\SuiteExtension;
-use Behat\Testwork\Translator\ServiceContainer\TranslatorExtension;
-use ReflectionClass;
-use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition;
-use Symfony\Component\DependencyInjection\ContainerBuilder;
-use Symfony\Component\DependencyInjection\Definition;
-use Symfony\Component\DependencyInjection\Reference;
-
-/**
- * Extends Behat with gherkin suites and features.
- *
- * @author Konstantin Kudryashov <ever.zet@gmail.com>
- */
-final class GherkinExtension implements Extension
-{
- /*
- * Available services
- */
- const MANAGER_ID = 'gherkin';
- const KEYWORDS_DUMPER_ID = 'gherkin.keywords_dumper';
- const KEYWORDS_ID = 'gherkin.keywords';
-
- /*
- * Available extension points
- */
- const LOADER_TAG = 'gherkin.loader';
-
- /**
- * @var ServiceProcessor
- */
- private $processor;
-
- /**
- * Initializes extension.
- *
- * @param null|ServiceProcessor $processor
- */
- public function __construct(ServiceProcessor $processor = null)
- {
- $this->processor = $processor ? : new ServiceProcessor();
- }
-
- /**
- * {@inheritdoc}
- */
- public function getConfigKey()
- {
- return 'gherkin';
- }
-
- /**
- * {@inheritdoc}
- */
- public function initialize(ExtensionManager $extensionManager)
- {
- }
-
- /**
- * {@inheritdoc}
- */
- public function configure(ArrayNodeDefinition $builder)
- {
- $builder
- ->addDefaultsIfNotSet()
- ->children()
- ->scalarNode('cache')
- ->info('Sets the gherkin parser cache folder')
- ->defaultValue(
- is_writable(sys_get_temp_dir())
- ? sys_get_temp_dir() . DIRECTORY_SEPARATOR . 'behat_gherkin_cache'
- : null
- )
- ->end()
- ->arrayNode('filters')
- ->info('Sets the gherkin filters (overridable by CLI options)')
- ->performNoDeepMerging()
- ->defaultValue(array())
- ->useAttributeAsKey('name')
- ->prototype('scalar')->end()
- ->end()
- ->end()
- ;
- }
-
- /**
- * {@inheritdoc}
- */
- public function load(ContainerBuilder $container, array $config)
- {
- $this->loadParameters($container);
- $this->loadGherkin($container);
- $this->loadKeywords($container);
- $this->loadParser($container);
- $this->loadDefaultLoaders($container, $config['cache']);
- $this->loadProfileFilters($container, $config['filters']);
- $this->loadSyntaxController($container);
- $this->loadFilterController($container);
- $this->loadSuiteWithPathsSetup($container);
- $this->loadFilesystemFeatureLocator($container);
- $this->loadFilesystemScenariosListLocator($container);
- $this->loadFilesystemRerunScenariosListLocator($container);
- }
-
- /**
- * {@inheritdoc}
- */
- public function process(ContainerBuilder $container)
- {
- $this->processLoaders($container);
- }
-
- /**
- * Loads default container parameters.
- *
- * @param ContainerBuilder $container
- */
- private function loadParameters(ContainerBuilder $container)
- {
- $container->setParameter('gherkin.paths.lib', $this->getLibPath());
- $container->setParameter('gherkin.paths.i18n', '%gherkin.paths.lib%/i18n.php');
- $container->setParameter(
- 'suite.generic.default_settings',
- array(
- 'paths' => array('%paths.base%/features'),
- 'contexts' => array('FeatureContext')
- )
- );
- }
-
- /**
- * Returns gherkin library path.
- *
- * @return string
- */
- private function getLibPath()
- {
- $reflection = new ReflectionClass('Behat\Gherkin\Gherkin');
- $libPath = rtrim(dirname($reflection->getFilename()) . '/../../../', DIRECTORY_SEPARATOR);
-
- return $libPath;
- }
-
- /**
- * Loads gherkin service.
- *
- * @param ContainerBuilder $container
- */
- private function loadGherkin(ContainerBuilder $container)
- {
- $definition = new Definition('Behat\Gherkin\Gherkin');
- $container->setDefinition(self::MANAGER_ID, $definition);
- }
-
- /**
- * Loads keyword services.
- *
- * @param ContainerBuilder $container
- */
- private function loadKeywords(ContainerBuilder $container)
- {
- $definition = new Definition('Behat\Gherkin\Keywords\CachedArrayKeywords', array(
- '%gherkin.paths.i18n%'
- ));
- $container->setDefinition(self::KEYWORDS_ID, $definition);
-
- $definition = new Definition('Behat\Gherkin\Keywords\KeywordsDumper', array(
- new Reference(self::KEYWORDS_ID)
- ));
- $container->setDefinition(self::KEYWORDS_DUMPER_ID, $definition);
- }
-
- /**
- * Loads gherkin parser.
- *
- * @param ContainerBuilder $container
- */
- private function loadParser(ContainerBuilder $container)
- {
- $definition = new Definition('Behat\Gherkin\Parser', array(
- new Reference('gherkin.lexer')
- ));
- $container->setDefinition('gherkin.parser', $definition);
-
- $definition = new Definition('Behat\Gherkin\Lexer', array(
- new Reference('gherkin.keywords')
- ));
- $container->setDefinition('gherkin.lexer', $definition);
- }
-
- /**
- * Loads gherkin loaders.
- *
- * @param ContainerBuilder $container
- * @param string $cachePath
- */
- private function loadDefaultLoaders(ContainerBuilder $container, $cachePath)
- {
- $definition = new Definition('Behat\Gherkin\Loader\GherkinFileLoader', array(
- new Reference('gherkin.parser')
- ));
-
- if ($cachePath) {
- $cacheDefinition = new Definition('Behat\Gherkin\Cache\FileCache', array($cachePath));
- } else {
- $cacheDefinition = new Definition('Behat\Gherkin\Cache\MemoryCache');
- }
-
- $definition->addMethodCall('setCache', array($cacheDefinition));
- $definition->addMethodCall('setBasePath', array('%paths.base%'));
- $definition->addTag(self::LOADER_TAG, array('priority' => 50));
- $container->setDefinition('gherkin.loader.gherkin_file', $definition);
- }
-
- /**
- * Loads profile-level gherkin filters.
- *
- * @param ContainerBuilder $container
- * @param array $filters
- */
- private function loadProfileFilters(ContainerBuilder $container, array $filters)
- {
- $gherkin = $container->getDefinition(self::MANAGER_ID);
- foreach ($filters as $type => $filterString) {
- $filter = $this->createFilterDefinition($type, $filterString);
- $gherkin->addMethodCall('addFilter', array($filter));
- }
- }
-
- /**
- * Loads syntax controller.
- *
- * @param ContainerBuilder $container
- */
- private function loadSyntaxController(ContainerBuilder $container)
- {
- $definition = new Definition('Behat\Behat\Gherkin\Cli\SyntaxController', array(
- new Reference(self::KEYWORDS_DUMPER_ID),
- new Reference(TranslatorExtension::TRANSLATOR_ID)
- ));
- $definition->addTag(CliExtension::CONTROLLER_TAG, array('priority' => 600));
- $container->setDefinition(CliExtension::CONTROLLER_TAG . '.gherkin_syntax', $definition);
- }
-
- /**
- * Loads filter controller.
- *
- * @param ContainerBuilder $container
- */
- private function loadFilterController(ContainerBuilder $container)
- {
- $definition = new Definition('Behat\Behat\Gherkin\Cli\FilterController', array(
- new Reference(self::MANAGER_ID)
- ));
- $definition->addTag(CliExtension::CONTROLLER_TAG, array('priority' => 700));
- $container->setDefinition(CliExtension::CONTROLLER_TAG . '.gherkin_filters', $definition);
- }
-
- /**
- * Loads suite with paths setup.
- *
- * @param ContainerBuilder $container
- */
- private function loadSuiteWithPathsSetup(ContainerBuilder $container)
- {
- $definition = new Definition('Behat\Behat\Gherkin\Suite\Setup\SuiteWithPathsSetup', array(
- '%paths.base%',
- new Reference(FilesystemExtension::LOGGER_ID)
- ));
- $definition->addTag(SuiteExtension::SETUP_TAG, array('priority' => 50));
- $container->setDefinition(SuiteExtension::SETUP_TAG . '.suite_with_paths', $definition);
- }
-
- /**
- * Loads filesystem feature locator.
- *
- * @param ContainerBuilder $container
- */
- private function loadFilesystemFeatureLocator(ContainerBuilder $container)
- {
- $definition = new Definition('Behat\Behat\Gherkin\Specification\Locator\FilesystemFeatureLocator', array(
- new Reference(self::MANAGER_ID),
- '%paths.base%'
- ));
- $definition->addTag(SpecificationExtension::LOCATOR_TAG, array('priority' => 60));
- $container->setDefinition(SpecificationExtension::LOCATOR_TAG . '.filesystem_feature', $definition);
- }
-
- /**
- * Loads filesystem scenarios list locator.
- *
- * @param ContainerBuilder $container
- */
- private function loadFilesystemScenariosListLocator(ContainerBuilder $container)
- {
- $definition = new Definition('Behat\Behat\Gherkin\Specification\Locator\FilesystemScenariosListLocator', array(
- new Reference(self::MANAGER_ID)
- ));
- $definition->addTag(SpecificationExtension::LOCATOR_TAG, array('priority' => 50));
- $container->setDefinition(SpecificationExtension::LOCATOR_TAG . '.filesystem_scenarios_list', $definition);
- }
-
- /**
- * Loads filesystem rerun scenarios list locator.
- *
- * @param ContainerBuilder $container
- */
- private function loadFilesystemRerunScenariosListLocator(ContainerBuilder $container)
- {
- $definition = new Definition('Behat\Behat\Gherkin\Specification\Locator\FilesystemRerunScenariosListLocator', array(
- new Reference(self::MANAGER_ID)
- ));
- $definition->addTag(SpecificationExtension::LOCATOR_TAG, array('priority' => 50));
- $container->setDefinition(SpecificationExtension::LOCATOR_TAG . '.filesystem_rerun_scenarios_list', $definition);
- }
-
- /**
- * Processes all available gherkin loaders.
- *
- * @param ContainerBuilder $container
- */
- private function processLoaders(ContainerBuilder $container)
- {
- $references = $this->processor->findAndSortTaggedServices($container, self::LOADER_TAG);
- $definition = $container->getDefinition(self::MANAGER_ID);
-
- foreach ($references as $reference) {
- $definition->addMethodCall('addLoader', array($reference));
- }
- }
-
- /**
- * Creates filter definition of provided type.
- *
- * @param string $type
- * @param string $filterString
- *
- * @return Definition
- *
- * @throws ExtensionException If filter type is not recognised
- */
- private function createFilterDefinition($type, $filterString)
- {
- if ('role' === $type) {
- return new Definition('Behat\Gherkin\Filter\RoleFilter', array($filterString));
- }
-
- if ('name' === $type) {
- return new Definition('Behat\Gherkin\Filter\NameFilter', array($filterString));
- }
-
- if ('tags' === $type) {
- return new Definition('Behat\Gherkin\Filter\TagFilter', array($filterString));
- }
-
- if ('narrative' === $type) {
- return new Definition('Behat\Gherkin\Filter\NarrativeFilter', array($filterString));
- }
-
- throw new ExtensionException(sprintf(
- '`%s` filter is not supported by the `filters` option of gherkin extension. Supported types are `%s`.',
- $type,
- implode('`, `', array('narrative', 'role', 'name', 'tags'))
- ), 'gherkin');
- }
-}