Merge "Http::getProxy() method to get proxy configuration"
[lhc/web/wiklou.git] / includes / diff / DiffFormatter.php
1 <?php
2 /**
3 * Base for diff rendering classes. Portions taken from phpwiki-1.3.3.
4 *
5 * Copyright © 2000, 2001 Geoffrey T. Dairiki <dairiki@dairiki.org>
6 * You may copy this code freely under the conditions of the GPL.
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License along
19 * with this program; if not, write to the Free Software Foundation, Inc.,
20 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
21 * http://www.gnu.org/copyleft/gpl.html
22 *
23 * @file
24 * @ingroup DifferenceEngine
25 */
26
27 /**
28 * Base class for diff formatters
29 *
30 * This class formats the diff in classic diff format.
31 * It is intended that this class be customized via inheritance,
32 * to obtain fancier outputs.
33 * @todo document
34 * @ingroup DifferenceEngine
35 */
36 abstract class DiffFormatter {
37
38 /** @var int Number of leading context "lines" to preserve.
39 *
40 * This should be left at zero for this class, but subclasses
41 * may want to set this to other values.
42 */
43 protected $leadingContextLines = 0;
44
45 /** @var int Number of trailing context "lines" to preserve.
46 *
47 * This should be left at zero for this class, but subclasses
48 * may want to set this to other values.
49 */
50 protected $trailingContextLines = 0;
51
52 /** @var string The output buffer; holds the output while it is built. */
53 private $result = '';
54
55 /**
56 * Format a diff.
57 *
58 * @param Diff $diff
59 *
60 * @return string The formatted output.
61 */
62 public function format( $diff ) {
63
64 $xi = $yi = 1;
65 $block = false;
66 $context = [];
67
68 $nlead = $this->leadingContextLines;
69 $ntrail = $this->trailingContextLines;
70
71 $this->startDiff();
72
73 // Initialize $x0 and $y0 to prevent IDEs from getting confused.
74 $x0 = $y0 = 0;
75 foreach ( $diff->edits as $edit ) {
76 if ( $edit->type == 'copy' ) {
77 if ( is_array( $block ) ) {
78 if ( count( $edit->orig ) <= $nlead + $ntrail ) {
79 $block[] = $edit;
80 } else {
81 if ( $ntrail ) {
82 $context = array_slice( $edit->orig, 0, $ntrail );
83 $block[] = new DiffOpCopy( $context );
84 }
85 $this->block( $x0, $ntrail + $xi - $x0,
86 $y0, $ntrail + $yi - $y0,
87 $block );
88 $block = false;
89 }
90 }
91 $context = $edit->orig;
92 } else {
93 if ( !is_array( $block ) ) {
94 $context = array_slice( $context, count( $context ) - $nlead );
95 $x0 = $xi - count( $context );
96 $y0 = $yi - count( $context );
97 $block = [];
98 if ( $context ) {
99 $block[] = new DiffOpCopy( $context );
100 }
101 }
102 $block[] = $edit;
103 }
104
105 if ( $edit->orig ) {
106 $xi += count( $edit->orig );
107 }
108 if ( $edit->closing ) {
109 $yi += count( $edit->closing );
110 }
111 }
112
113 if ( is_array( $block ) ) {
114 $this->block( $x0, $xi - $x0,
115 $y0, $yi - $y0,
116 $block );
117 }
118
119 $end = $this->endDiff();
120
121 return $end;
122 }
123
124 /**
125 * @param int $xbeg
126 * @param int $xlen
127 * @param int $ybeg
128 * @param int $ylen
129 * @param array $edits
130 *
131 * @throws MWException If the edit type is not known.
132 */
133 protected function block( $xbeg, $xlen, $ybeg, $ylen, &$edits ) {
134 $this->startBlock( $this->blockHeader( $xbeg, $xlen, $ybeg, $ylen ) );
135 foreach ( $edits as $edit ) {
136 if ( $edit->type == 'copy' ) {
137 $this->context( $edit->orig );
138 } elseif ( $edit->type == 'add' ) {
139 $this->added( $edit->closing );
140 } elseif ( $edit->type == 'delete' ) {
141 $this->deleted( $edit->orig );
142 } elseif ( $edit->type == 'change' ) {
143 $this->changed( $edit->orig, $edit->closing );
144 } else {
145 throw new MWException( "Unknown edit type: {$edit->type}" );
146 }
147 }
148 $this->endBlock();
149 }
150
151 protected function startDiff() {
152 $this->result = '';
153 }
154
155 /**
156 * Writes a string to the output buffer.
157 *
158 * @param string $text
159 */
160 protected function writeOutput( $text ) {
161 $this->result .= $text;
162 }
163
164 /**
165 * @return string
166 */
167 protected function endDiff() {
168 $val = $this->result;
169 $this->result = '';
170
171 return $val;
172 }
173
174 /**
175 * @param int $xbeg
176 * @param int $xlen
177 * @param int $ybeg
178 * @param int $ylen
179 *
180 * @return string
181 */
182 protected function blockHeader( $xbeg, $xlen, $ybeg, $ylen ) {
183 if ( $xlen > 1 ) {
184 $xbeg .= ',' . ( $xbeg + $xlen - 1 );
185 }
186 if ( $ylen > 1 ) {
187 $ybeg .= ',' . ( $ybeg + $ylen - 1 );
188 }
189
190 return $xbeg . ( $xlen ? ( $ylen ? 'c' : 'd' ) : 'a' ) . $ybeg;
191 }
192
193 /**
194 * Called at the start of a block of connected edits.
195 * This default implementation writes the header and a newline to the output buffer.
196 *
197 * @param string $header
198 */
199 protected function startBlock( $header ) {
200 $this->writeOutput( $header . "\n" );
201 }
202
203 /**
204 * Called at the end of a block of connected edits.
205 * This default implementation does nothing.
206 */
207 protected function endBlock() {
208 }
209
210 /**
211 * Writes all (optionally prefixed) lines to the output buffer, separated by newlines.
212 *
213 * @param string[] $lines
214 * @param string $prefix
215 */
216 protected function lines( $lines, $prefix = ' ' ) {
217 foreach ( $lines as $line ) {
218 $this->writeOutput( "$prefix $line\n" );
219 }
220 }
221
222 /**
223 * @param string[] $lines
224 */
225 protected function context( $lines ) {
226 $this->lines( $lines );
227 }
228
229 /**
230 * @param string[] $lines
231 */
232 protected function added( $lines ) {
233 $this->lines( $lines, '>' );
234 }
235
236 /**
237 * @param string[] $lines
238 */
239 protected function deleted( $lines ) {
240 $this->lines( $lines, '<' );
241 }
242
243 /**
244 * Writes the two sets of lines to the output buffer, separated by "---" and a newline.
245 *
246 * @param string[] $orig
247 * @param string[] $closing
248 */
249 protected function changed( $orig, $closing ) {
250 $this->deleted( $orig );
251 $this->writeOutput( "---\n" );
252 $this->added( $closing );
253 }
254
255 }