Passed
Push — develop ( a4c97f...02f249 )
by ANTHONIUS
04:04
created

Extension::configureReport()   B

Complexity

Conditions 8
Paths 13

Size

Total Lines 39
Code Lines 27

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 19
CRAP Score 9.6648

Importance

Changes 0
Metric Value
eloc 27
c 0
b 0
f 0
dl 0
loc 39
rs 8.4444
ccs 19
cts 27
cp 0.7037
cc 8
nc 13
nop 4
crap 9.6648
1
<?php
2
3
4
namespace Doyo\PhpSpec\CodeCoverage;
5
6
use Doyo\Behat\Coverage\Bridge\CodeCoverage\Driver\Dummy;
7
use Doyo\PhpSpec\CodeCoverage\Listener\CoverageListener;
8
use Doyo\Symfony\Bridge\EventDispatcher\EventDispatcher;
9
use PhpSpec\Extension as BaseExtension;
10
use PhpSpec\ServiceContainer;
11
use SebastianBergmann\CodeCoverage\Driver\PHPDBG;
12
use SebastianBergmann\CodeCoverage\Driver\Xdebug;
13
use SebastianBergmann\CodeCoverage\Filter;
14
use SebastianBergmann\CodeCoverage\Report\Html\Facade;
15
use SebastianBergmann\CodeCoverage\Report\PHP;
16
use SebastianBergmann\Environment\Runtime;
17
use Symfony\Component\Console\Input\InputOption;
18
use Doyo\PhpSpec\CodeCoverage\Processor;
19
20
class Extension implements BaseExtension
21
{
22
    public function load(ServiceContainer $container, array $params)
23
    {
24
        $this->addCoverageOptions($container);
25
        $this->loadCoverageListener($container, $params);
26
    }
27
28 1
    public function addCoverageOptions(ServiceContainer $container)
29
    {
30
        /* @var \PhpSpec\Console\Command\RunCommand $command */
31 1
        $command = $container->get('console.commands.run');
32 1
        $command->addOption(
33 1
            'coverage',
34 1
            null,
35 1
            InputOption::VALUE_NONE,
36 1
            'Run phpspec with code coverage'
37
        );
38
    }
39
40 2
    public function loadCoverageListener(ServiceContainer $container, array $params)
41
    {
42
        /* @var \Symfony\Component\Console\Input\InputInterface $input */
43 2
        $input = $container->get('console.input');
44
45 2
        if(false === $input->hasParameterOption(['--coverage'])){
46 1
            return;
47
        }
48
49 1
        if(static::getDriverClass() === Dummy::class){
50
            /* @var \PhpSpec\Console\ConsoleIO $output */
51
            $output = $container->get('console.io');
52
            $output->writeln('<error>No code coverage driver available</error>');
53
            return;
54
        }
55
56 1
        $this->loadDriver($container, $params);
57 1
        $this->loadFilter($container, $params);
58 1
        $this->loadProcessor($container, $params);
59 1
        $this->loadReports($container, $params);
60 1
        $container->define('doyo.coverage.dispatcher', function($container){
0 ignored issues
show
Unused Code introduced by
The parameter $container is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

60
        $container->define('doyo.coverage.dispatcher', function(/** @scrutinizer ignore-unused */ $container){

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
61
            $dispatcher = new EventDispatcher();
62
63
            return $dispatcher;
64 1
        });
65
66 1
        $container->define('doyo.coverage.listener',function($container){
67
            $dispatcher = $container->get('doyo.coverage.dispatcher');
68
            $consoleIO = $container->get('console.io');
69
            $processor = $container->get('doyo.coverage.processor');
70
            return new CoverageListener($dispatcher, $processor, $consoleIO);
71 1
        }, ['event_dispatcher.listeners']);
72
73 1
        $reports = $container->getByTag('doyo.coverage.reports');
74 1
        $dispatcher = $container->get('doyo.coverage.dispatcher');
75 1
        foreach($reports as $report){
76 1
            $dispatcher->addSubscriber($report);
77
        }
78
    }
79
80 1
    public static function getDriverClass()
81
    {
82 1
        static $runtime;
83 1
        if(!$runtime instanceof Runtime){
84
            $runtime = new Runtime();
85
        }
86
87 1
        $driverClass = Dummy::class;
88 1
        if($runtime->canCollectCodeCoverage()){
89 1
            if($runtime->isPHPDBG()){
90 1
                $driverClass = PHPDBG::class;
91
            }else{
92
                $driverClass = Xdebug::class;
93
            }
94
        }
95
96 1
        return $driverClass;
97
    }
98
99 1
    private function loadDriver(ServiceContainer $container, array $params)
100
    {
101 1
        $driverClass = static::getDriverClass();
102 1
        $container->define('doyo.coverage.driver', function() use ($params, $driverClass){
0 ignored issues
show
Unused Code introduced by
The import $params is not used and could be removed.

This check looks for imports that have been defined, but are not used in the scope.

Loading history...
103
            return new $driverClass;
104 1
        });
105
    }
106
107
    private function loadFilter(ServiceContainer $container, array $params)
108
    {
109 1
        $container->define('doyo.coverage.filter', function() use ($params){
110
            $filters = $params['filters'] ?:[];
111
            $whitelist = isset($filters['whitelist']) ? $filters['whitelist']:[];
112
            $blacklist = isset($filters['blacklist']) ? $filters['blacklist']:[];
113
            $filter = new Filter();
114
115
            foreach($whitelist as $dir){
116
                $filter->addDirectoryToWhitelist($dir);
117
            }
118
119
            foreach($blacklist as $dir){
120
                $filter->removeDirectoryFromWhitelist($dir);
121
            }
122
123
            return $filter;
124 1
        });
125
    }
126
127
    private function loadProcessor(ServiceContainer $container, array $params)
128
    {
129 1
        $container->define('doyo.coverage.processor', function($container) use ($params){
0 ignored issues
show
Unused Code introduced by
The import $params is not used and could be removed.

This check looks for imports that have been defined, but are not used in the scope.

Loading history...
130
            $driver = $container->get('doyo.coverage.driver');
131
            $filter = $container->get('doyo.coverage.filter');
132
            $processor = new Processor($driver, $filter);
133
134
            return $processor;
135 1
        });
136
    }
137
138 1
    private function loadReports(ServiceContainer $container, array $params)
139
    {
140
        $reports = [
141 1
            'html' => Facade::class,
142
            'php' => PHP::class
143
        ];
144
145 1
        $reportConfig = isset($params['reports']) ? $params['reports']:[];
146 1
        foreach($reports as $type => $class){
147 1
            $this->configureReport($container, $reportConfig, $type, $class);
148
        }
149
    }
150
151 1
    private function configureReport(ServiceContainer $container, array $reportConfig, $type, $class)
152
    {
153 1
        if(!isset($reportConfig[$type])){
154
            return;
155
        }
156
157 1
        $dirTypes = ['html'];
158 1
        $fsType = in_array($type, $dirTypes) ? 'dir':'file';
159 1
        $options = array();
160 1
        $test = $reportConfig[$type];
161
162 1
        if(is_string($test)){
163 1
            $options['target'] = $test;
164
        }else{
165
            $options = $reportConfig[$type];
166
        }
167
168 1
        $options['type'] = $fsType;
169 1
        $r = new \ReflectionClass($class);
170 1
        $constructorParams = [];
171
172 1
        if(!is_null($r->getConstructor())){
173 1
            foreach($r->getConstructor()->getParameters() as $parameter){
174 1
                $name = $parameter->getName();
175 1
                if($parameter->isDefaultValueAvailable()){
176 1
                    break;
177
                }
178
                $default = $parameter->getDefaultValue();
179
                $constructorParams[] = isset($options[$name]) ? $options[$name]:$default;
180
            }
181
        }
182
183 1
        $id = 'doyo.coverage.reports.'.$type;
184 1
        $container->define($id, function($container) use ($class, $constructorParams, $options){
0 ignored issues
show
Unused Code introduced by
The parameter $container is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

184
        $container->define($id, function(/** @scrutinizer ignore-unused */ $container) use ($class, $constructorParams, $options){

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
185
            $r = new \ReflectionClass($class);
186
            $processor = $r->newInstanceArgs($constructorParams);
187
            $report = new Report($processor, $options);
188
            return $report;
189 1
        },['doyo.coverage.reports']);
190
    }
191
}