Completed
Push — master ( 899eaf...7feae9 )
by Dave
29s queued 14s
created

JunitOutputFormatter::outputResults()   B

Complexity

Conditions 10
Paths 17

Size

Total Lines 84
Code Lines 59

Duplication

Lines 0
Ratio 0 %

Importance

Changes 4
Bugs 1 Features 1
Metric Value
cc 10
eloc 59
c 4
b 1
f 1
nc 17
nop 1
dl 0
loc 84
rs 7.0278

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
declare(strict_types=1);
4
5
namespace DaveLiddament\StaticAnalysisResultsBaseliner\Plugins\OutputFormatters;
6
7
use DaveLiddament\StaticAnalysisResultsBaseliner\Domain\Common\SarbException;
8
use DaveLiddament\StaticAnalysisResultsBaseliner\Domain\OutputFormatter\OutputFormatter;
9
use DaveLiddament\StaticAnalysisResultsBaseliner\Domain\ResultsParser\AnalysisResults;
10
use DOMDocument;
11
use SimpleXMLElement;
12
13
class JunitOutputFormatter implements OutputFormatter
14
{
15
    /**
16
     * @throws SarbException
17
     */
18
    public function outputResults(AnalysisResults $analysisResults): string
19
    {
20
        if (!extension_loaded('simplexml')) {
21
            throw new SarbException('Simple XML required for JUnit output format'); // @codeCoverageIgnore
22
        }
23
24
        if (0 === $analysisResults->getCount()) {
25
            return <<<XML
26
<?xml version="1.0" encoding="UTF-8"?>
27
<testsuites
28
        name="SARB" tests="1" failures="0">
29
    <testsuite errors="0" tests="1" failures="0" name="Success">
30
        <testcase name="Success"/>
31
    </testsuite>
32
</testsuites>
33
34
XML;
35
        }
36
37
        $xml = $this->getXmlString($analysisResults->getCount());
38
        $test = new SimpleXMLElement($xml);
39
40
        $caseCount = 0;
41
        $previousRelativeFileName = null;
42
        $testsuite = null;
43
        foreach ($analysisResults->getAnalysisResults() as $analysisResult) {
44
            $details = $analysisResult->getFullDetails();
45
46
            /** @var mixed $column */
47
            $column = $details['column'] ?? null;
48
            if (is_numeric($column)) {
49
                $column = (string) ((int) $column);
50
            } else {
51
                $column = '0';
52
            }
53
54
            $relativeFileName = $analysisResult->getLocation()->getRelativeFileName()->getFileName();
55
56
            if ((null === $testsuite) || ($previousRelativeFileName !== $relativeFileName)) {
57
                // Add final counts to previous testsuite (if one exists)
58
                $this->addCounts($testsuite, $caseCount);
59
60
                $testsuite = $test->addChild('testsuite');
61
                $testsuite->addAttribute('name', $relativeFileName);
62
63
                $previousRelativeFileName = $relativeFileName;
64
                $caseCount = 0;
65
            }
66
67
            $lineSprint = sprintf(
68
                '%s at %s (%d:%s)',
69
                $analysisResult->getType()->getType(),
70
                $analysisResult->getLocation()->getAbsoluteFileName()->getFileName(),
71
                $analysisResult->getLocation()->getLineNumber()->getLineNumber(),
72
                $column
73
            );
74
            $testcase = $testsuite->addChild('testcase');
75
            $testcase->addAttribute('name', $lineSprint);
76
            $failure = $testcase->addChild('failure');
77
            $failure->addAttribute('type', $analysisResult->getSeverity()->getSeverity());
78
            $failure->addAttribute(
79
                'message',
80
                $analysisResult->getMessage()
81
            );
82
            ++$caseCount;
83
        }
84
85
        $this->addCounts($testsuite, $caseCount);
86
87
        $dom = new DOMDocument('1.0');
88
        $dom->preserveWhiteSpace = false;
89
        $dom->formatOutput = true;
90
        $asXml = $test->asXML();
91
92
        if ((false !== $asXml) && ('' !== $asXml)) {
93
            $dom->loadXML($asXml);
0 ignored issues
show
Bug introduced by
It seems like $asXml can also be of type true; however, parameter $source of DOMDocument::loadXML() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

93
            $dom->loadXML(/** @scrutinizer ignore-type */ $asXml);
Loading history...
94
        } else {
95
            throw new SarbException('xml could not be loaded'); // @codeCoverageIgnore
96
        }
97
        $saveXml = $dom->saveXML();
98
        if (false !== $saveXml) {
99
            return $saveXml;
100
        }
101
        throw new SarbException('dom could not be saved'); // @codeCoverageIgnore
102
    }
103
104
    private function getXmlString(int $issues): string
105
    {
106
        $xmlstr = <<<XML
107
<?xml version="1.0" encoding="UTF-8"?>
108
<testsuites
109
        name="SARB" tests="{$issues}" failures="{$issues}">
110
</testsuites>
111
112
XML;
113
114
        return $xmlstr;
115
    }
116
117
    public function getIdentifier(): string
118
    {
119
        return 'junit';
120
    }
121
122
    private function addCounts(?SimpleXMLElement $testsuite, int $caseCount): void
123
    {
124
        if (null !== $testsuite) {
125
            $testsuite->addAttribute('errors', '0');
126
            $testsuite->addAttribute('tests', (string) $caseCount);
127
            $testsuite->addAttribute('failures', (string) $caseCount);
128
        }
129
    }
130
}
131