Chris@0
|
1 <?php
|
Chris@0
|
2
|
Chris@0
|
3 namespace Drupal\Component\Diff;
|
Chris@0
|
4
|
Chris@0
|
5 use Drupal\Component\Diff\Engine\DiffEngine;
|
Chris@0
|
6
|
Chris@0
|
7 /**
|
Chris@0
|
8 * Class representing a 'diff' between two sequences of strings.
|
Chris@0
|
9 * @todo document
|
Chris@0
|
10 * @subpackage DifferenceEngine
|
Chris@0
|
11 *
|
Chris@0
|
12 * Copied from https://www.drupal.org/project/diff which was based PHP diff
|
Chris@0
|
13 * engine for phpwiki. (Taken from phpwiki-1.3.3) The original code in phpwiki
|
Chris@0
|
14 * was copyright (C) 2000, 2001 Geoffrey T. Dairiki <dairiki@dairiki.org> and
|
Chris@0
|
15 * licensed under GPL.
|
Chris@0
|
16 */
|
Chris@0
|
17 class Diff {
|
Chris@0
|
18
|
Chris@0
|
19 /**
|
Chris@0
|
20 * The list of differences as an array of diff operations.
|
Chris@0
|
21 *
|
Chris@0
|
22 * @var \Drupal\Component\Diff\Engine\DiffOp[]
|
Chris@0
|
23 */
|
Chris@0
|
24 protected $edits;
|
Chris@0
|
25
|
Chris@0
|
26 /**
|
Chris@0
|
27 * Constructor.
|
Chris@0
|
28 * Computes diff between sequences of strings.
|
Chris@0
|
29 *
|
Chris@0
|
30 * @param array $from_lines
|
Chris@0
|
31 * An array of strings.
|
Chris@0
|
32 * (Typically these are lines from a file.)
|
Chris@0
|
33 * @param array $to_lines
|
Chris@0
|
34 * An array of strings.
|
Chris@0
|
35 */
|
Chris@0
|
36 public function __construct($from_lines, $to_lines) {
|
Chris@0
|
37 $eng = new DiffEngine();
|
Chris@0
|
38 $this->edits = $eng->diff($from_lines, $to_lines);
|
Chris@0
|
39 //$this->_check($from_lines, $to_lines);
|
Chris@0
|
40 }
|
Chris@0
|
41
|
Chris@0
|
42 /**
|
Chris@0
|
43 * Compute reversed Diff.
|
Chris@0
|
44 *
|
Chris@0
|
45 * SYNOPSIS:
|
Chris@0
|
46 *
|
Chris@0
|
47 * $diff = new Diff($lines1, $lines2);
|
Chris@0
|
48 * $rev = $diff->reverse();
|
Chris@0
|
49 * @return object
|
Chris@0
|
50 * A Diff object representing the inverse of the original diff.
|
Chris@0
|
51 */
|
Chris@0
|
52 public function reverse() {
|
Chris@0
|
53 $rev = $this;
|
Chris@0
|
54 $rev->edits = [];
|
Chris@0
|
55 foreach ($this->edits as $edit) {
|
Chris@0
|
56 $rev->edits[] = $edit->reverse();
|
Chris@0
|
57 }
|
Chris@0
|
58 return $rev;
|
Chris@0
|
59 }
|
Chris@0
|
60
|
Chris@0
|
61 /**
|
Chris@0
|
62 * Check for empty diff.
|
Chris@0
|
63 *
|
Chris@0
|
64 * @return bool True iff two sequences were identical.
|
Chris@0
|
65 */
|
Chris@0
|
66 public function isEmpty() {
|
Chris@0
|
67 foreach ($this->edits as $edit) {
|
Chris@0
|
68 if ($edit->type != 'copy') {
|
Chris@0
|
69 return FALSE;
|
Chris@0
|
70 }
|
Chris@0
|
71 }
|
Chris@0
|
72 return TRUE;
|
Chris@0
|
73 }
|
Chris@0
|
74
|
Chris@0
|
75 /**
|
Chris@0
|
76 * Compute the length of the Longest Common Subsequence (LCS).
|
Chris@0
|
77 *
|
Chris@0
|
78 * This is mostly for diagnostic purposed.
|
Chris@0
|
79 *
|
Chris@0
|
80 * @return int The length of the LCS.
|
Chris@0
|
81 */
|
Chris@0
|
82 public function lcs() {
|
Chris@0
|
83 $lcs = 0;
|
Chris@0
|
84 foreach ($this->edits as $edit) {
|
Chris@0
|
85 if ($edit->type == 'copy') {
|
Chris@0
|
86 $lcs += sizeof($edit->orig);
|
Chris@0
|
87 }
|
Chris@0
|
88 }
|
Chris@0
|
89 return $lcs;
|
Chris@0
|
90 }
|
Chris@0
|
91
|
Chris@0
|
92 /**
|
Chris@0
|
93 * Gets the original set of lines.
|
Chris@0
|
94 *
|
Chris@0
|
95 * This reconstructs the $from_lines parameter passed to the
|
Chris@0
|
96 * constructor.
|
Chris@0
|
97 *
|
Chris@0
|
98 * @return array The original sequence of strings.
|
Chris@0
|
99 */
|
Chris@0
|
100 public function orig() {
|
Chris@0
|
101 $lines = [];
|
Chris@0
|
102
|
Chris@0
|
103 foreach ($this->edits as $edit) {
|
Chris@0
|
104 if ($edit->orig) {
|
Chris@0
|
105 array_splice($lines, sizeof($lines), 0, $edit->orig);
|
Chris@0
|
106 }
|
Chris@0
|
107 }
|
Chris@0
|
108 return $lines;
|
Chris@0
|
109 }
|
Chris@0
|
110
|
Chris@0
|
111 /**
|
Chris@0
|
112 * Gets the closing set of lines.
|
Chris@0
|
113 *
|
Chris@0
|
114 * This reconstructs the $to_lines parameter passed to the
|
Chris@0
|
115 * constructor.
|
Chris@0
|
116 *
|
Chris@0
|
117 * @return array The sequence of strings.
|
Chris@0
|
118 */
|
Chris@0
|
119 public function closing() {
|
Chris@0
|
120 $lines = [];
|
Chris@0
|
121
|
Chris@0
|
122 foreach ($this->edits as $edit) {
|
Chris@0
|
123 if ($edit->closing) {
|
Chris@0
|
124 array_splice($lines, sizeof($lines), 0, $edit->closing);
|
Chris@0
|
125 }
|
Chris@0
|
126 }
|
Chris@0
|
127 return $lines;
|
Chris@0
|
128 }
|
Chris@0
|
129
|
Chris@0
|
130 /**
|
Chris@0
|
131 * Check a Diff for validity.
|
Chris@0
|
132 *
|
Chris@0
|
133 * This is here only for debugging purposes.
|
Chris@0
|
134 */
|
Chris@0
|
135 public function check($from_lines, $to_lines) {
|
Chris@0
|
136 if (serialize($from_lines) != serialize($this->orig())) {
|
Chris@0
|
137 trigger_error("Reconstructed original doesn't match", E_USER_ERROR);
|
Chris@0
|
138 }
|
Chris@0
|
139 if (serialize($to_lines) != serialize($this->closing())) {
|
Chris@0
|
140 trigger_error("Reconstructed closing doesn't match", E_USER_ERROR);
|
Chris@0
|
141 }
|
Chris@0
|
142
|
Chris@0
|
143 $rev = $this->reverse();
|
Chris@0
|
144 if (serialize($to_lines) != serialize($rev->orig())) {
|
Chris@0
|
145 trigger_error("Reversed original doesn't match", E_USER_ERROR);
|
Chris@0
|
146 }
|
Chris@0
|
147 if (serialize($from_lines) != serialize($rev->closing())) {
|
Chris@0
|
148 trigger_error("Reversed closing doesn't match", E_USER_ERROR);
|
Chris@0
|
149 }
|
Chris@0
|
150
|
Chris@0
|
151 $prevtype = 'none';
|
Chris@0
|
152 foreach ($this->edits as $edit) {
|
Chris@0
|
153 if ( $prevtype == $edit->type ) {
|
Chris@0
|
154 trigger_error("Edit sequence is non-optimal", E_USER_ERROR);
|
Chris@0
|
155 }
|
Chris@0
|
156 $prevtype = $edit->type;
|
Chris@0
|
157 }
|
Chris@0
|
158
|
Chris@0
|
159 $lcs = $this->lcs();
|
Chris@0
|
160 trigger_error('Diff okay: LCS = ' . $lcs, E_USER_NOTICE);
|
Chris@0
|
161 }
|
Chris@0
|
162
|
Chris@0
|
163 /**
|
Chris@0
|
164 * Gets the list of differences as an array of diff operations.
|
Chris@0
|
165 *
|
Chris@0
|
166 * @return \Drupal\Component\Diff\Engine\DiffOp[]
|
Chris@0
|
167 * The list of differences as an array of diff operations.
|
Chris@0
|
168 */
|
Chris@0
|
169 public function getEdits() {
|
Chris@0
|
170 return $this->edits;
|
Chris@0
|
171 }
|
Chris@0
|
172
|
Chris@0
|
173 }
|