Passed
Push — master ( efb190...c1b4c5 )
by Doug
07:59
created

Extension::setupCodeCoverage()   A

Complexity

Conditions 3
Paths 4

Size

Total Lines 20
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 12
CRAP Score 3

Importance

Changes 3
Bugs 0 Features 0
Metric Value
cc 3
eloc 13
nc 4
nop 1
dl 0
loc 20
ccs 12
cts 12
cp 1
crap 3
rs 9.8333
c 3
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 1
 */
35
class Extension implements ExtensionInterface
36
{
37
    /**
38
     * {@inheritdoc}
39 2
     */
40
    public function initialize(ExtensionManager $extensionManager): void
41 2
    {
42
    }
43
44
    /**
45
     * {@inheritdoc}
46 2
     */
47
    public function load(ContainerBuilder $container, array $config): void
48 2
    {
49
        $loader = new XmlFileLoader($container, new FileLocator(__DIR__ . '/Resources/config'));
50 2
51 2
        $servicesFile = 'services.xml';
52
        $loader->load($servicesFile);
53 2
54 2
        $container->setParameter('behat.code_coverage.config.filter', $config['filter']);
55 2
        $container->setParameter('behat.code_coverage.config.reports', $config['reports'] ?? []);
56
    }
57
58
    /**
59
     * {@inheritdoc}
60 4
     */
61
    public function configure(ArrayNodeDefinition $builder): void
62
    {
63 4
        $builder
64 4
            ->children()
65 4
                ->arrayNode('filter')
66 4
                    ->addDefaultsIfNotSet()
67 4
                    ->children()
68 4
                        ->scalarNode('includeUncoveredFiles')
69 4
                            ->defaultTrue()
70 4
                        ->end()
71 4
                        ->scalarNode('processUncoveredFiles')
0 ignored issues
show
Bug introduced by
The method scalarNode() 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

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