Passed
Push — remove_compat_layer ( 27dc5c...3c8467 )
by Doug
03:22
created

Extension::getConfigKey()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
eloc 1
dl 0
loc 3
ccs 2
cts 2
cp 1
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 0
crap 1
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 4
    public function initialize(ExtensionManager $extensionManager): void
41
    {
42 4
    }
43
44
    /**
45
     * {@inheritdoc}
46
     */
47 4
    public function load(ContainerBuilder $container, array $config): void
48
    {
49 4
        $loader = new XmlFileLoader($container, new FileLocator(__DIR__ . '/Resources/config'));
50
51 4
        $servicesFile = 'services.xml';
52 4
        $loader->load($servicesFile);
53
54 4
        $container->setParameter('behat.code_coverage.config.filter', $config['filter']);
55 4
        $container->setParameter('behat.code_coverage.config.branchAndPathCoverage', $config['branchAndPathCoverage']);
56 4
        $container->setParameter('behat.code_coverage.config.reports', $config['reports'] ?? []);
57 4
    }
58
59
    /**
60
     * {@inheritdoc}
61
     */
62 8
    public function configure(ArrayNodeDefinition $builder): void
63
    {
64
        $builder
65 8
            ->children()
66 8
                ->booleanNode('branchAndPathCoverage')
67 8
                  ->defaultNull() // use null to mean auto
68 8
                ->end()
69 8
                ->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 8
                    ->addDefaultsIfNotSet()
71 8
                    ->children()
72 8
                        ->scalarNode('includeUncoveredFiles')
73 8
                            ->defaultTrue()
74 8
                        ->end()
75 8
                        ->scalarNode('processUncoveredFiles')
76 8
                            ->defaultFalse()
77 8
                        ->end()
78 8
                        ->arrayNode('include')
79 8
                            ->addDefaultsIfNotSet()
80 8
                            ->children()
81 8
                                ->arrayNode('directories')
82 8
                                   ->useAttributeAsKey('name')
83 8
                                   ->normalizeKeys(false)
84 8
                                   ->prototype('array')
85 8
                                       ->children()
86 8
                                           ->scalarNode('prefix')->defaultValue('')->end()
87 8
                                           ->scalarNode('suffix')->defaultValue('.php')->end()
88 8
                                       ->end()
89 8
                                   ->end()
90 8
                                ->end()
91 8
                                ->arrayNode('files')
92 8
                                   ->prototype('scalar')->end()
93 8
                                ->end()
94 8
                            ->end()
95 8
                        ->end()
96 8
                        ->arrayNode('exclude')
97 8
                            ->addDefaultsIfNotSet()
98 8
                            ->children()
99 8
                                ->arrayNode('directories')
100 8
                                   ->useAttributeAsKey('name')
101 8
                                   ->normalizeKeys(false)
102 8
                                   ->prototype('array')
103 8
                                       ->children()
104 8
                                           ->scalarNode('prefix')->defaultValue('')->end()
105 8
                                           ->scalarNode('suffix')->defaultValue('.php')->end()
106 8
                                       ->end()
107 8
                                   ->end()
108 8
                                ->end()
109 8
                                ->arrayNode('files')
110 8
                                   ->prototype('scalar')->end()
111 8
                                ->end()
112 8
                            ->end()
113 8
                        ->end()
114 8
                    ->end()
115 8
                ->end()
116 8
                ->arrayNode('reports')
117 8
                    ->children()
118 8
                        ->arrayNode('clover')
119 8
                            ->children()
120 8
                                ->scalarNode('name')->defaultNull()->end()
121 8
                                ->scalarNode('target')->isRequired()->cannotBeEmpty()->end()
122 8
                            ->end()
123 8
                        ->end()
124 8
                        ->arrayNode('crap4j')
125 8
                            ->children()
126 8
                                ->scalarNode('name')->defaultNull()->end()
127 8
                                ->scalarNode('target')->isRequired()->cannotBeEmpty()->end()
128 8
                            ->end()
129 8
                        ->end()
130 8
                        ->arrayNode('html')
131 8
                            ->children()
132 8
                                ->scalarNode('target')->isRequired()->cannotBeEmpty()->end()
133 8
                                ->scalarNode('lowUpperBound')->defaultValue(50)->end()
134 8
                                ->scalarNode('highLowerBound')->defaultValue(90)->end()
135 8
                            ->end()
136 8
                        ->end()
137 8
                        ->arrayNode('php')
138 8
                            ->children()
139 8
                                ->scalarNode('target')->isRequired()->cannotBeEmpty()->end()
140 8
                            ->end()
141 8
                        ->end()
142 8
                        ->arrayNode('text')
143 8
                            ->children()
144 8
                                ->booleanNode('showColors')->defaultValue(false)->end()
145 8
                                ->scalarNode('lowUpperBound')->defaultValue(50)->end()
146 8
                                ->scalarNode('highLowerBound')->defaultValue(90)->end()
147 8
                                ->booleanNode('showOnlySummary')->defaultValue(false)->end()
148 8
                                ->booleanNode('showUncoveredFiles')->defaultValue(false)->end()
149 8
                            ->end()
150 8
                        ->end()
151 8
                        ->arrayNode('xml')
152 8
                            ->children()
153 8
                                ->scalarNode('target')->isRequired()->cannotBeEmpty()->end()
154 8
                            ->end()
155 8
                        ->end()
156 8
                    ->end()
157 8
                ->end()
158 8
            ->end()
159 8
        ->end();
160 8
    }
