Implementation of DIFF in pure-php

Simply copy-paste the code to your editor:
The Code is free to use.
Here you can see the file in action

<?php

    
/**
        Diff implemented in pure php, written from scratch.
        Copyright (C) 2003  Daniel Unterberger <diff.phpnet@holomind.de>
        Copyright (C) 2005  Nils Knappmeier next version 
        
        This program is free software; you can redistribute it and/or
        modify it under the terms of the GNU General Public License
        as published by the Free Software Foundation; either version 2
        of the License, or (at your option) any later version.
        
        This program is distributed in the hope that it will be useful,
        but WITHOUT ANY WARRANTY; without even the implied warranty of
        MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
        GNU General Public License for more details.
        
        You should have received a copy of the GNU General Public License
        along with this program; if not, write to the Free Software
        Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
        
        http://www.gnu.org/licenses/gpl.html

        About:
        I searched a function to compare arrays and the array_diff()
        was not specific enough. It ignores the order of the array-values.
        So I reimplemented the diff-function which is found on unix-systems
        but this you can use directly in your code and adopt for your needs.
        Simply adopt the formatline-function. with the third-parameter of arr_diff()
        you can hide matching lines. Hope someone has use for this.

        Contact: d.u.diff@holomind.de <daniel unterberger>
    **/

    
## PHPDiff returns the differences between $old and $new, formatted
## in the standard diff(1) output format.
function PHPDiff($old,$new
{
   
# split the source text into arrays of lines
   
$t1 explode("\n",$old);
   
$x=array_pop($t1); 
   if (
$x>''$t1[]="$x\n\\ No newline at end of file";
   
$t2 explode("\n",$new);
   
$x=array_pop($t2); 
   if (
$x>''$t2[]="$x\n\\ No newline at end of file";

   
# build a reverse-index array using the line as key and line number as value
   # don't store blank lines, so they won't be targets of the shortest distance
   # search
   
foreach($t1 as $i=>$x) if ($x>''$r1[$x][]=$i;
   foreach(
$t2 as $i=>$x) if ($x>''$r2[$x][]=$i;

   
$a1=0$a2=0;   # start at beginning of each list
   
$actions=array();

   
# walk this loop until we reach the end of one of the lists
   
while ($a1<count($t1) && $a2<count($t2)) {
     
# if we have a common element, save it and go to the next
     
if ($t1[$a1]==$t2[$a2]) { $actions[]=4$a1++; $a2++; continue; } 

     
# otherwise, find the shortest move (Manhattan-distance) from the
     # current location
     
$best1=count($t1); $best2=count($t2);
     
$s1=$a1$s2=$a2;
     while((
$s1+$s2-$a1-$a2) < ($best1+$best2-$a1-$a2)) {
       
$d=-1;
       foreach((array)@
$r1[$t2[$s2]] as $n
         if (
$n>=$s1) { $d=$n; break; }
       if (
$d>=$s1 && ($d+$s2-$a1-$a2)<($best1+$best2-$a1-$a2))
         { 
$best1=$d$best2=$s2; }
       
$d=-1;
       foreach((array)@
$r2[$t1[$s1]] as $n
         if (
$n>=$s2) { $d=$n; break; }
       if (
$d>=$s2 && ($s1+$d-$a1-$a2)<($best1+$best2-$a1-$a2))
         { 
$best1=$s1$best2=$d; }
       
$s1++; $s2++;
     }
     while (
$a1<$best1) { $actions[]=1$a1++; }  # deleted elements
     
while ($a2<$best2) { $actions[]=2$a2++; }  # added elements
  
}

  
# we've reached the end of one list, now walk to the end of the other
  
while($a1<count($t1)) { $actions[]=1$a1++; }  # deleted elements
  
while($a2<count($t2)) { $actions[]=2$a2++; }  # added elements

  # and this marks our ending point
  
$actions[]=8;

  
# now, let's follow the path we just took and report the added/deleted
  # elements into $out.
  
$op 0;
  
$x0=$x1=0$y0=$y1=0;
  
$out = array();
  foreach(
$actions as $act) {
    if (
$act==1) { $op|=$act$x1++; continue; }
    if (
$act==2) { $op|=$act$y1++; continue; }
    if (
$op>0) {
      
$xstr = ($x1==($x0+1)) ? $x1 : ($x0+1).",$x1";
      
$ystr = ($y1==($y0+1)) ? $y1 : ($y0+1).",$y1";
      if (
$op==1$out[] = "{$xstr}d{$y1}";
      elseif (
$op==3$out[] = "{$xstr}c{$ystr}";
      while (
$x0<$x1) { $out[] = '< '.$t1[$x0]; $x0++; }   # deleted elems
      
if ($op==2$out[] = "{$x1}a{$ystr}";
      elseif (
$op==3$out[] = '---';
      while (
$y0<$y1) { $out[] = '> '.$t2[$y0]; $y0++; }   # added elems
    
}
    
$x1++; $x0=$x1;
    
$y1++; $y0=$y1;
    
$op=0;
  }
  
$out[] = '';
  return 
join("\n",$out);
}

    
?><html>
<head><title>diff example</title></head>

<body>
<h3>Implementation of DIFF in pure-php</h3>
this outputs the difference in gnu diff(1) syntax. 
<br />

<?
    
#example usage:
    
     
$f1_arr=Array(  "<html>",
                
"<head><title>Text</title></head>",
                
"<body>",
                
"code a",
                
"code b",
                
"code c",
                
"code d",
                
"code e",

                
"code g",
                
"</body>",
                
"</html>" );

    
$f2_arr=Array(  "<html>",
                
"<head><title>Text2</title></head>",
                
"<body>",
                
"code a",
                
"code a",

                
"code c",
                
"code d",
                
"code e",


                
"code g",
                
"code f",
                
"</body>",
                
"</html>" );

    
#you can use files as input and compare them
    # simply with, this gives you simple diff in your webserver.
    #
    # $f3= file ("path to file");
    
    
$f1 implode"\n"$f1_arr ); 
    
$f2 implode"\n"$f2_arr ); 

    print 
"<pre>";
    print 
"Input-Data: <xmp>";
    
print_r$f1_arr );
    
print_r$f2_arr );
    print 
"</xmp>";

    print 
"<hr />new, old <br />"
    print 
PHPDiff$f1$f2 );

    print 
"<hr />old, new <br />"
    print 
PHPDiff$f2$f1 );


    
#comparing with array_diff()

    
print "<hr>Compared: array_diff( \$f1_arr, \$f2_arr );<br> ";
    print 
"<xmp>";
    
print_r array_diff$f1_arr$f2_arr ) );
    print 
"</xmp>";
    
    print 
"<hr>Compared: array_diff( \$f2_arr, \$f1_arr );<br> ";
    print 
"<xmp>";
    
print_r array_diff$f2_arr$f1_arr ) );
    print 
"</xmp>";
    print 
"</pre>";

    print 
"<hr>";

    print 
"&copy 2003-2006 <a href='mailto:d.u.phpnet@holomind.de?subject=diff'>Daniel Unterberger</a>. ";
    print 
"<a href='./diff2.src.php'> view source </a>.";
?></body></html>

©2003-2006 Daniel Unterberger