3 namespace Drupal\Component\Diff;
5 use Drupal\Component\Diff\Engine\DiffOpCopy;
8 * A class to format Diffs
10 * This class formats the diff in classic diff format.
11 * It is intended that this class be customized via inheritance,
12 * to obtain fancier outputs.
15 * @subpackage DifferenceEngine
19 * Should a block header be shown?
21 public $show_header = TRUE;
24 * Number of leading context "lines" to preserve.
26 * This should be left at zero for this class, but subclasses
27 * may want to set this to other values.
29 public $leading_context_lines = 0;
32 * Number of trailing context "lines" to preserve.
34 * This should be left at zero for this class, but subclasses
35 * may want to set this to other values.
37 public $trailing_context_lines = 0;
44 protected $line_stats = [
45 'counter' => ['x' => 0, 'y' => 0],
46 'offset' => ['x' => 0, 'y' => 0],
52 * @param \Drupal\Component\Diff\Diff $diff
56 * The formatted output.
58 public function format(Diff $diff) {
63 $nlead = $this->leading_context_lines;
64 $ntrail = $this->trailing_context_lines;
68 foreach ($diff->getEdits() as $edit) {
69 if ($edit->type == 'copy') {
70 if (is_array($block)) {
71 if (sizeof($edit->orig) <= $nlead + $ntrail) {
76 $context = array_slice($edit->orig, 0, $ntrail);
77 $block[] = new DiffOpCopy($context);
79 $this->_block($x0, $ntrail + $xi - $x0, $y0, $ntrail + $yi - $y0, $block);
83 $context = $edit->orig;
86 if (!is_array($block)) {
87 $context = array_slice($context, sizeof($context) - $nlead);
88 $x0 = $xi - sizeof($context);
89 $y0 = $yi - sizeof($context);
92 $block[] = new DiffOpCopy($context);
99 $xi += sizeof($edit->orig);
101 if ($edit->closing) {
102 $yi += sizeof($edit->closing);
106 if (is_array($block)) {
107 $this->_block($x0, $xi - $x0, $y0, $yi - $y0, $block);
109 $end = $this->_end_diff();
112 $this->line_stats['counter']['x'] += $xi;
115 $this->line_stats['counter']['y'] += $yi;
121 protected function _block($xbeg, $xlen, $ybeg, $ylen, &$edits) {
122 $this->_start_block($this->_block_header($xbeg, $xlen, $ybeg, $ylen));
123 foreach ($edits as $edit) {
124 if ($edit->type == 'copy') {
125 $this->_context($edit->orig);
127 elseif ($edit->type == 'add') {
128 $this->_added($edit->closing);
130 elseif ($edit->type == 'delete') {
131 $this->_deleted($edit->orig);
133 elseif ($edit->type == 'change') {
134 $this->_changed($edit->orig, $edit->closing);
137 trigger_error('Unknown edit type', E_USER_ERROR);
143 protected function _start_diff() {
147 protected function _end_diff() {
148 $val = ob_get_contents();
153 protected function _block_header($xbeg, $xlen, $ybeg, $ylen) {
155 $xbeg .= "," . ($xbeg + $xlen - 1);
158 $ybeg .= "," . ($ybeg + $ylen - 1);
161 return $xbeg . ($xlen ? ($ylen ? 'c' : 'd') : 'a') . $ybeg;
164 protected function _start_block($header) {
165 if ($this->show_header) {
170 protected function _end_block() {
173 protected function _lines($lines, $prefix = ' ') {
174 foreach ($lines as $line) {
175 echo "$prefix $line\n";
179 protected function _context($lines) {
180 $this->_lines($lines);
183 protected function _added($lines) {
184 $this->_lines($lines, '>');
187 protected function _deleted($lines) {
188 $this->_lines($lines, '<');
191 protected function _changed($orig, $closing) {
192 $this->_deleted($orig);
194 $this->_added($closing);