Completed
Pull Request — master (#112)
by Alessandro
06:28
created

ParallelConfiguration::buildContainer()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 14
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 7
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 0
Metric Value
dl 0
loc 14
ccs 7
cts 7
cp 1
rs 9.4285
c 1
b 0
f 0
cc 1
eloc 9
nc 1
nop 2
crap 1
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Paraunit\Configuration;
6
7
use Paraunit\Configuration\DependencyInjection\ParallelContainerDefinition;
8
use Paraunit\Printer\DebugPrinter;
9
use Symfony\Component\Console\Input\InputInterface;
10
use Symfony\Component\Console\Output\OutputInterface;
11
use Symfony\Component\DependencyInjection\Alias;
12
use Symfony\Component\DependencyInjection\ContainerBuilder;
13
use Symfony\Component\DependencyInjection\Definition;
14
use Symfony\Component\DependencyInjection\Reference;
15
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
16
17
/**
18
 * Class Paraunit
19
 * @package Paraunit\Configuration
20
 */
21
class ParallelConfiguration
22
{
23
    const TAG_EVENT_SUBSCRIBER = 'paraunit.event_subscriber';
24
    const PUBLIC_ALIAS_FORMAT = '%s_public_alias';
25
26
    /** @var ParallelContainerDefinition */
27
    protected $containerDefinition;
28 20
29
    /** @var bool */
30 20
    private $createPublicServiceAliases;
31
32
    /**
33
     * ParallelConfiguration constructor.
34
     * @param bool $createPublicServiceAliases
35
     */
36
    public function __construct(bool $createPublicServiceAliases = false)
37
    {
38
        $this->containerDefinition = new ParallelContainerDefinition();
39
        $this->createPublicServiceAliases = $createPublicServiceAliases;
40 63
    }
41
42 63
    /**
43
     * @param InputInterface $input
44 63
     * @param OutputInterface $output
45 63
     * @return ContainerBuilder
46 63
     * @throws \Symfony\Component\DependencyInjection\Exception\BadMethodCallException
47 63
     * @throws \Exception
48
     */
49 63
    public function buildContainer(InputInterface $input, OutputInterface $output): ContainerBuilder
50
    {
51 63
        $containerBuilder = new ContainerBuilder();
52
53 63
        $this->containerDefinition->configure($containerBuilder);
54
        $this->loadCommandLineOptions($containerBuilder, $input);
55
        $this->tagEventSubscribers($containerBuilder);
56 63
57
        $this->createPublicAliases($containerBuilder);
58 63
        $containerBuilder->compile();
59 63
        $containerBuilder->set(OutputInterface::class, $output);
60 63
61
        return $containerBuilder;
62
    }
63 63
64 63
    protected function tagEventSubscribers(ContainerBuilder $container)
65
    {
66
        foreach ($container->getDefinitions() as $definition) {
67
            if ($definition->isSynthetic() || $definition->isAbstract()) {
68
                continue;
69 63
            }
70
71 63
            if (array_key_exists(EventSubscriberInterface::class, class_implements($definition->getClass()))) {
72 63
                $definition->addTag(self::TAG_EVENT_SUBSCRIBER);
73 63
            }
74 63
        }
75 63
    }
76
77 63
    protected function loadCommandLineOptions(ContainerBuilder $containerBuilder, InputInterface $input)
78 3
    {
79
        $containerBuilder->setParameter('paraunit.max_process_count', $input->getOption('parallel'));
80
        $containerBuilder->setParameter('paraunit.phpunit_config_filename', $input->getOption('configuration') ?? '.');
81
        $containerBuilder->setParameter('paraunit.testsuite', $input->getOption('testsuite'));
82
        $containerBuilder->setParameter('paraunit.string_filter', $input->getArgument('stringFilter'));
83
        $containerBuilder->setParameter('paraunit.show_logo', $input->getOption('logo'));
84
85
        if ($input->getOption('debug')) {
86 63
            $this->enableDebugMode($containerBuilder);
87
        }
88 63
    }
89 63
90
    private function enableDebugMode(ContainerBuilder $containerBuilder)
91 63
    {
92
        $definition = new Definition(DebugPrinter::class, [new Reference(OutputInterface::class)]);
93
        $definition->addTag(self::TAG_EVENT_SUBSCRIBER);
94 3
95
        $containerBuilder->setDefinition(DebugPrinter::class, $definition);
96 3
    }
97 3
98
    private function createPublicAliases(ContainerBuilder $containerBuilder)
99 3
    {
100
        if (! $this->createPublicServiceAliases) {
101
            return;
102
        }
103
104
        $services = $containerBuilder->getServiceIds();
105
        // the synthetic service isn't listed
106
        $services[] = OutputInterface::class;
107
        foreach ($services as $serviceName) {
108
            $containerBuilder->setAlias(
109
                sprintf(self::PUBLIC_ALIAS_FORMAT, $serviceName),
110
                new Alias($serviceName, true)
111
            );
112
        }
113
    }
114
}
115