Completed
Pull Request — master (#403)
by
unknown
03:32 queued 01:56
created

Reporter   A

Complexity

Total Complexity 14

Size/Duplication

Total Lines 166
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 5

Importance

Changes 0
Metric Value
dl 0
loc 166
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 75 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
    /**
141
     * Returns the CLI output block dedicated to Git stats.
142
     * @param Consolidated $consolidated
143
     * @return string
144
     */
145
    private function reportGitUsages(Consolidated $consolidated)
146
    {
147
        $out = '';
148
        $commits = [];
149
        foreach ($consolidated->getFiles() as $name => $file) {
150
            $commits[$name] = $file['gitChanges'];
151
        }
152
        arsort($commits);
153
        $commits = array_slice($commits, 0, 10);
154
155
        $out .= "\nTop 10 committed files";
156
        foreach ($commits as $file => $nb) {
157
            $out .= sprintf("\n    %d    %s", $nb, $file);
158
        }
159
        if ([] === $commits) {
160
            $out .= "\n    NA";
161
        }
162
        $out .= "\n";
163
164
        return $out;
165
    }
166
167
    /**
168
     * Returns the CLI output block dedicated to Unit Testing stats.
169
     * @param Metric $unitTestingMetric
170
     * @return string
171
     */
172
    private function reportUnitTesting(Metric $unitTestingMetric)
173
    {
174
        return <<<EOT
175
176
Unit testing
177
    Number of unit tests                        {$unitTestingMetric->get('nbSuites')}
178
    Classes called by tests                     {$unitTestingMetric->get('nbCoveredClasses')}
179
    Classes called by tests (percent)           {$unitTestingMetric->get('percentCoveredClasses')} %
180
181
EOT;
182
    }
183
}
184