home *** CD-ROM | disk | FTP | other *** search
/ Cricao de Sites - 650 Layouts Prontos / WebMasters.iso / Blogs / wordpress2.6.exe / wordpress2.6 / wp-includes / Text / Diff / Engine / shell.php < prev    next >
Encoding:
PHP Script  |  2008-04-19  |  5.1 KB  |  165 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.  * $Horde: framework/Text_Diff/Diff/Engine/shell.php,v 1.8 2008/01/04 10:07:50 jan Exp $
  9.  *
  10.  * Copyright 2007-2008 The Horde Project (http://www.horde.org/)
  11.  *
  12.  * See the enclosed file COPYING for license information (LGPL). If you did
  13.  * not receive this file, see http://opensource.org/licenses/lgpl-license.php.
  14.  *
  15.  * @author  Milian Wolff <mail@milianw.de>
  16.  * @package Text_Diff
  17.  * @since   0.3.0
  18.  */
  19. class Text_Diff_Engine_shell {
  20.  
  21.     /**
  22.      * Path to the diff executable
  23.      *
  24.      * @var string
  25.      */
  26.     var $_diffCommand = 'diff';
  27.  
  28.     /**
  29.      * Returns the array of differences.
  30.      *
  31.      * @param array $from_lines lines of text from old file
  32.      * @param array $to_lines   lines of text from new file
  33.      *
  34.      * @return array all changes made (array with Text_Diff_Op_* objects)
  35.      */
  36.     function diff($from_lines, $to_lines)
  37.     {
  38.         array_walk($from_lines, array('Text_Diff', 'trimNewlines'));
  39.         array_walk($to_lines, array('Text_Diff', 'trimNewlines'));
  40.  
  41.         $temp_dir = Text_Diff::_getTempDir();
  42.  
  43.         // Execute gnu diff or similar to get a standard diff file.
  44.         $from_file = tempnam($temp_dir, 'Text_Diff');
  45.         $to_file = tempnam($temp_dir, 'Text_Diff');
  46.         $fp = fopen($from_file, 'w');
  47.         fwrite($fp, implode("\n", $from_lines));
  48.         fclose($fp);
  49.         $fp = fopen($to_file, 'w');
  50.         fwrite($fp, implode("\n", $to_lines));
  51.         fclose($fp);
  52.         $diff = shell_exec($this->_diffCommand . ' ' . $from_file . ' ' . $to_file);
  53.         unlink($from_file);
  54.         unlink($to_file);
  55.  
  56.         if (is_null($diff)) {
  57.             // No changes were made
  58.             return array(new Text_Diff_Op_copy($from_lines));
  59.         }
  60.  
  61.         $from_line_no = 1;
  62.         $to_line_no = 1;
  63.         $edits = array();
  64.  
  65.         // Get changed lines by parsing something like:
  66.         // 0a1,2
  67.         // 1,2c4,6
  68.         // 1,5d6
  69.         preg_match_all('#^(\d+)(?:,(\d+))?([adc])(\d+)(?:,(\d+))?$#m', $diff,
  70.             $matches, PREG_SET_ORDER);
  71.  
  72.         foreach ($matches as $match) {
  73.             if (!isset($match[5])) {
  74.                 // This paren is not set every time (see regex).
  75.                 $match[5] = false;
  76.             }
  77.  
  78.             if ($match[3] == 'a') {
  79.                 $from_line_no--;
  80.             }
  81.  
  82.             if ($match[3] == 'd') {
  83.                 $to_line_no--;
  84.             }
  85.  
  86.             if ($from_line_no < $match[1] || $to_line_no < $match[4]) {
  87.                 // copied lines
  88.                 assert('$match[1] - $from_line_no == $match[4] - $to_line_no');
  89.                 array_push($edits,
  90.                     new Text_Diff_Op_copy(
  91.                         $this->_getLines($from_lines, $from_line_no, $match[1] - 1),
  92.                         $this->_getLines($to_lines, $to_line_no, $match[4] - 1)));
  93.             }
  94.  
  95.             switch ($match[3]) {
  96.             case 'd':
  97.                 // deleted lines
  98.                 array_push($edits,
  99.                     new Text_Diff_Op_delete(
  100.                         $this->_getLines($from_lines, $from_line_no, $match[2])));
  101.                 $to_line_no++;
  102.                 break;
  103.  
  104.             case 'c':
  105.                 // changed lines
  106.                 array_push($edits,
  107.                     new Text_Diff_Op_change(
  108.                         $this->_getLines($from_lines, $from_line_no, $match[2]),
  109.                         $this->_getLines($to_lines, $to_line_no, $match[5])));
  110.                 break;
  111.  
  112.             case 'a':
  113.                 // added lines
  114.                 array_push($edits,
  115.                     new Text_Diff_Op_add(
  116.                         $this->_getLines($to_lines, $to_line_no, $match[5])));
  117.                 $from_line_no++;
  118.                 break;
  119.             }
  120.         }
  121.  
  122.         if (!empty($from_lines)) {
  123.             // Some lines might still be pending. Add them as copied
  124.             array_push($edits,
  125.                 new Text_Diff_Op_copy(
  126.                     $this->_getLines($from_lines, $from_line_no,
  127.                                      $from_line_no + count($from_lines) - 1),
  128.                     $this->_getLines($to_lines, $to_line_no,
  129.                                      $to_line_no + count($to_lines) - 1)));
  130.         }
  131.  
  132.         return $edits;
  133.     }
  134.  
  135.     /**
  136.      * Get lines from either the old or new text
  137.      *
  138.      * @access private
  139.      *
  140.      * @param array &$text_lines Either $from_lines or $to_lines
  141.      * @param int   &$line_no    Current line number
  142.      * @param int   $end         Optional end line, when we want to chop more
  143.      *                           than one line.
  144.      *
  145.      * @return array The chopped lines
  146.      */
  147.     function _getLines(&$text_lines, &$line_no, $end = false)
  148.     {
  149.         if (!empty($end)) {
  150.             $lines = array();
  151.             // We can shift even more
  152.             while ($line_no <= $end) {
  153.                 array_push($lines, array_shift($text_lines));
  154.                 $line_no++;
  155.             }
  156.         } else {
  157.             $lines = array(array_shift($text_lines));
  158.             $line_no++;
  159.         }
  160.  
  161.         return $lines;
  162.     }
  163.  
  164. }
  165.