161
162
    /**
163
     * {@inheritdoc}
164
     */
165 8
    public function getConfigKey()
166
    {
167 8
        return 'code_coverage';
168
    }
169
170
    /**
171
     * {@inheritdoc}
172
     */
173 16
    public function process(ContainerBuilder $container): void
174
    {
175
        /** @var InputInterface $input */
176 16
        $input = $container->get('cli.input');
177
178
        /** @var OutputInterface $output */
179 16
        $output = $container->get('cli.output');
180
181 16
        $filterConfig = $container->getParameter('behat.code_coverage.config.filter');
182 16
        $branchPathConfig = $container->getParameter('behat.code_coverage.config.branchAndPathCoverage');
183
184 16
        $canCollectCodeCoverage = true;
185
        try {
186 16
            $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 12
            $codeCoverageDefinition->setArguments([$filterDefinition, $filterConfig, $branchPathConfig, $output]);
192 4
        } catch (NoCodeCoverageDriverAvailableException $e) {
193 4
            $output->writeln('<comment>No code coverage driver is available</comment>');
194 4
            $canCollectCodeCoverage = false;
195
        }
196
197 16
        if (!$canCollectCodeCoverage || $input->hasParameterOption('--no-coverage')) {
198
            $container->getDefinition(EventSubscriber::class)->setArgument('$coverage', null);
199
        }
200 16
    }
201
202 12
    public function initCodeCoverage(Filter $filter, array $filterConfig, ?bool $branchPathConfig, OutputInterface $output): CodeCoverage
203
    {
204
        // set up filter
205 12
        array_walk($filterConfig['include']['directories'], static function (array $dir, string $path, Filter $filter): void {
206 12
            $filter->includeDirectory($path, $dir['suffix'], $dir['prefix']);
207 12
        }, $filter);
208
209 12
        array_walk($filterConfig['include']['files'], static function (string $file, string $key, Filter $filter): void {
210 12
            $filter->includeFile($file);
211 12
        }, $filter);
212
213 12
        array_walk($filterConfig['exclude']['directories'], static function (array $dir, string $path, Filter $filter): void {
214 12
            $filter->excludeDirectory($path, $dir['suffix'], $dir['prefix']);
215 12
        }, $filter);
216
217 12
        array_walk($filterConfig['exclude']['files'], static function (string $file, string $key, Filter $filter): void {
218 12
            $filter->excludeFile($file);
219 12
        }, $filter);
220
221
        // see if we can get a driver
222 12
        $driver = Driver::forLineCoverage($filter);
223 12
        if ($branchPathConfig !== false) {
224
            try {
225 12
                $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 12
        $codeCoverage = new CodeCoverage($driver, $filter);
236
237 12
        if ($filterConfig['includeUncoveredFiles']) {
238 4
            $codeCoverage->includeUncoveredFiles();
239
        } else {
240 8
            $codeCoverage->excludeUncoveredFiles();
241
        }
242
243 12
        if ($filterConfig['processUncoveredFiles']) {
244 4
            $codeCoverage->processUncoveredFiles();
245
        } else {
246 8
            $codeCoverage->doNotProcessUncoveredFiles();
247
        }
248
249 12
        return $codeCoverage;
250
    }
251
}
252