~canonical-sysadmins/wordpress/4.7.4

« back to all changes in this revision

Viewing changes to wp-includes/Text/Diff/Renderer.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
 * A class to render Diffs in different formats.
 
4
 *
 
5
 * This class renders the diff in classic diff format. It is intended that
 
6
 * this class be customized via inheritance, to obtain fancier outputs.
 
7
 *
 
8
 * Copyright 2004-2010 The Horde Project (http://www.horde.org/)
 
9
 *
 
10
 * See the enclosed file COPYING for license information (LGPL). If you did
 
11
 * not receive this file, see http://opensource.org/licenses/lgpl-license.php.
 
12
 *
 
13
 * @package Text_Diff
 
14
 */
 
15
class Text_Diff_Renderer {
 
16
 
 
17
    /**
 
18
     * Number of leading context "lines" to preserve.
 
19
     *
 
20
     * This should be left at zero for this class, but subclasses may want to
 
21
     * set this to other values.
 
22
     */
 
23
    var $_leading_context_lines = 0;
 
24
 
 
25
    /**
 
26
     * Number of trailing context "lines" to preserve.
 
27
     *
 
28
     * This should be left at zero for this class, but subclasses may want to
 
29
     * set this to other values.
 
30
     */
 
31
    var $_trailing_context_lines = 0;
 
32
 
 
33
    /**
 
34
     * Constructor.
 
35
     */
 
36
    function Text_Diff_Renderer($params = array())
 
37
    {
 
38
        foreach ($params as $param => $value) {
 
39
            $v = '_' . $param;
 
40
            if (isset($this->$v)) {
 
41
                $this->$v = $value;
 
42
            }
 
43
        }
 
44
    }
 
45
 
 
46
    /**
 
47
     * Get any renderer parameters.
 
48
     *
 
49
     * @return array  All parameters of this renderer object.
 
50
     */
 
51
    function getParams()
 
52
    {
 
53
        $params = array();
 
54
        foreach (get_object_vars($this) as $k => $v) {
 
55
            if ($k[0] == '_') {
 
56
                $params[substr($k, 1)] = $v;
 
57
            }
 
58
        }
 
59
 
 
60
        return $params;
 
61
    }
 
62
 
 
63
    /**
 
64
     * Renders a diff.
 
65
     *
 
66
     * @param Text_Diff $diff  A Text_Diff object.
 
67
     *
 
68
     * @return string  The formatted output.
 
69
     */
 
70
    function render($diff)
 
71
    {
 
72
        $xi = $yi = 1;
 
73
        $block = false;
 
74
        $context = array();
 
75
 
 
76
        $nlead = $this->_leading_context_lines;
 
77
        $ntrail = $this->_trailing_context_lines;
 
78
 
 
79
        $output = $this->_startDiff();
 
80
 
 
81
        $diffs = $diff->getDiff();
 
82
        foreach ($diffs as $i => $edit) {
 
83
            /* If these are unchanged (copied) lines, and we want to keep
 
84
             * leading or trailing context lines, extract them from the copy
 
85
             * block. */
 
86
            if (is_a($edit, 'Text_Diff_Op_copy')) {
 
87
                /* Do we have any diff blocks yet? */
 
88
                if (is_array($block)) {
 
89
                    /* How many lines to keep as context from the copy
 
90
                     * block. */
 
91
                    $keep = $i == count($diffs) - 1 ? $ntrail : $nlead + $ntrail;
 
92
                    if (count($edit->orig) <= $keep) {
 
93
                        /* We have less lines in the block than we want for
 
94
                         * context => keep the whole block. */
 
95
                        $block[] = $edit;
 
96
                    } else {
 
97
                        if ($ntrail) {
 
98
                            /* Create a new block with as many lines as we need
 
99
                             * for the trailing context. */
 
100
                            $context = array_slice($edit->orig, 0, $ntrail);
 
101
                            $block[] = new Text_Diff_Op_copy($context);
 
102
                        }
 
103
                        /* @todo */
 
104
                        $output .= $this->_block($x0, $ntrail + $xi - $x0,
 
105
                                                 $y0, $ntrail + $yi - $y0,
 
106
                                                 $block);
 
107
                        $block = false;
 
108
                    }
 
109
                }
 
110
                /* Keep the copy block as the context for the next block. */
 
111
                $context = $edit->orig;
 
112
            } else {
 
113
                /* Don't we have any diff blocks yet? */
 
114
                if (!is_array($block)) {
 
115
                    /* Extract context lines from the preceding copy block. */
 
116
                    $context = array_slice($context, count($context) - $nlead);
 
117
                    $x0 = $xi - count($context);
 
118
                    $y0 = $yi - count($context);
 
119
                    $block = array();
 
120
                    if ($context) {
 
121
                        $block[] = new Text_Diff_Op_copy($context);
 
122
                    }
 
123
                }
 
124
                $block[] = $edit;
 
125
            }
 
126
 
 
127
            if ($edit->orig) {
 
128
                $xi += count($edit->orig);
 
129
            }
 
130
            if ($edit->final) {
 
131
                $yi += count($edit->final);
 
132
            }
 
133
        }
 
134
 
 
135
        if (is_array($block)) {
 
136
            $output .= $this->_block($x0, $xi - $x0,
 
137
                                     $y0, $yi - $y0,
 
138
                                     $block);
 
139
        }
 
140
 
 
141
        return $output . $this->_endDiff();
 
142
    }
 
143
 
 
144
    function _block($xbeg, $xlen, $ybeg, $ylen, &$edits)
 
145
    {
 
146
        $output = $this->_startBlock($this->_blockHeader($xbeg, $xlen, $ybeg, $ylen));
 
147
 
 
148
        foreach ($edits as $edit) {
 
149
            switch (strtolower(get_class($edit))) {
 
150
            case 'text_diff_op_copy':
 
151
                $output .= $this->_context($edit->orig);
 
152
                break;
 
153
 
 
154
            case 'text_diff_op_add':
 
155
                $output .= $this->_added($edit->final);
 
156
                break;
 
157
 
 
158
            case 'text_diff_op_delete':
 
159
                $output .= $this->_deleted($edit->orig);
 
160
                break;
 
161
 
 
162
            case 'text_diff_op_change':
 
163
                $output .= $this->_changed($edit->orig, $edit->final);
 
164
                break;
 
165
            }
 
166
        }
 
167
 
 
168
        return $output . $this->_endBlock();
 
169
    }
 
170
 
 
171
    function _startDiff()
 
172
    {
 
173
        return '';
 
174
    }
 
175
 
 
176
    function _endDiff()
 
177
    {
 
178
        return '';
 
179
    }
 
180
 
 
181
    function _blockHeader($xbeg, $xlen, $ybeg, $ylen)
 
182
    {
 
183
        if ($xlen > 1) {
 
184
            $xbeg .= ',' . ($xbeg + $xlen - 1);
 
185
        }
 
186
        if ($ylen > 1) {
 
187
            $ybeg .= ',' . ($ybeg + $ylen - 1);
 
188
        }
 
189
 
 
190
        // this matches the GNU Diff behaviour
 
191
        if ($xlen && !$ylen) {
 
192
            $ybeg--;
 
193
        } elseif (!$xlen) {
 
194
            $xbeg--;
 
195
        }
 
196
 
 
197
        return $xbeg . ($xlen ? ($ylen ? 'c' : 'd') : 'a') . $ybeg;
 
198
    }
 
199
 
 
200
    function _startBlock($header)
 
201
    {
 
202
        return $header . "\n";
 
203
    }
 
204
 
 
205
    function _endBlock()
 
206
    {
 
207
        return '';
 
208
    }
 
209
 
 
210
    function _lines($lines, $prefix = ' ')
 
211
    {
 
212
        return $prefix . implode("\n$prefix", $lines) . "\n";
 
213
    }
 
214
 
 
215
    function _context($lines)
 
216
    {
 
217
        return $this->_lines($lines, '  ');
 
218
    }
 
219
 
 
220
    function _added($lines)
 
221
    {
 
222
        return $this->_lines($lines, '> ');
 
223
    }
 
224
 
 
225
    function _deleted($lines)
 
226
    {
 
227
        return $this->_lines($lines, '< ');
 
228
    }
 
229
 
 
230
    function _changed($orig, $final)
 
231
    {
 
232
        return $this->_deleted($orig) . "---\n" . $this->_added($final);
 
233
    }
 
234
 
 
235
}