Additional Product Images as Thumbnails

Modules, Add-ons and custom code that's more than just a quick hack or Mod.
Post Reply
jgaris
Confirmed
Confirmed
Posts: 1
Joined: Thu Jun 25, 2009 7:00 pm

Additional Product Images as Thumbnails

Post by jgaris »

Here is a mod we posted on the Interspire forum but had requests to also post it here...

The mod is free. We also offer installation for a small fee.
Attachments
Secondary_Thumbnails_5-0-4.zip
(11.28 KiB) Downloaded 1079 times
jonahcoyote
Posts: 1
Joined: Sat Sep 05, 2009 11:48 pm

Re: Additional Product Images as Thumbnails

Post by jonahcoyote »

I know product images are going to be overhauled in the near future but am wondering if anybody has this mod working in 5.0.6?
jvilla
Posts: 15
Joined: Thu Dec 03, 2009 7:32 pm

Re: Additional Product Images as Thumbnails

Post by jvilla »

Jgaris,

Can you post "Secondary Thumbanils 5.0.6.zip ?

Thank you!
Martin
Site Admin
Site Admin
Posts: 1854
Joined: Wed Jun 17, 2009 6:30 pm
Location: South Yorkshire UK
Contact:

Re: Additional Product Images as Thumbnails

Post by Martin »

The class.product.php file is easy to update...

Open: includes/classes/class.product.php

Find:

Code: Select all

				$GLOBALS['CurrentProductLink'] = ProdLink($this->_prodname);
			}
		}
After, Add:

Code: Select all

		public function GetImages()
		{
			$images = array();
			$query = "
				SELECT *
				FROM [|PREFIX|]product_images
				WHERE  imageprodid='".$this->_prodid."' AND imageisthumb='0' 
				ORDER BY imagesort
			";
			$result = $GLOBALS['ISC_CLASS_DB']->Query($query);
			while ($row = $GLOBALS['ISC_CLASS_DB']->Fetch($result))
				$images[] = $row;                                           
			return $images;
		}
Unfortunately the display/ProductDetails.php has been almost completely rewritten between 5.0.4 and 5.0.6 so it's definitely not compatible or wise to continue to use it...
Tony Barnes
Posts: 744
Joined: Thu Jun 18, 2009 8:59 am

Re: Additional Product Images as Thumbnails

Post by Tony Barnes »

This is being implemented properly in the next ISC release I believe
jvilla
Posts: 15
Joined: Thu Dec 03, 2009 7:32 pm

Re: Additional Product Images as Thumbnails

Post by jvilla »

>Martin

That fist line of code doesn't appear in my class.product.php file:

Code: Select all

