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

ParallelContainerDefinition::configureServices()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 19
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 13
CRAP Score 2.0014

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 19
ccs 13
cts 14
cp 0.9286
rs 9.4285
cc 2
eloc 14
nc 2
nop 1
crap 2.0014
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Paraunit\Configuration\DependencyInjection;
6
7
use Paraunit\Configuration\ParallelConfiguration;
8
use Paraunit\Configuration\PHPUnitBinFile;
9
use Paraunit\Configuration\PHPUnitConfig;
10
use Paraunit\Configuration\TempFilenameFactory;
11
use Paraunit\File\Cleaner;
12
use Paraunit\File\TempDirectory;
13
use Paraunit\Filter\Filter;
14
use Paraunit\Printer\ConsoleFormatter;
15
use Paraunit\Printer\FailuresPrinter;
16
use Paraunit\Printer\FilesRecapPrinter;
17
use Paraunit\Printer\FinalPrinter;
18
use Paraunit\Printer\ProcessPrinter;
19
use Paraunit\Printer\SharkPrinter;
20
use Paraunit\Printer\SingleResultFormatter;
21
use Paraunit\Process\CommandLine;
22
use Paraunit\Process\ProcessBuilderFactory;
23
use Paraunit\Process\ProcessFactory;
24
use Paraunit\Process\ProcessFactoryInterface;
25
use Paraunit\Proxy\PHPUnitUtilXMLProxy;
26
use Paraunit\Runner\PipelineCollection;
27
use Paraunit\Runner\PipelineFactory;
28
use Paraunit\Runner\Runner;
29
use Paraunit\TestResult\TestResultList;
30
use SebastianBergmann\FileIterator\Facade;
31
use Symfony\Component\Console\Output\OutputInterface;
32
use Symfony\Component\DependencyInjection\ContainerBuilder;
33
use Symfony\Component\DependencyInjection\Definition;
34
use Symfony\Component\DependencyInjection\Reference;
35
use Symfony\Component\EventDispatcher\ContainerAwareEventDispatcher;
36
use Symfony\Component\EventDispatcher\DependencyInjection\RegisterListenersPass;
37
use Symfony\Component\EventDispatcher\EventDispatcher;
38
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
39
use Symfony\Component\Process\Process;
40
41
class ParallelContainerDefinition
42
{
43
    /** @var ParserDefinition */
44
    private $parserDefinition;
45
46
    /** @var TestResultDefinition */
47
    private $testResult;
48
49 24
    public function __construct()
50
    {
51 24
        $this->parserDefinition = new ParserDefinition();
52 24
        $this->testResult = new TestResultDefinition();
53
    }
54
55 69
    public function configure(ContainerBuilder $container): ContainerBuilder
56
    {
57 69
        $container->setParameter('paraunit.max_retry_count', 3);
58 69
        $container->setParameter('kernel.root_dir', 'src');
59 69
        $this->configureConfiguration($container);
60 69
        $this->configureEventDispatcher($container);
61 69
        $this->configureFile($container);
62 69
        $this->parserDefinition->configure($container);
63 69
        $this->configurePrinter($container);
64 69
        $this->configureProcess($container);
65 69
        $this->configureRunner($container);
66 69
        $this->configureServices($container);
67 69
        $this->testResult->configure($container);
68
69 69
        return $container;
70
    }
71
72 69
    private function configureConfiguration(ContainerBuilder $container)
73
    {
74 69
        $container->setDefinition(PHPUnitBinFile::class, new Definition(PHPUnitBinFile::class));
75 69
        $container->setDefinition(PHPUnitConfig::class, new Definition(PHPUnitConfig::class, [
76 69
            '%paraunit.phpunit_config_filename%',
77
        ]))
78 69
            ->setPublic(true);
79 69
        $container->setDefinition(TempFilenameFactory::class, new Definition(TempFilenameFactory::class, [
80 69
            new Reference(TempDirectory::class),
81
        ]));
82
    }
83
84 69
    private function configureEventDispatcher(ContainerBuilder $container)
85
    {
86 69
        if (class_exists('Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument')) {
87 69
            $container->setDefinition(EventDispatcherInterface::class, new Definition(EventDispatcher::class));
88
        } else {
89
            $container->setDefinition(
90
                EventDispatcherInterface::class,
91
                new Definition(ContainerAwareEventDispatcher::class, [new Reference('service_container')])
92
            );
93
        }
94
95 69
        $container->addCompilerPass(
96 69
            new RegisterListenersPass(
97 69
                EventDispatcherInterface::class,
98 69
                '',
99 69
                ParallelConfiguration::TAG_EVENT_SUBSCRIBER
100
            )
101
        );
102
    }
103
104 69
    private function configureFile(ContainerBuilder $container)
105
    {
106 69
        $container->setDefinition(TempDirectory::class, new Definition(TempDirectory::class));
107 69
        $container->setDefinition(Cleaner::class, new Definition(Cleaner::class, [
108 69
            new Reference(TempDirectory::class),
109
        ]));
110
    }
111
112 69
    private function configurePrinter(ContainerBuilder $container)
113
    {
114 69
        $output = new Reference(OutputInterface::class);
115
116 69
        $container->setDefinition(SharkPrinter::class, new Definition(SharkPrinter::class, [
117 69
            $output,
118 69
            '%paraunit.show_logo%',
119
        ]));
120 69
        $container->setDefinition(ProcessPrinter::class, new Definition(ProcessPrinter::class, [
121 69
            new Reference(SingleResultFormatter::class),
122 69
            $output,
123
        ]));
124
125
        $finalPrinterArguments = [
126 69
            new Reference(TestResultList::class),
127 69
            $output,
128
        ];
129 69
        $container->setDefinition(FinalPrinter::class, new Definition(FinalPrinter::class, $finalPrinterArguments));
130 69
        $container->setDefinition(FailuresPrinter::class, new Definition(FailuresPrinter::class, $finalPrinterArguments));
131 69
        $container->setDefinition(FilesRecapPrinter::class, new Definition(FilesRecapPrinter::class, $finalPrinterArguments));
132
133 69
        $container->setDefinition(ConsoleFormatter::class, new Definition(ConsoleFormatter::class, [$output]));
134 69
        $container->setDefinition(SingleResultFormatter::class, new Definition(SingleResultFormatter::class, [
135 69
            new Reference(TestResultList::class),
136
        ]));
137
    }
138
139 69
    private function configureProcess(ContainerBuilder $container)
140
    {
141 69
        $container->setDefinition(CommandLine::class, new Definition(CommandLine::class, [
142 69
            new Reference(PHPUnitBinFile::class),
143
        ]));
144
145 69
        $container->setDefinition(ProcessFactoryInterface::class, new Definition($this->getProcessFactoryClass(), [
146 69
            new Reference(CommandLine::class),
147 69
            new Reference(PHPUnitConfig::class),
148 69
            new Reference(TempFilenameFactory::class),
149
        ]));
150
    }
151
152 69
    private function configureRunner(ContainerBuilder $container)
153
    {
154 69
        $container->setDefinition(PipelineFactory::class, new Definition(PipelineFactory::class, [
155 69
            new Reference(EventDispatcherInterface::class),
156
        ]));
157 69
        $container->setDefinition(PipelineCollection::class, new Definition(PipelineCollection::class, [
158 69
            new Reference(PipelineFactory::class),
159 69
            '%paraunit.max_process_count%',
160
        ]));
161 69
        $container->setDefinition(Runner::class, new Definition(Runner::class, [
162 69
            new Reference(EventDispatcherInterface::class),
163 69
            new Reference(ProcessFactoryInterface::class),
164 69
            new Reference(Filter::class),
165 69
            new Reference(PipelineCollection::class),
166
        ]))
167 69
            ->setPublic(true);
168
    }
169
170 69
    private function configureServices(ContainerBuilder $container)
171
    {
172 69
        if (! class_exists('SebastianBergmann\FileIterator\Facade')) {
173
            \class_alias('\File_Iterator_Facade', 'SebastianBergmann\FileIterator\Facade');
174
        }
175
176 69
        $container->register(OutputInterface::class, OutputInterface::class)
177 69
            ->setPublic(true)
178 69
            ->setSynthetic(true);
179 69
        $container->setDefinition(PHPUnitUtilXMLProxy::class, new Definition(PHPUnitUtilXMLProxy::class));
180 69
        $container->setDefinition(Facade::class, new Definition(Facade::class));
181 69
        $container->setDefinition(Filter::class, new Definition(Filter::class, [
182 69
            new Reference(PHPUnitUtilXMLProxy::class),
183 69
            new Reference(Facade::class),
184 69
            new Reference(PHPUnitConfig::class),
185 69
            '%paraunit.testsuite%',
186 69
            '%paraunit.string_filter%',
187
        ]));
188
    }
189
190 69
    private function getProcessFactoryClass(): string
191
    {
192
        // only reliable way to detect symfony/process 3.3+: CLI parsing
193 69
        $process = new Process(['cmd as array']);
194 69
        if (\is_array($process->getCommandLine())) {
195
            // Commandline not parsed, we have Symfony < 3.3
196
            return ProcessBuilderFactory::class;
197
        }
198
199 69
        return ProcessFactory::class;
200
    }
201
}
202