1<?php
2
3namespace Drupal\Component\Diff;
4
5use Drupal\Component\Diff\Engine\HWLDFWordAccumulator;
6
7/**
8 * @todo document
9 * @private
10 * @subpackage DifferenceEngine
11 */
12class WordLevelDiff extends MappedDiff {
13
14  const MAX_LINE_LENGTH = 10000;
15
16  public function __construct($orig_lines, $closing_lines) {
17    list($orig_words, $orig_stripped) = $this->_split($orig_lines);
18    list($closing_words, $closing_stripped) = $this->_split($closing_lines);
19
20    parent::__construct($orig_words, $closing_words, $orig_stripped, $closing_stripped);
21  }
22
23  protected function _split($lines) {
24    $words = [];
25    $stripped = [];
26    $first = TRUE;
27    foreach ($lines as $line) {
28      // If the line is too long, just pretend the entire line is one big word
29      // This prevents resource exhaustion problems
30      if ( $first ) {
31        $first = FALSE;
32      }
33      else {
34        $words[] = "\n";
35        $stripped[] = "\n";
36      }
37      if (mb_strlen($line) > $this::MAX_LINE_LENGTH) {
38        $words[] = $line;
39        $stripped[] = $line;
40      }
41      else {
42        if (preg_match_all('/ ( [^\S\n]+ | [0-9_A-Za-z\x80-\xff]+ | . ) (?: (?!< \n) [^\S\n])? /xs', $line, $m)) {
43          $words = array_merge($words, $m[0]);
44          $stripped = array_merge($stripped, $m[1]);
45        }
46      }
47    }
48    return [$words, $stripped];
49  }
50
51  public function orig() {
52    $orig = new HWLDFWordAccumulator();
53
54    foreach ($this->edits as $edit) {
55      if ($edit->type == 'copy') {
56        $orig->addWords($edit->orig);
57      }
58      elseif ($edit->orig) {
59        $orig->addWords($edit->orig, 'mark');
60      }
61    }
62    $lines = $orig->getLines();
63    return $lines;
64  }
65
66  public function closing() {
67    $closing = new HWLDFWordAccumulator();
68
69    foreach ($this->edits as $edit) {
70      if ($edit->type == 'copy') {
71        $closing->addWords($edit->closing);
72      }
73      elseif ($edit->closing) {
74        $closing->addWords($edit->closing, 'mark');
75      }
76    }
77    $lines = $closing->getLines();
78    return $lines;
79  }
80
81}
82