PHP中的文本版本控制与差异突出显示

mik*_*725 5 php version-control

如果您曾在StackOverflow上编辑过一个问题,您可能已经注意到它会跟踪应用于问题的确切更改.它通过突出显示已删除的文本的红色部分以及在特定编辑时添加的绿色而以表格形式显示.我的问题是如何自己实现这样一个系统.我正在尝试使用MySQL在PHP中创建自定义CMS,这似乎是一个非常酷的功能来解决.

任何建议或者可能有开源库已经可以做到这一点我可以分析它们是如何做到的?

示范

在这里,我添加了一些文本,如果您单击编辑链接以查看更改,将显示绿色.

Chr*_*ian 8

/*
    Paul's Simple Diff Algorithm v 0.1
    (C) Paul Butler 2007 <http://www.paulbutler.org/>
    May be used and distributed under the zlib/libpng license.

    This code is intended for learning purposes; it was written with short
    code taking priority over performance. It could be used in a practical
    application, but there are a few ways it could be optimized.

    Given two arrays, the function diff will return an array of the changes.
    I won't describe the format of the array, but it will be obvious
    if you use print_r() on the result of a diff on some test data.

    htmlDiff is a wrapper for the diff command, it takes two strings and
    returns the differences in HTML. The tags used are <ins> and <del>,
    which can easily be styled with CSS.
*/

function diff($old, $new){
    $maxlen = 0;
    foreach($old as $oindex => $ovalue){
        $nkeys = array_keys($new, $ovalue);
        foreach($nkeys as $nindex){
            $matrix[$oindex][$nindex] = isset($matrix[$oindex - 1][$nindex - 1]) ?
                $matrix[$oindex - 1][$nindex - 1] + 1 : 1;
            if($matrix[$oindex][$nindex] > $maxlen){
                $maxlen = $matrix[$oindex][$nindex];
                $omax = $oindex + 1 - $maxlen;
                $nmax = $nindex + 1 - $maxlen;
            }
        }
    }
    if($maxlen == 0) return array(array('d'=>$old, 'i'=>$new));
    return array_merge(
        diff(array_slice($old, 0, $omax), array_slice($new, 0, $nmax)),
        array_slice($new, $nmax, $maxlen),
        diff(array_slice($old, $omax + $maxlen), array_slice($new, $nmax + $maxlen)));
}

function htmlDiff($old, $new){
    $ret = '';
    $diff = diff(explode(' ', $old), explode(' ', $new));
    foreach($diff as $k){
        if(is_array($k))
            $ret .= (!empty($k['d'])?'<del>'.implode(' ',$k['d']).'</del> ':'').
                (!empty($k['i'])?'<ins>'.implode(' ',$k['i']).'</ins> ':'');
        else $ret .= $k . ' ';
    }
    return $ret;
}
Run Code Online (Sandbox Code Playgroud)

我很确定我改变了一些东西.除此之外,它应该完美地工作.

使用示例:

$a='abc defg h 12345';
$b='acb defg ikl 66 123 456';
echo htmlDiff($a,$b);
Run Code Online (Sandbox Code Playgroud)

结果如下:

<del>abc</del> <ins>acb</ins> defg <del>h 12345</del> <ins>ikl 66 123 456</ins> 
Run Code Online (Sandbox Code Playgroud)

并且明显地:

ABC acb defg12345 ikl 66 123 456


Pas*_*TIN 1

PEARText_Diff组件在这里可能会有所帮助:它允许执行和呈现两个文本数据之间的差异。


如果您查看渲染器示例页面,内联应该执行您想要的操作:在给定的示例中,它:

  • 包围删除文本 by<del></del>
  • <ins>用和包围添加的文本</ins>

如果你使用一些 CSS 来设置它们的样式,你应该能够得到你所要求的。