[ Index ]

PHP Cross Reference of WordPress

title

Body

[close]

/wp-includes/Text/Diff/Engine/ -> shell.php (source)

   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      /**
  20       * Path to the diff executable
  21       *
  22       * @var string
  23       */
  24      var $_diffCommand = 'diff';
  25  
  26      /**
  27       * Returns the array of differences.
  28       *
  29       * @param array $from_lines lines of text from old file
  30       * @param array $to_lines   lines of text from new file
  31       *
  32       * @return array all changes made (array with Text_Diff_Op_* objects)
  33       */
  34      function diff($from_lines, $to_lines)
  35      {
  36          array_walk($from_lines, array('Text_Diff', 'trimNewlines'));
  37          array_walk($to_lines, array('Text_Diff', 'trimNewlines'));
  38  
  39          $temp_dir = Text_Diff::_getTempDir();
  40  
  41          // Execute gnu diff or similar to get a standard diff file.
  42          $from_file = tempnam($temp_dir, 'Text_Diff');
  43          $to_file = tempnam($temp_dir, 'Text_Diff');
  44          $fp = fopen($from_file, 'w');
  45          fwrite($fp, implode("\n", $from_lines));
  46          fclose($fp);
  47          $fp = fopen($to_file, 'w');
  48          fwrite($fp, implode("\n", $to_lines));
  49          fclose($fp);
  50          $diff = shell_exec($this->_diffCommand . ' ' . $from_file . ' ' . $to_file);
  51          unlink($from_file);
  52          unlink($to_file);
  53  
  54          if (is_null($diff)) {
  55              // No changes were made
  56              return array(new Text_Diff_Op_copy($from_lines));
  57          }
  58  
  59          $from_line_no = 1;
  60          $to_line_no = 1;
  61          $edits = array();
  62  
  63          // Get changed lines by parsing something like:
  64          // 0a1,2
  65          // 1,2c4,6
  66          // 1,5d6
  67          preg_match_all('#^(\d+)(?:,(\d+))?([adc])(\d+)(?:,(\d+))?$#m', $diff,
  68              $matches, PREG_SET_ORDER);
  69  
  70          foreach ($matches as $match) {
  71              if (!isset($match[5])) {
  72                  // This paren is not set every time (see regex).
  73                  $match[5] = false;
  74              }
  75  
  76              if ($match[3] == 'a') {
  77                  $from_line_no--;
  78              }
  79  
  80              if ($match[3] == 'd') {
  81                  $to_line_no--;
  82              }
  83  
  84              if ($from_line_no < $match[1] || $to_line_no < $match[4]) {
  85                  // copied lines
  86                  assert($match[1] - $from_line_no == $match[4] - $to_line_no);
  87                  array_push($edits,
  88                      new Text_Diff_Op_copy(
  89                          $this->_getLines($from_lines, $from_line_no, $match[1] - 1),
  90                          $this->_getLines($to_lines, $to_line_no, $match[4] - 1)));
  91              }
  92  
  93              switch ($match[3]) {
  94              case 'd':
  95                  // deleted lines
  96                  array_push($edits,
  97                      new Text_Diff_Op_delete(
  98                          $this->_getLines($from_lines, $from_line_no, $match[2])));
  99                  $to_line_no++;
 100                  break;
 101  
 102              case 'c':
 103                  // changed lines
 104                  array_push($edits,
 105                      new Text_Diff_Op_change(
 106                          $this->_getLines($from_lines, $from_line_no, $match[2]),
 107                          $this->_getLines($to_lines, $to_line_no, $match[5])));
 108                  break;
 109  
 110              case 'a':
 111                  // added lines
 112                  array_push($edits,
 113                      new Text_Diff_Op_add(
 114                          $this->_getLines($to_lines, $to_line_no, $match[5])));
 115                  $from_line_no++;
 116                  break;
 117              }
 118          }
 119  
 120          if (!empty($from_lines)) {
 121              // Some lines might still be pending. Add them as copied
 122              array_push($edits,
 123                  new Text_Diff_Op_copy(
 124                      $this->_getLines($from_lines, $from_line_no,
 125                                       $from_line_no + count($from_lines) - 1),
 126                      $this->_getLines($to_lines, $to_line_no,
 127                                       $to_line_no + count($to_lines) - 1)));
 128          }
 129  
 130          return $edits;
 131      }
 132  
 133      /**
 134       * Get lines from either the old or new text
 135       *
 136       * @access private
 137       *
 138       * @param array $text_lines Either $from_lines or $to_lines (passed by reference).
 139       * @param int   $line_no    Current line number (passed by reference).
 140       * @param int   $end        Optional end line, when we want to chop more
 141       *                          than one line.
 142       *
 143       * @return array The chopped lines
 144       */
 145      function _getLines(&$text_lines, &$line_no, $end = false)
 146      {
 147          if (!empty($end)) {
 148              $lines = array();
 149              // We can shift even more
 150              while ($line_no <= $end) {
 151                  array_push($lines, array_shift($text_lines));
 152                  $line_no++;
 153              }
 154          } else {
 155              $lines = array(array_shift($text_lines));
 156              $line_no++;
 157          }
 158  
 159          return $lines;
 160      }
 161  
 162  }


Generated: Tue Mar 19 01:00:02 2024 Cross-referenced by PHPXref 0.7.1