Completed
Push — master ( 7ec665...146f6b )
by personal
08:22 queued 05:17
created

RunMetricsCommand   B

Complexity

Total Complexity 11

Size/Duplication

Total Lines 148
Duplicated Lines 0 %

Coupling/Cohesion

Components 0
Dependencies 16

Importance

Changes 7
Bugs 3 Features 3
Metric Value
wmc 11
c 7
b 3
f 3
lcom 0
cbo 16
dl 0
loc 148
rs 8.4614

2 Methods

Rating   Name   Duplication   Size   Complexity  
A configure() 0 64 1
C execute() 0 73 10
1
<?php
2
3
/*
4
 * (c) Jean-François Lépine <https://twitter.com/Halleck45>
5
 *
6
 * For the full copyright and license information, please view the LICENSE
7
 * file that was distributed with this source code.
8
 */
9
10
namespace Hal\Application\Command;
11
use Hal\Application\Command\Job\QueueAnalyzeFactory;
12
use Hal\Application\Command\Job\QueueFactory;
13
use Hal\Application\Command\Job\QueueReportFactory;
14
use Hal\Application\Config\ConfigFactory;
15
use Hal\Application\Extension\ExtensionService;
16
use Hal\Application\Extension\Repository;
17
use Hal\Component\Bounds\Bounds;
18
use Hal\Component\Evaluation\Evaluator;
19
use Hal\Component\File\Finder;
20
use Hal\Component\Result\ResultCollection;
21
use Symfony\Component\Console\Command\Command;
22
use Symfony\Component\Console\Input\InputArgument;
23
use Symfony\Component\Console\Input\InputInterface;
24
use Symfony\Component\Console\Input\InputOption;
25
use Symfony\Component\Console\Output\OutputInterface;
26
27
/**
28
 * Command for run analysis
29
 *
30
 * @author Jean-François Lépine <https://twitter.com/Halleck45>
31
 */
