1: <?php
2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14:
15: class Horde_Text_Diff_Renderer
16: {
17: 18: 19: 20: 21: 22:
23: protected $_leading_context_lines = 0;
24:
25: 26: 27: 28: 29: 30:
31: protected $_trailing_context_lines = 0;
32:
33: 34: 35:
36: public function __construct($params = array())
37: {
38: foreach ($params as $param => $value) {
39: $v = '_' . $param;
40: if (isset($this->$v)) {
41: $this->$v = $value;
42: }
43: }
44: }
45:
46: 47: 48: 49: 50:
51: public function getParams()
52: {
53: $params = array();
54: foreach (get_object_vars($this) as $k => $v) {
55: if ($k[0] == '_') {
56: $params[substr($k, 1)] = $v;
57: }
58: }
59:
60: return $params;
61: }
62:
63: 64: 65: 66: 67: 68: 69:
70: public function render($diff)
71: {
72: $xi = $yi = 1;
73: $block = false;
74: $context = array();
75:
76: $nlead = $this->_leading_context_lines;
77: $ntrail = $this->_trailing_context_lines;
78:
79: $output = $this->_startDiff();
80:
81: $diffs = $diff->getDiff();
82: foreach ($diffs as $i => $edit) {
83: 84: 85:
86: if ($edit instanceof Horde_Text_Diff_Op_Copy) {
87:
88: if (is_array($block)) {
89: 90:
91: $keep = $i == count($diffs) - 1 ? $ntrail : $nlead + $ntrail;
92: if (count($edit->orig) <= $keep) {
93: 94:
95: $block[] = $edit;
96: } else {
97: if ($ntrail) {
98: 99:
100: $context = array_slice($edit->orig, 0, $ntrail);
101: $block[] = new Horde_Text_Diff_Op_Copy($context);
102: }
103:
104: $output .= $this->_block($x0, $ntrail + $xi - $x0,
105: $y0, $ntrail + $yi - $y0,
106: $block);
107: $block = false;
108: }
109: }
110:
111: $context = $edit->orig;
112: } else {
113:
114: if (!is_array($block)) {
115:
116: $context = array_slice($context, count($context) - $nlead);
117: $x0 = $xi - count($context);
118: $y0 = $yi - count($context);
119: $block = array();
120: if ($context) {
121: $block[] = new Horde_Text_Diff_Op_Copy($context);
122: }
123: }
124: $block[] = $edit;
125: }
126:
127: if ($edit->orig) {
128: $xi += count($edit->orig);
129: }
130: if ($edit->final) {
131: $yi += count($edit->final);
132: }
133: }
134:
135: if (is_array($block)) {
136: $output .= $this->_block($x0, $xi - $x0,
137: $y0, $yi - $y0,
138: $block);
139: }
140:
141: return $output . $this->_endDiff();
142: }
143:
144: protected function _block($xbeg, $xlen, $ybeg, $ylen, &$edits)
145: {
146: $output = $this->_startBlock($this->_blockHeader($xbeg, $xlen, $ybeg, $ylen));
147:
148: foreach ($edits as $edit) {
149: switch (get_class($edit)) {
150: case 'Horde_Text_Diff_Op_Copy':
151: $output .= $this->_context($edit->orig);
152: break;
153:
154: case 'Horde_Text_Diff_Op_Add':
155: $output .= $this->_added($edit->final);
156: break;
157:
158: case 'Horde_Text_Diff_Op_Delete':
159: $output .= $this->_deleted($edit->orig);
160: break;
161:
162: case 'Horde_Text_Diff_Op_Change':
163: $output .= $this->_changed($edit->orig, $edit->final);
164: break;
165: }
166: }
167:
168: return $output . $this->_endBlock();
169: }
170:
171: protected function _startDiff()
172: {
173: return '';
174: }
175:
176: protected function _endDiff()
177: {
178: return '';
179: }
180:
181: protected function ($xbeg, $xlen, $ybeg, $ylen)
182: {
183: if ($xlen > 1) {
184: $xbeg .= ',' . ($xbeg + $xlen - 1);
185: }
186: if ($ylen > 1) {
187: $ybeg .= ',' . ($ybeg + $ylen - 1);
188: }
189:
190:
191: if ($xlen && !$ylen) {
192: $ybeg--;
193: } elseif (!$xlen) {
194: $xbeg--;
195: }
196:
197: return $xbeg . ($xlen ? ($ylen ? 'c' : 'd') : 'a') . $ybeg;
198: }
199:
200: protected function _startBlock($header)
201: {
202: return $header . "\n";
203: }
204:
205: protected function _endBlock()
206: {
207: return '';
208: }
209:
210: protected function _lines($lines, $prefix = ' ')
211: {
212: return $prefix . implode("\n$prefix", $lines) . "\n";
213: }
214:
215: protected function _context($lines)
216: {
217: return $this->_lines($lines, ' ');
218: }
219:
220: protected function _added($lines)
221: {
222: return $this->_lines($lines, '> ');
223: }
224:
225: protected function _deleted($lines)
226: {
227: return $this->_lines($lines, '< ');
228: }
229:
230: protected function _changed($orig, $final)
231: {
232: return $this->_deleted($orig) . "---\n" . $this->_added($final);
233: }
234: }
235: