Passed
Push — main ( cb175f...77c564 )
by mikhail
03:13
created

CDS   A

Complexity

Total Complexity 16

Size/Duplication

Total Lines 93
Duplicated Lines 0 %

Test Coverage

Coverage 96.15%

Importance

Changes 0
Metric Value
wmc 16
eloc 44
dl 0
loc 93
ccs 50
cts 52
cp 0.9615
rs 10
c 0
b 0
f 0

8 Methods

Rating   Name   Duplication   Size   Complexity  
A prepareCDS() 0 6 1
A __construct() 0 4 1
A calculateRawScore() 0 14 3
A getMaxPossibleScore() 0 7 1
A getMinPossibleScore() 0 16 4
A calculateCDS() 0 11 2
A getColorForCDS() 0 10 3
A hasExceededThreshold() 0 3 1
1
<?php
2
3
declare(strict_types=1);
4
5
namespace SavinMikhail\CommentsDensity\Metrics;
6
7
use InvalidArgumentException;
8
use Mikhail\PrimitiveWrappers\Int\Integer;
9
use SavinMikhail\CommentsDensity\Comments\CommentFactory;
10
use SavinMikhail\CommentsDensity\Comments\DocBlockComment;
11
use SavinMikhail\CommentsDensity\DTO\Output\CdsDTO;
0 ignored issues
show
Bug introduced by
The type SavinMikhail\CommentsDensity\DTO\Output\CdsDTO was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
12
13
use function in_array;
14
use function round;
15
16
final class CDS
17
{
18
    private const MISSING_DOCBLOCK_WEIGHT = -1;
19
20
    private bool $exceedThreshold = false;
21
22 4
    public function __construct(
23
        private readonly array $thresholds,
24
        private readonly CommentFactory $commentFactory,
25
    ) {
26 4
    }
27
28 2
    public function calculateCDS(array $commentStatistics): float
29
    {
30 2
        $rawScore = $this->calculateRawScore($commentStatistics);
31 2
        $minPossibleScore = $this->getMinPossibleScore($commentStatistics);
32 2
        $maxPossibleScore = $this->getMaxPossibleScore($commentStatistics);
33
34
        try {
35 2
            return (new Integer(0))
36 2
                ->scaleToRange($rawScore, $minPossibleScore, $maxPossibleScore);
37
        } catch (InvalidArgumentException) {
38
            return 0;
39
        }
40
    }
41
42 2
    private function calculateRawScore(array $commentStatistics): float
43
    {
44 2
        $rawScore = 0;
45
46 2
        foreach ($commentStatistics as $type => $stat) {
47 2
            $comment = $this->commentFactory->getCommentType($type);
48 2
            if ($comment) {
49 2
                $rawScore += $stat['count'] * $comment->getWeight();
50 2
                continue;
51
            }
52 2
            $rawScore += $stat['count'] * self::MISSING_DOCBLOCK_WEIGHT;
53
        }
54
55 2
        return $rawScore;
56
    }
57
58 2
    private function getMinPossibleScore(array $commentStatistics): float
59
    {
60 2
        $minScore = 0;
61 2
        foreach ($commentStatistics as $type => $stat) {
62 2
            $comment = $this->commentFactory->getCommentType($type);
63 2
            if (!$comment) {
64 2
                $minScore += self::MISSING_DOCBLOCK_WEIGHT * $stat['count'];
65 2
                continue;
66
            }
67 2
            if ($comment->getWeight() < 0) {
68 1
                $minScore += $comment->getWeight() * $stat['count'];
69 1
                continue;
70
            }
71 2
            $minScore -= $comment->getWeight() * $stat['count'];
72
        }
73 2
        return $minScore;
74
    }
75
76 2
    private function getMaxPossibleScore(array $commentStatistics): float
77
    {
78 2
        return (
79 2
                ($commentStatistics['missingDocblock']['count'] ?? 0)
80 2
                + ($commentStatistics['docblock']['count'] ?? 0)
81 2
            )
82 2
            * ((new DocBlockComment())->getWeight());
83
    }
84
85 2
    public function prepareCDS(float $cds): CdsDTO
86
    {
87 2
        $cds = round($cds, 2);
88 2
        return new CdsDTO(
89 2
            $cds,
90 2
            $this->getColorForCDS($cds),
91 2
        );
92
    }
93
94 3
    private function getColorForCDS(float $cds): string
95
    {
96 3
        if (! isset($this->thresholds['CDS'])) {
97 1
            return 'white';
98
        }
99 3
        if ($cds >= $this->thresholds['CDS']) {
100 2
            return 'green';
101
        }
102 2
        $this->exceedThreshold = true;
103 2
        return 'red';
104
    }
105
106 1
    public function hasExceededThreshold(): bool
107
    {
108 1
        return $this->exceedThreshold;
109
    }
110
}
111