Passed
Push — master ( 5bf230...aa1843 )
by Doug
07:19
created

Extension::process()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 11
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 0
Metric Value
eloc 7
c 0
b 0
f 0
dl 0
loc 11
ccs 0
cts 8
cp 0
rs 10
cc 2
nc 2
nop 1
crap 6
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 Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition;
17
use Symfony\Component\Config\FileLocator;
18
use Symfony\Component\DependencyInjection\ContainerBuilder;
19
use Symfony\Component\DependencyInjection\Loader\XmlFileLoader;
20
use Symfony\Component\DependencyInjection\Reference;
21
22
/**
23
 * Code coverage extension.
24
 *
25
 * @author Anthon Pang <[email protected]>
26
 */
27
class Extension implements ExtensionInterface
28
{
29
    /**
30
     * @var string
31
     */
32
    private $configFolder;
33
34
    /**
35
     * Constructor.
36
     *
37
     * @param string $configFolder
38
     */
39
    public function __construct($configFolder = null)
40
    {
41
        $this->configFolder = $configFolder ?: __DIR__ . '/Resources/config';
42
    }
43
44
    /**
45
     * {@inheritdoc}
46
     */
47
    public function initialize(ExtensionManager $extensionManager): void
48
    {
49
    }
50
51
    /**
52
     * {@inheritdoc}
53
     */
54
    public function load(ContainerBuilder $container, array $config): void
55
    {
56
        $loader = new XmlFileLoader($container, new FileLocator($this->configFolder));
57
58
        $servicesFile = 'services.xml';
59
        $loader->load($servicesFile);
60
61
        if (!isset($config['auth']['user']) || !isset($config['auth']['password'])) {
62
            $config['auth'] = null;
63
        }
64
65
        if (!count($config['drivers'])) {
66
            $config['drivers'] = ['local'];
67
        }
68
69
        if (!count($config['report']['options'])) {
70
            $config['report']['options'] = [
71
                'target' => '/tmp',
72
            ];
73
        }
74
75
        if (!$container->hasParameter('mink.base_url')) {
76
            $container->setParameter('mink.base_url', null);
77
        }
78
79
        $container->setParameter('behat.code_coverage.config.auth', $config['auth']);
80
        $container->setParameter('behat.code_coverage.config.create', $config['create']);
81
        $container->setParameter('behat.code_coverage.config.read', $config['read']);
82
        $container->setParameter('behat.code_coverage.config.delete', $config['delete']);
83
        $container->setParameter('behat.code_coverage.config.drivers', $config['drivers']);
84
        $container->setParameter('behat.code_coverage.config.filter', $config['filter']);
85
        $container->setParameter('behat.code_coverage.config.report', $config['report'] ?? []);
86
        $container->setParameter('behat.code_coverage.config.reports', $config['reports'] ?? []);
87
    }
88
89
    /**
90
     * {@inheritdoc}
91
     */
92
    public function configure(ArrayNodeDefinition $builder): void
93
    {
94
        $builder
95
            ->children()
96
                ->arrayNode('auth')
97
                    ->children()
98
                        ->scalarNode('user')->end()
99
                        ->scalarNode('password')->end()
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

99
                        ->/** @scrutinizer ignore-call */ scalarNode('password')->end()
Loading history...
100
                    ->end()
101
                ->end()
102
                ->arrayNode('create')
103
                    ->addDefaultsIfNotSet()
104
                    ->children()
105
                        ->scalarNode('method')->defaultValue('POST')->end()
106
                        ->scalarNode('path')->defaultValue('/')->end()
107
                    ->end()
108
                ->end()
109
                ->arrayNode('read')
110
                    ->addDefaultsIfNotSet()
111
                    ->children()
112
                        ->scalarNode('method')->defaultValue('GET')->end()
113
                        ->scalarNode('path')->defaultValue('/')->end()
114
                    ->end()
115
                ->end()
116
                ->arrayNode('delete')
117
                    ->addDefaultsIfNotSet()
118
                    ->children()
119
                        ->scalarNode('method')->defaultValue('DELETE')->end()
120
                        ->scalarNode('path')->defaultValue('/')->end()
121
                    ->end()
122
                ->end()
123
                ->arrayNode('drivers')
124
                    ->prototype('scalar')->end()
125
                ->end()
126
                ->arrayNode('filter')
127
                    ->addDefaultsIfNotSet()
128
                    ->children()
129
                        ->scalarNode('forceCoversAnnotation')
130
                            ->defaultFalse()
131
                        ->end()
132
                        ->scalarNode('mapTestClassNameToCoveredClassName')
133
                            ->defaultFalse()
134
                        ->end()
135
                        ->arrayNode('whitelist')
136
                            ->addDefaultsIfNotSet()
137
                            ->children()
138
                                ->scalarNode('addUncoveredFilesFromWhitelist')
139
                                    ->defaultTrue()
140
                                ->end()
141
                                ->scalarNode('processUncoveredFilesFromWhitelist')
142
                                    ->defaultFalse()
143
                                ->end()
144
                                ->arrayNode('include')
145
                                    ->addDefaultsIfNotSet()
146
                                    ->children()
147
                                        ->arrayNode('directories')
148
                                           ->useAttributeAsKey('name')
149
                                           ->normalizeKeys(false)
150
                                           ->prototype('array')
151
                                               ->children()
152
                                                   ->scalarNode('prefix')->defaultValue('')->end()
153
                                                   ->scalarNode('suffix')->defaultValue('.php')->end()
154
                                               ->end()
155
                                           ->end()
156
                                        ->end()
157
                                        ->arrayNode('files')
158
                                           ->prototype('scalar')->end()
159
                                        ->end()
160
                                    ->end()
161
                                ->end()
162
                                ->arrayNode('exclude')
163
                                    ->addDefaultsIfNotSet()
164
                                    ->children()
165
                                        ->arrayNode('directories')
166
                                           ->useAttributeAsKey('name')
167
                                           ->normalizeKeys(false)
168
                                           ->prototype('array')
169
                                               ->children()
170
                                                   ->scalarNode('prefix')->defaultValue('')->end()
171
                                                   ->scalarNode('suffix')->defaultValue('.php')->end()
172
                                               ->end()
173
                                           ->end()
174
                                        ->end()
175
                                        ->arrayNode('files')
176
                                           ->prototype('scalar')->end()
177
                                        ->end()
178
                                    ->end()
179
                                ->end()
180
                            ->end()
181
                        ->end()
182
                    ->end()
183
                ->end()
184
                ->arrayNode('report')
185
                    ->setDeprecated('The "report" option is deprecated. Use "reports" instead.')
186
                    ->children()
187
                        ->scalarNode('format')->defaultValue('html')->end()
188
                        ->arrayNode('options')
189
                            ->useAttributeAsKey('name')
190
                            ->prototype('scalar')->end()
191
                        ->end()
192
                    ->end()
193
                ->end()
194
                ->arrayNode('reports')
195
                    ->children()
196
                        ->arrayNode('clover')
197
                            ->children()
198
                                ->scalarNode('name')->end()
199
                                ->scalarNode('target')->end()
200
                            ->end()
201
                        ->end()
202
                        ->arrayNode('crap4j')
203
                            ->children()
204
                                ->scalarNode('name')->end()
205
                                ->scalarNode('target')->end()
206
                            ->end()
207
                        ->end()
208
                        ->arrayNode('html')
209
                            ->children()
210
                                ->scalarNode('target')->end()
211
                                ->scalarNode('lowUpperBound')->end()
212
                                ->scalarNode('highLowerBound')->end()
213
                            ->end()
214
                        ->end()
215
                        ->arrayNode('php')
216
                            ->children()
217
                                ->scalarNode('target')->end()
218
                            ->end()
219
                        ->end()
220
                        ->arrayNode('text')
221
                            ->children()
222
                                ->booleanNode('showColors')->end()
223
                                ->scalarNode('lowUpperBound')->end()
224
                                ->scalarNode('highLowerBound')->end()
225
                                ->booleanNode('showOnlySummary')->end()
226
                                ->booleanNode('showUncoveredFiles')->end()
227
                            ->end()
228
                        ->end()
229
                        ->arrayNode('xml')
230
                            ->children()
231
                                ->scalarNode('target')->end()
232
                            ->end()
233
                        ->end()
234
                    ->end()
235
                ->end()
236
            ->end()
237
        ->end();
238
    }
239
240
    /**
241
     * {@inheritdoc}
242
     */
243
    public function getConfigKey()
244
    {
245
        return 'code_coverage';
246
    }
247
248
    /**
249
     * {@inheritdoc}
250
     */
251
    public function process(ContainerBuilder $container): void
252
    {
253
        $input = $container->get('cli.input');
254
        if ($input->hasParameterOption('--no-coverage')) {
255
            $container->getParameterBag()->set('behat.code_coverage.skip', true);
256
        }
257
258
        $this->setupDriver($container);
259
        $this->setupFactory($container);
260
        $this->setupCodeCoverage($container);
261
        $this->setupCodeCoverageFilter($container);
262
    }
263
264
    private function setupDriver(ContainerBuilder $container): void
265
    {
266
        if (!$container->hasDefinition('behat.code_coverage.driver.proxy')) {
267
            return;
268
        }
269
270
        $proxy = $container->getDefinition('behat.code_coverage.driver.proxy');
271
        $enabled = $container->getParameter('behat.code_coverage.config.drivers');
272
273
        foreach ($container->findTaggedServiceIds('behat.code_coverage.driver') as $id => $tagAttributes) {
274
            foreach ($tagAttributes as $attributes) {
275
                if (isset($attributes['alias'])
276
                    && in_array($attributes['alias'], $enabled)
277
                ) {
278
                    $proxy->addMethodCall('addDriver', [new Reference($id)]);
279
                }
280
            }
281
        }
282
    }
283
284
    public function setupFactory(ContainerBuilder $container): void
285
    {
286
        if (!$container->hasDefinition('dvdoug.code_coverage.driver.factory')) {
287
            return;
288
        }
289
290
        $factory = $container->getDefinition('dvdoug.code_coverage.driver.factory');
291
        $drivers = [];
292
        $ids = $container->findTaggedServiceIds('dvdoug.code_coverage.driver');
293
294
        foreach ($ids as $id => $attributes) {
295
            $drivers[] = $container->getDefinition($id)->getClass();
296
        }
297
298
        $factory->setArguments([$drivers]);
299
    }
300
301
    private function setupCodeCoverage(ContainerBuilder $container): void
302
    {
303
        if (!$container->hasDefinition('behat.code_coverage.php_code_coverage')) {
304
            return;
305
        }
306
307
        $coverage = $container->getDefinition('behat.code_coverage.php_code_coverage');
308
        $config = $container->getParameter('behat.code_coverage.config.filter');
309
310
        $coverage->addMethodCall(
311
            'setAddUncoveredFilesFromWhitelist',
312
            [$config['whitelist']['addUncoveredFilesFromWhitelist']]
313
        );
314
        $coverage->addMethodCall(
315
            'setProcessUncoveredFilesFromWhiteList',
316
            [$config['whitelist']['processUncoveredFilesFromWhitelist']]
317
        );
318
        $coverage->addMethodCall(
319
            'setForceCoversAnnotation',
320
            [$config['forceCoversAnnotation']]
321
        );
322
    }
323
324
    private function setupCodeCoverageFilter(ContainerBuilder $container): void
325
    {
326
        if (!$container->hasDefinition('behat.code_coverage.php_code_coverage_filter')) {
327
            return;
328
        }
329
330
        $filter = $container->getDefinition('behat.code_coverage.php_code_coverage_filter');
331
        $config = $container->getParameter('behat.code_coverage.config.filter');
332
333
        $dirs = [
334
            'addDirectoryToWhiteList' => ['whitelist', 'include', 'directories'],
335
            'removeDirectoryFromWhiteList' => ['whitelist', 'exclude', 'directories'],
336
        ];
337
338
        foreach ($dirs as $method => $hiera) {
339
            foreach ($config[$hiera[0]][$hiera[1]][$hiera[2]] as $path => $dir) {
340
                $filter->addMethodCall($method, [$path, $dir['suffix'], $dir['prefix']]);
341
            }
342
        }
343
344
        $files = [
345
            'addFileToWhiteList' => ['whitelist', 'include', 'files'],
346
            'removeFileFromWhiteList' => ['whitelist', 'exclude', 'files'],
347
        ];
348
349
        foreach ($files as $method => $hiera) {
350
            foreach ($config[$hiera[0]][$hiera[1]][$hiera[2]] as $file) {
351
                $filter->addMethodCall($method, [$file]);
352
            }
353
        }
354
    }
355
}
356