PhpMd::getErrorsOnLine()   A
last analyzed

Complexity

Conditions 5
Paths 4

Size

Total Lines 18
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 5
eloc 10
nc 4
nop 2
dl 0
loc 18
rs 9.6111
c 0
b 0
f 0
1
<?php
2
namespace exussum12\CoverageChecker\Loaders;
3
4
use exussum12\CoverageChecker\FileChecker;
5
use XMLReader;
6
7
/**
8
 * Class PhpMd
9
 * Used for parsing phpmd xml output
10
 * @package exussum12\CoverageChecker
11
 */
12
class PhpMd implements FileChecker
13
{
14
    /**
15
     * @var string
16
     */
17
    protected $file;
18
19
    /**
20
     * @var array
21
     */
22
    protected $errors = [];
23
24
    /**
25
     * @var array
26
     */
27
    protected $errorRanges = [];
28
29
    /**
30
     * PhpMdLoader constructor.
31
     * @param string $file the path to the phpmd xml file
32
     */
33
    public function __construct($file)
34
    {
35
        $this->file = $file;
36
    }
37
38
    /**
39
     * {@inheritdoc}
40
     */
41
    public function parseLines(): array
42
    {
43
        $this->errors = [];
44
        $this->errorRanges = [];
45
        $reader = new XMLReader;
46
        $reader->open($this->file);
47
        $currentFile = "";
48
        while ($reader->read()) {
49
            $currentFile = $this->checkForNewFile($reader, $currentFile);
50
            $this->checkForViolation($reader, $currentFile);
51
        }
52
53
        return array_keys($this->errors);
54
    }
55
56
    /**
57
     * {@inheritdoc}
58
     */
59
    public function getErrorsOnLine(string $file, int $lineNumber)
60
    {
61
        $errors = [];
62
        if (empty($this->errorRanges[$file])) {
63
            return $errors;
64
        }
65
66
        foreach ($this->errorRanges[$file] as $number => $error) {
67
            if ((
68
                $error['start'] <= $lineNumber &&
69
                $error['end'] >= $lineNumber
70
            )) {
71
                $errors[] = $error['error'];
72
                unset($this->errorRanges[$file][$number]);
73
            }
74
        }
75
76
        return $errors;
77
    }
78
79
    /**
80
     * @param XMLReader $reader
81
     * @param string $currentFile
82
     */
83
    protected function checkForViolation(XMLReader $reader, $currentFile)
84
    {
85
        if ((
86
            $reader->name === 'violation' &&
87
            $reader->nodeType == XMLReader::ELEMENT
88
        )) {
89
            $error = trim($reader->readString());
90
            $start = $reader->getAttribute('beginline');
91
            $end = $reader->getAttribute('endline');
92
            $this->errorRanges[$currentFile][] = [
93
                'start' => $start,
94
                'end' => $end,
95
                'error' => $error,
96
            ];
97
98
            $this->addForAllLines($currentFile, $start, $end, $error);
99
        }
100
    }
101
102
    /**
103
     * @param XMLReader $reader
104
     * @param string $currentFile
105
     * @return string the currentFileName
106
     */
107
    protected function checkForNewFile(XMLReader $reader, $currentFile)
108
    {
109
        if ((
110
            $reader->name === 'file' &&
111
            $reader->nodeType == XMLReader::ELEMENT
112
        )
113
        ) {
114
            $currentFile = $reader->getAttribute('name');
115
            $this->errors[$currentFile] = [];
116
            return $currentFile;
117
        }
118
        return $currentFile;
119
    }
120
121
    /**
122
     * {@inheritdoc}
123
     */
124
    public function handleNotFoundFile()
125
    {
126
        return true;
127
    }
128
129
    /**
130
     * {@inheritdoc}
131
     */
132
    public static function getDescription(): string
133
    {
134
        return 'Parses the xml report format of phpmd, this mode ' .
135
            'reports multi line violations once per diff, instead ' .
136
            'of on each line the violation occurs';
137
    }
138
139
    protected function addForAllLines($currentFile, $start, $end, $error)
140
    {
141
        for ($i = $start; $i <= $end; $i++) {
142
            if ((
143
                !isset($this->errors[$currentFile][$i]) ||
144
                !in_array($error, $this->errors[$currentFile][$i])
145
            )) {
146
                $this->errors[$currentFile][$i][] = $error;
147
            }
148
        }
149
    }
150
}
151