wp/wp-includes/Text/Diff/Engine/shell.php
author ymh <ymh.work@gmail.com>
Mon, 14 Oct 2019 17:39:30 +0200
changeset 7 cf61fcea0001
parent 0 d970ebf37754
child 16 a86126ab1dd4
permissions -rw-r--r--
resynchronize code repo with production
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
0
d970ebf37754 first import
ymh <ymh.work@gmail.com>
parents:
diff changeset
     1
<?php
d970ebf37754 first import
ymh <ymh.work@gmail.com>
parents:
diff changeset
     2
/**
d970ebf37754 first import
ymh <ymh.work@gmail.com>
parents:
diff changeset
     3
 * Class used internally by Diff to actually compute the diffs.
d970ebf37754 first import
ymh <ymh.work@gmail.com>
parents:
diff changeset
     4
 *
d970ebf37754 first import
ymh <ymh.work@gmail.com>
parents:
diff changeset
     5
 * This class uses the Unix `diff` program via shell_exec to compute the
d970ebf37754 first import
ymh <ymh.work@gmail.com>
parents:
diff changeset
     6
 * differences between the two input arrays.
d970ebf37754 first import
ymh <ymh.work@gmail.com>
parents:
diff changeset
     7
 *
d970ebf37754 first import
ymh <ymh.work@gmail.com>
parents:
diff changeset
     8
 * Copyright 2007-2010 The Horde Project (http://www.horde.org/)
d970ebf37754 first import
ymh <ymh.work@gmail.com>
parents:
diff changeset
     9
 *
d970ebf37754 first import
ymh <ymh.work@gmail.com>
parents:
diff changeset
    10
 * See the enclosed file COPYING for license information (LGPL). If you did
d970ebf37754 first import
ymh <ymh.work@gmail.com>
parents:
diff changeset
    11
 * not receive this file, see http://opensource.org/licenses/lgpl-license.php.
d970ebf37754 first import
ymh <ymh.work@gmail.com>
parents:
diff changeset
    12
 *
d970ebf37754 first import
ymh <ymh.work@gmail.com>
parents:
diff changeset
    13
 * @author  Milian Wolff <mail@milianw.de>
d970ebf37754 first import
ymh <ymh.work@gmail.com>
parents:
diff changeset
    14
 * @package Text_Diff
d970ebf37754 first import
ymh <ymh.work@gmail.com>
parents:
diff changeset
    15
 * @since   0.3.0
d970ebf37754 first import
ymh <ymh.work@gmail.com>
parents:
diff changeset
    16
 */
d970ebf37754 first import
ymh <ymh.work@gmail.com>
parents:
diff changeset
    17
