Passed
Push — master ( bb7edd...36179b )
by Doug
04:09
created

Extension::initialize()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 2
Code Lines 0

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

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

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