|
11 | 11 | *
|
12 | 12 | * PHP version 7.2 or greater
|
13 | 13 | *
|
14 |
| - * @package jblond\Diff\Renderer\Text |
15 |
| - * @author Chris Boulton <chris.boulton@interspire.com> |
| 14 | + * @package jblond\Diff\Renderer\Text |
| 15 | + * @author Chris Boulton <chris.boulton@interspire.com> |
16 | 16 | * @copyright (c) 2009 Chris Boulton
|
17 |
| - * @license New BSD License http://www.opensource.org/licenses/bsd-license.php |
18 |
| - * @version 1.15 |
19 |
| - * @link https://github.com/JBlond/php-diff |
| 17 | + * @license New BSD License http://www.opensource.org/licenses/bsd-license.php |
| 18 | + * @version 1.15 |
| 19 | + * @link https://github.com/JBlond/php-diff |
20 | 20 | */
|
21 | 21 | class Context extends RendererAbstract
|
22 | 22 | {
|
23 | 23 | /**
|
24 | 24 | * @var array Array of the different op-code tags and how they map to the context diff-view equivalent.
|
25 | 25 | */
|
26 | 26 | private $tagMap = [
|
27 |
| - 'insert' => '+', |
28 |
| - 'delete' => '-', |
29 |
| - 'replace' => '!', |
30 |
| - 'equal' => ' ' |
| 27 | + 'insert' => '+', |
| 28 | + 'delete' => '-', |
| 29 | + 'replace' => '!', |
| 30 | + 'equal' => ' ', |
31 | 31 | ];
|
32 | 32 |
|
33 | 33 | /**
|
34 | 34 | * Render and return a context formatted (old school!) diff-view.
|
35 | 35 | *
|
| 36 | + * @link https://www.gnu.org/software/diffutils/manual/html_node/Detailed-Context.html#Detailed-Context |
| 37 | + * |
36 | 38 | * @return string The generated context diff-view.
|
37 | 39 | */
|
38 | 40 | public function render(): string
|
39 | 41 | {
|
40 |
| - $diff = ''; |
41 |
| - $opCodes = $this->diff->getGroupedOpCodes(); |
| 42 | + $diff = ''; |
| 43 | + $opCodes = $this->diff->getGroupedOpCodes(); |
42 | 44 |
|
43 | 45 | foreach ($opCodes as $group) {
|
44 |
| - $diff .= "***************\n"; |
45 |
| - $lastItem = count($group) - 1; |
46 |
| - $i1 = $group['0']['1']; |
47 |
| - $i2 = $group[$lastItem]['2']; |
48 |
| - $j1 = $group['0']['3']; |
49 |
| - $j2 = $group[$lastItem]['4']; |
50 |
| - |
51 |
| - if ($i2 - $i1 >= 2) { |
52 |
| - $diff .= '*** ' . ($group['0']['1'] + 1) . ',' . $i2 . " ****\n"; |
53 |
| - } else { |
54 |
| - $diff .= '*** ' . $i2 . " ****\n"; |
55 |
| - } |
56 |
| - |
57 |
| - if ($j2 - $j1 >= 2) { |
58 |
| - $separator = '--- ' . ($j1 + 1) . ',' . $j2 . " ----\n"; |
59 |
| - } else { |
60 |
| - $separator = '--- ' . $j2 . " ----\n"; |
61 |
| - } |
62 |
| - |
63 |
| - $hasVisible = false; |
64 |
| - |
65 |
| - foreach ($group as $code) { |
66 |
| - if ($code['0'] == 'replace' || $code['0'] == 'delete') { |
67 |
| - $hasVisible = true; |
68 |
| - break; |
69 |
| - } |
70 |
| - } |
71 |
| - |
72 |
| - if ($hasVisible) { |
73 |
| - foreach ($group as [$tag, $i1, $i2, $j1, $j2]) { |
74 |
| - if ($tag == 'insert') { |
75 |
| - continue; |
76 |
| - } |
| 46 | + $diff .= "***************\n"; |
| 47 | + $lastItem = count($group) - 1; |
| 48 | + $start1 = $group['0']['1']; |
| 49 | + $end1 = $group[$lastItem]['2']; |
| 50 | + $start2 = $group['0']['3']; |
| 51 | + $end2 = $group[$lastItem]['4']; |
| 52 | + |
| 53 | + // Line to line header for version 1. |
| 54 | + $diffStart = $end1 - $start1 >= 2 ? $start1 + 1 . ',' : ''; |
| 55 | + $diff .= '*** ' . $diffStart . $end1 . " ****\n"; |
| 56 | + |
| 57 | + // Line to line header for version 2. |
| 58 | + $diffStart = $end2 - $start2 >= 2 ? ($start2 + 1) . ',' : ''; |
| 59 | + $separator = '--- ' . $diffStart . $end2 . " ----\n"; |
| 60 | + |
| 61 | + // Check for visible changes by replace or delete operations. |
| 62 | + if (!empty(array_intersect(['replace', 'delete'], array_column($group, 0)))) { |
| 63 | + // Line differences between versions or lines of version 1 are removed from version 2. |
| 64 | + // Add all operations to diff-view of version 1, except for insert. |
| 65 | + $filteredGroups = $this->filterGroups($group, 'insert'); |
| 66 | + foreach ($filteredGroups as [$tag, $start1, $end1, $start2, $end2]) { |
77 | 67 | $diff .= $this->tagMap[$tag] . ' ' .
|
78 | 68 | implode(
|
79 | 69 | "\n" . $this->tagMap[$tag] . ' ',
|
80 |
| - $this->diff->getArrayRange($this->diff->getVersion1(), $i1, $i2) |
| 70 | + $this->diff->getArrayRange($this->diff->getVersion1(), $start1, $end1) |
81 | 71 | ) . "\n";
|
82 | 72 | }
|
83 | 73 | }
|
84 | 74 |
|
85 |
| - $hasVisible = false; |
86 |
| - |
87 |
| - foreach ($group as $code) { |
88 |
| - if ($code['0'] == 'replace' || $code['0'] == 'insert') { |
89 |
| - $hasVisible = true; |
90 |
| - break; |
91 |
| - } |
92 |
| - } |
93 |
| - |
94 | 75 | $diff .= $separator;
|
95 | 76 |
|
96 |
| - if ($hasVisible) { |
97 |
| - foreach ($group as [$tag, $i1, $i2, $j1, $j2]) { |
98 |
| - if ($tag == 'delete') { |
99 |
| - continue; |
100 |
| - } |
| 77 | + // Check for visible changes by replace or insert operations. |
| 78 | + if (!empty(array_intersect(['replace', 'insert'], array_column($group, 0)))) { |
| 79 | + // Line differences between versions or lines are inserted into version 2. |
| 80 | + // Add all operations to diff-view of version 2, except for delete. |
| 81 | + $filteredGroups = $this->filterGroups($group, 'delete'); |
| 82 | + foreach ($filteredGroups as [$tag, $start1, $end1, $start2, $end2]) { |
101 | 83 | $diff .= $this->tagMap[$tag] . ' ' .
|
102 | 84 | implode(
|
103 | 85 | "\n" . $this->tagMap[$tag] . ' ',
|
104 |
| - $this->diff->getArrayRange($this->diff->getVersion2(), $j1, $j2) |
| 86 | + $this->diff->getArrayRange($this->diff->getVersion2(), $start2, $end2) |
105 | 87 | ) . "\n";
|
106 | 88 | }
|
107 | 89 | }
|
108 | 90 | }
|
109 | 91 |
|
110 | 92 | return $diff;
|
111 | 93 | }
|
| 94 | + |
| 95 | + /** |
| 96 | + * Filter out groups by tag. |
| 97 | + * |
| 98 | + * Given an array of groups, all groups which don't have the specified tag are returned. |
| 99 | + * |
| 100 | + * @param array $groups A series of opCode groups. |
| 101 | + * @param string $excludedTag Name of the opCode Tag to filter out. |
| 102 | + * |
| 103 | + * @return array Filtered opCode Groups. |
| 104 | + */ |
| 105 | + private function filterGroups(array $groups, string $excludedTag): array |
| 106 | + { |
| 107 | + return array_filter( |
| 108 | + $groups, |
| 109 | + function ($operation) use ($excludedTag) { |
| 110 | + return $operation[0] != $excludedTag; |
| 111 | + } |
| 112 | + ); |
| 113 | + } |
112 | 114 | }
|
0 commit comments