Mercurial > hg > isophonics-drupal-site
comparison vendor/sebastian/diff/src/Output/UnifiedDiffOutputBuilder.php @ 14:1fec387a4317
Update Drupal core to 8.5.2 via Composer
author | Chris Cannam |
---|---|
date | Mon, 23 Apr 2018 09:46:53 +0100 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
13:5fb285c0d0e3 | 14:1fec387a4317 |
---|---|
1 <?php declare(strict_types=1); | |
2 /* | |
3 * This file is part of sebastian/diff. | |
4 * | |
5 * (c) Sebastian Bergmann <sebastian@phpunit.de> | |
6 * | |
7 * For the full copyright and license information, please view the LICENSE | |
8 * file that was distributed with this source code. | |
9 */ | |
10 | |
11 namespace SebastianBergmann\Diff\Output; | |
12 | |
13 /** | |
14 * Builds a diff string representation in unified diff format in chunks. | |
15 */ | |
16 final class UnifiedDiffOutputBuilder extends AbstractChunkOutputBuilder | |
17 { | |
18 /** | |
19 * @var string | |
20 */ | |
21 private $header; | |
22 | |
23 /** | |
24 * @var bool | |
25 */ | |
26 private $addLineNumbers; | |
27 | |
28 public function __construct(string $header = "--- Original\n+++ New\n", bool $addLineNumbers = false) | |
29 { | |
30 $this->header = $header; | |
31 $this->addLineNumbers = $addLineNumbers; | |
32 } | |
33 | |
34 public function getDiff(array $diff): string | |
35 { | |
36 $buffer = \fopen('php://memory', 'r+b'); | |
37 | |
38 if ('' !== $this->header) { | |
39 \fwrite($buffer, $this->header); | |
40 if ("\n" !== \substr($this->header, -1, 1)) { | |
41 \fwrite($buffer, "\n"); | |
42 } | |
43 } | |
44 | |
45 $this->writeDiffChunked($buffer, $diff, $this->getCommonChunks($diff)); | |
46 | |
47 $diff = \stream_get_contents($buffer, -1, 0); | |
48 | |
49 \fclose($buffer); | |
50 | |
51 return $diff; | |
52 } | |
53 | |
54 // `old` is an array with key => value pairs . Each pair represents a start and end index of `diff` | |
55 // of a list of elements all containing `same` (0) entries. | |
56 private function writeDiffChunked($output, array $diff, array $old) | |
57 { | |
58 $upperLimit = \count($diff); | |
59 $start = 0; | |
60 $fromStart = 0; | |
61 $toStart = 0; | |
62 | |
63 if (\count($old)) { // no common parts, list all diff entries | |
64 \reset($old); | |
65 | |
66 // iterate the diff, go from chunk to chunk skipping common chunk of lines between those | |
67 do { | |
68 $commonStart = \key($old); | |
69 $commonEnd = \current($old); | |
70 | |
71 if ($commonStart !== $start) { | |
72 list($fromRange, $toRange) = $this->getChunkRange($diff, $start, $commonStart); | |
73 $this->writeChunk($output, $diff, $start, $commonStart, $fromStart, $fromRange, $toStart, $toRange); | |
74 | |
75 $fromStart += $fromRange; | |
76 $toStart += $toRange; | |
77 } | |
78 | |
79 $start = $commonEnd + 1; | |
80 $commonLength = $commonEnd - $commonStart + 1; // calculate number of non-change lines in the common part | |
81 $fromStart += $commonLength; | |
82 $toStart += $commonLength; | |
83 } while (false !== \next($old)); | |
84 | |
85 \end($old); // short cut for finding possible last `change entry` | |
86 $tmp = \key($old); | |
87 \reset($old); | |
88 if ($old[$tmp] === $upperLimit - 1) { | |
89 $upperLimit = $tmp; | |
90 } | |
91 } | |
92 | |
93 if ($start < $upperLimit - 1) { // check for trailing (non) diff entries | |
94 do { | |
95 --$upperLimit; | |
96 } while (isset($diff[$upperLimit][1]) && $diff[$upperLimit][1] === 0); | |
97 ++$upperLimit; | |
98 | |
99 list($fromRange, $toRange) = $this->getChunkRange($diff, $start, $upperLimit); | |
100 $this->writeChunk($output, $diff, $start, $upperLimit, $fromStart, $fromRange, $toStart, $toRange); | |
101 } | |
102 } | |
103 | |
104 private function writeChunk( | |
105 $output, | |
106 array $diff, | |
107 int $diffStartIndex, | |
108 int $diffEndIndex, | |
109 int $fromStart, | |
110 int $fromRange, | |
111 int $toStart, | |
112 int $toRange | |
113 ) { | |
114 if ($this->addLineNumbers) { | |
115 \fwrite($output, '@@ -' . (1 + $fromStart)); | |
116 | |
117 if ($fromRange > 1) { | |
118 \fwrite($output, ',' . $fromRange); | |
119 } | |
120 | |
121 \fwrite($output, ' +' . (1 + $toStart)); | |
122 if ($toRange > 1) { | |
123 \fwrite($output, ',' . $toRange); | |
124 } | |
125 | |
126 \fwrite($output, " @@\n"); | |
127 } else { | |
128 \fwrite($output, "@@ @@\n"); | |
129 } | |
130 | |
131 for ($i = $diffStartIndex; $i < $diffEndIndex; ++$i) { | |
132 if ($diff[$i][1] === 1 /* ADDED */) { | |
133 \fwrite($output, '+' . $diff[$i][0]); | |
134 } elseif ($diff[$i][1] === 2 /* REMOVED */) { | |
135 \fwrite($output, '-' . $diff[$i][0]); | |
136 } else { /* Not changed (old) 0 or Warning 3 */ | |
137 \fwrite($output, ' ' . $diff[$i][0]); | |
138 } | |
139 | |
140 $lc = \substr($diff[$i][0], -1); | |
141 if ($lc !== "\n" && $lc !== "\r") { | |
142 \fwrite($output, "\n"); // \No newline at end of file | |
143 } | |
144 } | |
145 } | |
146 | |
147 private function getChunkRange(array $diff, int $diffStartIndex, int $diffEndIndex): array | |
148 { | |
149 $toRange = 0; | |
150 $fromRange = 0; | |
151 | |
152 for ($i = $diffStartIndex; $i < $diffEndIndex; ++$i) { | |
153 if ($diff[$i][1] === 1) { // added | |
154 ++$toRange; | |
155 } elseif ($diff[$i][1] === 2) { // removed | |
156 ++$fromRange; | |
157 } elseif ($diff[$i][1] === 0) { // same | |
158 ++$fromRange; | |
159 ++$toRange; | |
160 } | |
161 } | |
162 | |
163 return [$fromRange, $toRange]; | |
164 } | |
165 } |