ILIAS  trunk Revision v13.0_alpha-62-g3b72d83f2e5
ILIAS\COPage\WordDiff\WordDiff Class Reference

Creates word-level marked-up versions of two text sequences. More...

+ Collaboration diagram for ILIAS\COPage\WordDiff\WordDiff:

Public Member Functions

 __construct (array $original_lines, array $closing_lines)
 
 orig ()
 
 closing ()
 

Private Member Functions

 split (array $lines)
 
 findMatches (array $left, array $right)
 
 findMatchesInRange (array $left, array $right, int $left_offset, int $right_offset)
 
 lcsLengths (array $left, array $right)
 
 appendChangedTokens (array $tokens, string $tag, array &$output_tokens, array &$output_tags)
 
 render (array $tokens, array $tags)
 
 flushGroup (string &$line, string &$group, string $tag)
 

Private Attributes

const MAX_LINE_LENGTH = 10000
 
array $original
 
array $closing
 

Detailed Description

Creates word-level marked-up versions of two text sequences.

Definition at line 26 of file class.WordDiff.php.

Constructor & Destructor Documentation

◆ __construct()

ILIAS\COPage\WordDiff\WordDiff::__construct ( array  $original_lines,
array  $closing_lines 
)
Parameters
list<string>$original_lines
list<string>$closing_lines

Definition at line 40 of file class.WordDiff.php.

41 {
42 [$original_words, $original_comparison] = $this->split($original_lines);
43 [$closing_words, $closing_comparison] = $this->split($closing_lines);
44
45 $matches = $this->findMatches($original_comparison, $closing_comparison);
46 $original_tokens = [];
47 $original_tags = [];
48 $closing_tokens = [];
49 $closing_tags = [];
50 $original_position = 0;
51 $closing_position = 0;
52
53 foreach ($matches as [$original_match, $closing_match]) {
55 array_slice($original_words, $original_position, $original_match - $original_position),
56 'del',
57 $original_tokens,
58 $original_tags
59 );
61 array_slice($closing_words, $closing_position, $closing_match - $closing_position),
62 'ins',
63 $closing_tokens,
64 $closing_tags
65 );
66
67 $original_tokens[] = $original_words[$original_match];
68 $original_tags[] = '';
69 $closing_tokens[] = $closing_words[$closing_match];
70 $closing_tags[] = '';
71 $original_position = $original_match + 1;
72 $closing_position = $closing_match + 1;
73 }
74
76 array_slice($original_words, $original_position),
77 'del',
78 $original_tokens,
79 $original_tags
80 );
82 array_slice($closing_words, $closing_position),
83 'ins',
84 $closing_tokens,
85 $closing_tags
86 );
87
88 $this->original = $this->render($original_tokens, $original_tags);
89 $this->closing = $this->render($closing_tokens, $closing_tags);
90 }
appendChangedTokens(array $tokens, string $tag, array &$output_tokens, array &$output_tags)
findMatches(array $left, array $right)
render(array $tokens, array $tags)

References ILIAS\COPage\WordDiff\WordDiff\appendChangedTokens(), ILIAS\COPage\WordDiff\WordDiff\closing(), ILIAS\COPage\WordDiff\WordDiff\findMatches(), ILIAS\COPage\WordDiff\WordDiff\render(), and ILIAS\COPage\WordDiff\WordDiff\split().

+ Here is the call graph for this function:

Member Function Documentation

◆ appendChangedTokens()

ILIAS\COPage\WordDiff\WordDiff::appendChangedTokens ( array  $tokens,
string  $tag,
array &  $output_tokens,
array &  $output_tags 
)
private
Parameters
list<string>$tokens
list<string>$output_tokens
list<string>$output_tags

Definition at line 231 of file class.WordDiff.php.

236 : void {
237 foreach ($tokens as $token) {
238 $output_tokens[] = $token;
239 $output_tags[] = $tag;
240 }
241 }
$token
Definition: xapitoken.php:69

