~canonical-sysadmins/wordpress/4.7.2

« back to all changes in this revision

Viewing changes to wp-includes/Text/Diff/Renderer/inline.php

  • Committer: Jacek Nykis
  • Date: 2015-01-05 16:17:05 UTC
  • Revision ID: jacek.nykis@canonical.com-20150105161705-w544l1h5mcg7u4w9
Initial commit

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
}