Passed
Push — master ( dc8587...0d4285 )
by Doug
03:53
created

Extension::configure()   B

Complexity

Conditions 1
Paths 1

Size

Total Lines 119
Code Lines 117

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 118
CRAP Score 1

Importance

Changes 7
Bugs 0 Features 0
Metric Value
cc 1
eloc 117
nc 1
nop 1
dl 0
loc 119
ccs 118
cts 118
cp 1
crap 1
rs 8
c 7
b 0
f 0

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
/**
3
 * Behat Code Coverage
4
 */
5
declare(strict_types=1);
6
7
namespace DVDoug\Behat\CodeCoverage;
8
9
use Behat\Testwork\Cli\Controller;
10
use Behat\Testwork\Cli\ServiceContainer\CliExtension;
11
use Behat\Testwork\EventDispatcher\ServiceContainer\EventDispatcherExtension;
12
use Behat\Testwork\ServiceContainer\Extension as ExtensionInterface;
13
use Behat\Testwork\ServiceContainer\ExtensionManager;
14
use Composer\InstalledVersions;
15
use Composer\Semver\VersionParser;
16
use DVDoug\Behat\CodeCoverage\Subscriber\EventSubscriber;
17
use SebastianBergmann\CodeCoverage\CodeCoverage;
18
use SebastianBergmann\CodeCoverage\Driver\Selector;
19
use SebastianBergmann\CodeCoverage\Driver\XdebugNotAvailableException;
20
use SebastianBergmann\CodeCoverage\Driver\XdebugNotEnabledException;
21
use SebastianBergmann\CodeCoverage\Filter;
22
use SebastianBergmann\CodeCoverage\NoCodeCoverageDriverAvailableException;
23
use SebastianBergmann\CodeCoverage\NoCodeCoverageDriverWithPathCoverageSupportAvailableException;
24
use SebastianBergmann\FileIterator\Facade as FileIteratorFacade;
25
use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition;
26
use Symfony\Component\Config\FileLocator;
27
use Symfony\Component\Console\Input\InputInterface;
28
use Symfony\Component\Console\Output\OutputInterface;
29
use Symfony\Component\DependencyInjection\ContainerBuilder;
30
use Symfony\Component\DependencyInjection\Loader\PhpFileLoader;
31
use Symfony\Component\DependencyInjection\Reference;
32
33
use function sprintf;
34
use function sys_get_temp_dir;
35
use function realpath;
36
37
class Extension implements ExtensionInterface
38
{
39 36
    public function initialize(ExtensionManager $extensionManager): void
40
    {
41 36
    }
42
43 36
    public function load(ContainerBuilder $container, array $config): void
44
    {
45 36
        $container->registerForAutoconfiguration(Controller::class)->addTag(CliExtension::CONTROLLER_TAG);
46 36
        $container->registerForAutoconfiguration(EventSubscriber::class)->addTag(EventDispatcherExtension::SUBSCRIBER_TAG);
47
48 36
        $loader = new PhpFileLoader($container, new FileLocator(__DIR__ . '/../config'));
49 36
        $loader->load('services.php');
50
51 36
        $container->setParameter('behat.code_coverage.config.filter', $config['filter']);
52 36
        $container->setParameter('behat.code_coverage.config.branchAndPathCoverage', $config['branchAndPathCoverage']);
53 36
        $container->setParameter('behat.code_coverage.config.reports', $config['reports'] ?? []);
54 36
        $container->setParameter('behat.code_coverage.config.cache', $config['cache']);
55
    }
56
57 72
    public function configure(ArrayNodeDefinition $builder): void
58
    {
59 72
        $builder
60 72
            ->children()
61 72
                ->scalarNode('cache')
62 72
                    ->defaultValue(sys_get_temp_dir() . '/behat-code-coverage-cache')
63 72
                ->end()
64 72
                ->booleanNode('branchAndPathCoverage')
0 ignored issues
show
Bug introduced by
The method booleanNode() 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

64
                ->/** @scrutinizer ignore-call */ booleanNode('branchAndPathCoverage')
Loading history...
65 72
                  ->defaultNull() // use null to mean auto
66 72
                ->end()
67 72
                ->arrayNode('filter')
68 72
                    ->addDefaultsIfNotSet()
69 72
                    ->children()
70 72
                        ->scalarNode('includeUncoveredFiles')
71 72
                            ->defaultTrue()
72 72
                        ->end()
73 72
                        ->scalarNode('processUncoveredFiles')
74 72
                            ->defaultFalse()
75 72
                            ->setDeprecated('dvdoug/behat-code-coverage', '5.3', 'the processUncoveredFiles setting is deprecated, it has been removed from php-code-coverage v10')
76 72
                        ->end()
77 72
                        ->arrayNode('include')
78 72
                            ->addDefaultsIfNotSet()
79 72
                            ->children()
80 72
                                ->arrayNode('directories')
81 72
                                   ->useAttributeAsKey('name')
82 72
                                   ->normalizeKeys(false)
83 72
                                   ->prototype('array')
84 72
                                       ->children()
85 72
                                           ->scalarNode('prefix')->defaultValue('')->end()
86 72
                                           ->scalarNode('suffix')->defaultValue('.php')->end()
87 72
                                       ->end()
88 72
                                   ->end()
89 72
                                ->end()
90 72
                                ->arrayNode('files')
91 72
                                   ->prototype('scalar')->end()
92 72
                                ->end()
93 72
                            ->end()
94 72
                        ->end()
95 72
                        ->arrayNode('exclude')
96 72
                            ->addDefaultsIfNotSet()
97 72
                            ->children()
98 72
                                ->arrayNode('directories')
99 72
                                   ->useAttributeAsKey('name')
100 72
                                   ->normalizeKeys(false)
101 72
                                   ->prototype('array')
102 72
                                       ->children()
103 72
                                           ->scalarNode('prefix')->defaultValue('')->end()
104 72
                                           ->scalarNode('suffix')->defaultValue('.php')->end()
105 72
                                       ->end()
106 72
                                   ->end()
107 72
                                ->end()
108 72
                                ->arrayNode('files')
109 72
                                   ->prototype('scalar')->end()
110 72
                                ->end()
111 72
                            ->end()
112 72
                        ->end()
113 72
                    ->end()
114 72
                ->end()
115 72
                ->arrayNode('reports')
116 72
                    ->children()
117 72
                        ->arrayNode('cobertura')
118 72
                            ->children()
119 72
                                ->scalarNode('name')->defaultNull()->end()
120 72
                                ->scalarNode('target')->isRequired()->cannotBeEmpty()->end()
121 72
                            ->end()
122 72
                        ->end()
123 72
                        ->arrayNode('clover')
124 72
                            ->children()
125 72
                                ->scalarNode('name')->defaultNull()->end()
126 72
                                ->scalarNode('target')->isRequired()->cannotBeEmpty()->end()
127 72
                            ->end()
128 72
                        ->end()
129 72
                        ->arrayNode('crap4j')
130 72
                            ->children()
131 72
                                ->scalarNode('name')->defaultNull()->end()
132 72
                                ->scalarNode('target')->isRequired()->cannotBeEmpty()->end()
133 72
                            ->end()
134 72
                        ->end()
135 72
                        ->arrayNode('html')
136 72
                            ->children()
137 72
                                ->scalarNode('target')->isRequired()->cannotBeEmpty()->end()
138 72
                                ->scalarNode('lowUpperBound')->defaultValue(50)->end()
139 72
                                ->scalarNode('highLowerBound')->defaultValue(90)->end()
140 72
                                ->arrayNode('colors')
141 72
                                    ->addDefaultsIfNotSet()
142 72
                                    ->children()
143 72
                                        ->scalarNode('successLow')->defaultValue('#dff0d8')->end()
144 72
                                        ->scalarNode('successMedium')->defaultValue('#c3e3b5')->end()
145 72
                                        ->scalarNode('successHigh')->defaultValue('#99cb84')->end()
146 72
                                        ->scalarNode('warning')->defaultValue('#fcf8e3')->end()
147 72
                                        ->scalarNode('danger')->defaultValue('#f2dede')->end()
148 72
                                    ->end()
149 72
                                ->end()
150 72
                                ->scalarNode('customCSSFile')->defaultNull()->end()
151 72
                            ->end()
152 72
                        ->end()
153 72
                        ->arrayNode('php')
154 72
                            ->children()
155 72
                                ->scalarNode('target')->isRequired()->cannotBeEmpty()->end()
156 72
                            ->end()
157 72
                        ->end()
158 72
                        ->arrayNode('text')
159 72
                            ->children()
160 72
                                ->booleanNode('showColors')->defaultValue(false)->end()
161 72
                                ->scalarNode('lowUpperBound')->defaultValue(50)->end()
162 72
                                ->scalarNode('highLowerBound')->defaultValue(90)->end()
163 72
                                ->booleanNode('showOnlySummary')->defaultValue(false)->end()
164 72
                                ->booleanNode('showUncoveredFiles')->defaultValue(false)->end()
165 72
                            ->end()
166 72
                        ->end()
167 72
                        ->arrayNode('xml')
168 72
                            ->children()
169 72
                                ->scalarNode('target')->isRequired()->cannotBeEmpty()->end()
170 72
                            ->end()
171 72
                        ->end()
172 72
                    ->end()
173 72
                ->end()
174 72
            ->end()
175 72
        ->end();
176
    }
177
178 72
    public function getConfigKey()
179
    {
180 72
        return 'code_coverage';
181
    }
182
183 144
    public function process(ContainerBuilder $container): void
184
    {
185
        /** @var InputInterface $input */
186 144
        $input = $container->get(CliExtension::INPUT_ID);
187
188
        /** @var OutputInterface $output */
189 144
        $output = $container->get(CliExtension::OUTPUT_ID);
190
191 144
        $filterConfig = $container->getParameter('behat.code_coverage.config.filter');
192 144
        $branchPathConfig = $container->getParameter('behat.code_coverage.config.branchAndPathCoverage');
193 144
        $cacheDir = $container->getParameter('behat.code_coverage.config.cache');
194
195 144
        $canCollectCodeCoverage = true;
196
        try {
197 144
            $this->initCodeCoverage(new Filter(), $filterConfig, null, $cacheDir, $output);
198
199 108
            $codeCoverageDefinition = $container->getDefinition(CodeCoverage::class);
200 108
            $filterDefinition = $container->getDefinition(Filter::class);
201 108
            $codeCoverageDefinition->setFactory([new Reference(self::class), 'initCodeCoverage']);
202 108
            $codeCoverageDefinition->setArguments([$filterDefinition, $filterConfig, $branchPathConfig, $cacheDir, $output]);
203 36
        } catch (NoCodeCoverageDriverAvailableException|XdebugNotEnabledException|XdebugNotAvailableException $e) {
204 36
            $output->writeln("<comment>No code coverage driver is available. {$e->getMessage()}</comment>");
205 36
            $canCollectCodeCoverage = false;
206
        }
207
208 144
        if (!$canCollectCodeCoverage || $input->hasParameterOption('--no-coverage')) {
209 72
            $container->getDefinition(EventSubscriber::class)->setArgument('$coverage', null);
210
        }
211
    }
212
213 108
    public function initCodeCoverage(Filter $filter, array $filterConfig, ?bool $branchPathConfig, string $cacheDir, OutputInterface $output): CodeCoverage
214
    {
215
        // set up filter
216 108
        $files = [];
217
218 108
        foreach ($filterConfig['include']['directories'] as $directoryToInclude => $details) {
219 108
            foreach ((new FileIteratorFacade())->getFilesAsArray($directoryToInclude, $details['suffix'], $details['prefix']) as $fileToInclude) {
220
                $files[realpath($fileToInclude)] = realpath($fileToInclude);
221
            }
222
        }
223
224 108
        foreach ($filterConfig['include']['files'] as $fileToInclude) {
225 108
            $files[$fileToInclude] = $fileToInclude;
226
        }
227
228 108
        foreach ($filterConfig['exclude']['directories'] as $directoryToExclude => $details) {
229 108
            foreach ((new FileIteratorFacade())->getFilesAsArray($directoryToExclude, $details['suffix'], $details['prefix']) as $fileToExclude) {
230
                unset($files[$fileToExclude]);
231
            }
232
        }
233
234 108
        foreach ($filterConfig['exclude']['files'] as $fileToExclude) {
235 108
            unset($files[realpath($fileToExclude)]);
236
        }
237
238 108
        foreach ($files as $file) {
239 108
            $filter->includeFile($file);
240
        }
241
242
        // see if we can get a driver
243 108
        $selector = new Selector();
244 108
        $driver = $selector->forLineCoverage($filter);
245 108
        if ($branchPathConfig !== false) {
246
            try {
247 108
                $driver = $selector->forLineAndPathCoverage($filter);
248 54
            } catch (NoCodeCoverageDriverWithPathCoverageSupportAvailableException|XdebugNotAvailableException|XdebugNotEnabledException $e) {
249
                // fallback driver is already set
250 54
                if ($branchPathConfig === true) { // only warn if explicitly enabled
0 ignored issues
show
introduced by
The condition $branchPathConfig === true is always true.
Loading history...
251 18
                    $output->writeln(sprintf('<info>%s does not support collecting branch and path data</info>', $driver->nameAndVersion()));
252
                }
253
            }
254
        }
255
256
        // and init coverage
257 108
        $codeCoverage = new CodeCoverage($driver, $filter);
258 108
        $codeCoverage->cacheStaticAnalysis($cacheDir);
259
260 108
        if ($filterConfig['includeUncoveredFiles']) {
261 36
            $codeCoverage->includeUncoveredFiles();
262
        } else {
263 72
            $codeCoverage->excludeUncoveredFiles();
264
        }
265
266 108
        return $codeCoverage;
267
    }
268
}
269