Passed
Push — remove_compat_layer ( c48121...1de0f9 )
by Doug
10:31 queued 01:39
created

Extension::initCodeCoverageV678()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 30
Code Lines 18

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 0
Metric Value
cc 2
eloc 18
nc 2
nop 4
dl 0
loc 30
ccs 0
cts 19
cp 0
crap 6
rs 9.6666
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
/**
5
 * Code Coverage Extension for Behat.
6
 *
7
 * @copyright 2013 Anthon Pang
8
 *
9
 * @license BSD-2-Clause
10
 */
11
12
namespace DVDoug\Behat\CodeCoverage;
13
14
use Behat\Testwork\ServiceContainer\Extension as ExtensionInterface;
15
use Behat\Testwork\ServiceContainer\ExtensionManager;
16
use DVDoug\Behat\CodeCoverage\Subscriber\EventSubscriber;
17
use SebastianBergmann\CodeCoverage\CodeCoverage;
18
use SebastianBergmann\CodeCoverage\Driver\Driver;
19
use SebastianBergmann\CodeCoverage\Filter;
20
use SebastianBergmann\CodeCoverage\NoCodeCoverageDriverAvailableException;
21
use SebastianBergmann\CodeCoverage\NoCodeCoverageDriverWithPathCoverageSupportAvailableException;
22
use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition;
23
use Symfony\Component\Config\FileLocator;
24
use Symfony\Component\Console\Input\InputInterface;
25
use Symfony\Component\Console\Output\OutputInterface;
26
use Symfony\Component\DependencyInjection\ContainerBuilder;
27
use Symfony\Component\DependencyInjection\Loader\XmlFileLoader;
28
use Symfony\Component\DependencyInjection\Reference;
29
30
/**
31
 * Code coverage extension.
32
 *
33
 * @author Anthon Pang <[email protected]>
34
 */
