wp/wp-includes/Text/Diff/Renderer/inline.php
changeset 0 d970ebf37754
child 21 48c4eec2b7e6
equal deleted inserted replaced
-1:000000000000 0:d970ebf37754
       
     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 }