PearDiff

Superceded -- see SimultaneousEdits?

Problem

When using Windows or a rather old Unix, the diff call (/usr/bin/diff3) to merge conflicts of an edited page will end up in an empty page. In fact I had the problem when working on a very old SunOS where all the options given to a newer Linux-diff3 do not exist. Anyways, on Windows it's nearly impossible, too. So a PHP solution is definitly the best way to handle it.

Solution

There exists a PEAR Package for text diff which works pretty well to perform this task.

Download the single Pear package and extract it to somwhere like local/Text. Create simuledit.php as in Implementation and include it in your config.php.

Implementation

I'd appreciate this to be included in PmWiki in some way, because system calls are a problem since the beginning of PmWiki. So Code goes here, modify as you like.
This is a custom simuledit.php

 
  <?php if (!defined('PmWiki')) exit();

  include('local/text_diff-0.0.4/Diff.php');
  include('local/text_diff-0.0.4/Diff3.php');
  include('local/text_diff-0.0.4/Diff/Renderer.php');
  include('local/text_diff-0.0.4/Diff/Renderer/inline.php');
  /** fix for php<4.2 **/
  if(!function_exists('is_a')) {
    function is_a($obj,$class) {return is_object($object);}
  }

  array_unshift($EditFunctions,'PearMergeSimulEdits');
  $HTMLStylesFmt[] = ".editconflict { color:green; font-style:italic;
    margin-top:1.33em; margin-bottom:1.33em; }\n";

  function PearMerge($newtext,$oldtext,$pagetext) {
    global $WorkDir,$SysMergeCmd;
    if (substr($newtext,-1,1)!="\n") $newtext.="\n";
    if (substr($oldtext,-1,1)!="\n") $oldtext.="\n";
    if (substr($pagetext,-1,1)!="\n") $pagetext.="\n";
    $tempnew = tempnam($WorkDir,"new");
    $tempold = tempnam($WorkDir,"old");
    $temppag = tempnam($WorkDir,"page");
    if ($newfp=fopen($tempnew,'w')) { fputs($newfp,$newtext); fclose($newfp); }
    if ($oldfp=fopen($tempold,'w')) { fputs($oldfp,$oldtext); fclose($oldfp); }
    if ($pagfp=fopen($temppag,'w')) { fputs($pagfp,$pagetext); fclose($pagfp); }
    $mergetext = '';

    $file1 = file($tempnew);
    $file2 = file($tempold);
    $file3 = file($temppag);

    $diff = &new Text_Diff($file2, $file3);
    $renderer = &new Text_Diff_Renderer_inline();
    $mergetext = $renderer->render($diff);
    @unlink($tempnew); @unlink($tempold); @unlink($temppag);
    return $mergetext;
  }

  function PearMergeSimulEdits($pagename,&$page,&$new) {
    global $EditMessageFmt;
    if (@!$_POST['basetime'] || !PageExists($pagename) ||
      $_POST['basetime']>=$page['time']) return;
    unset($_POST['post']);
    $EditMessageFmt = "<p class='editconflict'>The page you are
      editing has been modified since you started editing it.
      The modifications have been merged into the text below,
      you may want to verify the results of the merge before
      pressing save.  Conflicts the system couldn't resolve are
      bracketed by &lt;ins&gt;&lt;/ins&gt; and
      &lt;del&gt;&lt;/del&gt;.  (<a target='_blank'
      href='\$PageUrl?action=diff'>View changes</a>)</p>\n";
    $old = array();
    RestorePage($pagename,$page,$old,"diff:{$_POST['basetime']}");
    $new['text'] = PearMerge($new['text'],$old['text'],$page['text']);
  }

Contributors