35
class Extension implements ExtensionInterface
36
{
37
    /**
38
     * {@inheritdoc}
39
     */
40 2
    public function initialize(ExtensionManager $extensionManager): void
41
    {
42 2
    }
43
44
    /**
45
     * {@inheritdoc}
46
     */
47 2
    public function load(ContainerBuilder $container, array $config): void
48
    {
49 2
        $loader = new XmlFileLoader($container, new FileLocator(__DIR__ . '/Resources/config'));
50
51 2
        $servicesFile = 'services.xml';
52 2
        $loader->load($servicesFile);
53
54 2
        $container->setParameter('behat.code_coverage.config.filter', $config['filter']);
55 2
        $container->setParameter('behat.code_coverage.config.branchAndPathCoverage', $config['branchAndPathCoverage']);
56 2
        $container->setParameter('behat.code_coverage.config.reports', $config['reports'] ?? []);
57 2
    }
58
59
    /**
60
     * {@inheritdoc}
61
     */
62 4
    public function configure(ArrayNodeDefinition $builder): void
63
    {
64
        $builder
65 4
            ->children()
66 4
                ->booleanNode('branchAndPathCoverage')
67 4
                  ->defaultNull() // use null to mean auto
68 4
                ->end()
69 4
                ->arrayNode('filter')
0 ignored issues
show
Bug introduced by
The method arrayNode() does not exist on Symfony\Component\Config...der\NodeParentInterface. It seems like you code against a sub-type of Symfony\Component\Config...der\NodeParentInterface such as Symfony\Component\Config...ion\Builder\NodeBuilder. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

69
                ->/** @scrutinizer ignore-call */ arrayNode('filter')
Loading history...
70 4
                    ->addDefaultsIfNotSet()
71 4
                    ->children()
72 4
                        ->scalarNode('includeUncoveredFiles')
73 4
                            ->defaultTrue()
74 4
                        ->end()
75 4
                        ->scalarNode('processUncoveredFiles')
76 4
                            ->defaultFalse()
77 4
                        ->end()
78 4
                        ->arrayNode('include')
79 4
                            ->addDefaultsIfNotSet()
80 4
                            ->children()
81 4
                                ->arrayNode('directories')
82 4
                                   ->useAttributeAsKey('name')
83 4
                                   ->normalizeKeys(false)
84 4
                                   ->prototype('array')
85 4
                                       ->children()
86 4
                                           ->scalarNode('prefix')->defaultValue('')->end()
87 4
                                           ->scalarNode('suffix')->defaultValue('.php')->end()
88 4
                                       ->end()
89 4
                                   ->end()
90 4
                                ->end()
91 4
                                ->arrayNode('files')
92 4
                                   ->prototype('scalar')->end()
93 4
                                ->end()
94 4
                            ->end()
95 4
                        ->end()
96 4
                        ->arrayNode('exclude')
97 4
                            ->addDefaultsIfNotSet()
98 4
                            ->children()
99 4
                                ->arrayNode('directories')
100 4
                                   ->useAttributeAsKey('name')
101 4
                                   ->normalizeKeys(false)
102 4
                                   ->prototype('array')
103 4
                                       ->children()
104 4
                                           ->scalarNode('prefix')->defaultValue('')->end()
105 4
                                           ->scalarNode('suffix')->defaultValue('.php')->end()
106 4
                                       ->end()
107 4
                                   ->end()
108 4
                                ->end()
109 4
                                ->arrayNode('files')
110 4
                                   ->prototype('scalar')->end()
111 4
                                ->end()
112 4
                            ->end()
113 4
                        ->end()
114 4
                    ->end()
115 4
                ->end()
116 4
                ->arrayNode('reports')
117 4
                    ->children()
118 4
                        ->arrayNode('clover')
119 4
                            ->children()
120 4
                                ->scalarNode('name')->defaultNull()->end()
121 4
                                ->scalarNode('target')->isRequired()->cannotBeEmpty()->end()
122 4
                            ->end()
123 4
                        ->end()
124 4
                        ->arrayNode('crap4j')
125 4
                            ->children()
126 4
                                ->scalarNode('name')->defaultNull()->end()
127 4
                                ->scalarNode('target')->isRequired()->cannotBeEmpty()->end()
128 4
                            ->end()
129 4
                        ->end()
130 4
                        ->arrayNode('html')
131 4
                            ->children()
132 4
                                ->scalarNode('target')->isRequired()->cannotBeEmpty()->end()
133 4
                                ->scalarNode('lowUpperBound')->defaultValue(50)->end()
134 4
                                ->scalarNode('highLowerBound')->defaultValue(90)->end()
135 4
                            ->end()
136 4
                        ->end()
137 4
                        ->arrayNode('php')
138 4
                            ->children()
139 4
                                ->scalarNode('target')->isRequired()->cannotBeEmpty()->end()
140 4
                            ->end()
141 4
                        ->end()
142 4
                        ->arrayNode('text')
143 4
                            ->children()
144 4
                                ->booleanNode('showColors')->defaultValue(false)->end()
145 4
                                ->scalarNode('lowUpperBound')->defaultValue(50)->end()
146 4
                                ->scalarNode('highLowerBound')->defaultValue(90)->end()
147 4
                                ->booleanNode('showOnlySummary')->defaultValue(false)->end()
148 4
                                ->booleanNode('showUncoveredFiles')->defaultValue(false)->end()
149 4
                            ->end()
150 4
                        ->end()
151 4
                        ->arrayNode('xml')
152 4
                            ->children()
153 4
                                ->scalarNode('target')->isRequired()->cannotBeEmpty()->end()
154 4
                            ->end()
155 4
                        ->end()
156 4
                    ->end()
157 4
                ->end()
158 4
            ->end()
159 4
        ->end();
160 4
    }
161
162
    /**
163
     * {@inheritdoc}
164
     */
165 4
    public function getConfigKey()
166
    {
167 4
        return 'code_coverage';
168
    }
169
170
    /**
171
     * {@inheritdoc}
172
     */
173 8
    public function process(ContainerBuilder $container): void
174
    {
175
        /** @var InputInterface $input */
176 8
        $input = $container->get('cli.input');
177
178
        /** @var OutputInterface $output */
179 8
        $output = $container->get('cli.output');
180
181 8
        $filterConfig = $container->getParameter('behat.code_coverage.config.filter');
182 8
        $branchPathConfig = $container->getParameter('behat.code_coverage.config.branchAndPathCoverage');
183
184 8
        $canCollectCodeCoverage = true;
185
        try {
186 8
            $this->initCodeCoverage(new Filter(), $filterConfig, null, $output);
187
188
            $codeCoverageDefinition = $container->getDefinition(CodeCoverage::class);
189
            $filterDefinition = $container->getDefinition(Filter::class);
190
            $codeCoverageDefinition->setFactory([new Reference(self::class), 'initCodeCoverage']);
191 6
            $codeCoverageDefinition->setArguments([$filterDefinition, $filterConfig, $branchPathConfig, $output]);
192 2
        } catch (NoCodeCoverageDriverAvailableException $e) {
193 2
            $output->writeln('<comment>No code coverage driver is available</comment>');
194 2
            $canCollectCodeCoverage = false;
195
        }
196
197 8
        if (!$canCollectCodeCoverage || $input->hasParameterOption('--no-coverage')) {
198
            $container->getDefinition(EventSubscriber::class)->setArgument('$coverage', null);
199
        }
200 8
    }
201
202 6
    public function initCodeCoverage(Filter $filter, array $filterConfig, ?bool $branchPathConfig, OutputInterface $output): CodeCoverage
203
    {
204
        // set up filter
205 6
        array_walk($filterConfig['include']['directories'], static function (array $dir, string $path, Filter $filter): void {
206 6
            $filter->includeDirectory($path, $dir['suffix'], $dir['prefix']);
207 6
        }, $filter);
208
209 6
        array_walk($filterConfig['include']['files'], static function (string $file, string $key, Filter $filter): void {
210 6
            $filter->includeFile($file);
211 6
        }, $filter);
212
213 6
        array_walk($filterConfig['exclude']['directories'], static function (array $dir, string $path, Filter $filter): void {
214 6
            $filter->excludeDirectory($path, $dir['suffix'], $dir['prefix']);
215 6
        }, $filter);
216
217 6
        array_walk($filterConfig['exclude']['files'], static function (string $file, string $key, Filter $filter): void {
218 6
            $filter->excludeFile($file);
219 6
        }, $filter);
220
221
        // see if we can get a driver
222 6
        $driver = Driver::forLineCoverage($filter);
223 6
        if ($branchPathConfig !== false) {
224
            try {
225 6
                $driver = Driver::forLineAndPathCoverage($filter);
226 3
            } catch (NoCodeCoverageDriverWithPathCoverageSupportAvailableException $e) {
227
                // fallback driver is already set
228 3
                if ($branchPathConfig === true) { //only warn if explicitly enabled
0 ignored issues
show
introduced by
The condition $branchPathConfig === true is always true.
Loading history...
229 1
                    $output->writeln(sprintf('<info>%s does not support collecting branch and path data</info>', $driver->nameAndVersion()));
230
                }
231
            }
232
        }
233
234
        // and init coverage
235 6
        $codeCoverage = new CodeCoverage($driver, $filter);
236
237 6
        if ($filterConfig['includeUncoveredFiles']) {
238 2
            $codeCoverage->includeUncoveredFiles();
239
        } else {
240 4
            $codeCoverage->excludeUncoveredFiles();
241
        }
242
243 6
        if ($filterConfig['processUncoveredFiles']) {
244 2
            $codeCoverage->processUncoveredFiles();
245
        } else {
246 4
            $codeCoverage->doNotProcessUncoveredFiles();
247
        }
248
249 6
        return $codeCoverage;
250
    }
251
}
252