[ Index ] |
PHP Cross Reference of MyBB |
[Summary view] [Print] [Text view]
1 <?php 2 /** 3 * Parses unified or context diffs output from eg. the diff utility. 4 * 5 * Example: 6 * <code> 7 * $patch = file_get_contents('example.patch'); 8 * $diff = new Horde_Text_Diff('string', array($patch)); 9 * $renderer = new Horde_Text_Diff_Renderer_inline(); 10 * echo $renderer->render($diff); 11 * </code> 12 * 13 * Copyright 2005 Örjan Persson <o@42mm.org> 14 * Copyright 2005-2011 Horde LLC (http://www.horde.org/) 15 * 16 * See the enclosed file COPYING for license information (LGPL). If you did 17 * not receive this file, see http://www.horde.org/licenses/lgpl21. 18 * 19 * @author Örjan Persson <o@42mm.org> 20 * @package Text_Diff 21 */ 22 23 // Disallow direct access to this file for security reasons 24 if(!defined("IN_MYBB")) 25 { 26 die("Direct initialization of this file is not allowed.<br /><br />Please make sure IN_MYBB is defined."); 27 } 28 29 class Horde_Text_Diff_Engine_String 30 { 31 /** 32 * Parses a unified or context diff. 33 * 34 * First param contains the whole diff and the second can be used to force 35 * a specific diff type. If the second parameter is 'autodetect', the 36 * diff will be examined to find out which type of diff this is. 37 * 38 * @param string $diff The diff content. 39 * @param string $mode The diff mode of the content in $diff. One of 40 * 'context', 'unified', or 'autodetect'. 41 * 42 * @return array List of all diff operations. 43 * @throws Horde_Text_Diff_Exception 44 */ 45 public function diff($diff, $mode = 'autodetect') 46 { 47 // Detect line breaks. 48 $lnbr = "\n"; 49 if (strpos($diff, "\r\n") !== false) { 50 $lnbr = "\r\n"; 51 } elseif (strpos($diff, "\r") !== false) { 52 $lnbr = "\r"; 53 } 54 55 // Make sure we have a line break at the EOF. 56 if (substr($diff, -strlen($lnbr)) != $lnbr) { 57 $diff .= $lnbr; 58 } 59 60 if ($mode != 'autodetect' && $mode != 'context' && $mode != 'unified') { 61 throw new Horde_Text_Diff_Exception('Type of diff is unsupported'); 62 } 63 64 if ($mode == 'autodetect') { 65 $context = strpos($diff, '***'); 66 $unified = strpos($diff, '---'); 67 if ($context === $unified) { 68 throw new Horde_Text_Diff_Exception('Type of diff could not be detected'); 69 } elseif ($context === false || $unified === false) { 70 $mode = $context !== false ? 'context' : 'unified'; 71 } else { 72 $mode = $context < $unified ? 'context' : 'unified'; 73 } 74 } 75 76 // Split by new line and remove the diff header, if there is one. 77 $diff = explode($lnbr, $diff); 78 if (($mode == 'context' && strpos($diff[0], '***') === 0) || 79 ($mode == 'unified' && strpos($diff[0], '---') === 0)) { 80 array_shift($diff); 81 array_shift($diff); 82 } 83 84 if ($mode == 'context') { 85 return $this->parseContextDiff($diff); 86 } else { 87 return $this->parseUnifiedDiff($diff); 88 } 89 } 90 91 /** 92 * Parses an array containing the unified diff. 93 * 94 * @param array $diff Array of lines. 95 * 96 * @return array List of all diff operations. 97 */ 98 public function parseUnifiedDiff($diff) 99 { 100 $edits = array(); 101 $end = count($diff) - 1; 102 for ($i = 0; $i < $end;) { 103 $diff1 = array(); 104 switch (substr($diff[$i], 0, 1)) { 105 case ' ': 106 do { 107 $diff1[] = substr($diff[$i], 1); 108 } while (++$i < $end && substr($diff[$i], 0, 1) == ' '); 109 $edits[] = new Horde_Text_Diff_Op_Copy($diff1); 110 break; 111 112 case '+': 113 // get all new lines 114 do { 115 $diff1[] = substr($diff[$i], 1); 116 } while (++$i < $end && substr($diff[$i], 0, 1) == '+'); 117 $edits[] = new Horde_Text_Diff_Op_Add($diff1); 118 break; 119 120 case '-': 121 // get changed or removed lines 122 $diff2 = array(); 123 do { 124 $diff1[] = substr($diff[$i], 1); 125 } while (++$i < $end && substr($diff[$i], 0, 1) == '-'); 126 127 while ($i < $end && substr($diff[$i], 0, 1) == '+') { 128 $diff2[] = substr($diff[$i++], 1); 129 } 130 if (count($diff2) == 0) { 131 $edits[] = new Horde_Text_Diff_Op_Delete($diff1); 132 } else { 133 $edits[] = new Horde_Text_Diff_Op_Change($diff1, $diff2); 134 } 135 break; 136 137 default: 138 $i++; 139 break; 140 } 141 } 142 143 return $edits; 144 } 145 146 /** 147 * Parses an array containing the context diff. 148 * 149 * @param array $diff Array of lines. 150 * 151 * @return array List of all diff operations. 152 */ 153 public function parseContextDiff(&$diff) 154 { 155 $edits = array(); 156 $i = $max_i = $j = $max_j = 0; 157 $end = count($diff) - 1; 158 while ($i < $end && $j < $end) { 159 while ($i >= $max_i && $j >= $max_j) { 160 // Find the boundaries of the diff output of the two files 161 for ($i = $j; 162 $i < $end && substr($diff[$i], 0, 3) == '***'; 163 $i++); 164 for ($max_i = $i; 165 $max_i < $end && substr($diff[$max_i], 0, 3) != '---'; 166 $max_i++); 167 for ($j = $max_i; 168 $j < $end && substr($diff[$j], 0, 3) == '---'; 169 $j++); 170 for ($max_j = $j; 171 $max_j < $end && substr($diff[$max_j], 0, 3) != '***'; 172 $max_j++); 173 } 174 175 // find what hasn't been changed 176 $array = array(); 177 while ($i < $max_i && 178 $j < $max_j && 179 strcmp($diff[$i], $diff[$j]) == 0) { 180 $array[] = substr($diff[$i], 2); 181 $i++; 182 $j++; 183 } 184 185 while ($i < $max_i && ($max_j-$j) <= 1) { 186 if ($diff[$i] != '' && substr($diff[$i], 0, 1) != ' ') { 187 break; 188 } 189 $array[] = substr($diff[$i++], 2); 190 } 191 192 while ($j < $max_j && ($max_i-$i) <= 1) { 193 if ($diff[$j] != '' && substr($diff[$j], 0, 1) != ' ') { 194 break; 195 } 196 $array[] = substr($diff[$j++], 2); 197 } 198 if (count($array) > 0) { 199 $edits[] = new Horde_Text_Diff_Op_Copy($array); 200 } 201 202 if ($i < $max_i) { 203 $diff1 = array(); 204 switch (substr($diff[$i], 0, 1)) { 205 case '!': 206 $diff2 = array(); 207 do { 208 $diff1[] = substr($diff[$i], 2); 209 if ($j < $max_j && substr($diff[$j], 0, 1) == '!') { 210 $diff2[] = substr($diff[$j++], 2); 211 } 212 } while (++$i < $max_i && substr($diff[$i], 0, 1) == '!'); 213 $edits[] = new Horde_Text_Diff_Op_Change($diff1, $diff2); 214 break; 215 216 case '+': 217 do { 218 $diff1[] = substr($diff[$i], 2); 219 } while (++$i < $max_i && substr($diff[$i], 0, 1) == '+'); 220 $edits[] = new Horde_Text_Diff_Op_Add($diff1); 221 break; 222 223 case '-': 224 do { 225 $diff1[] = substr($diff[$i], 2); 226 } while (++$i < $max_i && substr($diff[$i], 0, 1) == '-'); 227 $edits[] = new Horde_Text_Diff_Op_Delete($diff1); 228 break; 229 } 230 } 231 232 if ($j < $max_j) { 233 $diff2 = array(); 234 switch (substr($diff[$j], 0, 1)) { 235 case '+': 236 do { 237 $diff2[] = substr($diff[$j++], 2); 238 } while ($j < $max_j && substr($diff[$j], 0, 1) == '+'); 239 $edits[] = new Horde_Text_Diff_Op_Add($diff2); 240 break; 241 242 case '-': 243 do { 244 $diff2[] = substr($diff[$j++], 2); 245 } while ($j < $max_j && substr($diff[$j], 0, 1) == '-'); 246 $edits[] = new Horde_Text_Diff_Op_Delete($diff2); 247 break; 248 } 249 } 250 } 251 252 return $edits; 253 } 254 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Tue Oct 8 19:19:50 2013 | Cross-referenced by PHPXref 0.7.1 |