References $token.

Referenced by ILIAS\COPage\WordDiff\WordDiff\__construct().

+ Here is the caller graph for this function:

◆ closing()

ILIAS\COPage\WordDiff\WordDiff::closing ( )
Returns
list<string>

Definition at line 99 of file class.WordDiff.php.

99 : array
100 {
101 return $this->closing;
102 }

References ILIAS\COPage\WordDiff\WordDiff\$closing.

Referenced by ILIAS\COPage\WordDiff\WordDiff\__construct().

+ Here is the caller graph for this function:

◆ findMatches()

ILIAS\COPage\WordDiff\WordDiff::findMatches ( array  $left,
array  $right 
)
private
Parameters
list<string>$left
list<string>$right
Returns
list<array{int, int}>

Definition at line 144 of file class.WordDiff.php.

144 : array
145 {
146 if ($left === $right) {
147 $matches = [];
148 foreach ($left as $index => $_word) {
149 $matches[] = [$index, $index];
150 }
151 return $matches;
152 }
153
154 return $this->findMatchesInRange($left, $right, 0, 0);
155 }
findMatchesInRange(array $left, array $right, int $left_offset, int $right_offset)

References ILIAS\COPage\WordDiff\WordDiff\findMatchesInRange().

Referenced by ILIAS\COPage\WordDiff\WordDiff\__construct().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ findMatchesInRange()

ILIAS\COPage\WordDiff\WordDiff::findMatchesInRange ( array  $left,
array  $right,
int  $left_offset,
int  $right_offset 
)
private
Parameters
list<string>$left
list<string>$right
Returns
list<array{int, int}>

Definition at line 162 of file class.WordDiff.php.

167 : array {
168 if ($left === [] || $right === []) {
169 return [];
170 }
171
172 if (count($left) === 1) {
173 $position = array_search($left[0], $right, true);
174 return $position === false ? [] : [[$left_offset, $right_offset + $position]];
175 }
176
177 $middle = intdiv(count($left), 2);
178 $left_half = array_slice($left, 0, $middle);
179 $right_half = array_slice($left, $middle);
180 $forward_lengths = $this->lcsLengths($left_half, $right);
181 $backward_lengths = $this->lcsLengths(array_reverse($right_half), array_reverse($right));
182
183 $right_split = 0;
184 $longest = -1;
185 $right_length = count($right);
186 for ($index = 0; $index <= $right_length; $index++) {
187 $length = $forward_lengths[$index] + $backward_lengths[$right_length - $index];
188 if ($length > $longest) {
189 $longest = $length;
190 $right_split = $index;
191 }
192 }
193
194 return array_merge(
195 $this->findMatchesInRange($left_half, array_slice($right, 0, $right_split), $left_offset, $right_offset),
196 $this->findMatchesInRange(
197 $right_half,
198 array_slice($right, $right_split),
199 $left_offset + $middle,
200 $right_offset + $right_split
201 )
202 );
203 }
lcsLengths(array $left, array $right)

Referenced by ILIAS\COPage\WordDiff\WordDiff\findMatches().

+ Here is the caller graph for this function:

◆ flushGroup()

ILIAS\COPage\WordDiff\WordDiff::flushGroup ( string &  $line,
string &  $group,
string  $tag 
)
private

Definition at line 276 of file class.WordDiff.php.

276 : void
277 {
278 if ($group !== '') {
279 if ($tag === 'ins') {
280 $line .= '[ilDiffInsStart]' . htmlspecialchars($group) . '[ilDiffInsEnd]';
281 } elseif ($tag === 'del') {
282 $line .= '[ilDiffDelStart]' . htmlspecialchars($group) . '[ilDiffDelEnd]';
283 } else {
284 $line .= htmlspecialchars($group);
285 }
286 }
287 $group = '';
288 }

◆ lcsLengths()

ILIAS\COPage\WordDiff\WordDiff::lcsLengths ( array  $left,
array  $right 
)
private
Parameters
list<string>$left
list<string>$right
Returns
list<int>

