PageRenderTime 44ms CodeModel.GetById 26ms app.highlight 15ms RepoModel.GetById 1ms app.codeStats 0ms

/HotelSpaWP/wp-includes/Text/Diff/Engine/string.php

https://bitbucket.org/Trulsh/personal-bootstrap-projects
PHP | 248 lines | 170 code | 23 blank | 55 comment | 92 complexity | 3a11b1933d17fc4da9c3000cacef6929 MD5 | raw file
  1<?php
  2/**
  3 * Parses unified or context diffs output from eg. the diff utility.
  4 *
  5 * Example:
  6 * <code>
  7 * $patch = file_get_contents('example.patch');
  8 * $diff = new Text_Diff('string', array($patch));
  9 * $renderer = new Text_Diff_Renderer_inline();
 10 * echo $renderer->render($diff);
 11 * </code>
 12 *
 13 * Copyright 2005 Örjan Persson <o@42mm.org>
 14 * Copyright 2005-2010 The Horde Project (http://www.horde.org/)
 15 *
 16 * See the enclosed file COPYING for license information (LGPL). If you did
 17 * not receive this file, see http://opensource.org/licenses/lgpl-license.php.
 18 *
 19 * @author  Örjan Persson <o@42mm.org>
 20 * @package Text_Diff
 21 * @since   0.2.0
 22 */
 23class Text_Diff_Engine_string {
 24
 25    /**
 26     * Parses a unified or context diff.
 27     *
 28     * First param contains the whole diff and the second can be used to force
 29     * a specific diff type. If the second parameter is 'autodetect', the
 30     * diff will be examined to find out which type of diff this is.
 31     *
 32     * @param string $diff  The diff content.
 33     * @param string $mode  The diff mode of the content in $diff. One of
 34     *                      'context', 'unified', or 'autodetect'.
 35     *
 36     * @return array  List of all diff operations.
 37     */
 38    function diff($diff, $mode = 'autodetect')
 39    {
 40        // Detect line breaks.
 41        $lnbr = "\n";
 42        if (strpos($diff, "\r\n") !== false) {
 43            $lnbr = "\r\n";
 44        } elseif (strpos($diff, "\r") !== false) {
 45            $lnbr = "\r";
 46        }
 47
 48        // Make sure we have a line break at the EOF.
 49        if (substr($diff, -strlen($lnbr)) != $lnbr) {
 50            $diff .= $lnbr;
 51        }
 52
 53        if ($mode != 'autodetect' && $mode != 'context' && $mode != 'unified') {
 54            return PEAR::raiseError('Type of diff is unsupported');
 55        }
 56
 57        if ($mode == 'autodetect') {
 58            $context = strpos($diff, '***');
 59            $unified = strpos($diff, '---');
 60            if ($context === $unified) {
 61                return PEAR::raiseError('Type of diff could not be detected');
 62            } elseif ($context === false || $unified === false) {
 63                $mode = $context !== false ? 'context' : 'unified';
 64            } else {
 65                $mode = $context < $unified ? 'context' : 'unified';
 66            }
 67        }
 68
 69        // Split by new line and remove the diff header, if there is one.
 70        $diff = explode($lnbr, $diff);
 71        if (($mode == 'context' && strpos($diff[0], '***') === 0) ||
 72            ($mode == 'unified' && strpos($diff[0], '---') === 0)) {
 73            array_shift($diff);
 74            array_shift($diff);
 75        }
 76
 77        if ($mode == 'context') {
 78            return $this->parseContextDiff($diff);
 79        } else {
 80            return $this->parseUnifiedDiff($diff);
 81        }
 82    }
 83
 84    /**
 85     * Parses an array containing the unified diff.
 86     *
 87     * @param array $diff  Array of lines.
 88     *
 89     * @return array  List of all diff operations.
 90     */
 91    function parseUnifiedDiff($diff)
 92    {
 93        $edits = array();
 94        $end = count($diff) - 1;
 95        for ($i = 0; $i < $end;) {
 96            $diff1 = array();
 97            switch (substr($diff[$i], 0, 1)) {
 98            case ' ':
 99                do {
100                    $diff1[] = substr($diff[$i], 1);
101                } while (++$i < $end && substr($diff[$i], 0, 1) == ' ');
102                $edits[] = new Text_Diff_Op_copy($diff1);
103                break;
104
105            case '+':
106                // get all new lines
107                do {
108                    $diff1[] = substr($diff[$i], 1);
109                } while (++$i < $end && substr($diff[$i], 0, 1) == '+');
110                $edits[] = new Text_Diff_Op_add($diff1);
111                break;
112
113            case '-':
114                // get changed or removed lines
115                $diff2 = array();
116                do {
117                    $diff1[] = substr($diff[$i], 1);
118                } while (++$i < $end && substr($diff[$i], 0, 1) == '-');
119
120                while ($i < $end && substr($diff[$i], 0, 1) == '+') {
121                    $diff2[] = substr($diff[$i++], 1);
122                }
123                if (count($diff2) == 0) {
124                    $edits[] = new Text_Diff_Op_delete($diff1);
125                } else {
126                    $edits[] = new Text_Diff_Op_change($diff1, $diff2);
127                }
128                break;
129
130            default:
131                $i++;
132                break;
133            }
134        }
135
136        return $edits;
137    }
138
139    /**
140     * Parses an array containing the context diff.
141     *
142     * @param array $diff  Array of lines.
143     *
144     * @return array  List of all diff operations.
145     */
146    function parseContextDiff(&$diff)
147    {
148        $edits = array();
149        $i = $max_i = $j = $max_j = 0;
150        $end = count($diff) - 1;
151        while ($i < $end && $j < $end) {
152            while ($i >= $max_i && $j >= $max_j) {
153                // Find the boundaries of the diff output of the two files
154                for ($i = $j;
155                     $i < $end && substr($diff[$i], 0, 3) == '***';
156                     $i++);
157                for ($max_i = $i;
158                     $max_i < $end && substr($diff[$max_i], 0, 3) != '---';
159                     $max_i++);
160                for ($j = $max_i;
161                     $j < $end && substr($diff[$j], 0, 3) == '---';
162                     $j++);
163                for ($max_j = $j;
164                     $max_j < $end && substr($diff[$max_j], 0, 3) != '***';
165                     $max_j++);
166            }
167
168            // find what hasn't been changed
169            $array = array();
170            while ($i < $max_i &&
171                   $j < $max_j &&
172                   strcmp($diff[$i], $diff[$j]) == 0) {
173                $array[] = substr($diff[$i], 2);
174                $i++;
175                $j++;
176            }
177
178            while ($i < $max_i && ($max_j-$j) <= 1) {
179                if ($diff[$i] != '' && substr($diff[$i], 0, 1) != ' ') {
180                    break;
181                }
182                $array[] = substr($diff[$i++], 2);
183            }
184
185            while ($j < $max_j && ($max_i-$i) <= 1) {
186                if ($diff[$j] != '' && substr($diff[$j], 0, 1) != ' ') {
187                    break;
188                }
189                $array[] = substr($diff[$j++], 2);
190            }
191            if (count($array) > 0) {
192                $edits[] = new Text_Diff_Op_copy($array);
193            }
194
195            if ($i < $max_i) {
196                $diff1 = array();
197                switch (substr($diff[$i], 0, 1)) {
198                case '!':
199                    $diff2 = array();
200                    do {
201                        $diff1[] = substr($diff[$i], 2);
202                        if ($j < $max_j && substr($diff[$j], 0, 1) == '!') {
203                            $diff2[] = substr($diff[$j++], 2);
204                        }
205                    } while (++$i < $max_i && substr($diff[$i], 0, 1) == '!');
206                    $edits[] = new Text_Diff_Op_change($diff1, $diff2);
207                    break;
208
209                case '+':
210                    do {
211                        $diff1[] = substr($diff[$i], 2);
212                    } while (++$i < $max_i && substr($diff[$i], 0, 1) == '+');
213                    $edits[] = new Text_Diff_Op_add($diff1);
214                    break;
215
216                case '-':
217                    do {
218                        $diff1[] = substr($diff[$i], 2);
219                    } while (++$i < $max_i && substr($diff[$i], 0, 1) == '-');
220                    $edits[] = new Text_Diff_Op_delete($diff1);
221                    break;
222                }
223            }
224
225            if ($j < $max_j) {
226                $diff2 = array();
227                switch (substr($diff[$j], 0, 1)) {
228                case '+':
229                    do {
230                        $diff2[] = substr($diff[$j++], 2);
231                    } while ($j < $max_j && substr($diff[$j], 0, 1) == '+');
232                    $edits[] = new Text_Diff_Op_add($diff2);
233                    break;
234
235                case '-':
236                    do {
237                        $diff2[] = substr($diff[$j++], 2);
238                    } while ($j < $max_j && substr($diff[$j], 0, 1) == '-');
239                    $edits[] = new Text_Diff_Op_delete($diff2);
240                    break;
241                }
242            }
243        }
244
245        return $edits;
246    }
247
248}