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

/**	=== PageDiffSize ===
 *	Copyright 2009 Eemeli Aro <eemeli@gmail.com>
 *
 *	Add an accurate count of characters added & removed to each edit summary
 *
 *	Developed and tested using PmWiki 2.2.x
 *
 *	To install, add the following to your configuration file:
		if ($action=='edit') include_once("$FarmD/cookbook/pagediffsize.php");
 *
 *	For more information, please see the online documentation at
 *		http://www.pmwiki.org/wiki/Cookbook/PageDiffSize
 *
 *	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.
 */

$RecipeInfo['PageDiffSize']['Version'] = '2009-06-09';

array_splice( $EditFunctions, array_search('PostPage',$EditFunctions), 0, 'PageDiffSize' );

function PageDiffSize( $pagename, &$page, &$new ) {
	global $EnablePost, $ChangeSummary, $DiffFunction, $FarmD, $Now, $PageDiffSizeFmt;
	if ( !$EnablePost || empty($DiffFunction) || !function_exists($DiffFunction) ) return;

	if (file_exists("$FarmD/cookbook/pagerevinline/Text/Diff.php")) {
		include_once("$FarmD/cookbook/pagerevinline/Text/Diff.php");
		include_once("$FarmD/cookbook/pagerevinline/Text/Diff/Renderer/inline.php");
		$pagerevinline = TRUE;
	} else $pagerevinline = FALSE;

	$difftxt = $DiffFunction( $new['text'], @$page['text'] );

	$ins = 0; $del = 0;
	$in=array(); $out=array(); $dtype='';
	foreach( explode("\n",$difftxt."\n") as $d ) {
		if ($d>'') {
			if ($d[0]=='-' || $d[0]=='\\') continue;
			if ($d[0]=='<') { $out[]=substr($d,2); continue; }
			if ($d[0]=='>') { $in[]=substr($d,2); continue; }
		}
		if (preg_match("/^\\d+(,\\d+)?([adc])\\d+/",$dtype,$match)) {
			switch($match[2]) {
				case 'a':
					$del += strlen(implode("\n",$in));
					break;
				case 'd':
					$ins += strlen(implode("\n",$out));
					break;
				case 'c':
					if ($pagerevinline) {
						$diff = &new Text_Diff($in, $out);
						$renderer = &new Text_Diff_Renderer_inline();
						preg_match_all( '!<(ins|del)>(.*?)</\1>!s', $renderer->render($diff), $dm, PREG_SET_ORDER );
						foreach ( $dm as $di ) switch($di[1]) {
							case 'del': $del += strlen($di[2]); break;
							case 'ins': $ins += strlen($di[2]); break;
						}
					} else {
						$in_s = implode("\\",$in);
						$out_s = implode("\\",$out);
						$lmin = min( strlen($in_s), strlen($out_s) );
						for ( $i = 0; $i < $lmin; ++$i ) if ( $in_s[$i] != $out_s[$i] ) break;
						for (
							$jo=strlen($out_s)-1, $ji=strlen($in_s)-1;
							( $jo >= $i ) && ( $ji >= $i );
							--$jo, --$ji
						) if ( $in_s[$ji] != $out_s[$jo] ) break;
						if ( $jo + 1 > $i ) $ins += $jo + 1 - $i;
						if ( $ji + 1 > $i ) $del += $ji + 1 - $i;
					}
					break;
			}
		}
		$in=array(); $out=array(); $dtype=$d;
	}

	SDVA( $PageDiffSizeFmt, array( 0=>' (ą0)', 1=>' (-$del)', 2=>' (+$ins)', 3=>' (+$ins/-$del)' ));
	$dsum = str_replace(
		array( '$ins', '$del', '$sum' ),
		array(  $ins,   $del,   $ins>$del?('+'.($ins-$del)):($ins-$del) ),
		$PageDiffSizeFmt[ ($ins?2:0) + ($del?1:0) ] );
	if ($dsum) {
		$ChangeSummary .= $dsum;
		$new["csum:$Now"] = $new['csum'] = $ChangeSummary;
	}
}