DiffOutputFilter::getTouchedFilesAndLines()   B
last analyzed

Complexity

Conditions 6
Paths 6

Size

Total Lines 24
Code Lines 15

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 24
rs 8.5125
c 0
b 0
f 0
cc 6
eloc 15
nc 6
nop 0
1
<?php
2
namespace phphound\output\filter;
3
4
use SebastianBergmann\Diff\Line;
5
6
/**
7
 * Limit AnalysisResult data by only the files and their lines touched by
8
 * the diff. For example: if the diff only touches a "costumer.php" file
9
 * at lines 10 and 11, the AnalysisResult will only return issues found on
10
 * that file and at those lines of code. All other issues will be ignored.
11
 */
12
class DiffOutputFilter implements OutputFilterInterface
13
{
14
    /**
15
     * Root path to which the diff file paths are relative.
16
     * @var string root path.
17
     */
18
    protected $root;
19
20
    /**
21
     * An array of Diff objects.
22
     * @var SebastianBergmann\Diff\Diff[] array of diff objects.
23
     */
24
    protected $diffs;
25
26
    /**
27
     * Constructor.
28
     * @param string $root root path.
29
     * @param SebastianBergmann\Diff\Diff[] $diffs array of diff objects.
30
     */
31
    public function __construct($root, array $diffs)
32
    {
33
        $this->root = $root;
34
        $this->diffs = $diffs;
35
    }
36
37
    /**
38
     * @inheritdoc
39
     */
40
    public function filter($data)
41
    {
42
        $filteredData = [];
43
44
        foreach ($this->getTouchedFilesAndLines() as $fileName => $lines) {
45
            if (!isset($data[$fileName])) {
46
                continue;
47
            }
48
            foreach ($lines as $line) {
49
                if (!isset($data[$fileName][$line])) {
50
                    continue;
51
                }
52
                if (!isset($filteredData[$fileName])) {
53
                    $filteredData[$fileName] = [];
54
                }
55
                $filteredData[$fileName][$line] = $data[$fileName][$line];
56
            }
57
        }
58
        return $filteredData;
59
    }
60
61
    /**
62
     * Files touched by the diff and that received at least one new line of code.
63
     * @return string[] files paths.
64
     */
65
    public function getFilesWithAddedCode()
66
    {
67
        $files = [];
68
        foreach ($this->getDiffsWithAddedCode() as $fileDiff) {
69
            $files[] = $this->root . DIRECTORY_SEPARATOR . substr($fileDiff->getTo(), 2);
70
        }
71
        return $files;
72
    }
73
74
    /**
75
     * Gets the list of files and lines touched by the diff.
76
     * @return array where the key is the file path and its values the lines.
77
     */
78
    protected function getTouchedFilesAndLines()
79
    {
80
        $resultFilter = [];
81
        foreach ($this->getDiffsWithAddedCode() as $fileDiff) {
82
            $file = $this->root . DIRECTORY_SEPARATOR . substr($fileDiff->getTo(), 2);
83
            $lines = [];
84
            foreach ($fileDiff->getChunks() as $chunkDiff) {
85
                $counter = -1;
86
                foreach ($chunkDiff->getLines() as $lineDiff) {
87
                    if ($lineDiff->getType() == Line::REMOVED) {
88
                        continue;
89
                    }
90
                    $counter++;
91
92
                    // Only display results for touched lines
93
                    if ($lineDiff->getType() == Line::ADDED) {
94
                        $lines[] = $chunkDiff->getStart() + $counter;
95
                    }
96
                }
97
            }
98
            $resultFilter[$file] = $lines;
99
        }
100
        return $resultFilter;
101
    }
102
103
    /**
104
     * Search for diffs where at least one line of code was added.
105
     * @return SebastianBergmann\Diff\Diff[] diffs adding code.
106
     */
107
    protected function getDiffsWithAddedCode()
108
    {
109
        $diffs = [];
110
        foreach ($this->diffs as $fileDiff) {
111
            foreach ($fileDiff->getChunks() as $chunkDiff) {
112
                foreach ($chunkDiff->getLines() as $lineDiff) {
113
                    if ($lineDiff->getType() == Line::ADDED) {
114
                        $diffs[] = $fileDiff;
115
                        break 2;
116
                    }
117
                }
118
            }
119
        }
120
        return $diffs;
121
    }
122
}
123