Utils   A
last analyzed

Complexity

Total Complexity 13

Size/Duplication

Total Lines 100
Duplicated Lines 0 %

Test Coverage

Coverage 100%

Importance

Changes 4
Bugs 2 Features 0
Metric Value
wmc 13
eloc 33
c 4
b 2
f 0
dl 0
loc 100
ccs 37
cts 37
cp 1
rs 10

5 Methods

Rating   Name   Duplication   Size   Complexity  
A formatCoverage() 0 3 1
A parseXml() 0 36 3
A validateThreshold() 0 3 2
A isPossiblyClover() 0 15 5
A validateCloverFile() 0 3 2
1
<?php
2
3
declare(strict_types=1);
4
5
/**
6
 * This file is part of PHPUnit Coverage Check.
7
 *
8
 * (c) Eric Sizemore <[email protected]>
9
 * (c) Richard Regeer <[email protected]>
10
 *
11
 * This source file is subject to the MIT license. For the full copyright,
12
 * license information, and credits/acknowledgements, please view the LICENSE
13
 * and README files that were distributed with this source code.
14
 */
15
16
namespace Esi\CoverageCheck;
17
18
use Exception;
19
use RuntimeException;
20
use SimpleXMLElement;
21
22
use function file_exists;
23
use function libxml_clear_errors;
24
use function libxml_get_errors;
25
use function libxml_use_internal_errors;
26
use function trim;
27
28
use const LIBXML_ERR_ERROR;
29
use const LIBXML_ERR_FATAL;
30
use const LIBXML_ERR_WARNING;
31
use const PHP_EOL;
32
33
abstract class Utils
34
{
35
    /**
36
     * Returns the given number formatted and rounded for percentage.
37
     */
38 13
    public static function formatCoverage(float $number): string
39
    {
40 13
        return \sprintf('%0.2F%%', $number);
41
    }
42
43
    /**
44
     * Attempts to determine if we are actually using a PHPUnit generated clover file.
45
     *
46
     * @todo As of version 12.2, PHPUnit now supports generating OpenClover.
47
     * @todo Look into validating against the official clover XSD.
48
     *
49
     * @see https://bitbucket.org/atlassian/clover/raw/master/etc/schema/clover.xsd
50
     * @see https://github.com/sebastianbergmann/phpunit/releases/tag/12.2.0
51
     */
52 23
    public static function isPossiblyClover(SimpleXMLElement $xml): bool
53
    {
54 23
        if ($xml->getName() !== 'coverage') {
55 2
            return false;
56
        }
57
58 21
        $hasChildren = $xml->children();
59
60 21
        if ($hasChildren === null || !isset($hasChildren->project, $hasChildren->project->metrics) || (array) $hasChildren->project->metrics === []) {
61 4
            return false;
62
        }
63
64 17
        unset($hasChildren);
65
66 17
        return true;
67
    }
68
69
    /**
70
     * Handles parsing the XML data returned by CoverageCheck::loadMetrics().
71
     *
72
     * Attempts to gather any potential errors returned by SimpleXml/LibXml and wrap them
73
     * in a RuntimeException.
74
     *
75
     * @see https://www.php.net/SimpleXMLElement
76
     * @see https://www.php.net/libxml_use_internal_errors
77
     * @see https://www.php.net/libxml_get_errors
78
     *
79
     * @throws RuntimeException For any xml parser related errors.
80
     */
81 24
    public static function parseXml(string $xmlData): SimpleXMLElement
82
    {
83
        /**
84
         * @var array<int, string> $errorLevels
85
         */
86 24
        static $errorLevels = [
87 24
            LIBXML_ERR_WARNING => 'Warning',
88 24
            LIBXML_ERR_ERROR   => 'Error',
89 24
            LIBXML_ERR_FATAL   => 'Fatal Error',
90 24
        ];
91
92 24
        libxml_use_internal_errors(true);
93
94
        try {
95 24
            $xml = new SimpleXMLElement($xmlData);
96 1
        } catch (Exception) {
97 1
            $errorMessage = PHP_EOL;
98
99 1
            foreach (libxml_get_errors() as $libXMLError) {
100 1
                $errorMessage .= \sprintf(
101 1
                    '%s %d: %s. Line %d Column %d',
102 1
                    $errorLevels[$libXMLError->level],
103 1
                    $libXMLError->code,
104 1
                    trim($libXMLError->message),
105 1
                    $libXMLError->line,
106 1
                    $libXMLError->column
107 1
                ) . PHP_EOL;
108
            }
109
110 1
            throw new RuntimeException(\sprintf('Unable to load Clover XML data. LibXml returned: %s', $errorMessage));
111
        } finally {
112 24
            libxml_clear_errors();
113 24
            libxml_use_internal_errors(false);
114
        }
115
116 23
        return $xml;
117
    }
118
119
    /**
120
     * A simple file_exists check on the Clover file.
121
     */
122 28
    public static function validateCloverFile(string $cloverFile): bool
123
    {
124 28
        return ($cloverFile !== '' && file_exists($cloverFile));
125
    }
126
127
    /**
128
     * A simple check to determine if threshold is within accepted range (Min. 1, Max. 100).
129
     */
130 28
    public static function validateThreshold(int $threshold): bool
131
    {
132 28
        return ($threshold > 0 && $threshold <= 100);
133
    }
134
}
135