PageRenderTime 52ms CodeModel.GetById 25ms RepoModel.GetById 1ms app.codeStats 0ms

/wp-includes/Text/Diff/Engine/shell.php

https://bitbucket.org/MaheshDhaduk/androidmobiles
PHP | 162 lines | 90 code | 19 blank | 53 comment | 13 complexity | 75ab41dc91cd7e4aaa5e74a5f9e6eeba MD5 | raw file
Possible License(s): GPL-3.0, LGPL-2.1, AGPL-1.0
  1. <?php
  2. /**
  3. * Class used internally by Diff to actually compute the diffs.
  4. *
  5. * This class uses the Unix `diff` program via shell_exec to compute the
  6. * differences between the two input arrays.
  7. *
  8. * Copyright 2007-2010 The Horde Project (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://opensource.org/licenses/lgpl-license.php.
  12. *
  13. * @author Milian Wolff <mail@milianw.de>
  14. * @package Text_Diff
  15. * @since 0.3.0
  16. */
  17. class Text_Diff_Engine_shell {
  18. /**
  19. * Path to the diff executable
  20. *
  21. * @var string
  22. */
  23. var $_diffCommand = 'diff';
  24. /**
  25. * Returns the array of differences.
  26. *
  27. * @param array $from_lines lines of text from old file
  28. * @param array $to_lines lines of text from new file
  29. *
  30. * @return array all changes made (array with Text_Diff_Op_* objects)
  31. */
  32. function diff($from_lines, $to_lines)
  33. {
  34. array_walk($from_lines, array('Text_Diff', 'trimNewlines'));
  35. array_walk($to_lines, array('Text_Diff', 'trimNewlines'));
  36. $temp_dir = Text_Diff::_getTempDir();
  37. // Execute gnu diff or similar to get a standard diff file.
  38. $from_file = tempnam($temp_dir, 'Text_Diff');
  39. $to_file = tempnam($temp_dir, 'Text_Diff');
  40. $fp = fopen($from_file, 'w');
  41. fwrite($fp, implode("\n", $from_lines));
  42. fclose($fp);
  43. $fp = fopen($to_file, 'w');
  44. fwrite($fp, implode("\n", $to_lines));
  45. fclose($fp);
  46. $diff = shell_exec($this->_diffCommand . ' ' . $from_file . ' ' . $to_file);
  47. unlink($from_file);
  48. unlink($to_file);
  49. if (is_null($diff)) {
  50. // No changes were made
  51. return array(new Text_Diff_Op_copy($from_lines));
  52. }
  53. $from_line_no = 1;
  54. $to_line_no = 1;
  55. $edits = array();
  56. // Get changed lines by parsing something like:
  57. // 0a1,2
  58. // 1,2c4,6
  59. // 1,5d6
  60. preg_match_all('#^(\d+)(?:,(\d+))?([adc])(\d+)(?:,(\d+))?$#m', $diff,
  61. $matches, PREG_SET_ORDER);
  62. foreach ($matches as $match) {
  63. if (!isset($match[5])) {
  64. // This paren is not set every time (see regex).
  65. $match[5] = false;
  66. }
  67. if ($match[3] == 'a') {
  68. $from_line_no--;
  69. }
  70. if ($match[3] == 'd') {
  71. $to_line_no--;
  72. }
  73. if ($from_line_no < $match[1] || $to_line_no < $match[4]) {
  74. // copied lines
  75. assert('$match[1] - $from_line_no == $match[4] - $to_line_no');
  76. array_push($edits,
  77. new Text_Diff_Op_copy(
  78. $this->_getLines($from_lines, $from_line_no, $match[1] - 1),
  79. $this->_getLines($to_lines, $to_line_no, $match[4] - 1)));
  80. }
  81. switch ($match[3]) {
  82. case 'd':
  83. // deleted lines
  84. array_push($edits,
  85. new Text_Diff_Op_delete(
  86. $this->_getLines($from_lines, $from_line_no, $match[2])));
  87. $to_line_no++;
  88. break;
  89. case 'c':
  90. // changed lines
  91. array_push($edits,
  92. new Text_Diff_Op_change(
  93. $this->_getLines($from_lines, $from_line_no, $match[2]),
  94. $this->_getLines($to_lines, $to_line_no, $match[5])));
  95. break;
  96. case 'a':
  97. // added lines
  98. array_push($edits,
  99. new Text_Diff_Op_add(
  100. $this->_getLines($to_lines, $to_line_no, $match[5])));
  101. $from_line_no++;
  102. break;
  103. }
  104. }
  105. if (!empty($from_lines)) {
  106. // Some lines might still be pending. Add them as copied
  107. array_push($edits,
  108. new Text_Diff_Op_copy(
  109. $this->_getLines($from_lines, $from_line_no,
  110. $from_line_no + count($from_lines) - 1),
  111. $this->_getLines($to_lines, $to_line_no,
  112. $to_line_no + count($to_lines) - 1)));
  113. }
  114. return $edits;
  115. }
  116. /**
  117. * Get lines from either the old or new text
  118. *
  119. * @access private
  120. *
  121. * @param array &$text_lines Either $from_lines or $to_lines
  122. * @param int &$line_no Current line number
  123. * @param int $end Optional end line, when we want to chop more
  124. * than one line.
  125. *
  126. * @return array The chopped lines
  127. */
  128. function _getLines(&$text_lines, &$line_no, $end = false)
  129. {
  130. if (!empty($end)) {
  131. $lines = array();
  132. // We can shift even more
  133. while ($line_no <= $end) {
  134. array_push($lines, array_shift($text_lines));
  135. $line_no++;
  136. }
  137. } else {
  138. $lines = array(array_shift($text_lines));
  139. $line_no++;
  140. }
  141. return $lines;
  142. }
  143. }