1<?php 2/** 3 * Class used internally by Diff to actually compute the diffs. 4 * 5 * This class uses the xdiff PECL package (http://pecl.php.net/package/xdiff) 6 * to compute the differences between the two input arrays. 7 * 8 * Copyright 2004-2017 Horde LLC (http://www.horde.org/) 9 * 10 * See the enclosed file COPYING for license information (LGPL). If you did 11 * not receive this file, see http://www.horde.org/licenses/lgpl21. 12 * 13 * @author Jon Parise <jon@horde.org> 14 * @package Text_Diff 15 */ 16class Horde_Text_Diff_Engine_Xdiff 17{ 18 /** 19 */ 20 public function diff($from_lines, $to_lines) 21 { 22 if (!extension_loaded('xdiff')) { 23 throw new Horde_Text_Diff_Exception('The xdiff extension is required for this diff engine'); 24 } 25 26 array_walk($from_lines, array('Horde_Text_Diff', 'trimNewlines')); 27 array_walk($to_lines, array('Horde_Text_Diff', 'trimNewlines')); 28 29 /* Convert the two input arrays into strings for xdiff processing. */ 30 $from_string = implode("\n", $from_lines); 31 $to_string = implode("\n", $to_lines); 32 33 /* Diff the two strings and convert the result to an array. */ 34 $diff = xdiff_string_diff($from_string, $to_string, count($to_lines)); 35 $diff = explode("\n", $diff); 36 37 /* Walk through the diff one line at a time. We build the $edits 38 * array of diff operations by reading the first character of the 39 * xdiff output (which is in the "unified diff" format). 40 * 41 * Note that we don't have enough information to detect "changed" 42 * lines using this approach, so we can't add Horde_Text_Diff_Op_Changed 43 * instances to the $edits array. The result is still perfectly 44 * valid, albeit a little less descriptive and efficient. */ 45 $edits = array(); 46 foreach ($diff as $line) { 47 if (!strlen($line)) { 48 continue; 49 } 50 switch ($line[0]) { 51 case ' ': 52 $edits[] = new Horde_Text_Diff_Op_Copy(array(substr($line, 1))); 53 break; 54 55 case '+': 56 $edits[] = new Horde_Text_Diff_Op_Add(array(substr($line, 1))); 57 break; 58 59 case '-': 60 $edits[] = new Horde_Text_Diff_Op_Delete(array(substr($line, 1))); 61 break; 62 } 63 } 64 65 return $edits; 66 } 67} 68