Wiki source for PageAndCategoryDivisionInACategory


Show raw source

=====Division between Pages and categories in a Category=====
>>Working for 1.3.6 (latest)>>''03/31/2016:version 2.1 (see below).''

this version builds on the beta-version from JavaWoman (running on this wiki) and has in total the following cchanges to the official action:

- pages belong to categories if you use the following markup: ""[[(cat)Name]]"". ""[[(cat)Name Alternative name for the link]]"" does work, too
- pages only need the category-action inside them, no more need for a name starting with "Category"
- template-pages , i.e. page-names ending with "template" are not shown, unless you force it or their name starts with "Category"
- output can be shown as a single list, or in a number of columns
- it is possible to show only (sub)"categories" or "pages" or "all" (both). In the last case, categories and pages are shown seperate and not in one list/column

Todo:
- extra css-class for ""[[(cat)...""
- TESTING
- upgrade-script
- code redundancies into a function?
- making name for main-category customizable
- possibility to show the alternative name in the markup in the categorylist instead of the page-name??
- possibility to show the pages belonging to the subcategories, too? Which depth? Problem of recursion! What if a page belongs to a category and a subcategory?
- possible? use a single list also for columns, using CSS to visually split up into columns - JW 2005-01-19
- update the todo-list in the action ;-)


===Explanations===
The new search-method uses two queries instead of one: one search for subcategories (searching for the category-action) and another for pages (searching for the new link version) belonging to a category (they only load the name, since we know from the search if its a category or not).

This allows any page to become a category, their names don't have to start with "Category" anymore. For this reason, i took the "forcecat" param out (if you put the action, for example, on the SandBox without "categorylinking" any page it will simply show that nothing could be found).


===Comments?===

===Installation===

Three things have to be changed:

==1. addition to formatters/wakka.php==

right before
%%(php)
// forced links
// \S : any character that is not a whitespace character
// \s : any whitespace character
%%

add the following:
%%(php)
//links to category pages
else if (preg_match("/^\[\[\(cat\)(\S+)(\s(.+))*\]\]$/si", $thing, $matches))
{
list(, $categorylink, $text) = $matches;
if ($categorylink)
{
return $result.$wakka->Link($categorylink, "", $text);
}
else
{
return "";
}
}
%%

==2. library/common/showarray.php==

The following file has to be saved as ##library/common/showarray.php##:
%%(php;1)
<?php
/**
* Sorts a given array in a given number of columns.
*
* @package Library
* @subpackage Common
* @name ShowArray
*
* @author {@link http://wikka.jsnx.com/JavaWoman JavaWoman} (table-less columns)
* @author {@link http://wikka.jsnx.com/NilsLindenberg NilsLindenberg} (function and "divison" of the array)
* @copyright Copyright © 2004,
* @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
* @since Wikka 1.0.0
*
* @input array $array necessary: the data to be shown
* @input integer $colnumber optional: number of colums; default: 0.
* @input string $class optional: class(es) to determine styling of the output list of table; default: none.
* @output list of data from an array, formatted as in columns
*
* @todo - possible? use a single list also for columns, using CSS to visually split up into columns - JW 2005-01-19
*/

function ShowArrayInColumns($array, $colnumber=1, $class="")
{
$str = "";
if (is_array($array))
{
$entries = count($array);
$width = (int) (100 / $colnumber);
$lines = 0;
$a = 0;

$str .= '<div'.$class.'>'."\n";

//how many lines with an entry in every column do we have?
while ($entries / $colnumber > 1)
{
$lines++;
$entries = $entries - $colnumber;
}

//prepare output
for ($i=0;$i<$colnumber;$i++)
{
$str .=' <div style="width: '.$width.'%; float: left;">'."\n";
for ($j=0;$j<$lines;$j++)
{
$str .= ' '.$array[$a].'<br />'."\n";
$a++;
}

//the rest of the entries (less then the number of cols)
if ($entries)
{
$str .= ' '.$array[$a].'<br />'."\n";
$entries--;
$a++;
}
$str .=" </div>\n";

}
$str .= '</div><br style="clear: both;">'."\n";
return ($str);
}
$str .= 'The data delivered to the function ShowArrayInColumns was no array.';
return ($str);
}

/**
* Sorts a given array as a list.
*
* @package Library
* @subpackage Common
* @name ShowArray
*
* @author {@link http://wikka.jsnx.com/JsnX JsnX} (list)
* @author {@link http://wikka.jsnx.com/NilsLindenberg NilsLindenberg} (function and "divison" of the array)
* @copyright Copyright © 2004,
* @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
* @since Wikka 1.0.0
*
* @input array $array necessary: the data to be shown
* @input string $class optional: class(es) to determine styling of the output list of table; default: none.
* @output list of data from an array, formatted as a list
*
*/

function ShowArrayAsList($array,$class="")
{
$str = "";
if (is_array($array))
{
$entries = count($array);
$str .= '<div'.$class.'>'."\n";
$str .= "<ul>\n";
for ($i=0;$i<$entries;$i++)
{
$str .= ' <li>'.$array[$i].'</li>';
}
$str .= "</ul>\n</div>\n";
return ($str);
}
$str .= "The data delivered to the function ShowArrayAsList was no array.";
return ($str);
}
?>
%%


==3. Plugin this in plugins/actions/category/category.php==
%%(php)
<?php
/**
* Shows the pages and subcategories belonging to a category.
*
* See WikiCategory to understand how the system works.
*
* @package Actions
* @version $Id$
*
* @input string $page optional: the category for which you want to display the pages and categories. Default: current page
* @input integer $compact optional: 0 produces a columnar layout with a layout table; 1 produces output in the form of an unordered list. Default: 0
* @input integer $col optional: number of columns (for compact=0). Default: 1
* @output A html table with pages
* @uses Wakka::GetPageTag();
* @uses Wakka::ListPages()
* @uses Wakka::LoadPagesLinkingTo()
* @license http://www.gnu.org/copyleft/gpl.html GNU General Public License
* @filesource
*/

//including the needed functions
require_once 'libs/showarray.php'; #the two functions showing the output in a list/ in columns

# 'col' option
$col = 1;
if(isset($vars['col']))
$col = $this->htmlspecialchars_ent($vars['col']);

# 'compact' option
$compact = 0;
if(isset($vars['compact']))
$compact = $this->htmlspecialchars_ent($vars['compact']);

# 'class' option
$class = 0;
if(isset($vars['class']))
$class = $this->htmlspecialchars_ent($vars['class']);

# 'sort' option
$sort = 'ASC';
if(isset($vars['sort']))
{
$val_sort = strtoupper($this->htmlspecialchars_ent($vars['sort']));
if(in_array($val_sort, ['ASC','DESC'])) $sort = $val_sort;
}

# 'inctpl' option
$inctpl = FALSE;
if(isset($vars['inctpl']))
$inctpl = TRUE;

# 'show' option
$show = 'all';
if(isset($vars['all']))
{
$val_show = $this->htmlspecialchars_ent($vars['class']);
if(in_array($val_show, ['all','pages','categories'])) $show = $val_show;
}

# 'page' option
if(isset($vars['page']))
$page = $this->htmlspecialchars_ent($vars['page']);
else
{
#232 : if page is not given, and if this action is called from an included page, use the name of the page that is included
# and not the caller's PageTag.
if (isset($this->config['includes']) && is_array($this->GetConfigValue('includes')))
{
$count = count($this->GetConfigValue('includes')) - 1;
$page = $this->config['includes'][$count];
echo $page.":"; print_r($this->config['includes']);
}
else
{
$page=$this->GetPageTag();
}
}
if ($page=="/") $page="CategoryCategory";

if (!$inctpl && preg_match('/Template$/',$page))
{
if (!preg_match('/^Category/',$page)) $page = 'CategoryCategory'; # exception for a category that contains templates
}

//searching for categories belonging to the requested category, if necessary, and preparing the output
if ($show == 'all' || $show == 'categories')
{
$categorySearchphrase = "
SELECT tag AS page_tag
FROM ".$this->GetConfigValue('table_prefix')."links
INNER JOIN ".$this->GetConfigValue('table_prefix')."pages
ON from_tag = tag
AND latest = 'Y'
AND body LIKE '%[[(cat)".$page."]]%'
AND body LIKE '%{{category%'
GROUP BY tag
ORDER BY tag ".strtoupper($sort);
$results = $this->LoadAll($categorySearchphrase);

// filter what we show AS content of the requested category
if($keys = array_keys(array_column($results, 'page_tag'), ['CategoryCategory', $page]))
foreach($keys as $key) unset($results[$key]);

$errmsg = '<em>'.sprintf(T_("No categories found for %s"), $page).'</em>';
$list_pages_option = array(
'nopagesText' => $errmsg,
'class' => $class,
'columns' => $col,
'sort' => 'no',
'compact' => $compact
);
$str = $this->ListPages($results, $list_pages_option);
print($this->Format(T_("=====Categories=====")));
if ($str != $errmsg)
{
if(1 < count($results))
printf(T_("The following %d categories belong to %s").'<br /><br />', count($results), $page);
else
printf(T_("The following category belongs to %s").'<br /><br />', $page);
}
print($str);
}
//if necessary, a division between the categories and the pages
if ($show == 'all') print('<br /><br />');
if ($show == 'all' || $show == 'categories')
{
$categorySearchphrase = "
SELECT tag AS page_tag
FROM ".$this->GetConfigValue('table_prefix')."links
INNER JOIN ".$this->GetConfigValue('table_prefix')."pages
ON from_tag = tag
AND latest = 'Y'
AND body LIKE '%[[(cat)".$page."]]%'
AND body NOT LIKE '%{{category%'
GROUP BY tag
ORDER BY tag ".strtoupper($sort);
$results = $this->LoadAll($categorySearchphrase);

// filter what we show AS content of the requested category
if($keys = array_keys(array_column($results, 'page_tag'), ['CategoryCategory', $page]))
foreach($keys as $key) unset($results[$key]);

$errmsg = '<em>'.sprintf(T_("No pages found for %s"), $page).'</em>';
$list_pages_option = array(
'nopagesText' => $errmsg,
'class' => $class,
'columns' => $col,
'sort' => 'no',
'compact' => $compact
);
$str = $this->ListPages($results, $list_pages_option);
print($this->Format(T_("=====Pages=====")));
if ($str != $errmsg)
{
if(1 < count($results))
printf(T_("The following %d pages belong to %s").'<br /><br />', count($results), $page);
else
printf(T_("The following page belongs to %s").'<br /><br />', $page);
}
print($str);
}
?>

%%

====Older Versions====
>>Working for 1.1.6.0 to 1.1.6.4 (latest)>>''04/04/2005:version 2.0 (see below).''
===Installation===

Three things have to be changed:

==1. addition to formatters/wakka.php==

right before
%%(php)
// forced links
// \S : any character that is not a whitespace character
// \s : any whitespace character
%%

add the following:
%%(php)
//links to category pages
else if (preg_match("/^\[\[\(cat\)(\S+)(\s(.+))*\]\]$/si", $thing, $matches))
{
list(, $categorylink, $text) = $matches;
if ($categorylink)
{
if (!$help) $help = $categorylink;
return $result.$wakka->Link($categorylink, "", $text);
}
else
{
return "";
}
}
%%

==2. library/common/showarray.php==

The following file has to be saved as ##library/common/showarray.php##:
%%(php;1)
<?php
/**
* Sorts a given array in a given number of columns.
*
* @package Library
* @subpackage Common
* @name ShowArray
*
* @author {@link http://wikka.jsnx.com/JavaWoman JavaWoman} (table-less columns)
* @author {@link http://wikka.jsnx.com/NilsLindenberg NilsLindenberg} (function and "divison" of the array)
* @copyright Copyright © 2004,
* @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
* @since Wikka 1.0.0
*
* @input array $array necessary: the data to be shown
* @input integer $colnumber optional: number of colums; default: 0.
* @input string $class optional: class(es) to determine styling of the output list of table; default: none.
* @output list of data from an array, formatted as in columns
*
* @todo - possible? use a single list also for columns, using CSS to visually split up into columns - JW 2005-01-19
*/

function ShowArrayInColumns($array, $colnumber=1, $class="")
{
$str = "";
if (is_array($array))
{
$entries = count($array);
$width = (int) (100 / $colnumber);
$lines = 0;
$a = 0;

$str .= '<div'.$class.'>'."\n";

//how many lines with an entry in every column do we have?
while ($entries / $colnumber > 1)
{
$lines++;
$entries = $entries - $colnumber;
}

//prepare output
for ($i=0;$i<$colnumber;$i++)
{
$str .=' <div style="width: '.$width.'%; float: left;">'."\n";
for ($j=0;$j<$lines;$j++)
{
$str .= ' '.$array[$a].'<br />'."\n";
$a++;
}

//the rest of the entries (less then the number of cols)
if ($entries)
{
$str .= ' '.$array[$a].'<br />'."\n";
$entries--;
$a++;
}
$str .=" </div>\n";

}
$str .= '</div><br style="clear: both;">'."\n";
return ($str);
}
$str .= 'The data delivered to the function ShowArrayInColumns was no array.';
return ($str);
}

/**
* Sorts a given array as a list.
*
* @package Library
* @subpackage Common
* @name ShowArray
*
* @author {@link http://wikka.jsnx.com/JsnX JsnX} (list)
* @author {@link http://wikka.jsnx.com/NilsLindenberg NilsLindenberg} (function and "divison" of the array)
* @copyright Copyright © 2004,
* @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
* @since Wikka 1.0.0
*
* @input array $array necessary: the data to be shown
* @input string $class optional: class(es) to determine styling of the output list of table; default: none.
* @output list of data from an array, formatted as a list
*
*/

function ShowArrayAsList($array,$class="")
{
$str = "";
if (is_array($array))
{
$entries = count($array);
$str .= '<div'.$class.'>'."\n";
$str .= "<ul>\n";
for ($i=0;$i<$entries;$i++)
{
$str .= ' <li>'.$array[$i].'</li>';
}
$str .= "</ul>\n</div>\n";
return ($str);
}
$str .= "The data delivered to the function ShowArrayAsList was no array.";
return ($str);
}
?>
%%

==3. Replacement of actions/category.php==

%%(php)
<?php
/**
* Generates a list of pages belonging to the specified or top-level category.
*
* If no category page is specified, the current page is assumed to be a category.
*
* Template pages (page name ending with 'Template') may contain category names; they are filtered
* out automatically unless 'inctpl' is set to 1. One exception: pagenames that start with
* 'Category' and end with 'Template' are considered a proper category so templates can themselves
* be categorized.
*
* Note: the list view ('compact' = 1) is nice for a sidebar while the columnar view
* ('compact' = 0) is more suited for a category page.
*
* Syntax:
* {{category [inctpl="0|1"] [page="categoryname"] [col="n"] [compact="0|1"] [class="class"] [show="pages|categories|all"]}}
*
* @package Actions
* @subpackage SystemContent
* @name Category
*
* @author {@link http://wikka.jsnx.com/JsnX JsnX}
* @author {@link http://wikka.jsnx.com/JavaWoman JavaWoman} (rewrite with filtering and table-less columns)
* @author {@link http://wikka.jsnx.com/NilsLindenberg NilsLindenberg} (seperation of categories, functions for output)
* @copyright Copyright © 2004, Jason Tourtelotte
* @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
* @since Wikka 1.0.0
* @version 2.0
*
* @input integer $inctpl optional: include "template" pages (1) or not (0); default: 0.
* @input integer $page optional: category to list members of; default: current page or CategoryCategory
* @input integer $col optional: number of columns for table; default: 1
* @input integer $compact optional: use table (0) or list (1); default: 0
* @input integer $class optional: class(es) to determine styling of the output list of table
* @input string $show optional: show "pages" "categories" or "all"; default: all
* @output list of categories and/or pages belonging to the specified or top-level category,
* formatted as a list or in columns
*
* @uses LoadAll()
* @uses Link()
* @todo - possible? use a single list also for columns, using CSS to visually split up into columns - JW 2005-01-19
*/

//including the needed functions
require_once 'library/common/showarray.php'; #the two functions showing the output in a list/ in columns

// set defaults
$lIncTpl = FALSE; # do not show template pages or treat a template as a category
$lPage = $this->tag; # current page is default category
$lCol = 1; # one column for table
$lCompact = FALSE; # use table, not list
$lClass = ''; # no class
$lShow = 'all'; # show pages and categories
$lOutput = ''; # the final output

// get parameters
if (is_array($vars))
{
foreach ($vars as $param => $value)
{
switch ($param)
{
case 'inctpl':
if ($value) $lIncTpl = TRUE;
break;
case 'page':
if ($this->existsPage($value)) $lPage = $value;
break;
case 'col':
if ($value === (string)(int)$value && (int)$value > 0) $lCol = (int)$value;
break;
case 'compact':
if ($value) $lCompact = TRUE;
break;
case 'class':
if ('' != $value) $lClass = $value;
break;
case 'show':
if ($value == 'pages' || $value == 'categories') $lShow = $value;
break;
}
}
}

// filter WHICH category we (may) show the content OF
if ($lPage == '/')
{
$lPage = 'CategoryCategory';
}
if (!$lIncTpl && preg_match('/Template$/',$lPage))
{
if (!preg_match('/^Category/',$lPage)) $lPage = 'CategoryCategory'; # exception for a category that contains templates
}

//searching for categories belonging to the requested category, if necessary, and preparing the output
if ($lShow == 'all' || $lShow == 'categories')
{
$lCategorySearchphrase = "SELECT tag FROM ".$this->config['table_prefix']."pages WHERE latest = 'Y' AND body LIKE '%[[(cat)".$lPage."%' AND body LIKE '%{{category%'";
$categoryresults = $this->LoadAll($lCategorySearchphrase);
//print_r($categoryresults); //DEBUG
if ($categoryresults)
{
$categorylist = array();

// filter what we show AS content of the requested category
foreach ($categoryresults as $ccategory)
{
// do not list top-level category as member
if ('CategoryCategory' == $ccategory['tag'])
{
continue;
}
// do not list requested category as member
if ($ccategory['tag'] == $lPage)
{
continue;
}

// we have a valid result: add to the list
if ($lCompact)
{
$categorylist[] = $this->Link($ccategory['tag'],'',preg_replace( "/Category/", "",$ccategory['tag']));
}
else
{
$categorylist[] = $this->Link($ccategory['tag'],'',preg_replace( "/Category/", "",$ccategory['tag']));
}
}
sort($categorylist);

// make simple list (useful for sidebar)
if ($lCompact)
{
$lOutput .= ShowArrayAsList($categorylist,$lClass);
}
// make columnar overview (useful for category pages)
else
{
$categorycount = count($categorylist);
$lOutput .= 'The following '.$categorycount.' categories belong to '.$lPage.':<br /><br />'."\n"; #i18n
$lOutput .= ShowArrayInColumns($categorylist, $lCol, $lClass);
}
}
else
{
$lOutput .= 'No categories found for '.$lPage.".\n"; #i18n
}
}

//if necessary, a division between the categories and the pages
if ($lShow == 'all') $lOutput .= '<br /><br />';

//searching for pages belonging to the requested category, if necessary, and preparing the output
if ($lShow == 'all' || $lShow == 'pages')
{
$lPageSearchphrase = "SELECT tag FROM ".$this->config['table_prefix']."pages WHERE latest = 'Y' and body LIKE '%[[(cat)".$lPage."%' AND body NOT LIKE '%{{category%'";
$pageresults = $this->LoadAll($lPageSearchphrase);
//print_r($pageresults); //DEBUG
if ($pageresults)
{
$pagelist = array();

// filter what we show AS content of the requested category
foreach ($pageresults as $cpage)
{
// do not list requested category as member
if ($cpage['tag'] == $lPage)
{
continue;
}
// unless inctpl is set, do not list template pages
elseif (!$lIncTpl && preg_match('/Template$/', $cpage['tag']))
{
continue;
}

// we have a valid result: add to the list
if ($lCompact)
{
$pagelist[] = $this->Link($cpage['tag'],'',$cpage['tag']);
}
else
{
$pagelist[] = $this->Link($cpage['tag']);
}
}
sort($pagelist);

// make simple list (useful for sidebar)
if ($lCompact)
{
$lOutput .= ShowArrayAsList($pagelist,$lClass);
}
// make columnar overview (useful for category pages)
else
{
$pagecount = count($pagelist);
$lOutput .= 'The following '.$pagecount.' pages belong to '.$lPage.':<br /><br />'."\n"; #i18n
$lOutput .= ShowArrayInColumns($pagelist, $lCol, $lClass);
}
}
else
{
$lOutput .= 'No pages found for '.$lPage.".\n"; #i18n
}
}

echo $lOutput;
?>
%%

----
CategoryDevelopmentActions
Valid XHTML :: Valid CSS: :: Powered by WikkaWiki