Text version control in PHP with honors

If you've ever edited a question right here in StackOverflow, you probably noticed that it keeps track of what exact changes have been applied to the question. It is displayed in the form, highlighting the red part of the text that has been deleted, and the green that has been added, since with specific editing. My question is how to implement such a system yourself. I am trying to create a custom CMS in PHP with MySQL, and this seems like a very interesting feature to solve.

Any tips or maybe there are open source libraries that can do this already, and I can just analyze how they do it?

Demonstration

Here I added text that will appear green if you click on the edit link to see the changes.

+5
source share
2 answers

The PEAR component can be useful here: it allows you to execute and visualize, differs between two text data. Text_Diff


If you look at the Rendering Examples , Inline one shoud will do what you want: in this example, it:

  • surrounds text deletion with <del>and</del>
  • add the added text <ins>and</ins>

If you use a little CSS for their styles, you can get what you ask for.

+1
source
/*
    Paul 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;
}

I am sure that I have changed something. Other than that, it should work just fine.

Usage example:

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

And the result:

<del>abc</del> <ins>acb</ins> defg <del>h 12345</del> <ins>ikl 66 123 456</ins> 

And noticeably:

abc acb defg h 12345 ikl 66 123 456

+8
source

All Articles