4 * This file is part of the Behat Testwork.
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\Testwork\Output\ServiceContainer;
13 use Behat\Testwork\Cli\ServiceContainer\CliExtension;
14 use Behat\Testwork\EventDispatcher\ServiceContainer\EventDispatcherExtension;
15 use Behat\Testwork\Output\ServiceContainer\Formatter\FormatterFactory;
16 use Behat\Testwork\ServiceContainer\Extension;
17 use Behat\Testwork\ServiceContainer\ExtensionManager;
18 use Behat\Testwork\ServiceContainer\ServiceProcessor;
19 use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition;
20 use Symfony\Component\DependencyInjection\ContainerBuilder;
21 use Symfony\Component\DependencyInjection\Definition;
22 use Symfony\Component\DependencyInjection\Reference;
25 * Provides output management services for testwork.
27 * @author Konstantin Kudryashov <ever.zet@gmail.com>
29 final class OutputExtension implements Extension
34 const MANAGER_ID = 'output.manager';
37 * Available extension points
39 const FORMATTER_TAG = 'output.formatter';
44 private $defaultFormatter;
46 * @var FormatterFactory[]
50 * @var ServiceProcessor
55 * Initializes extension.
57 * @param string $defaultFormatter
58 * @param FormatterFactory[] $formatterFactories
59 * @param null|ServiceProcessor $processor
61 public function __construct($defaultFormatter, array $formatterFactories, ServiceProcessor $processor = null)
63 $this->defaultFormatter = $defaultFormatter;
64 $this->factories = $formatterFactories;
65 $this->processor = $processor ? : new ServiceProcessor();
69 * Registers formatter factory.
71 * @param FormatterFactory $factory
73 public function registerFormatterFactory(FormatterFactory $factory)
75 $this->factories[] = $factory;
81 public function getConfigKey()
89 public function initialize(ExtensionManager $extensionManager)
96 public function configure(ArrayNodeDefinition $builder)
99 ->defaultValue(array($this->defaultFormatter => array('enabled' => true)))
100 ->useAttributeAsKey('name')
102 ->beforeNormalization()
103 ->ifTrue(function ($a) {
104 return is_array($a) && !isset($a['enabled']);
106 ->then(function ($a) {
107 return array_merge($a, array('enabled' => true));
110 ->useAttributeAsKey('name')
111 ->treatTrueLike(array('enabled' => true))
112 ->treatNullLike(array('enabled' => true))
113 ->treatFalseLike(array('enabled' => false))
114 ->prototype('variable')->end()
122 public function load(ContainerBuilder $container, array $config)
124 $this->loadOutputController($container);
125 $this->loadFormatters($container);
126 $this->loadManager($container, $config);
132 public function process(ContainerBuilder $container)
134 $this->processFormatters($container);
135 $this->processDynamicallyRegisteredFormatters($container);
139 * Loads output controller.
141 * @param ContainerBuilder $container
143 private function loadOutputController(ContainerBuilder $container)
145 $definition = new Definition('Behat\Testwork\Output\Cli\OutputController', array(
146 new Reference(self::MANAGER_ID)
148 $definition->addTag(CliExtension::CONTROLLER_TAG, array('priority' => 1000));
149 $container->setDefinition(CliExtension::CONTROLLER_TAG . '.output', $definition);
153 * Loads output manager.
155 * @param ContainerBuilder $container
156 * @param array $formatters
158 private function loadManager(ContainerBuilder $container, array $formatters)
160 $definition = new Definition('Behat\Testwork\Output\OutputManager', array(
161 new Reference(EventDispatcherExtension::DISPATCHER_ID)
164 foreach ($formatters as $name => $parameters) {
165 if ($parameters['enabled']) {
166 $definition->addMethodCall('enableFormatter', array($name));
168 $definition->addMethodCall('disableFormatter', array($name));
171 unset($parameters['enabled']);
172 $definition->addMethodCall('setFormatterParameters', array($name, $parameters));
175 $container->setDefinition(self::MANAGER_ID, $definition);
179 * Loads default formatters using registered factories.
181 * @param ContainerBuilder $container
183 private function loadFormatters(ContainerBuilder $container)
185 foreach ($this->factories as $factory) {
186 $factory->buildFormatter($container);
191 * Processes formatters using registered factories.
193 * @param ContainerBuilder $container
195 private function processFormatters(ContainerBuilder $container)
197 foreach ($this->factories as $factory) {
198 $factory->processFormatter($container);
203 * Processes all available output formatters.
205 * @param ContainerBuilder $container
207 private function processDynamicallyRegisteredFormatters(ContainerBuilder $container)
209 $references = $this->processor->findAndSortTaggedServices($container, self::FORMATTER_TAG);
210 $definition = $container->getDefinition(self::MANAGER_ID);
212 $previousCalls = $definition->getMethodCalls();
213 $definition->setMethodCalls();
215 foreach ($references as $reference) {
216 $definition->addMethodCall('registerFormatter', array($reference));
219 foreach ($previousCalls as $call) {
220 $definition->addMethodCall($call[0], $call[1]);