home *** CD-ROM | disk | FTP | other *** search
/ HTML Examples / WP.iso / wordpress2 / wp-includes / Text / Diff / Engine / shell.php < prev    next >
Encoding:
PHP Script  |  2017-10-02  |  5.1 KB  |  163 lines

  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. }
  163.