Search code examples
phpstringcomparison

How to highlight next and previous sub-string if sub-string in between is found deleted by comparing Strings?


I am comparing two strings in PHP. In modified new string, I am writing code for highlighting the changes with comparison to old string. But I stuck here.

For example:

Old string : Here is the my content.

New string : Here is my content.

In this, I want something like this.

New string : Here is my content.

I have tried matching words by saving previous words. but nothing works.

class ContentController extends Controller
{ 
 public function diffArray($old, $new){
    $matrix = array();
    $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(
        self::diffArray(array_slice($old, 0, $omax), array_slice($new, 0, $nmax)),
        array_slice($new, $nmax, $maxlen),
        self::diffArray(array_slice($old, $omax + $maxlen), array_slice($new, $nmax + $maxlen)));
}

public function htmlDiff($old, $new){
    $ret = '';
    $diff = self::diffArray(explode(' ', $old), explode(' ', $new));
    foreach($diff as $k){
        if(is_array($k)){
            $ret .= /*(!empty($k['d'])?'<del style="background-color:#ffcccc">'.implode(' ',$k['d']).'</del> ':'').*/(!empty($k['i'])?'<span style="background-color:#ccffcc">'.implode(' ',$k['i']).'</span> ':'');
        }else{
            $ret .= $k . ' ';
        }
    }
    return $ret;
}

$old_content = "Here is the my content";
$new_content = "Here is my content";
$highlighted_content = ContentController::htmlDiff($old_content, $new_content);

}

Solution

  • Solved. After coding of hours, I got this. Here is the modified code.

    public function diffArray($old, $new){
        $matrix = array();
        $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(
            self::diffArray(array_slice($old, 0, $omax), array_slice($new, 0, $nmax)),
            array_slice($new, $nmax, $maxlen),
            self::diffArray(array_slice($old, $omax + $maxlen), array_slice($new, $nmax + $maxlen)));
    }
    
    function htmlDiff($old, $new){
        $diff = self::diffArray(explode(' ', $old), explode(' ', $new));
        $flag = 0;
        $ret = "";
        foreach($diff as $i => $k){
            if(is_array($k)){
                if((count($k['d']) != 0) && (count($k['i']) == 0)){
                    $flag = 1;
                }
                else if((count($k['d']) != 0) && (count($k['i']) != 0)){
                    $ret .= (!empty($k['i'])?"<span style='background-color:#ccffcc'>".implode(' ',$k['i'])."</span> ":'');
                }
                else if((count($k['d']) == 0) && (count($k['i']) != 0)){
                    $ret .= (!empty($k['i'])?"<span style='background-color:#ccffcc'>".implode(' ',$k['i'])."</span> ":'');
                }
            }
            else{
                if($flag == 0){
                    $ret .= $k . ' ';
                }
                else if($flag == 1){
                    $pre = $i - 2;
                    $post = $i;
                    $ret= preg_replace('/\W\w+\s*(\W*)$/', '$1', $ret);
                    $ret .= " <span style='background-color:#ccffcc'>".$diff[$pre]." ".$diff[$post]."</span> ";
                }
                $flag = 0;
            }
        }
        return $ret;
    }
    
    $old_content = "Here is the my content";
    $new_content = "Here is my content";
    $highlighted_content = ContentController::htmlDiff($old_content, $new_content);