Utils::validateCloverFile()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 2

Importance

Changes 0
Metric Value
cc 2
eloc 1
nc 2
nop 1
dl 0
loc 3
rs 10
c 0
b 0
f 0
ccs 2
cts 2
cp 1
crap 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 10
    public static function formatCoverage(float $number): string
39
    {
40 10
        return \sprintf('%0.2F%%', $number);
41
    }
42
43
    /**
44
     * Attempts to determine if we are actually using a PHPUnit generated clover file.
45
     *
46
     * As of 2024/03/28, the Clover XML report generated by PHPUnit (using phpunit-code-coverage) does
47
     * not validate against the official Atlassian/OpenClover clover XSD.
48
     *
49
     * @see https://bitbucket.org/atlassian/clover/raw/master/etc/schema/clover.xsd
50
     * @see https://github.com/sebastianbergmann/php-code-coverage/issues/578
51
     *
52
     * So this is a workaround of sorts.
53
     */
54 20
    public static function isPossiblyClover(SimpleXMLElement $xml): bool
55
    {
56 20
        if ($xml->getName() !== 'coverage') {
57 2
            return false;
58
        }
59
60 18
        $hasChildren = $xml->children();
61
62 18
        if ($hasChildren === null || !isset($hasChildren->project, $hasChildren->project->metrics) || (array) $hasChildren->project->metrics === []) {
63 4
            return false;
64
        }
65
66 14
        unset($hasChildren);
67
68 14
        return true;
69
    }
70
71
    /**
72
     * Handles parsing the XML data returned by CoverageCheck::loadMetrics().
73
     *
74
     * Attempts to gather any potential errors returned by SimpleXml/LibXml and wrap them
75
     * in a RuntimeException.
76
     *
77
     * @see https://www.php.net/SimpleXMLElement
78
     * @see https://www.php.net/libxml_use_internal_errors
79
     * @see https://www.php.net/libxml_get_errors
80
     *
81
     * @throws RuntimeException For any xml parser related errors.
82
     */
83 21
    public static function parseXml(string $xmlData): SimpleXMLElement
84
    {
85
        /**
86
         * @var array<int, string> $errorLevels
87
         */
88 21
        static $errorLevels = [
89 21
            LIBXML_ERR_WARNING => 'Warning',
90 21
            LIBXML_ERR_ERROR   => 'Error',
91 21
            LIBXML_ERR_FATAL   => 'Fatal Error',
92 21
        ];
93
94 21
        libxml_use_internal_errors(true);
95
96
        try {
97 21
            $xml = new SimpleXMLElement($xmlData);
98 1
        } catch (Exception) {
99 1
            $errorMessage = PHP_EOL;
100
101 1
            foreach (libxml_get_errors() as $libXMLError) {
102 1
                $errorMessage .= \sprintf(
103 1
                    '%s %d: %s. Line %d Column %d',
104 1
                    $errorLevels[$libXMLError->level],
105 1
                    $libXMLError->code,
106 1
                    trim($libXMLError->message),
107 1
                    $libXMLError->line,
108 1
                    $libXMLError->column
109 1
                ) . PHP_EOL;
110
            }
111
112 1
            throw new RuntimeException(\sprintf('Unable to load Clover XML data. LibXml returned: %s', $errorMessage));
113
        } finally {
114 21
            libxml_clear_errors();
115 21
            libxml_use_internal_errors(false);
116
        }
117
118 20
        return $xml;
119
    }
120
121
    /**
122
     * A simple file_exists check on the Clover file.
123
     */
124 25
    public static function validateCloverFile(string $cloverFile): bool
125
    {
126 25
        return ($cloverFile !== '' && file_exists($cloverFile));
127
    }
128
129
    /**
130
     * A simple check to determine if threshold is within accepted range (Min. 1, Max. 100).
131
     */
132 25
    public static function validateThreshold(int $threshold): bool
133
    {
134 25
        return ($threshold > 0 && $threshold <= 100);
135
    }
136
}
137