Passed
Push — master ( 835bd0...7384e9 )
by Doug
18:54 queued 04:22
created

Extension::initCodeCoverage()   A

Complexity

Conditions 4
Paths 8

Size

Total Lines 42
Code Lines 26

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 24
CRAP Score 4

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 4
eloc 26
c 1
b 0
f 0
nc 8
nop 2
dl 0
loc 42
ccs 24
cts 24
cp 1
crap 4
rs 9.504
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 1
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.reports', $config['reports'] ?? []);
56 2
    }
57
58
    /**
59
     * {@inheritdoc}
60
     */
61 4
    public function configure(ArrayNodeDefinition $builder): void
62
    {
63
        $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 4
    }
157
158
    /**
159
     * {@inheritdoc}
160
     */
161 4
    public function getConfigKey()
162
    {
163 4
        return 'code_coverage';
164
    }
165
166
    /**
167
     * {@inheritdoc}
168
     */
169 8
    public function process(ContainerBuilder $container): void
170
    {
171
        /** @var InputInterface $input */
172 8
        $input = $container->get('cli.input');
173
174
        /** @var OutputInterface $output */
175 8
        $output = $container->get('cli.output');
176
177 8
        $config = $container->getParameter('behat.code_coverage.config.filter');
178
179 8
        $canCollectCodeCoverage = true;
180
        try {
181 8
            $this->initCodeCoverage(new Filter(), $config);
182
183 6
            $codeCoverage = $container->getDefinition(CodeCoverage::class);
184 6
            $filter = $container->getDefinition(Filter::class);
185 6
            $codeCoverage->setFactory([new Reference(self::class), 'initCodeCoverage']);
186 6
            $codeCoverage->setArguments([$filter, $config]);
187 2
        } catch (NoCodeCoverageDriverAvailableException $e) {
188 2
            $output->writeln('<comment>No code coverage driver is available</comment>');
189 2
            $canCollectCodeCoverage = false;
190
        }
191
192 8
        if (!$canCollectCodeCoverage || $input->hasParameterOption('--no-coverage')) {
193 4
            $container->getDefinition(EventSubscriber::class)->setArgument('$coverage', null);
194
        }
195 8
    }
196
197 6
    public function initCodeCoverage(Filter $filter, array $config): CodeCoverage
198
    {
199
        // set up filter
200 6
        array_walk($config['include']['directories'], static function ($dir, $path, $filter): void {
201 6
            $filter->includeDirectory($path, $dir['suffix'], $dir['prefix']);
202 6
        }, $filter);
203
204 6
        array_walk($config['include']['files'], static function ($file, $key, $filter): void {
205 6
            $filter->includeFile($file);
206 6
        }, $filter);
207
208 6
        array_walk($config['exclude']['directories'], static function ($dir, $path, $filter): void {
209 6
            $filter->excludeDirectory($path, $dir['suffix'], $dir['prefix']);
210 6
        }, $filter);
211
212 6
        array_walk($config['exclude']['files'], static function ($file, $key, $filter): void {
213 6
            $filter->excludeFile($file);
214 6
        }, $filter);
215
216
        // see if we can get a driver
217
        try {
218 6
            $driver = Driver::forLineAndPathCoverage($filter);
219 3
        } catch (NoCodeCoverageDriverWithPathCoverageSupportAvailableException $e) {
220 3
            $driver = Driver::forLineCoverage($filter);
221
        }
222
223
        // and init coverage
224 6
        $codeCoverage = new CodeCoverage($driver, $filter);
225
226 6
        if ($config['includeUncoveredFiles']) {
227 2
            $codeCoverage->includeUncoveredFiles();
228
        } else {
229 4
            $codeCoverage->excludeUncoveredFiles();
230
        }
231
232 6
        if ($config['processUncoveredFiles']) {
233 2
            $codeCoverage->processUncoveredFiles();
234
        } else {
235 4
            $codeCoverage->doNotProcessUncoveredFiles();
236
        }
237
238 6
        return $codeCoverage;
239
    }
240
}
241