Passed
Push — master ( 1280f5...efb190 )
by Doug
03:15
created

Extension::__construct()   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 1
Bugs 0 Features 0
Metric Value
eloc 1
c 1
b 0
f 0
dl 0
loc 3
ccs 2
cts 2
cp 1
rs 10
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\NoCodeCoverageDriverWithPathCoverageSupportAvailableException;
21
use SebastianBergmann\Environment\Runtime;
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
29
/**
30
 * Code coverage extension.
31
 *
32
 * @author Anthon Pang <[email protected]>
33
 */
34 1
class Extension implements ExtensionInterface
35
{
36
    /**
37
     * {@inheritdoc}
38
     */
39 2
    public function initialize(ExtensionManager $extensionManager): void
40
    {
41 2
    }
42
43
    /**
44
     * {@inheritdoc}
45
     */
46 2
    public function load(ContainerBuilder $container, array $config): void
47
    {
48 2
        $loader = new XmlFileLoader($container, new FileLocator(__DIR__ . '/Resources/config'));
49
50 2
        $servicesFile = 'services.xml';
51 2
        $loader->load($servicesFile);
52
53 2
        $container->setParameter('behat.code_coverage.config.filter', $config['filter']);
54 2
        $container->setParameter('behat.code_coverage.config.reports', $config['reports'] ?? []);
55 2
    }
56
57
    /**
58
     * {@inheritdoc}
59
     */
60 4
    public function configure(ArrayNodeDefinition $builder): void
61
    {
62
        $builder
63 4
            ->children()
64 4
                ->arrayNode('filter')
65 4
                    ->addDefaultsIfNotSet()
66 4
                    ->children()
67 4
                        ->scalarNode('includeUncoveredFiles')
68 4
                            ->defaultTrue()
69 4
                        ->end()
70 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

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