Definition at line 210 of file class.WordDiff.php.

210 : array
211 {
212 $previous = array_fill(0, count($right) + 1, 0);
213 foreach ($left as $left_word) {
214 $current = [0];
215 foreach ($right as $index => $right_word) {
216 $current[] = $left_word === $right_word
217 ? $previous[$index] + 1
218 : max($previous[$index + 1], $current[$index]);
219 }
220 $previous = $current;
221 }
222
223 return $previous;
224 }

◆ orig()

ILIAS\COPage\WordDiff\WordDiff::orig ( )
Returns
list<string>

Definition at line 93 of file class.WordDiff.php.

93 : array
94 {
95 return $this->original;
96 }

References ILIAS\COPage\WordDiff\WordDiff\$original.

◆ render()

ILIAS\COPage\WordDiff\WordDiff::render ( array  $tokens,
array  $tags 
)
private
Parameters
list<string>$tokens
list<string>$tags
Returns
list<string>

Definition at line 248 of file class.WordDiff.php.

248 : array
249 {
250 $lines = [];
251 $line = '';
252 $group = '';
253 $current_tag = '';
254
255 foreach ($tokens as $index => $token) {
256 $tag = $tags[$index];
257 if ($tag !== $current_tag) {
258 $this->flushGroup($line, $group, $current_tag);
259 $current_tag = $tag;
260 }
261
262 if ($token !== '' && $token[0] === "\n") {
263 $this->flushGroup($line, $group, $current_tag);
264 $lines[] = $line !== '' ? $line : '&#160;';
265 $line = '';
266 $token = substr($token, 1);
267 }
268 $group .= $token;
269 }
270
271 $this->flushGroup($line, $group, $current_tag);
272 $lines[] = $line !== '' ? $line : '&#160;';
273 return $lines;
274 }
flushGroup(string &$line, string &$group, string $tag)

References $token.

Referenced by ILIAS\COPage\WordDiff\WordDiff\__construct().

+ Here is the caller graph for this function:

◆ split()

ILIAS\COPage\WordDiff\WordDiff::split ( array  $lines)
private
Parameters
list<string>$lines
Returns
array{list<string>, list<string>}

Definition at line 108 of file class.WordDiff.php.

108 : array
109 {
110 $words = [];
111 $comparison = [];
112
113 foreach ($lines as $index => $line) {
114 if ($index > 0) {
115 $words[] = "\n";
116 $comparison[] = "\n";
117 }
118
119 if (strlen($line) > self::MAX_LINE_LENGTH) {
120 $words[] = $line;
121 $comparison[] = $line;
122 continue;
123 }
124
125 $matches = [];
126 if (preg_match_all(
127 '/ ( [^\S\n]+ | [0-9_A-Za-z\x80-\xff]+ | . ) (?: (?!< \n) [^\S\n])? /xs',
128 $line,
129 $matches
130 )) {
131 array_push($words, ...$matches[0]);
132 array_push($comparison, ...$matches[1]);
133 }
134 }
135
136 return [$words, $comparison];
137 }

Referenced by ILIAS\COPage\WordDiff\WordDiff\__construct().

+ Here is the caller graph for this function:

Field Documentation

◆ $closing

array ILIAS\COPage\WordDiff\WordDiff::$closing
private

Definition at line 34 of file class.WordDiff.php.

Referenced by ILIAS\COPage\WordDiff\WordDiff\closing().

◆ $original

array ILIAS\COPage\WordDiff\WordDiff::$original
private

Definition at line 31 of file class.WordDiff.php.

Referenced by ILIAS\COPage\WordDiff\WordDiff\orig().

◆ MAX_LINE_LENGTH

const ILIAS\COPage\WordDiff\WordDiff::MAX_LINE_LENGTH = 10000
private

Definition at line 28 of file class.WordDiff.php.


The documentation for this class was generated from the following file: