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

/*  === PageDiffSize ===
 *  Copyright 2009-2010 Eemeli Aro <eemeli@gmail.com>
 *
 *  Add an accurate count of characters added & removed to each edit summary
 *
 *  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/UserAdmin
 *
 *
 *  This script 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 3 of the License, or
 *  (at your option) any later version.
 *
 *  This script 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, see <http://www.gnu.org/licenses/>.
 */

$RecipeInfo['PageDiffSize']['Version'] = '2010-06-17';

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

include_once("$FarmD/scripts/pagerev.php");

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

	SDVA($PageDiffSizeFmt, array(-1 => ' (deleted)', 0=>' (ą0)', 1=>' (-$del)', 2=>' (+$ins)', 3=>' (+$ins/-$del)'));

	SDV($DeleteKeyPattern,"^\\s*delete\\s*$");
	if (preg_match("/$DeleteKeyPattern/", $new['text'])) {
		$ChangeSummary .= $PageDiffSizeFmt[-1];
		$new["csum:$Now"] = $new['csum'] = $ChangeSummary;
		return;
	}

	SDV($DiffRenderSourceFunction, 'DiffRenderSource');
	$diff_chars = !empty($DiffRenderSourceFunction) && function_exists($DiffRenderSourceFunction);

	$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 ($diff_chars) {
						preg_match_all('!<del>(.*?)</del>!s', $DiffRenderSourceFunction($in, $out, 0), $in_m);
						$del += strlen(implode('', $in_m[1]));
						preg_match_all('!<ins>(.*?)</ins>!s', $DiffRenderSourceFunction($in, $out, 1), $out_m);
						$ins += strlen(implode('', $out_m[1]));
					} 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;
	}

	$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;
	}
}