Passed
Push — master ( 037497...68e9e6 )
by Pierre
01:53
created

Checker::getRatio()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 2.0625

Importance

Changes 2
Bugs 1 Features 0
Metric Value
cc 2
eloc 3
c 2
b 1
f 0
nc 2
nop 2
dl 0
loc 6
ccs 3
cts 4
cp 0.75
crap 2.0625
rs 10
1
<?php
2
3
declare(strict_types=1);
4
5
namespace PierInfor\Undercover;
6
7
use PierInfor\Undercover\Interfaces\IChecker;
8
use PierInfor\Undercover\Args;
9
10
/**
11
 * Checker is a coverage cover format file checker
12
 *
13
 * @author Pierre Fromager <info@pier_infor.fr>
14
 * @version 1.0
15
 * @package PierInfor\Undercover
16
 */
17
class Checker implements IChecker
18
{
19
20
    protected $cloverArgs;
21
    protected $filename;
22
    protected $content;
23
    protected $error;
24
    protected $results;
25
    protected $thresholds;
26
27
    /**
28
     * constructor
29
     */
30 14
    public function __construct()
31
    {
32 14
        $this->cloverArgs = new Args();
33 14
        $this->init();
34
    }
35
36
    /**
37
     * runner
38
     *
39
     * @return int
40
     */
41 1
    public function run(): int
42
    {
43 1
        if (!empty($this->getContent())) {
44 1
            $this->parse()->check();
45
        }
46 1
        return ($this->error && $this->isBlocking())
47
            ? 1
48 1
            : 0;
49
    }
50
51
    /**
52
     * initializer
53
     *
54
     * @return Checker
55
     */
56 1
    protected function init(): Checker
57
    {
58 1
        $this->filename = $this->cloverArgs->getFilename();
59 1
        $this->setContent();
60 1
        $this->error = false;
61 1
        $this->thresholds = $this->cloverArgs->getThresholds();
62 1
        $this->results = [];
63 1
        return $this;
64
    }
65
66
    /**
67
     * parse xml clover file and set coverage results
68
     *
69
     * @return Checker
70
     */
71 1
    protected function parse(): Checker
72
    {
73 1
        $xml = new \SimpleXMLElement($this->getContent());
74 1
        $metrics = $xml->project->metrics;
75 1
        $classes = $xml->xpath(self::XPATH_SEARCH);
76 1
        $coveredClasses = 0;
77 1
        foreach ($classes as $class) {
78 1
            $methods = (int) $class->metrics[Args::_METHODS];
79 1
            $areMethodsCovered = ($methods > 0
80 1
                && $methods === (int) $class->metrics[self::COVERED_METHODS]);
81 1
            if ($areMethodsCovered) {
82 1
                $coveredClasses++;
83
            }
84
        }
85 1
        $this->setResults($coveredClasses, $metrics);
86 1
        return $this;
87
    }
88
89
    /**
90
     * returns result metrics coverage ratios as array
91
     *
92
     * @return string
93
     */
94 1
    protected function getResults(): array
95
    {
96 1
        return $this->results;
97
    }
98
99
    /**
100
     * returns coverage file content
101
     *
102
     * @return string
103
     */
104 1
    protected function getContent(): string
105
    {
106 1
        return $this->content;
107
    }
108
109
    /**
110
     * display msg and set error if under coverage
111
     *
112
     * @return Checker
113
     */
114 1
    protected function check(): Checker
115
    {
116 1
        echo self::TITLE;
117 1
        $errCount = 0;
118 1
        foreach ($this->results as $k => $v) {
119 1
            $valid = $v >= $this->thresholds[$k];
120 1
            if (!$valid) {
121
                ++$errCount;
122
            }
123 1
            echo PHP_EOL . $this->getMsgLine($k, $v, $valid);
124
        }
125 1
        echo PHP_EOL . self::T_BEFORE;
126 1
        $this->error = ($errCount > 0);
127 1
        return $this;
128
    }
129
130
    /**
131
     * return formated msg line
132
     *
133
     * @param string $k
134
     * @param float $v
135
     * @return string
136
     */
137 1
    protected function getMsgLine(string $k, float $v, bool $valid): string
138
    {
139 1
        return sprintf(
140 1
            self::MSG_FORMAT,
141 1
            ucfirst($k),
142
            $v,
143 1
            'limit',
144 1
            $this->thresholds[$k],
145 1
            $valid ? self::_OK : self::_KO
146
        );
147
    }
148
149
    /**
150
     * set results
151
     *
152
     * @param integer $coveredClasses
153
     * @param \SimpleXMLElement $metrics
154
     * @return Checker
155
     */
156 1
    protected function setResults(int $coveredClasses, \SimpleXMLElement $metrics): Checker
157
    {
158 1
        $this->results = [
159 1
            Args::_LINES => $this->getElementsRatio($metrics),
160 1
            Args::_METHODS => $this->getMethodsRatio($metrics),
161 1
            Args::_STATEMENTS => $this->getStatementsRatio($metrics),
162 1
            Args::_CLASSES => $this->getClassesRatio(
163 1
                $coveredClasses,
164
                $metrics
165
            )
166
        ];
167 1
        return $this;
168
    }
169
170
    /**
171
     * returns lines coverage ratio as float
172
     *
173
     * @param \SimpleXMLElement $mets
174
     * @return float
175
     */
176 1
    protected function getElementsRatio(\SimpleXMLElement $mets): float
177
    {
178 1
        return isset($mets[self::_ELEMENTS])
179 1
            ? $this->getRatio(
180 1
                (float) $mets[self::COVERED_ELEMENTS],
181 1
                (float) $mets[self::_ELEMENTS]
182
            )
183 1
            : 0;
184
    }
185
186
    /**
187
     * returns methods coverage ratio as float
188
     *
189
     * @param \SimpleXMLElement $mets
190
     * @return float
191
     */
192 1
    protected function getMethodsRatio(\SimpleXMLElement $mets): float
193
    {
194 1
        return isset($mets[Args::_METHODS])
195 1
            ? $this->getRatio(
196 1
                (float) $mets[self::COVERED_METHODS],
197 1
                (float) $mets[Args::_METHODS]
198
            )
199 1
            : 0;
200
    }
201
202
    /**
203
     * returns statements coverage ratio as float
204
     *
205
     * @param \SimpleXMLElement $mets
206
     * @return float
207
     */
208 1
    protected function getStatementsRatio(\SimpleXMLElement $mets): float
209
    {
210 1
        return isset($mets[Args::_STATEMENTS])
211 1
            ? $this->getRatio(
212 1
                (float) $mets[self::COVERED_STATEMENTS],
213 1
                (float) $mets[Args::_STATEMENTS]
214
            )
215 1
            : 0;
216
    }
217
218
    /**
219
     * returns classes coverage ratio as float
220
     *
221
     * @param integer $coveredClasses
222
     * @param \SimpleXMLElement $mets
223
     * @return float
224
     */
225 1
    protected function getClassesRatio(int $coveredClasses, \SimpleXMLElement $mets): float
226
    {
227 1
        return isset($mets[Args::_CLASSES])
228 1
            ? $this->getRatio(
229 1
                (float) $coveredClasses,
230 1
                (float) $mets[Args::_CLASSES]
231
            )
232 1
            : 0;
233
    }
234
235
    /**
236
     * return ratio computation as float
237
     *
238
     * @param float $min
239
     * @param float $max
240
     * @return float
241
     */
242 1
    protected function getRatio(float $min, float $max): float
243
    {
244 1
        if ($max === 0) {
0 ignored issues
show
introduced by
The condition $max === 0 is always false.
Loading history...
245
            $max = 0.0000001;
246
        }
247 1
        return ($min / $max) * 100;
248
    }
249
250
    /**
251
     * set content from file
252
     *
253
     * @return Checker
254
     */
255 1
    protected function setContent(): Checker
256
    {
257 1
        $this->content = ($this->exists())
258
            ? file_get_contents($this->filename)
259 1
            : '';
260 1
        return $this;
261
    }
262
263
    /**
264
     * returns true if file exists
265
     *
266
     * @return boolean
267
     */
268 1
    protected function exists(): bool
269
    {
270 1
        return file_exists($this->filename);
271
    }
272
273
    /**
274
     * return true if blocking option was set
275
     *
276
     * @return boolean
277
     */
278 1
    protected function isBlocking(): bool
279
    {
280 1
        return $this->cloverArgs->isBlocking();
281
    }
282
}
283