]> scripts.mit.edu Git - autoinstalls/wordpress.git/blob - wp-includes/Text/Diff/Renderer/inline.php
Wordpress 3.6
[autoinstalls/wordpress.git] / wp-includes / Text / Diff / Renderer / inline.php
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 }