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 / Renderer.php
Encoding:
PHP Script  |  2008-04-19  |  6.6 KB  |  238 lines

  1. <?php
  2. /**
  3.  * A class to render Diffs in different formats.
  4.  *
  5.  * This class renders the diff in classic diff format. It is intended that
  6.  * this class be customized via inheritance, to obtain fancier outputs.
  7.  *
  8.  * $Horde: framework/Text_Diff/Diff/Renderer.php,v 1.21 2008/01/04 10:07:50 jan Exp $
  9.  *
  10.  * Copyright 2004-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.  * @package Text_Diff
  16.  */
  17. class Text_Diff_Renderer {
  18.  
  19.     /**
  20.      * Number of leading context "lines" to preserve.
  21.      *
  22.      * This should be left at zero for this class, but subclasses may want to
  23.      * set this to other values.
  24.      */
  25.     var $_leading_context_lines = 0;
  26.  
  27.     /**
  28.      * Number of trailing context "lines" to preserve.
  29.      *
  30.      * This should be left at zero for this class, but subclasses may want to
  31.      * set this to other values.
  32.      */
  33.     var $_trailing_context_lines = 0;
  34.  
  35.     /**
  36.      * Constructor.
  37.      */
  38.     function Text_Diff_Renderer($params = array())
  39.     {
  40.         foreach ($params as $param => $value) {
  41.             $v = '_' . $param;
  42.             if (isset($this->$v)) {
  43.                 $this->$v = $value;
  44.             }
  45.         }
  46.     }
  47.  
  48.     /**
  49.      * Get any renderer parameters.
  50.      *
  51.      * @return array  All parameters of this renderer object.
  52.      */
  53.     function getParams()
  54.     {
  55.         $params = array();
  56.         foreach (get_object_vars($this) as $k => $v) {
  57.             if ($k[0] == '_') {
  58.                 $params[substr($k, 1)] = $v;
  59.             }
  60.         }
  61.  
  62.         return $params;
  63.     }
  64.  
  65.     /**
  66.      * Renders a diff.
  67.      *
  68.      * @param Text_Diff $diff  A Text_Diff object.
  69.      *
  70.      * @return string  The formatted output.
  71.      */
  72.     function render($diff)
  73.     {
  74.         $xi = $yi = 1;
  75.         $block = false;
  76.         $context = array();
  77.  
  78.         $nlead = $this->_leading_context_lines;
  79.         $ntrail = $this->_trailing_context_lines;
  80.  
  81.         $output = $this->_startDiff();
  82.  
  83.         $diffs = $diff->getDiff();
  84.         foreach ($diffs as $i => $edit) {
  85.             /* If these are unchanged (copied) lines, and we want to keep
  86.              * leading or trailing context lines, extract them from the copy
  87.              * block. */
  88.             if (is_a($edit, 'Text_Diff_Op_copy')) {
  89.                 /* Do we have any diff blocks yet? */
  90.                 if (is_array($block)) {
  91.                     /* How many lines to keep as context from the copy
  92.                      * block. */
  93.                     $keep = $i == count($diffs) - 1 ? $ntrail : $nlead + $ntrail;
  94.                     if (count($edit->orig) <= $keep) {
  95.                         /* We have less lines in the block than we want for
  96.                          * context => keep the whole block. */
  97.                         $block[] = $edit;
  98.                     } else {
  99.                         if ($ntrail) {
  100.                             /* Create a new block with as many lines as we need
  101.                              * for the trailing context. */
  102.                             $context = array_slice($edit->orig, 0, $ntrail);
  103.                             $block[] = &new Text_Diff_Op_copy($context);
  104.                         }
  105.                         /* @todo */
  106.                         $output .= $this->_block($x0, $ntrail + $xi - $x0,
  107.                                                  $y0, $ntrail + $yi - $y0,
  108.                                                  $block);
  109.                         $block = false;
  110.                     }
  111.                 }
  112.                 /* Keep the copy block as the context for the next block. */
  113.                 $context = $edit->orig;
  114.             } else {
  115.                 /* Don't we have any diff blocks yet? */
  116.                 if (!is_array($block)) {
  117.                     /* Extract context lines from the preceding copy block. */
  118.                     $context = array_slice($context, count($context) - $nlead);
  119.                     $x0 = $xi - count($context);
  120.                     $y0 = $yi - count($context);
  121.                     $block = array();
  122.                     if ($context) {
  123.                         $block[] = &new Text_Diff_Op_copy($context);
  124.                     }
  125.                 }
  126.                 $block[] = $edit;
  127.             }
  128.  
  129.             if ($edit->orig) {
  130.                 $xi += count($edit->orig);
  131.             }
  132.             if ($edit->final) {
  133.                 $yi += count($edit->final);
  134.             }
  135.         }
  136.  
  137.         if (is_array($block)) {
  138.             $output .= $this->_block($x0, $xi - $x0,
  139.                                      $y0, $yi - $y0,
  140.                                      $block);
  141.         }
  142.  
  143.         return $output . $this->_endDiff();
  144.     }
  145.  
  146.     function _block($xbeg, $xlen, $ybeg, $ylen, &$edits)
  147.     {
  148.         $output = $this->_startBlock($this->_blockHeader($xbeg, $xlen, $ybeg, $ylen));
  149.  
  150.         foreach ($edits as $edit) {
  151.             switch (strtolower(get_class($edit))) {
  152.             case 'text_diff_op_copy':
  153.                 $output .= $this->_context($edit->orig);
  154.                 break;
  155.  
  156.             case 'text_diff_op_add':
  157.                 $output .= $this->_added($edit->final);
  158.                 break;
  159.  
  160.             case 'text_diff_op_delete':
  161.                 $output .= $this->_deleted($edit->orig);
  162.                 break;
  163.  
  164.             case 'text_diff_op_change':
  165.                 $output .= $this->_changed($edit->orig, $edit->final);
  166.                 break;
  167.             }
  168.         }
  169.  
  170.         return $output . $this->_endBlock();
  171.     }
  172.  
  173.     function _startDiff()
  174.     {
  175.         return '';
  176.     }
  177.  
  178.     function _endDiff()
  179.     {
  180.         return '';
  181.     }
  182.  
  183.     function _blockHeader($xbeg, $xlen, $ybeg, $ylen)
  184.     {
  185.         if ($xlen > 1) {
  186.             $xbeg .= ',' . ($xbeg + $xlen - 1);
  187.         }
  188.         if ($ylen > 1) {
  189.             $ybeg .= ',' . ($ybeg + $ylen - 1);
  190.         }
  191.  
  192.         // this matches the GNU Diff behaviour
  193.         if ($xlen && !$ylen) {
  194.             $ybeg--;
  195.         } elseif (!$xlen) {
  196.             $xbeg--;
  197.         }
  198.  
  199.         return $xbeg . ($xlen ? ($ylen ? 'c' : 'd') : 'a') . $ybeg;
  200.     }
  201.  
  202.     function _startBlock($header)
  203.     {
  204.         return $header . "\n";
  205.     }
  206.  
  207.     function _endBlock()
  208.     {
  209.         return '';
  210.     }
  211.  
  212.     function _lines($lines, $prefix = ' ')
  213.     {
  214.         return $prefix . implode("\n$prefix", $lines) . "\n";
  215.     }
  216.  
  217.     function _context($lines)
  218.     {
  219.         return $this->_lines($lines, '  ');
  220.     }
  221.  
  222.     function _added($lines)
  223.     {
  224.         return $this->_lines($lines, '> ');
  225.     }
  226.  
  227.     function _deleted($lines)
  228.     {
  229.         return $this->_lines($lines, '< ');
  230.     }
  231.  
  232.     function _changed($orig, $final)
  233.     {
  234.         return $this->_deleted($orig) . "---\n" . $this->_added($final);
  235.     }
  236.  
  237. }
  238.