home *** CD-ROM | disk | FTP | other *** search
/ HTML Examples / WP.iso / wordpress / wp-includes / Text / Diff / Renderer / inline.php
Encoding:
PHP Script  |  2010-02-18  |  5.4 KB  |  207 lines

  1. <?php
  2. /**
  3.  * "Inline" diff renderer.
  4.  *
  5.  * Copyright 2004-2010 The Horde Project (http://www.horde.org/)
  6.  *
  7.  * See the enclosed file COPYING for license information (LGPL). If you did
  8.  * not receive this file, see http://opensource.org/licenses/lgpl-license.php.
  9.  *
  10.  * @author  Ciprian Popovici
  11.  * @package Text_Diff
  12.  */
  13.  
  14. /** Text_Diff_Renderer */
  15.  
  16. // WP #7391
  17. require_once dirname(dirname(__FILE__)) . '/Renderer.php';
  18.  
  19. /**
  20.  * "Inline" diff renderer.
  21.  *
  22.  * This class renders diffs in the Wiki-style "inline" format.
  23.  *
  24.  * @author  Ciprian Popovici
  25.  * @package Text_Diff
  26.  */
  27. class Text_Diff_Renderer_inline extends Text_Diff_Renderer {
  28.  
  29.     /**
  30.      * Number of leading context "lines" to preserve.
  31.      *
  32.      * @var integer
  33.      */
  34.     var $_leading_context_lines = 10000;
  35.  
  36.     /**
  37.      * Number of trailing context "lines" to preserve.
  38.      *
  39.      * @var integer
  40.      */
  41.     var $_trailing_context_lines = 10000;
  42.  
  43.     /**
  44.      * Prefix for inserted text.
  45.      *
  46.      * @var string
  47.      */
  48.     var $_ins_prefix = '<ins>';
  49.  
  50.     /**
  51.      * Suffix for inserted text.
  52.      *
  53.      * @var string
  54.      */
  55.     var $_ins_suffix = '</ins>';
  56.  
  57.     /**
  58.      * Prefix for deleted text.
  59.      *
  60.      * @var string
  61.      */
  62.     var $_del_prefix = '<del>';
  63.  
  64.     /**
  65.      * Suffix for deleted text.
  66.      *
  67.      * @var string
  68.      */
  69.     var $_del_suffix = '</del>';
  70.  
  71.     /**
  72.      * Header for each change block.
  73.      *
  74.      * @var string
  75.      */
  76.     var $_block_header = '';
  77.  
  78.     /**
  79.      * Whether to split down to character-level.
  80.      *
  81.      * @var boolean
  82.      */
  83.     var $_split_characters = false;
  84.  
  85.     /**
  86.      * What are we currently splitting on? Used to recurse to show word-level
  87.      * or character-level changes.
  88.      *
  89.      * @var string
  90.      */
  91.     var $_split_level = 'lines';
  92.  
  93.     function _blockHeader($xbeg, $xlen, $ybeg, $ylen)
  94.     {
  95.         return $this->_block_header;
  96.     }
  97.  
  98.     function _startBlock($header)
  99.     {
  100.         return $header;
  101.     }
  102.  
  103.     function _lines($lines, $prefix = ' ', $encode = true)
  104.     {
  105.         if ($encode) {
  106.             array_walk($lines, array(&$this, '_encode'));
  107.         }
  108.  
  109.         if ($this->_split_level == 'lines') {
  110.             return implode("\n", $lines) . "\n";
  111.         } else {
  112.             return implode('', $lines);
  113.         }
  114.     }
  115.  
  116.     function _added($lines)
  117.     {
  118.         array_walk($lines, array(&$this, '_encode'));
  119.         $lines[0] = $this->_ins_prefix . $lines[0];
  120.         $lines[count($lines) - 1] .= $this->_ins_suffix;
  121.         return $this->_lines($lines, ' ', false);
  122.     }
  123.  
  124.     function _deleted($lines, $words = false)
  125.     {
  126.         array_walk($lines, array(&$this, '_encode'));
  127.         $lines[0] = $this->_del_prefix . $lines[0];
  128.         $lines[count($lines) - 1] .= $this->_del_suffix;
  129.         return $this->_lines($lines, ' ', false);
  130.     }
  131.  
  132.     function _changed($orig, $final)
  133.     {
  134.         /* If we've already split on characters, just display. */
  135.         if ($this->_split_level == 'characters') {
  136.             return $this->_deleted($orig)
  137.                 . $this->_added($final);
  138.         }
  139.  
  140.         /* If we've already split on words, just display. */
  141.         if ($this->_split_level == 'words') {
  142.             $prefix = '';
  143.             while ($orig[0] !== false && $final[0] !== false &&
  144.                    substr($orig[0], 0, 1) == ' ' &&
  145.                    substr($final[0], 0, 1) == ' ') {
  146.                 $prefix .= substr($orig[0], 0, 1);
  147.                 $orig[0] = substr($orig[0], 1);
  148.                 $final[0] = substr($final[0], 1);
  149.             }
  150.             return $prefix . $this->_deleted($orig) . $this->_added($final);
  151.         }
  152.  
  153.         $text1 = implode("\n", $orig);
  154.         $text2 = implode("\n", $final);
  155.  
  156.         /* Non-printing newline marker. */
  157.         $nl = "\0";
  158.  
  159.         if ($this->_split_characters) {
  160.             $diff = new Text_Diff('native',
  161.                                   array(preg_split('//', $text1),
  162.                                         preg_split('//', $text2)));
  163.         } else {
  164.             /* We want to split on word boundaries, but we need to preserve
  165.              * whitespace as well. Therefore we split on words, but include
  166.              * all blocks of whitespace in the wordlist. */
  167.             $diff = new Text_Diff('native',
  168.                                   array($this->_splitOnWords($text1, $nl),
  169.                                         $this->_splitOnWords($text2, $nl)));
  170.         }
  171.  
  172.         /* Get the diff in inline format. */
  173.         $renderer = new Text_Diff_Renderer_inline
  174.             (array_merge($this->getParams(),
  175.                          array('split_level' => $this->_split_characters ? 'characters' : 'words')));
  176.  
  177.         /* Run the diff and get the output. */
  178.         return str_replace($nl, "\n", $renderer->render($diff)) . "\n";
  179.     }
  180.  
  181.     function _splitOnWords($string, $newlineEscape = "\n")
  182.     {
  183.         // Ignore \0; otherwise the while loop will never finish.
  184.         $string = str_replace("\0", '', $string);
  185.  
  186.         $words = array();
  187.         $length = strlen($string);
  188.         $pos = 0;
  189.  
  190.         while ($pos < $length) {
  191.             // Eat a word with any preceding whitespace.
  192.             $spaces = strspn(substr($string, $pos), " \n");
  193.             $nextpos = strcspn(substr($string, $pos + $spaces), " \n");
  194.             $words[] = str_replace("\n", $newlineEscape, substr($string, $pos, $spaces + $nextpos));
  195.             $pos += $spaces + $nextpos;
  196.         }
  197.  
  198.         return $words;
  199.     }
  200.  
  201.     function _encode(&$string)
  202.     {
  203.         $string = htmlspecialchars($string);
  204.     }
  205.  
  206. }
  207.