Merge "Remove duplicate entries in messages.inc"
[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 * 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 /**
46 * Number of trailing context "lines" to preserve.
47 *
48 * This should be left at zero for this class, but subclasses
49 * may want to set this to other values.
50 */
51 protected $trailingContextLines = 0;
52
53 /**
54 * Format a diff.
55 *
56 * @param $diff Diff A Diff object.
57 * @return string The formatted output.
58 */
59 public function format( $diff ) {
60 wfProfileIn( __METHOD__ );
61
62 $xi = $yi = 1;
63 $block = false;
64 $context = array();
65
66 $nlead = $this->leadingContextLines;
67 $ntrail = $this->trailingContextLines;
68
69 $this->startDiff();
70
71 foreach ( $diff->edits as $edit ) {
72 if ( $edit->type == 'copy' ) {
73 if ( is_array( $block ) ) {
74 if ( count( $edit->orig ) <= $nlead + $ntrail ) {
75 $block[] = $edit;
76 } else {
77 if ( $ntrail ) {
78 $context = array_slice( $edit->orig, 0, $ntrail );
79 $block[] = new DiffOp_Copy( $context );
80 }
81 $this->block( $x0, $ntrail + $xi - $x0,
82 $y0, $ntrail + $yi - $y0,
83 $block );
84 $block = false;
85 }
86 }
87 $context = $edit->orig;
88 } else {
89 if ( !is_array( $block ) ) {
90 $context = array_slice( $context, count( $context ) - $nlead );
91 $x0 = $xi - count( $context );
92 $y0 = $yi - count( $context );
93 $block = array();
94 if ( $context ) {
95 $block[] = new DiffOp_Copy( $context );
96 }
97 }
98 $block[] = $edit;
99 }
100
101 if ( $edit->orig ) {
102 $xi += count( $edit->orig );
103 }
104 if ( $edit->closing ) {
105 $yi += count( $edit->closing );
106 }
107 }
108
109 if ( is_array( $block ) ) {
110 $this->block( $x0, $xi - $x0,
111 $y0, $yi - $y0,
112 $block );
113 }
114
115 $end = $this->endDiff();
116 wfProfileOut( __METHOD__ );
117 return $end;
118 }
119
120 /**
121 * @param $xbeg
122 * @param $xlen
123 * @param $ybeg
124 * @param $ylen
125 * @param $edits
126 */
127 protected function block( $xbeg, $xlen, $ybeg, $ylen, &$edits ) {
128 wfProfileIn( __METHOD__ );
129 $this->startBlock( $this->blockHeader( $xbeg, $xlen, $ybeg, $ylen ) );
130 foreach ( $edits as $edit ) {
131 if ( $edit->type == 'copy' ) {
132 $this->context( $edit->orig );
133 } elseif ( $edit->type == 'add' ) {
134 $this->added( $edit->closing );
135 } elseif ( $edit->type == 'delete' ) {
136 $this->deleted( $edit->orig );
137 } elseif ( $edit->type == 'change' ) {
138 $this->changed( $edit->orig, $edit->closing );
139 } else {
140 throw new MWException( "Unknown edit type: {$edit->type}" );
141 }
142 }
143 $this->endBlock();
144 wfProfileOut( __METHOD__ );
145 }
146
147 protected function startDiff() {
148 ob_start();
149 }
150
151 /**
152 * @return string
153 */
154 protected function endDiff() {
155 $val = ob_get_contents();
156 ob_end_clean();
157 return $val;
158 }
159
160 /**
161 * @param $xbeg
162 * @param $xlen
163 * @param $ybeg
164 * @param $ylen
165 * @return string
166 */
167 protected function blockHeader( $xbeg, $xlen, $ybeg, $ylen ) {
168 if ( $xlen > 1 ) {
169 $xbeg .= ',' . ( $xbeg + $xlen - 1 );
170 }
171 if ( $ylen > 1 ) {
172 $ybeg .= ',' . ( $ybeg + $ylen - 1 );
173 }
174
175 return $xbeg . ( $xlen ? ( $ylen ? 'c' : 'd' ) : 'a' ) . $ybeg;
176 }
177
178 protected function startBlock( $header ) {
179 echo $header . "\n";
180 }
181
182 protected function endBlock() {
183 }
184
185 /**
186 * @param $lines
187 * @param $prefix string
188 */
189 protected function lines( $lines, $prefix = ' ' ) {
190 foreach ( $lines as $line ) {
191 echo "$prefix $line\n";
192 }
193 }
194
195 /**
196 * @param $lines
197 */
198 protected function context( $lines ) {
199 $this->lines( $lines );
200 }
201
202 /**
203 * @param $lines
204 */
205 protected function added( $lines ) {
206 $this->lines( $lines, '>' );
207 }
208
209 /**
210 * @param $lines
211 */
212 protected function deleted( $lines ) {
213 $this->lines( $lines, '<' );
214 }
215
216 /**
217 * @param $orig
218 * @param $closing
219 */
220 protected function changed( $orig, $closing ) {
221 $this->deleted( $orig );
222 echo "---\n";
223 $this->added( $closing );
224 }
225 }