# Blosxom Plugin: storylog
# Author: Mike Downey
# Version: 0.29

package storylog;

# -------- Configure variables --------

# What kind of list do we want?
# 0 = no, 1 = simple list, 2 = unordered list, 3 = ordered list
my $logkeywords = 0;
my $logcategories = 0;
my $logcombined = 1;

my $keywordlogfile = "$blosxom::plugin_state_dir/keyword.log";
my $categorylogfile = "$blosxom::plugin_state_dir/category.log";

my $debugfile = "$blosxom::plugin_state_dir/full.log";

my $display = 10; 			# how many to display
my $categoryiskeyword = 1;		# allows /keyword as well as ?keyword=
my $showcount = 0;	 		# display number of views?

my $ignore = "posterror|blog|.*[.].*";		# regex to ignore
my $useragent_block="fast|bot|Yahoo";	# regex useragents to definitely block

# -------------------------------------

# To display the most-clicked categories or keywords, use:
# $storylog::keywords
# $storylog::categories
# $storylog::combined

$keywords="";
$categories="";
$combined="";

my %keywordcount;
my %categorycount;
my $keywordlink;
my $token;		# how much to add to the category count
my $count;		# don't log anything if no stories viewed.

use CGI qw/:standard/;
use Fcntl qw/:flock/;

sub start{
	$count=0;
	
	# Load in the log files
	open KWF,"<$keywordlogfile";
	flock KWF, LOCK_SH;
	while (my $line = <KWF>){
		chomp $line;
		my ($keyword,$count) = split(",",$line);
		$keywordcount{lc $keyword} = $count;
		}
	close KWF;
	
	open KWF,"<$categorylogfile";
	flock KWF, LOCK_SH;
	while (my $line = <KWF>){
		chomp $line;
		my ($category,$count) = split(",",$line);
		if ($category =~ /^[\w|\/]+$/){	# if category is only words or /
			$categorycount{$category} = $count;
			}
	}
	close KWF;
	
	# Build up the lists.
	$keywords = build_list($logkeywords,$keywordlink,\%keywordcount);
	$categories = build_list($logcategories,"/",\%categorycount);

	# Build the combined list if required
	if ($logcombined){
		foreach my $path (keys %categorycount){
			my $endofpath = (split("/",$path))[-1];
			$keywordcount{lc $endofpath} += $categorycount{$path};
		}
		$combined = build_list($logcombined,$keywordlink,\%keywordcount);
	}
	1;
}

sub last {
	if (!$count){return 1;}	# don't store if no stories generated
	
	# Don't log if certain user agents are used
	my $useragent = CGI::user_agent();
	if ($useragent =~ /$useragent_block/i)
		{$token=0}
	else
		{$token=1}
	
	# use /keyword or ?keyword= as appropriate
	$keywordlink=$categoryiskeyword?"/":"?keyword=";

	# Sort out keyword logging
	if ($logkeywords || $logcombined){
		my $keyword_from_user = "" | CGI::param("keyword") || $storyfilter::keywordfilter;

		if ($keyword_from_user){
			$keywordcount{lc $keyword_from_user} += $token;
			open KWF,">$keywordlogfile";
			flock KWF, LOCK_EX;
			foreach $kw (keys %keywordcount){
				print KWF "$kw,$keywordcount{$kw}\n";
				}
			}
			close KWF;
		}

	# Deal with the category log
	if ($logcategories || $logcombined){

		if($blosxom::path_info){
			my $storypath = $blosxom::path_info;
			# strip any story name from the end of the path
			$storypath =~ s/\/\w*\..*$//;

			$categorycount{$storypath} += $token;

			open KWF,">$categorylogfile";
			flock KWF, LOCK_EX;
			foreach $kw (keys %categorycount)
				{print KWF "$kw,$categorycount{$kw}\n";}
			close KWF;		
		}
	}

	1;
}

sub story {
#	my ($pkg, $path, $filename, $story_ref, $title_ref, $body_ref) = @_;
# may eventually log how many times each story gets viewed

	$count++;
	1;
}

sub build_list{
	my ($logtype,$linktype,$logref) = @_;
	if (!$logtype)
		{return ""};

	my $count=0;
	my $list=("","<ul>","<ol>")[--$logtype];
	
	foreach $item (sort {$$logref{$b} <=> $$logref{$a}} keys %$logref){
		
		next if ($item =~ /$ignore/);
		my $makelink = "<a href=\"$blosxom::url$linktype$item\">";
		my $displayname = $item;
		$displayname =~ s/[_-](.)/ \u$1/g;
		$makelink .= ucfirst ($displayname)."</a>";
		$list .= ("","<li>","<li>")[$logtype] . $makelink;
		if ($showcount){$list .= " ($$logref{$item})";}
		$list .= ("<br>","</li>","</li>")[$logtype]."\n";
		last if (++$count >= $display);
	}

	$list .= ("","</ul>","</ol>")[$logtype];
	return $list;
}

1;

