1
+ − 1
<?php
+ − 2
/**
+ − 3
* A class to render Diffs in different formats.
+ − 4
*
+ − 5
* This class renders the diff in classic diff format. It is intended that
+ − 6
* this class be customized via inheritance, to obtain fancier outputs.
+ − 7
*
+ − 8
* $Horde: framework/Text_Diff/Diff/Renderer.php,v 1.12 2005/12/16 11:07:33 jan Exp $
+ − 9
*
+ − 10
* @package Text_Diff
+ − 11
*/
+ − 12
class Text_Diff_Renderer {
+ − 13
+ − 14
/**
+ − 15
* Number of leading context "lines" to preserve.
+ − 16
*
+ − 17
* This should be left at zero for this class, but subclasses may want to
+ − 18
* set this to other values.
+ − 19
*/
+ − 20
var $_leading_context_lines = 0;
+ − 21
+ − 22
/**
+ − 23
* Number of trailing context "lines" to preserve.
+ − 24
*
+ − 25
* This should be left at zero for this class, but subclasses may want to
+ − 26
* set this to other values.
+ − 27
*/
+ − 28
var $_trailing_context_lines = 0;
+ − 29
+ − 30
/**
+ − 31
* Constructor.
+ − 32
*/
+ − 33
function Text_Diff_Renderer($params = array())
+ − 34
{
+ − 35
foreach ($params as $param => $value) {
+ − 36
$v = '_' . $param;
+ − 37
if (isset($this->$v)) {
+ − 38
$this->$v = $value;
+ − 39
}
+ − 40
}
+ − 41
}
+ − 42
+ − 43
/**
+ − 44
* Get any renderer parameters.
+ − 45
*
+ − 46
* @return array All parameters of this renderer object.
+ − 47
*/
+ − 48
function getParams()
+ − 49
{
+ − 50
$params = array();
+ − 51
foreach (get_object_vars($this) as $k => $v) {
+ − 52
if ($k[0] == '_') {
+ − 53
$params[substr($k, 1)] = $v;
+ − 54
}
+ − 55
}
+ − 56
+ − 57
return $params;
+ − 58
}
+ − 59
+ − 60
/**
+ − 61
* Renders a diff.
+ − 62
*
+ − 63
* @param Text_Diff $diff A Text_Diff object.
+ − 64
*
+ − 65
* @return string The formatted output.
+ − 66
*/
+ − 67
function render($diff)
+ − 68
{
+ − 69
$xi = $yi = 1;
+ − 70
$block = false;
+ − 71
$context = array();
+ − 72
+ − 73
$nlead = $this->_leading_context_lines;
+ − 74
$ntrail = $this->_trailing_context_lines;
+ − 75
+ − 76
$output = $this->_startDiff();
+ − 77
+ − 78
$diffs = $diff->getDiff();
+ − 79
foreach ($diffs as $i => $edit) {
+ − 80
if (is_a($edit, 'Text_Diff_Op_copy')) {
+ − 81
if (is_array($block)) {
+ − 82
$keep = $i == count($diffs) - 1 ? $ntrail : $nlead + $ntrail;
+ − 83
if (count($edit->orig) <= $keep) {
+ − 84
$block[] = $edit;
+ − 85
} else {
+ − 86
if ($ntrail) {
+ − 87
$context = array_slice($edit->orig, 0, $ntrail);
+ − 88
$block[] = &new Text_Diff_Op_copy($context);
+ − 89
}
+ − 90
$output .= $this->_block($x0, $ntrail + $xi - $x0,
+ − 91
$y0, $ntrail + $yi - $y0,
+ − 92
$block);
+ − 93
$block = false;
+ − 94
}
+ − 95
}
+ − 96
$context = $edit->orig;
+ − 97
} else {
+ − 98
if (!is_array($block)) {
+ − 99
$context = array_slice($context, count($context) - $nlead);
+ − 100
$x0 = $xi - count($context);
+ − 101
$y0 = $yi - count($context);
+ − 102
$block = array();
+ − 103
if ($context) {
+ − 104
$block[] = &new Text_Diff_Op_copy($context);
+ − 105
}
+ − 106
}
+ − 107
$block[] = $edit;
+ − 108
}
+ − 109
+ − 110
if ($edit->orig) {
+ − 111
$xi += count($edit->orig);
+ − 112
}
+ − 113
if ($edit->final) {
+ − 114
$yi += count($edit->final);
+ − 115
}
+ − 116
}
+ − 117
+ − 118
if (is_array($block)) {
+ − 119
$output .= $this->_block($x0, $xi - $x0,
+ − 120
$y0, $yi - $y0,
+ − 121
$block);
+ − 122
}
+ − 123
+ − 124
return $output . $this->_endDiff();
+ − 125
}
+ − 126
+ − 127
function _block($xbeg, $xlen, $ybeg, $ylen, &$edits)
+ − 128
{
+ − 129
$output = $this->_startBlock($this->_blockHeader($xbeg, $xlen, $ybeg, $ylen));
+ − 130
+ − 131
foreach ($edits as $edit) {
+ − 132
switch (strtolower(get_class($edit))) {
+ − 133
case 'text_diff_op_copy':
+ − 134
$output .= $this->_context($edit->orig);
+ − 135
break;
+ − 136
+ − 137
case 'text_diff_op_add':
+ − 138
$output .= $this->_added($edit->final);
+ − 139
break;
+ − 140
+ − 141
case 'text_diff_op_delete':
+ − 142
$output .= $this->_deleted($edit->orig);
+ − 143
break;
+ − 144
+ − 145
case 'text_diff_op_change':
+ − 146
$output .= $this->_changed($edit->orig, $edit->final);
+ − 147
break;
+ − 148
}
+ − 149
}
+ − 150
+ − 151
return $output . $this->_endBlock();
+ − 152
}
+ − 153
+ − 154
function _startDiff()
+ − 155
{
+ − 156
return '';
+ − 157
}
+ − 158
+ − 159
function _endDiff()
+ − 160
{
+ − 161
return '';
+ − 162
}
+ − 163
+ − 164
function _blockHeader($xbeg, $xlen, $ybeg, $ylen)
+ − 165
{
+ − 166
if ($xlen > 1) {
+ − 167
$xbeg .= ',' . ($xbeg + $xlen - 1);
+ − 168
}
+ − 169
if ($ylen > 1) {
+ − 170
$ybeg .= ',' . ($ybeg + $ylen - 1);
+ − 171
}
+ − 172
+ − 173
return $xbeg . ($xlen ? ($ylen ? 'c' : 'd') : 'a') . $ybeg;
+ − 174
}
+ − 175
+ − 176
function _startBlock($header)
+ − 177
{
+ − 178
return $header . "\n";
+ − 179
}
+ − 180
+ − 181
function _endBlock()
+ − 182
{
+ − 183
return '';
+ − 184
}
+ − 185
+ − 186
function _lines($lines, $prefix = ' ')
+ − 187
{
+ − 188
return $prefix . implode("\n$prefix", $lines) . "\n";
+ − 189
}
+ − 190
+ − 191
function _context($lines)
+ − 192
{
+ − 193
return $this->_lines($lines);
+ − 194
}
+ − 195
+ − 196
function _added($lines)
+ − 197
{
+ − 198
return $this->_lines($lines, '>');
+ − 199
}
+ − 200
+ − 201
function _deleted($lines)
+ − 202
{
+ − 203
return $this->_lines($lines, '<');
+ − 204
}
+ − 205
+ − 206
function _changed($orig, $final)
+ − 207
{
+ − 208
return $this->_deleted($orig) . "---\n" . $this->_added($final);
+ − 209
}
+ − 210
+ − 211
}