Completed
Pull Request — master (#403)
by
unknown
01:38
created

Reporter   A

Complexity

Total Complexity 14

Size/Duplication

Total Lines 165
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 5

Importance

Changes 0
Metric Value
dl 0
loc 165
rs 10
c 0
b 0
f 0
wmc 14
lcom 1
cbo 5

5 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 5 1
A generate() 0 19 4
B reportConsolidated() 0 74 4
A reportGitUsages() 0 21 4
A reportUnitTesting() 0 11 1
1
<?php
2
namespace Hal\Report\Cli;
3
4
use Hal\Application\Config\Config;
5
use Hal\Component\Output\Output;
6
use Hal\Metric\Consolidated;
7
use Hal\Metric\Metric;
8
use Hal\Metric\Metrics;
9
use Hal\Report\ReporterInterface;
10
use function array_slice;
11
use function arsort;
12
use function round;
13
use function sprintf;
14
15
/**
16
 * This class takes care about the global output into the STDOUT of consolidated metrics.
17
 */
18
final class Reporter implements ReporterInterface
19
{
20
    /** @var Config */
21
    private $config;
22
23
    /** @var Output */
24
    private $output;
25
26
    /**
27
     * @param Config $config
28
     * @param Output $output
29
     */
30
    public function __construct(Config $config, Output $output)
31
    {
32
        $this->config = $config;
33
        $this->output = $output;
34
    }
35
36
    /**
37
     * {@inheritDoc}
38
     */
39
    public function generate(Metrics $metrics)
40
    {
41
        if ($this->config->has('quiet')) {
42
            return;
43
        }
44
45
        $consolidated = new Consolidated($metrics);
46
        $out = $this->reportConsolidated($metrics, $consolidated);
47
48
        if ($this->config->has('git')) {
49
            $out .= $this->reportGitUsages($consolidated);
50
        }
51
52
        if ($this->config->has('junit')) {
53
            $out .= $this->reportUnitTesting($metrics->get('unitTesting'));
0 ignored issues
show
Bug introduced by
It seems like $metrics->get('unitTesting') can be null; however, reportUnitTesting() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
54
        }
55
56
        $this->output->write($out . "\n");
57
    }
58
59
    /**
60
     * @param Metrics $metrics
61
     * @param Consolidated $consolidated
62
     * @return string
63
     */
64
    private function reportConsolidated(Metrics $metrics, Consolidated $consolidated)
65
    {
66
        $sum = $consolidated->getSum();
67
        $avg = $consolidated->getAvg();
68
69
        $methodsByClass = $locByClass = $locByMethod = 0;
70
        if ($sum->nbClasses > 0) {
71
            $methodsByClass = round($sum->nbMethods / $sum->nbClasses, 2);
72
            $locByClass = round($sum->lloc / $sum->nbClasses);
73
        }
74
        if ($sum->nbMethods > 0) {
75
            $locByMethod = round($sum->lloc / $sum->nbMethods);
76
        }
77
78
        $inheritanceTreeDepthReport = '';
79
        $treeMetric = $metrics->get('tree');
80
        if (null !== $treeMetric) {
81
            $inheritanceTreeDepthReport = <<<EOT
82
Depth of Inheritance Tree                   {$treeMetric->get('depthOfInheritanceTree')}
83
84
EOT;
85
        }
86
87
        return <<<EOT
88
LOC
89
    Lines of code                               {$sum->loc}
90
    Logical lines of code                       {$sum->lloc}
91
    Comment lines of code                       {$sum->cloc}
92
    Average volume                              {$avg->volume}
93
    Average comment weight                      {$avg->commentWeight}
94
    Average intelligent content                 {$avg->commentWeight}
95
    Logical lines of code by class              {$locByClass}
96
    Logical lines of code by method             {$locByMethod}
97
98
Object oriented programming
99
    Classes                                     {$sum->nbClasses}
100
    Interface                                   {$sum->nbInterfaces}
101
    Methods                                     {$sum->nbMethods}
102
    Methods by class                            {$methodsByClass}
103
    Lack of cohesion of methods                 {$avg->lcom}
104
105
Coupling
106
    Average afferent coupling                   {$avg->afferentCoupling}
107
    Average efferent coupling                   {$avg->efferentCoupling}
108
    Average instability                         {$avg->instability}
109
    {$inheritanceTreeDepthReport}
110
111
Package
112
    Packages                                    {$sum->nbPackages}
113
    Average classes per package                 {$avg->classesPerPackage}
114
    Average distance                            {$avg->distance}
115
    Average incoming class dependencies         {$avg->incomingCDep}
116
    Average outgoing class dependencies         {$avg->outgoingCDep}
117
    Average incoming package dependencies       {$avg->incomingPDep}
118
    Average outgoing package dependencies       {$avg->outgoingPDep}
119
120
Complexity
121
    Average Cyclomatic complexity by class      {$avg->ccn}
122
    Average Weighted method count by class      {$avg->wmc}
123
    Average Relative system complexity          {$avg->relativeSystemComplexity}
124
    Average Difficulty                          {$avg->difficulty}
125
126
Bugs
127
    Average bugs by class                       {$avg->bugs}
128
    Average defects by class (Kan)              {$avg->kanDefect}
129
130
Violations
131
    Critical                                    {$sum->violations->critical}
132
    Error                                       {$sum->violations->error}
133
    Warning                                     {$sum->violations->warning}
134
    Information                                 {$sum->violations->information}
135
136
EOT;
137
    }
138
139
    /**
140
     * Returns the CLI output block dedicated to Git stats.
141
     * @param Consolidated $consolidated
142
     * @return string
143
     */
144
    private function reportGitUsages(Consolidated $consolidated)
145
    {
146
        $out = '';
147
        $commits = [];
148
        foreach ($consolidated->getFiles() as $name => $file) {
149
            $commits[$name] = $file['gitChanges'];
150
        }
151
        arsort($commits);
152
        $commits = array_slice($commits, 0, 10);
153
154
        $out .= "\nTop 10 committed files";
155
        foreach ($commits as $file => $nb) {
156
            $out .= sprintf("\n    %d    %s", $nb, $file);
157
        }
158
        if ([] === $commits) {
159
            $out .= "\n    NA";
160
        }
161
        $out .= "\n";
162
163
        return $out;
164
    }
165
166
    /**
167
     * Returns the CLI output block dedicated to Unit Testing stats.
168
     * @param Metric $unitTestingMetric
169
     * @return string
170
     */
171
    private function reportUnitTesting(Metric $unitTestingMetric)
172
    {
173
        return <<<EOT
174
175
Unit testing
176
    Number of unit tests                        {$unitTestingMetric->get('nbSuites')}
177
    Classes called by tests                     {$unitTestingMetric->get('nbCoveredClasses')}
178
    Classes called by tests (percent)           {$unitTestingMetric->get('percentCoveredClasses')} %
179
180
EOT;
181
    }
182
}
183