Passed
Push — master ( 545089...353eb0 )
by Pierre
02:47 queued 27s
created

Checker::shutdown()   A

Complexity

Conditions 3
Paths 2

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 3.1406

Importance

Changes 0
Metric Value
cc 3
eloc 3
nc 2
nop 0
dl 0
loc 6
ccs 3
cts 4
cp 0.75
crap 3.1406
rs 10
c 0
b 0
f 0
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
            ? $mets[self::COVERED_ELEMENTS] / $mets[self::_ELEMENTS] * 100
180 1
            : 0;
181
    }
182
183
    /**
184
     * returns methods coverage ratio as float
185
     *
186
     * @param \SimpleXMLElement $mets
187
     * @return float
188
     */
189 1
    protected function getMethodsRatio(\SimpleXMLElement $mets): float
190
    {
191 1
        return isset($mets[Args::_METHODS])
192 1
            ? $mets[self::COVERED_METHODS] / $mets[Args::_METHODS] * 100
193 1
            : 0;
194
    }
195
196
    /**
197
     * returns statements coverage ratio as float
198
     *
199
     * @param \SimpleXMLElement $mets
200
     * @return float
201
     */
202 1
    protected function getStatementsRatio(\SimpleXMLElement $mets): float
203
    {
204 1
        return isset($mets[Args::_STATEMENTS])
205 1
            ? $this->getRatio(
206 1
                (float) $mets[self::COVERED_STATEMENTS],
207 1
                (float) $mets[Args::_STATEMENTS]
208
            )
209 1
            : 0;
210
    }
211
212
    /**
213
     * returns classes coverage ratio as float
214
     *
215
     * @param integer $coveredClasses
216
     * @param \SimpleXMLElement $mets
217
     * @return float
218
     */
219 1
    protected function getClassesRatio(int $coveredClasses, \SimpleXMLElement $mets): float
220
    {
221 1
        return isset($mets[Args::_CLASSES])
222 1
            ? $this->getRatio(
223 1
                (float) $coveredClasses,
224 1
                (float) $mets[Args::_CLASSES]
225
            )
226 1
            : 0;
227
    }
228
229
    /**
230
     * return ratio computation as float
231
     *
232
     * @param float $min
233
     * @param float $max
234
     * @return float
235
     */
236 1
    protected function getRatio(float $min, float $max): float
237
    {
238 1
        return ($min / $max) * 100;
239
    }
240
241
    /**
242
     * set content from file
243
     *
244
     * @return Checker
245
     */
246 1
    protected function setContent(): Checker
247
    {
248 1
        $this->content = ($this->exists())
249
            ? file_get_contents($this->filename)
250 1
            : '';
251 1
        return $this;
252
    }
253
254
    /**
255
     * returns true if file exists
256
     *
257
     * @return boolean
258
     */
259 1
    protected function exists(): bool
260
    {
261 1
        return file_exists($this->filename);
262
    }
263
264
    /**
265
     * return true if blocking option was set
266
     *
267
     * @return boolean
268
     */
269 1
    protected function isBlocking(): bool
270
    {
271 1
        return $this->cloverArgs->isBlocking();
272
    }
273
}
274