<?php

	class ISC_PRODUCT
	{

		var $_product = array();

		var $_prodid = 0;
		var $_prodprice = 0;
		var $_prodcalculatedprice = 0;
		var $_prodretailprice = 0;
		var $_prodsaleprice = 0;
		var $_prodimages = 0;
		var $_prodfixedshippingcost = 0;
		var $_prodtype = 0;
		var $_prodweight = 0;
		var $_prodavgrating = 0;
		var $_prodoptionsrequired = 0;
		var $_prodnumreviews = 0;
		var $_prodnumcustomfields = 0;
		var $_prodinvtrack = 0;
		var $_prodcurrentinv = 0;

		var $_prodallowpurchases = 1;
		var $_prodhideprice = 0;
		var $_prodcallforpricinglabel = '';

		var $_prodname = "";
		var $_prodthumb = "";
		var $_proddesc = "";
		var $_prodbrandname = "";
		var $_prodavailability = "";
		var $_prodrelatedproducts = "";
		var $_prodlayoutfile = "";
		var $_prodsku = "";

		var $_prodpagetitle = '';
		var $_prodmetakeywords = '';
		var $_prodmetadesc = '';

		var $_prodfreeshipping = false;
		var $_prodvariations = array();
		var $_prodvariationcombinations = array();
		var $_prodvariationoptions = array();

		var $_currencyrecord = null;

		function __construct($productid=0)
		{
			// Load the data for this product
			$this->_SetProductData($productid);

			// Add it to the list of recently viewed products
			if($productid == 0) {
				$this->_AddToRecentlyViewedProducts();

				// Workout the breadcrumb(s)
				$this->_BuildBreadCrumbs();

				// Track a view for this page
				$this->_TrackView();
			}
		}

		function _SetProductData($productid=0)
		{

			if ($productid == 0) {
				// Retrieve the query string variables. Can't use the $_GET array
				// because of SEO friendly links in the URL
				SetPGQVariablesManually();
				if (isset($_REQUEST['product'])) {
					$product = $_REQUEST['product'];
				}
				else if(isset($GLOBALS['PathInfo'][1])) {
					$product = preg_replace('#\.html$#i', '', $GLOBALS['PathInfo'][1]);
				}
				else {
					$product = '';
				}

				$product = $GLOBALS['ISC_CLASS_DB']->Quote(MakeURLNormal($product));
				$productSQL = sprintf("p.prodname='%s'", $product);
			}
			else {
				$productSQL = sprintf("p.productid='%s'", (int)$productid);
			}

			$query = "
				SELECT p.*, FLOOR(prodratingtotal/prodnumratings) AS prodavgrating, imageisthumb, imagefile, ".GetProdCustomerGroupPriceSQL().",
				(SELECT COUNT(fieldid) FROM [|PREFIX|]product_customfields WHERE fieldprodid=p.productid) AS numcustomfields,
				(SELECT COUNT(reviewid) FROM [|PREFIX|]reviews WHERE revstatus='1' AND revproductid=p.productid AND revstatus='1') AS numreviews,
				(SELECT brandname FROM [|PREFIX|]brands WHERE brandid=p.prodbrandid) AS prodbrandname,
				(SELECT COUNT(imageid) FROM [|PREFIX|]product_images WHERE imageprodid=p.productid AND imageisthumb=0) AS numimages
				FROM [|PREFIX|]products p
				LEFT JOIN [|PREFIX|]product_images pi ON (p.productid=pi.imageprodid)
				WHERE ".$productSQL." AND p.prodvisible='1' AND (imageisthumb=1 OR ISNULL(imageisthumb))
			";
			$result = $GLOBALS['ISC_CLASS_DB']->Query($query);
			if ($row = $GLOBALS['ISC_CLASS_DB']->Fetch($result)) {
				$this->_product = $row;
				$this->_prodid = $row['productid'];
				$this->_prodname = $row['prodname'];
				$this->_prodsku = $row['prodcode'];
				$this->_prodthumb = $row['imagefile'];
				$this->_proddesc = $row['proddesc'];
				$this->_prodimages = $row['numimages'];
				$this->_prodprice = $row['prodprice'];
				$this->_prodretailprice = $row['prodretailprice'];
				$this->_prodsaleprice = $row['prodsaleprice'];
				$this->_prodfixedshippingcost = $row['prodfixedshippingcost'];
				$this->_prodbrandname = $row['prodbrandname'];
				$this->_prodweight = $row['prodweight'];
				$this->_prodavgrating = (int)$row['prodavgrating'];
				$this->_prodcalculatedprice = $row['prodcalculatedprice'];
				$this->_prodoptionsrequired = $row['prodoptionsrequired'];
				$this->_prodnumreviews = $row['numreviews'];
				$this->_prodavailability = $row['prodavailability'];
				$this->_prodnumcustomfields = $row['numcustomfields'];
				$this->_prodrelatedproducts = $row['prodrelatedproducts'];
				if($row['prodlayoutfile'] != '') {
					$File = str_replace(array(".html", ".htm"), "", $row['prodlayoutfile']);
					if(!file_exists(ISC_BASE_PATH."/templates/".GetConfig('template')."/".$row['prodlayoutfile'])) {
						$this->_prodlayoutfile = 'product';
					}
					else {
						$this->_prodlayoutfile = $File;
					}
				}
				else {
					$this->_prodlayoutfile = 'product';
				}
				$this->_prodpagetitle = $row['prodpagetitle'];
				$this->_prodmetakeywords = $row['prodmetakeywords'];
				$this->_prodmetadesc = $row['prodmetadesc'];
				$this->_prodinvtrack = $row['prodinvtrack'];
				$this->_prodcurrentinv = $row['prodcurrentinv'];

				if ($row['prodtype'] == 1) {
					$this->_prodtype = PT_PHYSICAL;
				} else {
					$this->_prodtype = PT_DIGITAL;
				}

				if ($row['prodfreeshipping'] == 0) {
					$this->_prodfreeshipping = false;
				} else {
					$this->_prodfreeshipping = true;
				}

				$this->_prodallowpurchases = $row['prodallowpurchases'];
				$this->_prodhideprice = $row['prodhideprice'];
				$this->_prodcallforpricinglabel = $row['prodcallforpricinglabel'];

				// If there are product variations, set them up
				if($row['prodvariationid'] > 0) {
					$this->SetupProductVariations();
				}
			}
		}

		/**
		*	Track a view for this product by updating the prodnumviews field in the products table
		*/
		function _TrackView()
		{
			$query = sprintf("update [|PREFIX|]products set prodnumviews=prodnumviews+1 where productid='%d'", $this->_prodid);
			$GLOBALS['ISC_CLASS_DB']->Query($query);
		}

		function _AddToRecentlyViewedProducts()
		{
			/*
				Store this product's ID in a persistent cookie
				that will be used to remember the last 5 products
				that this person has viewed
			*/

			$viewed_products = array();

			if (isset($_COOKIE['RECENTLY_VIEWED_PRODUCTS'])) {
				$viewed_products = explode(",", $_COOKIE['RECENTLY_VIEWED_PRODUCTS']);
			}

			if (in_array($this->GetProductId(), $viewed_products)) {
				// Remove it from the array
				foreach ($viewed_products as $k=>$v) {
					if ($v == $this->GetProductId()) {
						unset($viewed_products[$k]);
					}
				}
			}

			// Add it to the list
			$viewed_products[] = $this->GetProductId();

			// Only store the 5 most recent product Id's
			if (sizeof($viewed_products) > 5) {
				$reverse_viewed_products = array_reverse($viewed_products);
				$viewed_products = array();

				for ($i = 0; $i < 5; $i++) {
					$viewed_products[] = $reverse_viewed_products[$i];
				}

				// Reverse the array so the oldest products show first
				$viewed_products = array_reverse($viewed_products);
			}

			$new_viewed_products = implode(",", $viewed_products);

			// Persist the cookie for 30 days
			ISC_SetCookie("RECENTLY_VIEWED_PRODUCTS", $new_viewed_products, time() + (3600*24*30));

			// Persist the cookie session-wide for use on the cart page
			$_SESSION['RECENTLY_VIEWED_PRODUCTS'] = $new_viewed_products;
		}

		function SetupProductVariations()
		{
			// Get a list of product variations for this product from the database
			$optionList = array();
			$query = "
				SELECT *
				FROM [|PREFIX|]product_variation_combinations
				WHERE vcproductid='".$GLOBALS['ISC_CLASS_DB']->Quote($this->GetProductId())."' AND vcenabled='1'
			";
			$result = $GLOBALS['ISC_CLASS_DB']->Query($query);

			while ($combination = $GLOBALS['ISC_CLASS_DB']->Fetch($result)) {
				$variationOptions = explode(",", $combination['vcoptionids']);

				// Product options must be sorted numerically for the javascript selections to work
				sort($variationOptions);

				$combination['vcoptionids'] = implode(",", $variationOptions);
				$this->_prodvariationcombinations[] = $combination;

				// Add the list of options available to the list we'll be selecting below
				$optionList = array_merge($optionList, $variationOptions);
			}

			if(!empty($optionList)) {
				// Fetch the list of option names and values
				$optionList = implode(",", array_unique($optionList));
				$query = "
					SELECT *
					FROM [|PREFIX|]product_variation_options
					WHERE voptionid IN (".$optionList.")
					ORDER BY voptionid
				";
				$result = $GLOBALS['ISC_CLASS_DB']->Query($query);
				$variationNames = array();
				$count = 0;
				while($option = $GLOBALS['ISC_CLASS_DB']->Fetch($result)) {
					if(!isset($variationNames[$option['voname']])) {
						++$count;
						$variationNames[$option['voname']] = $count;
					}
					else {
						$count = $variationNames[$option['voname']];
					}
					if(!isset($this->_prodvariations[$option['voname']])) {
						$this->_prodvariations[$option['voname']] = array();
					}
					$this->_prodvariations[$option['voname']][] = $option;
					$this->_prodvariationslookup[$option['voptionid']] = $count;
					$this->_prodvariationoptions[$option['voptionid']] = $option;
				}
			}
		}
		function GetVariationCombination($combination)
		{
			if(!is_array($combination)) {
				$combination = explode(",", $combination);
			}

			// Sort it numerically
			sort($combination, SORT_NUMERIC);
			$combination = implode(",", $combination);

			foreach($this->_prodvariationcombinations as $variation) {
				// Sort this combination numerically too
				$vcombination = explode(",", $variation['vcoptionids']);
				sort($vcombination, SORT_NUMERIC);
				$vcombination = implode(",", $vcombination);
				if($vcombination == $combination) {
					return $variation['combinationid'];
				}
			}

			// Nothing found, return false
			return false;
		}

		function GetProductVariationCombinationJavascript()
		{
			if(empty($this->_prodvariationcombinations)) {
				return '';
			}
			$script = "<script type=\"text/javascript\">\n";
			$script .= " var VariationList = new Array();\n";

			foreach($this->_prodvariationcombinations as $variation) {
				$variationPrice = CurrencyConvertFormatPrice(CalcProductVariationPrice($this->_prodcalculatedprice, $variation['vcpricediff'], $variation['vcprice'], $this->_product));
				$variationWeight = FormatWeight(CalcProductVariationWeight($this->_prodweight, $variation['vcweightdiff'], $variation['vcweight']), true);

				if($variation['vcthumb'] != '') {
					$thumb = $GLOBALS['ShopPath']."/".GetConfig('ImageDirectory')."/".$variation['vcthumb'];
				}
				else {
					$thumb = '';
				}
				if($variation['vcimage'] != '') {
					$image = $GLOBALS['ShopPath'].'/'.GetConfig('ImageDirectory').'/'.$variation['vcimage'];
				}
				else {
					$image = '';
				}

				$ids = explode(",", $variation['vcoptionids']);
				$optionList = array();
				foreach($ids as $id) {
					$key = $this->_prodvariationslookup[$id];
					$optionList[$key] = $id;
				}
				ksort($optionList);
				$optionList = implode(",", $optionList);

				$script .= " VariationList[".$variation['combinationid']."] = {";
				$script .= " combination: '".$optionList."', ";
				$script .= " price: '".$variationPrice."', ";
				$script .= " sku: '".isc_html_escape($variation['vcsku'])."', ";
				$script .= " weight: '".$variationWeight."', ";
				$script .= " thumb: '".$thumb."', ";
				$script .= " image: '".$image."', ";
				// Tracking inventory on a product variation level
				if($this->_prodinvtrack == 2) {
					if(GetConfig('ShowInventory') == 1) {
						$script .= "stock: '".$variation['vcstock']."', ";
					}
					if($variation['vcstock'] <= 0) {
						$script .= " instock: false";
					}
					else {
						$script .= " instock: true";
					}
				}
				else {
					$script .= " instock: true";
				}
				$script .= "};\n";
			}

			$script .= "</script>";
			return $script;

		}

		function GetProductVariations()
		{
			return $this->_prodvariations;
		}

		function GetProductInventoryTracking()
		{
			return $this->_prodinvtrack;
		}

		function GetInventoryLevel()
		{
			return $this->_prodcurrentinv;
		}

		function IsOptionRequired()
		{
			if ($this->_prodoptionsrequired == 1) {
				return true;
			} else {
				return false;
			}
		}

		function _BuildBreadCrumbs()
		{
			/*
				Build a list of one or more breadcrumb trails for this
				product based on which categories it appears in
			*/

			// Build the arrays that will contain the category names to build the trails
			$count = 0;

			$GLOBALS['BreadCrumbs'] = "";
			$GLOBALS['FindByCategory'] = "";

			// First we need to fetch the parent lists of all of the categories
			$trailCategories = array();
			$crumbList = array();
			$query = sprintf("
				SELECT c.categoryid, c.catparentlist
				FROM [|PREFIX|]categoryassociations ca
				INNER JOIN [|PREFIX|]categories c ON (c.categoryid=ca.categoryid)
				WHERE ca.productid='%d'",
				$GLOBALS['ISC_CLASS_DB']->Quote($this->GetProductId())
			);
			$result = $GLOBALS['ISC_CLASS_DB']->Query($query);
			while ($row = $GLOBALS['ISC_CLASS_DB']->Fetch($result)) {
				if ($row['catparentlist'] == '') {
					$row['catparentlist'] = $row['categoryid'];
				}
				$cats = explode(",", $row['catparentlist']);
				$trailCategories = array_merge($trailCategories, $cats);
				$crumbList[$row['categoryid']] = $row['catparentlist'];
			}

			$trailCategories = implode(",", array_unique($trailCategories));
			$categories = array();
			if ($trailCategories != '') {
				// Now load the names for the parent categories from the database
				$query = sprintf("SELECT categoryid, catname FROM [|PREFIX|]categories WHERE categoryid IN (%s)", $trailCategories);
				$result = $GLOBALS['ISC_CLASS_DB']->Query($query);
				while ($row = $GLOBALS['ISC_CLASS_DB']->Fetch($result)) {
					$categories[$row['categoryid']] = $row['catname'];
				}
			}

			// Now we have all of the information we need to build the trails, lets actually build them
			foreach ($crumbList as $trail) {
				$GLOBALS['CatTrailLink'] = $GLOBALS['ShopPath'];
				$GLOBALS['CatTrailName'] = GetLang('Home');
				$GLOBALS['BreadcrumbItems'] = $GLOBALS['ISC_CLASS_TEMPLATE']->GetSnippet("BreadcrumbItem");
				$GLOBALS['FindByCategoryItems'] = "";

				$cats = explode(",", $trail);
				foreach ($cats as $categoryid) {
					if(!CustomerGroupHasAccessToCategory($categoryid)) {
						continue;
					}
					if (isset($categories[$categoryid])) {
						$catname = $categories[$categoryid];
						$GLOBALS['CatTrailLink'] = CatLink($categoryid, $catname);
						$GLOBALS['CatTrailName'] = isc_html_escape($catname);
						$GLOBALS['BreadcrumbItems'] .= $GLOBALS['ISC_CLASS_TEMPLATE']->GetSnippet("BreadcrumbItem");
						$GLOBALS['FindByCategoryItems'] .= $GLOBALS['ISC_CLASS_TEMPLATE']->GetSnippet("ProductFindByCategoryItem");
					}
				}

				$GLOBALS['CatTrailName'] = isc_html_escape($this->GetProductName());
				$GLOBALS['BreadcrumbItems'] .= $GLOBALS['ISC_CLASS_TEMPLATE']->GetSnippet("BreadcrumbItemCurrent");
				$GLOBALS['BreadCrumbs'] .= $GLOBALS['ISC_CLASS_TEMPLATE']->GetSnippet("ProductBreadCrumb");
				$GLOBALS['FindByCategory'] .= $GLOBALS['ISC_CLASS_TEMPLATE']->GetSnippet("ProductFindByCategory");
			}
		}

		function HandlePage()
		{
			$this->ShowPage();
		}

		function HasFreeShipping()
		{
			return $this->_prodfreeshipping;
		}

		function GetFixedShippingCost()
		{
			return $this->_prodfixedshippingcost;
		}

		function GetProduct()
		{
			return $this->_product;
		}

		function GetProductName()
		{
			return $this->_prodname;
		}

		function GetProductId()
		{
			return $this->_prodid;
		}

		function GetThumb()
		{
			return $this->_prodthumb;
		}

		function GetDesc()
		{
			return $this->_proddesc;
		}

		function GetNumImages()
		{
			return $this->_prodimages;
		}

		function GetPrice()
		{
			return $this->_prodprice;
		}

		function GetRetailPrice()
		{
			return $this->_prodretailprice;
		}

		function GetSalePrice()
		{
			return $this->_prodsaleprice;
		}

		function GetCalculatedPrice()
		{
			return CalculateProductPrice($this->_product, true, true, false);
		}

		function GetFinalPrice()
		{
			return CalcProdCustomerGroupPrice($this->_product, $this->_prodcalculatedprice);
		}

		function GetBrandName()
		{
			return $this->_prodbrandname;
		}

		function GetProductType()
		{
			return $this->_prodtype;
		}

		function GetWeight()
		{
			return FormatWeight($this->_prodweight, true);
		}

		function GetRating()
		{
			return $this->_prodavgrating;
		}

		function GetNumReviews()
		{
			return $this->_prodnumreviews;
		}

		function GetSKU()
		{
			return $this->_prodsku;
		}

		function GetAvailability()
		{
			return $this->_prodavailability;
		}

		function GetNumCustomFields()
		{
			return $this->_prodnumcustomfields;
		}

		function GetRelatedProducts()
		{
			// Related products are set to automatic, find them
			return GetRelatedProducts($this->_prodid, $this->_prodname, $this->_prodrelatedproducts);
		}

		function IsPurchasingAllowed()
		{
			return $this->_prodallowpurchases;
		}

		function ArePricesHidden()
		{
			if(!GetConfig('ShowProductPrice') || $this->_prodhideprice == 1) {
				return true;
			}

			return false;
		}

		function GetProductCallForPricingLabel()
		{
			return $this->_prodcallforpricinglabel;
		}

		function GetPageTitle()
		{
			return $this->_prodpagetitle;
		}
		
		public function GetProductWarranty()
		{
			return $this->_product['prodwarranty'];
		}

		function BuildTitle()
		{
			$title = '';
			if ($this->GetPageTitle()!="") {
				$title = $this->GetPageTitle();
			} elseif ($this->GetProductName()!="") {
				$title = sprintf("%s - %s", $this->GetProductName(), GetConfig('StoreName'));
			} else {
				$title = sprintf("%s %s", GetConfig('StoreName'), GetLang('Products'));
			}
			return $title;
		}

		function ShowPage()
		{
			if ($this->_prodid > 0) {
				// Check that the customer has permisison to view this product
				$canView = false;
				$productCategories = explode(',', $this->_product['prodcatids']);
				foreach($productCategories as $categoryId) {
					// Do we have permission to access this category?
					if(CustomerGroupHasAccessToCategory($categoryId)) {
						$canView = true;
					}
				}
				if($canView == false) {
					$noPermissionsPage = GetClass('ISC_403');
					$noPermissionsPage->HandlePage();
					exit;
				}

				if ($this->_prodmetakeywords != "") {
					$GLOBALS['ISC_CLASS_TEMPLATE']->SetMetaKeywords(isc_html_escape($this->_prodmetakeywords));
				}

				if ($this->_prodmetadesc != "") {
					$GLOBALS['ISC_CLASS_TEMPLATE']->SetMetaDescription(isc_html_escape($this->_prodmetadesc));
				}

				$GLOBALS['CompareLink'] = CompareLink();

				// If we're showing images as a lightbox, we need to load up the URLs for the other images for this product
				if(GetConfig('ProductImageMode') == 'lightbox') {
					$GLOBALS['AdditionalStylesheets'] = array(
						GetConfig('ShopPath').'/javascript/jquery/plugins/lightbox/lightbox.css'
					);
				}

				$GLOBALS['ISC_CLASS_TEMPLATE']->SetTemplate($this->_prodlayoutfile);
				$GLOBALS['ISC_CLASS_TEMPLATE']->ParseTemplate();
			}
			// Visiting an invalid product, show a lovely error message
			else {
				ShowInvalidError('product');
				die();
			}
		}
	}

?>
Would you mind posting the version of display/ProductDetails.php that you have?

>Tony
I can't wait for the next release, but thanks for your input!
Post Reply