class Text_Diff_Engine_shell {
d970ebf37754 first import
ymh <ymh.work@gmail.com>
parents:
diff changeset
    18
d970ebf37754 first import
ymh <ymh.work@gmail.com>
parents:
diff changeset
    19
    /**
d970ebf37754 first import
ymh <ymh.work@gmail.com>
parents:
diff changeset
    20
     * Path to the diff executable
d970ebf37754 first import
ymh <ymh.work@gmail.com>
parents:
diff changeset
    21
     *
d970ebf37754 first import
ymh <ymh.work@gmail.com>
parents:
diff changeset
    22
     * @var string
d970ebf37754 first import
ymh <ymh.work@gmail.com>
parents:
diff changeset
    23
     */
d970ebf37754 first import
ymh <ymh.work@gmail.com>
parents:
diff changeset
    24
    var $_diffCommand = 'diff';
d970ebf37754 first import
ymh <ymh.work@gmail.com>
parents:
diff changeset
    25
d970ebf37754 first import
ymh <ymh.work@gmail.com>
parents:
diff changeset
    26
    /**
d970ebf37754 first import
ymh <ymh.work@gmail.com>
parents:
diff changeset
    27
     * Returns the array of differences.
d970ebf37754 first import
ymh <ymh.work@gmail.com>
parents:
diff changeset
    28
     *
d970ebf37754 first import
ymh <ymh.work@gmail.com>
parents:
diff changeset
    29
     * @param array $from_lines lines of text from old file
d970ebf37754 first import
ymh <ymh.work@gmail.com>
parents:
diff changeset
    30
     * @param array $to_lines   lines of text from new file
d970ebf37754 first import
ymh <ymh.work@gmail.com>
parents:
diff changeset
    31
     *
d970ebf37754 first import
ymh <ymh.work@gmail.com>
parents:
diff changeset
    32
     * @return array all changes made (array with Text_Diff_Op_* objects)
d970ebf37754 first import
ymh <ymh.work@gmail.com>
parents:
diff changeset
    33
     */
d970ebf37754 first import
ymh <ymh.work@gmail.com>
parents:
diff changeset
    34
    function diff($from_lines, $to_lines)
d970ebf37754 first import
ymh <ymh.work@gmail.com>
parents:
diff changeset
    35
    {
d970ebf37754 first import
ymh <ymh.work@gmail.com>
parents:
diff changeset
    36
        array_walk($from_lines, array('Text_Diff', 'trimNewlines'));
d970ebf37754 first import
ymh <ymh.work@gmail.com>
parents:
diff changeset
    37
        array_walk($to_lines, array('Text_Diff', 'trimNewlines'));
d970ebf37754 first import
ymh <ymh.work@gmail.com>
parents:
diff changeset
    38
d970ebf37754 first import
ymh <ymh.work@gmail.com>
parents:
diff changeset
    39
        $temp_dir = Text_Diff::_getTempDir();
d970ebf37754 first import
ymh <ymh.work@gmail.com>
parents:
diff changeset
    40
d970ebf37754 first import
ymh <ymh.work@gmail.com>
parents:
diff changeset
    41
        // Execute gnu diff or similar to get a standard diff file.
d970ebf37754 first import
ymh <ymh.work@gmail.com>
parents:
diff changeset
    42
        $from_file = tempnam($temp_dir, 'Text_Diff');
d970ebf37754 first import
ymh <ymh.work@gmail.com>
parents:
diff changeset
    43
        $to_file = tempnam($temp_dir, 'Text_Diff');
d970ebf37754 first import
ymh <ymh.work@gmail.com>
parents:
diff changeset
    44
        $fp = fopen($from_file, 'w');
d970ebf37754 first import
ymh <ymh.work@gmail.com>
parents:
diff changeset
    45
        fwrite($fp, implode("\n", $from_lines));
d970ebf37754 first import
ymh <ymh.work@gmail.com>
parents:
diff changeset
    46
        fclose($fp);
d970ebf37754 first import
ymh <ymh.work@gmail.com>
parents:
diff changeset
    47
        $fp = fopen($to_file, 'w');
d970ebf37754 first import
ymh <ymh.work@gmail.com>
parents:
diff changeset
    48
        fwrite($fp, implode("\n", $to_lines));
d970ebf37754 first import
ymh <ymh.work@gmail.com>
parents:
diff changeset
    49
        fclose($fp);
d970ebf37754 first import
ymh <ymh.work@gmail.com>
parents:
diff changeset
    50
        $diff = shell_exec($this->_diffCommand . ' ' . $from_file . ' ' . $to_file);
d970ebf37754 first import
ymh <ymh.work@gmail.com>
parents:
diff changeset
    51
        unlink($from_file);
d970ebf37754 first import
ymh <ymh.work@gmail.com>
parents:
diff changeset
    52
        unlink($to_file);
d970ebf37754 first import
ymh <ymh.work@gmail.com>
parents:
diff changeset
    53
d970ebf37754 first import
ymh <ymh.work@gmail.com>
parents:
diff changeset
    54
        if (is_null($diff)) {
d970ebf37754 first import
ymh <ymh.work@gmail.com>
parents:
diff changeset
    55
            // No changes were made
d970ebf37754 first import
ymh <ymh.work@gmail.com>
parents:
diff changeset
    56
            return array(new Text_Diff_Op_copy($from_lines));
d970ebf37754 first import
ymh <ymh.work@gmail.com>
parents:
diff changeset
    57
        }
d970ebf37754 first import
ymh <ymh.work@gmail.com>
parents:
diff changeset
    58
d970ebf37754 first import
ymh <ymh.work@gmail.com>
parents:
diff changeset
    59
        $from_line_no = 1;
d970ebf37754 first import
ymh <ymh.work@gmail.com>
parents:
diff changeset
    60
        $to_line_no = 1;
d970ebf37754 first import
ymh <ymh.work@gmail.com>
parents:
diff changeset
    61
        $edits = array();
d970ebf37754 first import
ymh <ymh.work@gmail.com>
parents:
diff changeset
    62
d970ebf37754 first import
ymh <ymh.work@gmail.com>
parents:
diff changeset
    63
        // Get changed lines by parsing something like:
d970ebf37754 first import
ymh <ymh.work@gmail.com>
parents:
diff changeset
    64
        // 0a1,2
d970ebf37754 first import
ymh <ymh.work@gmail.com>
parents:
diff changeset
    65
        // 1,2c4,6
d970ebf37754 first import
ymh <ymh.work@gmail.com>
parents:
diff changeset
    66
        // 1,5d6
d970ebf37754 first import
ymh <ymh.work@gmail.com>
parents:
diff changeset
    67
        preg_match_all('#^(\d+)(?:,(\d+))?([adc])(\d+)(?:,(\d+))?$#m', $diff,
d970ebf37754 first import
ymh <ymh.work@gmail.com>
parents:
diff changeset
    68
            $matches, PREG_SET_ORDER);
d970ebf37754 first import
ymh <ymh.work@gmail.com>
parents:
diff changeset
    69
d970ebf37754 first import
ymh <ymh.work@gmail.com>
parents:
diff changeset
    70
        foreach ($matches as $match) {
d970ebf37754 first import
ymh <ymh.work@gmail.com>
parents:
diff changeset
    71
            if (!isset($match[5])) {
d970ebf37754 first import
ymh <ymh.work@gmail.com>
parents:
diff changeset
    72
                // This paren is not set every time (see regex).
d970ebf37754 first import
ymh <ymh.work@gmail.com>
parents:
diff changeset
    73
                $match[5] = false;
d970ebf37754 first import
ymh <ymh.work@gmail.com>
parents:
diff changeset
    74
            }
d970ebf37754 first import
ymh <ymh.work@gmail.com>
parents:
diff changeset
    75
d970ebf37754 first import
ymh <ymh.work@gmail.com>
parents:
diff changeset
    76
            if ($match[3] == 'a') {
d970ebf37754 first import
ymh <ymh.work@gmail.com>
parents:
diff changeset
    77
                $from_line_no--;
d970ebf37754 first import
ymh <ymh.work@gmail.com>
parents:
diff changeset
    78
            }
d970ebf37754 first import
ymh <ymh.work@gmail.com>
parents:
diff changeset
    79
d970ebf37754 first import
ymh <ymh.work@gmail.com>
parents:
diff changeset
    80
            if ($match[3] == 'd') {
d970ebf37754 first import
ymh <ymh.work@gmail.com>
parents:
diff changeset
    81
                $to_line_no--;
d970ebf37754 first import
ymh <ymh.work@gmail.com>
parents:
diff changeset
    82
            }
d970ebf37754 first import
ymh <ymh.work@gmail.com>
parents:
diff changeset
    83
d970ebf37754 first import
ymh <ymh.work@gmail.com>
parents:
diff changeset
    84
            if ($from_line_no < $match[1] || $to_line_no < $match[4]) {
d970ebf37754 first import
ymh <ymh.work@gmail.com>
parents:
diff changeset
    85
                // copied lines
d970ebf37754 first import
ymh <ymh.work@gmail.com>
parents:
diff changeset
    86
                assert('$match[1] - $from_line_no == $match[4] - $to_line_no');
d970ebf37754 first import
ymh <ymh.work@gmail.com>
parents:
diff changeset
    87
                array_push($edits,
d970ebf37754 first import
ymh <ymh.work@gmail.com>
parents:
diff changeset
    88
                    new Text_Diff_Op_copy(
d970ebf37754 first import
ymh <ymh.work@gmail.com>
parents:
diff changeset
    89
                        $this->_getLines($from_lines, $from_line_no, $match[1] - 1),
d970ebf37754 first import
ymh <ymh.work@gmail.com>
parents:
diff changeset
    90
                        $this->_getLines($to_lines, $to_line_no, $match[4] - 1)));
d970ebf37754 first import
ymh <ymh.work@gmail.com>
parents:
diff changeset
    91
            }
d970ebf37754 first import
ymh <ymh.work@gmail.com>
parents:
diff changeset
    92
d970ebf37754 first import
ymh <ymh.work@gmail.com>
parents:
diff changeset
    93
            switch ($match[3]) {
d970ebf37754 first import
ymh <ymh.work@gmail.com>
parents:
diff changeset
    94
            case 'd':
d970ebf37754 first import
ymh <ymh.work@gmail.com>
parents:
diff changeset
    95
                // deleted lines
d970ebf37754 first import
ymh <ymh.work@gmail.com>
parents:
diff changeset
    96
                array_push($edits,
d970ebf37754 first import
ymh <ymh.work@gmail.com>
parents:
diff changeset
    97
                    new Text_Diff_Op_delete(
d970ebf37754 first import
ymh <ymh.work@gmail.com>
parents:
diff changeset
    98
                        $this->_getLines($from_lines, $from_line_no, $match[2])));
d970ebf37754 first import
ymh <ymh.work@gmail.com>
parents:
diff changeset
    99
                $to_line_no++;
d970ebf37754 first import
ymh <ymh.work@gmail.com>
parents:
diff changeset
   100
                break;
d970ebf37754 first import
ymh <ymh.work@gmail.com>
parents:
diff changeset
   101
d970ebf37754 first import
ymh <ymh.work@gmail.com>
parents:
diff changeset
   102
            case 'c':
d970ebf37754 first import
ymh <ymh.work@gmail.com>
parents:
diff changeset
   103
                // changed lines
d970ebf37754 first import
ymh <ymh.work@gmail.com>
parents:
diff changeset
   104
                array_push($edits,
d970ebf37754 first import
ymh <ymh.work@gmail.com>
parents:
diff changeset
   105
                    new Text_Diff_Op_change(
d970ebf37754 first import
ymh <ymh.work@gmail.com>
parents:
diff changeset
   106
                        $this->_getLines($from_lines, $from_line_no, $match[2]),
d970ebf37754 first import
ymh <ymh.work@gmail.com>
parents:
diff changeset
   107
                        $this->_getLines($to_lines, $to_line_no, $match[5])));
d970ebf37754 first import
ymh <ymh.work@gmail.com>
parents:
diff changeset
   108
                break;
d970ebf37754 first import
ymh <ymh.work@gmail.com>
parents:
diff changeset
   109
d970ebf37754 first import
ymh <ymh.work@gmail.com>
parents:
diff changeset
   110
            case 'a':
d970ebf37754 first import
ymh <ymh.work@gmail.com>
parents:
diff changeset
   111
                // added lines
d970ebf37754 first import
ymh <ymh.work@gmail.com>
parents:
diff changeset
   112
                array_push($edits,
d970ebf37754 first import
ymh <ymh.work@gmail.com>
parents:
diff changeset
   113
                    new Text_Diff_Op_add(
d970ebf37754 first import
ymh <ymh.work@gmail.com>
parents:
diff changeset
   114
                        $this->_getLines($to_lines, $to_line_no, $match[5])));
d970ebf37754 first import
ymh <ymh.work@gmail.com>
parents:
diff changeset
   115
                $from_line_no++;
d970ebf37754 first import
ymh <ymh.work@gmail.com>
parents:
diff changeset
   116
                break;
d970ebf37754 first import
ymh <ymh.work@gmail.com>
parents:
diff changeset
   117
            }
d970ebf37754 first import
ymh <ymh.work@gmail.com>
parents:
diff changeset
   118
        }
d970ebf37754 first import
ymh <ymh.work@gmail.com>
parents:
diff changeset
   119
d970ebf37754 first import
ymh <ymh.work@gmail.com>
parents:
diff changeset
   120
        if (!empty($from_lines)) {
d970ebf37754 first import
ymh <ymh.work@gmail.com>
parents:
diff changeset
   121
            // Some lines might still be pending. Add them as copied
d970ebf37754 first import
ymh <ymh.work@gmail.com>
parents:
diff changeset
   122
            array_push($edits,
d970ebf37754 first import
ymh <ymh.work@gmail.com>
parents:
diff changeset
   123
                new Text_Diff_Op_copy(
d970ebf37754 first import
ymh <ymh.work@gmail.com>
parents:
diff changeset
   124
                    $this->_getLines($from_lines, $from_line_no,
d970ebf37754 first import
ymh <ymh.work@gmail.com>
parents:
diff changeset
   125
                                     $from_line_no + count($from_lines) - 1),
d970ebf37754 first import
ymh <ymh.work@gmail.com>
parents:
diff changeset
   126
                    $this->_getLines($to_lines, $to_line_no,
d970ebf37754 first import
ymh <ymh.work@gmail.com>
parents:
diff changeset
   127
                                     $to_line_no + count($to_lines) - 1)));
d970ebf37754 first import
ymh <ymh.work@gmail.com>
parents:
diff changeset
   128
        }
d970ebf37754 first import
ymh <ymh.work@gmail.com>
parents:
diff changeset
   129
d970ebf37754 first import
ymh <ymh.work@gmail.com>
parents:
diff changeset
   130
        return $edits;
d970ebf37754 first import
ymh <ymh.work@gmail.com>
parents:
diff changeset
   131
    }
d970ebf37754 first import
ymh <ymh.work@gmail.com>
parents:
diff changeset
   132
d970ebf37754 first import
ymh <ymh.work@gmail.com>
parents:
diff changeset
   133
    /**
d970ebf37754 first import
ymh <ymh.work@gmail.com>
parents:
diff changeset
   134
     * Get lines from either the old or new text
d970ebf37754 first import
ymh <ymh.work@gmail.com>
parents:
diff changeset
   135
     *
d970ebf37754 first import
ymh <ymh.work@gmail.com>
parents:
diff changeset
   136
     * @access private
d970ebf37754 first import
ymh <ymh.work@gmail.com>
parents:
diff changeset
   137
     *
7
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents: 0
diff changeset
   138
     * @param array $text_lines Either $from_lines or $to_lines (passed by reference).
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents: 0
diff changeset
   139
     * @param int   $line_no    Current line number (passed by reference).
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents: 0
diff changeset
   140
     * @param int   $end        Optional end line, when we want to chop more
cf61fcea0001 resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents: 0
diff changeset
   141
     *                          than one line.
0
d970ebf37754 first import
ymh <ymh.work@gmail.com>
parents:
diff changeset
   142
     *
d970ebf37754 first import
ymh <ymh.work@gmail.com>
parents:
diff changeset
   143
     * @return array The chopped lines
d970ebf37754 first import
ymh <ymh.work@gmail.com>
parents:
diff changeset
   144
     */
d970ebf37754 first import
ymh <ymh.work@gmail.com>
parents:
diff changeset
   145
    function _getLines(&$text_lines, &$line_no, $end = false)
d970ebf37754 first import
ymh <ymh.work@gmail.com>
parents:
diff changeset
   146
    {
d970ebf37754 first import
ymh <ymh.work@gmail.com>
parents:
diff changeset
   147
        if (!empty($end)) {
d970ebf37754 first import
ymh <ymh.work@gmail.com>
parents:
diff changeset
   148
            $lines = array();
d970ebf37754 first import
ymh <ymh.work@gmail.com>
parents:
diff changeset
   149
            // We can shift even more
d970ebf37754 first import
ymh <ymh.work@gmail.com>
parents:
diff changeset
   150
            while ($line_no <= $end) {
d970ebf37754 first import
ymh <ymh.work@gmail.com>
parents:
diff changeset
   151
                array_push($lines, array_shift($text_lines));
d970ebf37754 first import
ymh <ymh.work@gmail.com>
parents:
diff changeset
   152
                $line_no++;
d970ebf37754 first import
ymh <ymh.work@gmail.com>
parents:
diff changeset
   153
            }
d970ebf37754 first import
ymh <ymh.work@gmail.com>
parents:
diff changeset
   154
        } else {
d970ebf37754 first import
ymh <ymh.work@gmail.com>
parents:
diff changeset
   155
            $lines = array(array_shift($text_lines));
d970ebf37754 first import
ymh <ymh.work@gmail.com>
parents:
diff changeset
   156
            $line_no++;
d970ebf37754 first import
ymh <ymh.work@gmail.com>
parents:
diff changeset
   157
        }
d970ebf37754 first import
ymh <ymh.work@gmail.com>
parents:
diff changeset
   158
d970ebf37754 first import
ymh <ymh.work@gmail.com>
parents:
diff changeset
   159
        return $lines;
d970ebf37754 first import
ymh <ymh.work@gmail.com>
parents:
diff changeset
   160
    }
d970ebf37754 first import
ymh <ymh.work@gmail.com>
parents:
diff changeset
   161
d970ebf37754 first import
ymh <ymh.work@gmail.com>
parents:
diff changeset
   162
}