32
class RunMetricsCommand extends Command
33
{
34
    /**
35
     * @inheritdoc
36
     */
37
    protected function configure()
38
    {
39
        $this
40
                ->setName('metrics')
41
                ->setDescription('Run analysis')
42
                ->addArgument(
43
                    'path', InputArgument::OPTIONAL, 'Path to explore'
44
                )
45
                ->addOption(
46
                    'report-html',null, InputOption::VALUE_REQUIRED, 'Path to save report in HTML format. Example: /tmp/report.html'
47
                )
48
                ->addOption(
49
                    'report-xml', null, InputOption::VALUE_REQUIRED, 'Path to save summary report in XML format. Example: /tmp/report.xml'
50
                )
51
                ->addOption(
52
                    'report-cli', null, InputOption::VALUE_NONE, 'Enable report in terminal'
53
                )
54
                ->addOption(
55
                    'violations-xml', null, InputOption::VALUE_REQUIRED, 'Path to save violations in XML format. Example: /tmp/report.xml'
56
                )
57
                ->addOption(
58
                    'report-csv', null, InputOption::VALUE_REQUIRED, 'Path to save summary report in CSV format. Example: /tmp/report.csv'
59
                )
60
                ->addOption(
61
                    'report-json', null, InputOption::VALUE_REQUIRED, 'Path to save detailed report in JSON format. Example: /tmp/report.json'
62
                )
63
                ->addOption(
64
                    'chart-bubbles', null, InputOption::VALUE_REQUIRED, 'Path to save Bubbles chart, in SVG format. Example: /tmp/chart.svg. Graphviz **IS** required'
65
                )
66
                ->addOption(
67
                    'level', null, InputOption::VALUE_REQUIRED, 'Depth of summary report', 0
68
                )
69
                ->addOption(
70
                    'extensions', null, InputOption::VALUE_REQUIRED, 'Regex of extensions to include', null
71
                )
72
                ->addOption(
73
                    'excluded-dirs', null, InputOption::VALUE_REQUIRED, 'Regex of subdirectories to exclude', null
74
                )
75
                ->addOption(
76
                    'symlinks', null, InputOption::VALUE_NONE, 'Enable following symlinks'
77
                )
78
                ->addOption(
79
                    'without-oop', null, InputOption::VALUE_NONE, 'If provided, tool will not extract any information about OOP model (faster)'
80
                )
81
                ->addOption(
82
                    'ignore-errors', null, InputOption::VALUE_NONE, 'If provided, files will be analyzed even with syntax errors'
83
                )
84
                ->addOption(
85
                    'failure-condition', null, InputOption::VALUE_REQUIRED, 'Optional failure condition, in english. For example: average.maintainabilityIndex < 50 or sum.loc > 10000', null
86
                )
87
                ->addOption(
88
                    'config', null, InputOption::VALUE_REQUIRED, 'Config file (YAML)', null
89
                )
90
                ->addOption(
91
                    'template-title', null, InputOption::VALUE_REQUIRED, 'Title for the HTML summary report', null
92
                )
93
                ->addOption(
94
                    'offline', null, InputOption::VALUE_NONE, 'Include all JavaScript and CSS files in HTML. Generated report will be bigger'
95
                )
96
                ->addOption(
97
                    'plugins', null, InputOption::VALUE_REQUIRED, 'Path of extensions to load, separated by comma (,)'
98
                )
99
        ;
100
    }
101
102
    /**
103
     * @inheritdoc
104
     */
105
    protected function execute(InputInterface $input, OutputInterface $output)
106
    {
107
108
        $output->writeln('PHPMetrics by Jean-François Lépine <https://twitter.com/Halleck45>');
109
        $output->writeln('');
110
111
        // config
112
        $configFactory = new ConfigFactory();
113
        $config = $configFactory->factory($input);
114
115
        // files
116
        if(null === $config->getPath()->getBasePath()) {
117
            throw new \LogicException('Please provide a path to analyze');
118
        }
119
120
        // files to analyze
121
        $finder = new Finder(
122
            $config->getPath()->getExtensions()
123
            , $config->getPath()->getExcludedDirs()
124
            , $config->getPath()->isFollowSymlinks() ? Finder::FOLLOW_SYMLINKS : null
125
        );
126
127
        // prepare plugins
128
        $repository = new Repository();
129
        foreach($config->getExtensions()->getExtensions() as $filename) {
130
            if(!file_exists($filename) ||!is_readable($filename)) {
131
                $output->writeln(sprintf('<error>Plugin %s skipped: not found</error>', $filename));
132
                continue;
133
            }
134
            $plugin = require_once($filename);
135
            $repository->attach($plugin);
136
        }
137
        $extensionService = new ExtensionService($repository);
138
139
        // prepare structures
140
        $bounds = new Bounds();
141
        $collection = new ResultCollection();
142
        $aggregatedResults = new ResultCollection();
143
144
        // execute analyze
145
        $queueFactory = new QueueAnalyzeFactory($input, $output, $config, $extensionService);
146
        $queue = $queueFactory->factory($finder, $bounds);
147
        gc_disable();
148
        $queue->execute($collection, $aggregatedResults);
149
        gc_enable();
150
151
        $output->writeln('');
152
153
        // provide data to extensions
154
        if(($n = sizeof($repository->all())) > 0) {
155
            $output->writeln(sprintf('%d %s. Executing analyzis', $n, ($n > 1 ? 'plugins are enabled' : 'plugin is enabled') ));
156
            $extensionService->receive($config, $collection, $aggregatedResults, $bounds);
157
        }
158
159
        // generating reports
160
        $output->writeln("Generating reports...");
161
        $queueFactory = new QueueReportFactory($input, $output, $config, $extensionService);
162
        $queue = $queueFactory->factory($finder, $bounds);
163
        $queue->execute($collection, $aggregatedResults);
164
165
        $output->writeln('<info>Done</info>');
166
167
        // evaluation of success
168
        $rule = $config->getFailureCondition();
169
        if(null !== $rule) {
170
            $evaluator = new Evaluator($collection, $aggregatedResults, $bounds);
171
            $result = $evaluator->evaluate($rule);
172
            // fail if failure-condition is realized
173
            return $result->isValid() ? 1 : 0;
174
        }
175
176
        return 0;
177
    }
178
179
}
180