Categories_For_Selected_Product displays a clickable list of all the categories assigned to
a product in a nested(indented) side menu, with the product's main cat-subcats shown first -
followed by others as sorted by Pos. in admin or alphabet.
The pixel amount to indent, down to no indenting, can be set in a product.php variable.
With indenting on, if a product is assigned to a subcategory but not its parent(s), then the
parent(s) will appear above it as non-hyperlinked place holders. Also in product.php there is
a variable for hiding or showing root (first level) categories.
To do something different with a category depending on whether or not it is available,
test the "avail" element value passed to smarty - see comments in the added template
"customer/categories_for_selected_product".
On a technical note: I am very pleased with the php code here since it is elegantly optimized with
arrays.
To see it action, check out the right side menu entitled "Copaiba
Categories/Conditions" in
this page.
To install open product.php and around line 143 insert the following:
Code:
/*This mod - categoriesForSelectedProduct - puts a product's categories into an array so we can access them from the added template: customer/categories_for_selected_product.tpl. */
# Set $rootLevel to 1 for listing 1st(Main) level categories otherwise set to 2
$rootLevel = 1;
# Set $indentPixels to the number of pixels to indent nested categories.
# If $indentPixels = 0 then no indent and no parent category placeholder names will be listed.
$indentPixels = 10;
$cat_result = db_query(" SELECT $sql_tbl[products_categories].categoryid,$sql_tbl[products_categories].main,$sql_tbl[categories].category,$sql_tbl[categories].categoryid_path,$sql_tbl[categories].order_by,$sql_tbl[categories].avail FROM $sql_tbl[products_categories],$sql_tbl[categories] WHERE $sql_tbl[products_categories].productid = $productid AND $sql_tbl[categories].categoryid = $sql_tbl[products_categories].categoryid AND $sql_tbl[categories].parentid != ($rootLevel-2) ORDER BY $sql_tbl[categories].categoryid_path");
$cat_result_main = db_query("SELECT $sql_tbl[products_categories].categoryid FROM $sql_tbl[products_categories] WHERE $sql_tbl[products_categories].productid = $productid AND $sql_tbl[products_categories].main = 'Y' ");
$categoryMain = db_fetch_row($cat_result_main);
$mainCatId = $categoryMain[0];
$i = 0;
$oldCatIDs_sortStrings = array();
$parentPlaceHolders = array();
$sortString = '';
while ($category = db_fetch_row($cat_result)) :
if ($category) {
$productCategories[] = $category;
# $productCategories initial assignments: catId[0] main[1] name[2] pathId[3] orderBy[4] avail[5]
$catName = $productCategories[$i][2];
$orderBy = $productCategories[$i][4];
$sortStingsRow = $productCategories[$i][3];
$catIDs_sortStrings = explode('/', $sortStingsRow);
if ($mainCatId == $catIDs_sortStrings[0]) {$sortPrefix = '!0000';} else {$sortPrefix = '00000';}
$totalCatLevels = count($catIDs_sortStrings);
$catIDs_sortStrings = array('catIDs' => $catIDs_sortStrings, 'sortStrings' => array_fill(0, $totalCatLevels, ''));
for ($j = $totalCatLevels; $j >= 1; $j--):
if ($j == $totalCatLevels) {
$sortString = substr_replace($sortPrefix, $orderBy, -strlen($orderBy), strlen($orderBy)) . $catName;
} else {
if ($catIDs_sortStrings[catIDs][$j-1] == $oldCatIDs_sortStrings[catIDs][$j-1]) {
$sortString = $oldCatIDs_sortStrings[sortStrings][$j-1];
} else {
$searchByCatId = $catIDs_sortStrings[catIDs][$j-1];
$cat_result_parent = db_query("SELECT $sql_tbl[categories].category,$sql_tbl[categories].order_by,$sql_tbl[categories].avail FROM $sql_tbl[categories] WHERE $sql_tbl[categories].categoryid = $searchByCatId");
$categoryParent = db_fetch_row($cat_result_parent);
if ($categoryParent) {
$sortString = substr_replace($sortPrefix, $categoryParent[1], -strlen($categoryParent[1]), strlen($categoryParent[1])) . $categoryParent[0];
if ($indentPixels > 0 && $j >= $rootLevel) { #Insert 2 rows (name & avail) to build placeholders from
if (count($catIDs_sortStrings) < 3) { $catIDs_sortStrings = array('catIDs' => $catIDs_sortStrings[catIDs], 'sortStrings' => $catIDs_sortStrings[sortStrings], 'catNames' => array_fill(0, $totalCatLevels, ''), 'catAvails' => array_fill(0, $totalCatLevels, '')); }
$catIDs_sortStrings['catNames'][$j-1] = $categoryParent[0];
$catIDs_sortStrings['catAvails'][$j-1] = $categoryParent[2];
}
}
}
}
$catIDs_sortStrings[sortStrings][$j-1] = $sortString;
endfor;
# $productCategories final assignments: catId[0] indent[1] name[2] pathId[3] sortString[4] avail[5]
$productCategories[$i][1] = (($totalCatLevels * $indentPixels ) - ($rootLevel * $indentPixels));
$productCategories[$i][4] = implode('', $catIDs_sortStrings[sortStrings]);
if (count($catIDs_sortStrings) > 2) {
# Placeholders values were inserted so create them below
for ($j = $rootLevel; $j < $totalCatLevels; $j++):
if ($catIDs_sortStrings['catNames'][$j-1] != '') {
$parentPlaceHolderRow = array('0','0','0','0','0','0');
$parentPlaceHolderRow[1] = (($j * $indentPixels ) - ($rootLevel * $indentPixels));
$parentPlaceHolderRow[2] = $catIDs_sortStrings['catNames'][$j-1];
$parentPlaceHolderRow[4] = implode('', array_slice($catIDs_sortStrings[sortStrings], 0, $j));
$parentPlaceHolderRow[5] = $catIDs_sortStrings[catAvails][$j-1];
$parentPlaceHolders[] = $parentPlaceHolderRow;
}
endfor;
}
$oldCatIDs_sortStrings = $catIDs_sortStrings;
}
$i++;
endwhile;
if (count($parentPlaceHolders)>0) {$productCategories = array_merge($productCategories, $parentPlaceHolders);}
function cmp($a, $b) {
return strcmp($a[4], $b[4]);
}
usort($productCategories, 'cmp');
$smarty->assign('productCategories',$productCategories);
Now create a new template in the customer directory and call it "categories_for_selected_product.tpl" -
this is just a modified "categories.tpl" file from the same directory. Give it the following code:
Code:
{* $Id: categories_for_selected_product.tpl based on categories.tpl,v 1.23 2004/06/24 09:53:29 max Exp $ *}
{*** See product.php for the creation of the $productCategories array used below. Array assignments are: catId[0] indent[1] name[2] pathId[3] sortString[4] avail[5] ***}
{capture name=menu}
{section name=category loop=$productCategories}
<FONT class="CategoriesList">
{if $productCategories[category].1 > 0}
{*** Do Indenting ***}
<IMG src="{$ImagesDir}/spacer.gif" width={$productCategories[category].1} height="1" border="0" align="top">
{/if}
{if $productCategories[category].0 == 0}
{*** This a parent place holder category ***}
{$productCategories[category].2}
{else}
<A href="home.php?cat={$productCategories[category].0}" class="VertMenuItems">{$productCategories[category].2}</A>
{/if}
</FONT>
{/section}
{/capture}
{ include file="menu.tpl" dingbats="dingbats_categorie.gif" menu_title=$lng.lbl_categories menu_content=$smarty.capture.menu }
Script an include for categories_for_selected_product.tpl in customer/main/product.tpl.
Please keep in mind that with the indent values passed to smarty(pants) it shouldn't be too
difficult to create an unordered list css drop menu instead of a side menu.
Thanks goes to jamesc for inspiring me to create this mod.