<?php if (!defined('PmWiki')) exit();
/*  Copyright 2006 Karl Loncarek (karl@loncarek.de)
    This file is part of PmWiki; 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.  See pmwiki.php for full details.

    This script gets the titles of all the files contained in a specified group
    and uses them to automatically replace all occurences of the title within
    the actual wikitext by the links to the corresponding files. It is intended
    for use in e.g. glossaries for automatic crosslink generation.
    
    Beware: only absolutely identical text (case sensitive) will be replaced
    by a link.
    
    Existing links are not touched
    
    *History*
    2006-02-17 first version, creates ".autolink-Group" files in which a list
                     of filename and their corresponding titles is created. It is
		updated when a file was deleted or touched after creation of
		the ".autolink-Group" file.
    2006-02-17 fixed corrupting Attach: markup with help of Pm
    2006-02-24 fixed problem, when Searchpatterns['default'] was not set
		  
    
*/

#set predefined values
$AutoLinkList = array();
$AutoLinkTime = 0;
SDV($AutoLinkMinSize,2);

# read the comparison table from a file and place it in an array
function AutoLinkListRead($group) {
	global $AutoLinkList, $AutoLinkTime,$WorkDir,$AutoLinkMinSize;
	# read information from file and fill array
	$filename =  "$WorkDir/.autolink-$group";
	if (file_exists($filename)) {
		$AutoLinkTime = filemtime($filename);
	}
	if  ($fp=@gzopen($filename, "r")) {
		while (!gzeof($fp)) { 
			$line = rtrim(gzgets($fp, 4096));
			$part = explode ("%0a", $line); # delimiter between data is string "%0a"
			if (strlen($part[1])>=$AutoLinkMinSize) {
				$AutoLinkList[$part[0]] = $part[1]; # add entry to array 
			}
		}
		gzclose ($fp);
	}
}

# sorting helper function to sort regarding textsize in mind, from longest to smallest
function sizersort($a,$b) {
	if (strlen($a)==strlen($b)) {
		return 0;
	}
	return (strlen($a) > strlen($b)) ? -1 : 1;
}

# check whether some files have been added/removed
function AutoLinkListUpdate($group) {
	global $AutoLinkTime,$AutoLinkList,$WorkDir,$SearchPatterns,$AutoLinkMinSize;
	$modified = false;
	$filename =  "$WorkDir/.autolink-$group";
	if ($handle = opendir($WorkDir)) { # get filenames that are matching
		while (false !== ($file = readdir($handle))) {
			if ($file != "." && $file!= ".." && substr($file,0,strlen($group)+1) == "$group.") {
				$count=0;
				if (isset($SearchPatterns['default'])) {
					foreach($SearchPatterns['default'] as $v) { #check for in search excluded files
						$count += preg_match($v,$file);
					}
				}
				if ($count==0) { #save only not excluded files
					$matches[]=$file;
				}
			}
		}
		closedir($handle);
	}
	# check if the filename/title combination is already included, if not, add it, check also for changes
	foreach($matches as $v){
		if (file_exists($v) && filemtime($v) >= $AutoLinkTime){
			unset($AutoLinkList[$v]);
		}
		if (empty($AutoLinkList[$v])) { # add only missing entries
			$modified = true;
			$page = ReadPage($v, READPAGE_CURRENT);
			if (empty($page['title'])){
				$AutoLinkList[$v] = substr(strstr($v,"."),1);
			}
			else {
				$AutoLinkList[$v] = trim($page['title']);
			}
			if (strlen($AutoLinkList[$v])<$AutoLinkMinSize) {
				unset($AutoLinkList[$v]);
			}
		}
	}
	# save filename/title combinations
	if ($modified) {
		if  ($fp=@gzopen($filename, "w")) {
			foreach($AutoLinkList as $k => $v) {
				if (substr($k,0,strpos($k,".")) == $group) {
					gzwrite($fp, "$k%0a$v\n");
				}
			}
			gzclose ($fp);
		}
	}
}

#replace with pagenames
function AutoLinkSet($pattern) {
	global $AutoLinkList,$pagename;
	# convert Pattern to Link, ignore selflinks
	foreach ($AutoLinkList as $k => $v) {
		if ($v==$pattern ) {
			return ($k!=$pagename) ? MakeLink($pagename,$k,$v) : $pattern;
		}
	}
}

# activate automatic link creation
function AutoLinkActivate($groups) {
	global $AutoLinkList,$WorkDir;
	$group = explode (" ",$groups);
	foreach ($group as $v) {
		AutoLinkListRead($v);
		AutoLinkListUpdate($v);
	}
	unset($AutoLinkList[""]); # remove empty entry
	# check whether files do exist, if not remove from filename/title list
	foreach($AutoLinkList as $k => $v) { #0,1 sec
		if (!file_exists("$WorkDir/$k")) {
			unset($AutoLinkList[$k]);
		}
	}
	uasort($AutoLinkList,"sizersort"); # sort array on size, largest entries first
	$AutoLinkPattern = implode("|",array_unique($AutoLinkList));
	$searcharray = array("\\", "^", "$", ".", "[" , "]", "(", ")", "?", "*", "+", "{", "}", "/" );
	$replacearray = array("\\\\", "\^", "\\$", "\.", "\[", "\]", "\(", "\)", "\?", "\*", "\+", "\{", "\}", "\/");
	$AutoLinkPattern = str_replace($searcharray,$replacearray,$AutoLinkPattern);
	Markup('autolinklinks', '>wikilink' ,"/($AutoLinkPattern)/e","Keep(AutoLinkSet('$0'),'L')");
}

##Testing area
#AutoLinkActivate("Haupt Techlib");
#Markup('autolink', 'directives',  '/\\(:autolink\\s+(\\S.*?):\\)/ei',  "PRR(AutoLinkActivate('$1'))");