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