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

define(WPCATEGORIES_VERSION, '1.6');
$RecipeInfo['WPCategories']['Version']='2007-10-07 - v1.6';

/*  Copyright 2005-2007 Mateusz Czaplinski (mateusz@czaplinski.pl)
    This file is WPCategories.php; 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.  


    This script partially implements Wikipedia-like (Wikipedia is a free
    encyclopedia located at http://wikipedia.org) categories 
    functionality. It collects all links to pages in Category group on
    a page and displays them all in one place in the page footer.

    To use this script, simply copy it into the cookbook/ directory
    and add the following line to config.php (or a per-page/per-group
    customization file).

        include_once('cookbook/WPCategories.php');

    From then on, every page in the Category group (or other you
    configured - see http://pmwiki.org/wiki/Cookbook/WPCategories
    for configuration details) you'll see a list of all pages
    belonging to that category (that is, linking to it).

    For more details, visit http://pmwiki.org/wiki/Cookbook/WPCategories

	---- History: ----

	* 2007-10-07 - v1.6
	 - modified for compatibility with Cookbook:MarkupExpressions
	* 2007-09-30 - v1.5 
	 - $EnableWPCategoriesInline to collect links not only from line beginning
	 - duplicates in the categories box are removed

*/


## The group, links to which are collected.
SDV( $WPCategoriesGroup, 'Category' );

## Making internationalisation easier.
## This string is used in the categories-box at the bottom of the page.
SDV( $WPCategoriesPlural, 'Categories' );
## This string is used on every Category-group page, above the
## category pages listing.
SDV( $WPCategoriesListingHeader, '!! Articles in category "$Namespaced"' );


## Whether to automatically add backlinks-listing to all
## Category-group pages.
SDV( $WPCategoriesAutoBacklinks, 1 );

## These variables form the HTML markup for a categories-box
## rendered in page footer.
## The box is rendered as:
## $WPCategoriesPre CategoryLink1 $WPCategoriesBetween CategoryLink2 ...
## $WPCategoriesPost
##
SDV( $WPCategoriesPre, 
  '<div class="WPCategoriesBox">' . $WPCategoriesPlural . ': ' );
SDV( $WPCategoriesBetween, ' | ' );
SDV( $WPCategoriesPost, '</div>' );

SDV( $HTMLStylesFmt['WPCategories'],
'.WPCategoriesBox {
    border: 1px solid #aaa;
    background-color: #f9f9f9;
    margin-top: 1em;
    clear: both;
    padding: .5em 5px .6em 5px;
    line-height: 1.5em;
}
');

## internal. Here we'll collect the links.
$WPCategoriesStack = array();

## Markup for finding links to categories. Sample links are:
## [[Category:Something]] 
## [[Category.Foo bar]]
## [[Category/BarFoo]]
## Note, that other link formats (like [[(Category.)Foobar]],
## [[Category.Foobar]], [[Category/Foobar]] ) are not
## recognised (or at least that's what I aimed for...)!
Markup(
	'CollectCategoryLinks',
	'<links',
	'/^\\[\\[' . $WPCategoriesGroup . '[\\.\\/:]([^\\|]*?)\\]\\]/e',
	"WPCategoriesCollect('\$1')"
);

## Markup for collecting 'PmWiki native category links' of the
## form: [[!Name of category]]
## (equivalent of: [[Category.Name of category]])
Markup(
	'Collect!CategoryLinks',
	'>CollectCategoryLinks',
	'/^\\[\\[!([^\\|]*?)\\]\\]/e',
	"WPCategoriesCollect('\$1')"
);

if( IsEnabled($EnableWPCategoriesInline,0) ) {
	Markup(
		'CollectCategoryLinks-inline',
		'>CollectCategoryLinks',
		'/(\\[\\[' . $WPCategoriesGroup . '[\\.\\/:]([^\\|]*?)\\]\\])/e',
		"WPCategoriesCollect('\$2','\$1')"
	);
	Markup(
		'Collect!CategoryLinks-inline',
		'>Collect!CategoryLinks',
		'/(\\[\\[!([^\\|]*?)\\]\\])/e',
		"WPCategoriesCollect('\$2','\$1')"
	);
}

## internal.
## A (:WPCategoriesList:) markup variable. It will be substituted
## with the Category-box. See also the "Implementation note" below,
## and WPCategoriesShow().
Markup(
	'DisplayCategoryLinks',
	'>Collect!CategoryLinks',
	'/\\(:WPCategoriesList:\\)/e',
	'WPCategoriesShow()'
);



## Add a backlinks-listing to all Category-group pages.
if( $WPCategoriesAutoBacklinks )
	$WPCategoriesListPages =
		'(:if group ' . $WPCategoriesGroup . ":)\n" .
		FmtPageName( $WPCategoriesListingHeader, $pagename ) .
          "\n" .
		'(:pagelist link={$Group}.{$Name} list=normal:)' .
		'(:if:)';
else
	$WPCategoriesListPages = '';

## Showing the Categories-box in the page footer.
##
## Implementation note:
## We're doing that by using a new markup directive.
$GroupFooterFmt = 
	$WPCategoriesListPages . '(:WPCategoriesList:)' . $GroupFooterFmt;


## internal.
## This function is invoked when Category-link markup is found.
## It removes the link from the page, stacking it for later usage.
function WPCategoriesCollect( $category, $keep=FALSE ) {
	global $WPCategoriesStack, $WPCategoriesGroup;
	global $LinkTargets;

	$WPCategoriesStack[] = '[[' . $WPCategoriesGroup . '/' . $category . ']]';

	## We have removed the link from the page above; the (not so) side
	## effect is, that PmWiki engine won't know there's a certain link in
	## the page at all, and thus it won't be saved in a special attribute of
	## the page, named 'targets' (*). That'd result in the page not showing
	## in Category's backlinks, what is certainly bad. Therefore, we must
	## take the hacky way and add it to said attribute ourselves:
	@$LinkTargets[ MakePageName( 
		$pagename, $WPCategoriesGroup . '/' . $category ) ]++;

	## (*) That's because PmWiki collects page links information when
	## saving the page, by running Markup-substitution, results of 
	## which are then ignored, apart from a special global variable 
	## $LinkTargets, which is set by link-parsing Markup handlers.

	return $keep ? $keep : '';
}

## internal.
## This function renders the Categories box when a special (:WPCategoriesList:)
## markup is found.
function WPCategoriesShow() {
	global $WPCategoriesStack, $WPCategoriesPre, $WPCategoriesBetween, $WPCategoriesPost;

	if( $WPCategoriesStack ) {
		## array_keys(array_flip($a)) returns unique values
		## (reference: http://www.php.net/manual/en/function.array-unique.php)
		return FmtPageName( $WPCategoriesPre . implode($WPCategoriesBetween,
			array_keys(array_flip($WPCategoriesStack))) . $WPCategoriesPost,
			$pagename );
	}
	else
		return '';
}