Index: branches/5.2.x/units/order_items/order_items_tag_processor.php
===================================================================
--- branches/5.2.x/units/order_items/order_items_tag_processor.php	(revision 15020)
+++ branches/5.2.x/units/order_items/order_items_tag_processor.php	(revision 15021)
@@ -1,297 +1,300 @@
 <?php
 /**
 * @version	$Id$
 * @package	In-Commerce
 * @copyright	Copyright (C) 1997 - 2009 Intechnic. All rights reserved.
 * @license	Commercial License
 * This software is protected by copyright law and international treaties.
 * Unauthorized reproduction or unlicensed usage of the code of this program,
 * or any portion of it may result in severe civil and criminal penalties,
 * and will be prosecuted to the maximum extent possible under the law
 * See http://www.in-portal.org/commercial-license for copyright notices and details.
 */
 
 defined('FULL_PATH') or die('restricted access!');
 
 class OrderItemsTagProcessor extends kDBTagProcessor
 {
 	function PrintGrid($params)
 	{
 		$order =& $this->Application->recallObject('ord');
 		/* @var $order kDBList */
 
 		if ( $order->GetDBField('Status') != ORDER_STATUS_INCOMPLETE ) {
 			$params['grid'] = $params['NotEditable'];
 		}
 		else {
 			$params['grid'] = $params['Editable'];
 		}
 
 		return $this->Application->ProcessParsedTag('m', 'ParseBlock', $params);
 	}
 
 	function IsTangible($params)
 	{
 		$object =& $this->getObject($params);
 		/* @var $object kDBItem */
 
 		return $object->GetDBField('Type') == PRODUCT_TYPE_TANGIBLE;
 	}
 
 	function HasQty($params)
 	{
 		$object =& $this->getObject($params);
 		/* @var $object kDBItem */
 
 		return in_array($object->GetDBField('Type'), Array (PRODUCT_TYPE_TANGIBLE, 6));
 	}
 
 	function HasDiscount($params)
 	{
 		$object =& $this->getObject($params);
 		/* @var $object kDBItem */
 
 		return (float)$object->GetDBField('ItemDiscount') ? 1 : 0;
 	}
 
 	function HasOptions($params)
 	{
 		$object =& $this->getObject($params);
 		$item_data = @unserialize($object->GetDBField('ItemData'));
 		return isset($item_data['Options']);
 	}
 
 	function PrintOptions($params)
 	{
 		$object =& $this->getObject($params);
 		/* @var $object kDBItem */
 
 		$item_data = @unserialize($object->GetDBField('ItemData'));
 
 		$render_as = $this->SelectParam($params, 'render_as');
 		$block_params['name'] = $render_as;
 
 		$opt_helper =& $this->Application->recallObject('kProductOptionsHelper');
 		/* @var $opt_helper kProductOptionsHelper */
 
 		$o = '';
 		$options = $item_data['Options'];
 		foreach ($options as $opt => $val) {
 			if ( !is_array($val) ) {
 				$val = kUtil::unhtmlentities($val);
 			}
 			$key_data = $opt_helper->ConvertKey($opt, $object->GetDBField('ProductId'));
 
 			$parsed = $opt_helper->ExplodeOptionValues($key_data);
 			if ( $parsed ) {
 				$values = $parsed['Values'];
 				$prices = $parsed['Prices'];
 				$price_types = $parsed['PriceTypes'];
 			}
 			else {
 				$values = array ();
 				$prices = array ();
 				$price_types = array ();
 			}
 
 			$key = $key_data['Name'];
 			/*if (is_array($val)) {
 				$val = join(',', $val);
 			}*/
 
 			$lang =& $this->Application->recallObject('lang.current');
 			/* @var $lang LanguagesItem */
 
 			if ( $render_as ) {
 				$block_params['option'] = $key;
 				if ( is_array($val) ) {
 					$block_params['value'] = $val;
 					$block_params['type'] = $key_data['OptionType'];
 					$block_params['price'] = $prices;
 					$block_params['price_type'] = $price_types;
 				}
 				else {
 					$price_type = array_key_exists($val, $price_types) ? $price_types[$val] : '';
 					$price = array_key_exists($val, $prices) ? $prices[$val] : '';
 
 					if ( $price_type == '$' ) {
 						$iso = $this->GetISO($params['currency']);
 						$value = $this->AddCurrencySymbol($lang->formatNumber($this->ConvertCurrency($price_type, $iso), 2), $iso, true); // true to force sign
 						$block_params['price'] = $value;
 						$block_params['price_type'] = '';
 						$block_params['sign'] = ''; // sign is included in the formatted value
 					}
 					else {
 						$block_params['price'] = $price;
 						$block_params['price_type'] = $price_type;
 						$block_params['sign'] = $price >= 0 ? '+' : '-';
 					}
 					$block_params['value'] = htmlspecialchars($val);
 					$block_params['type'] = $key_data['OptionType'];
 				}
 				$o .= $this->Application->ParseBlock($block_params, 1);
 			}
 			else {
 				$o .= $key . ': ' . $val . '<br>';
 			}
 		}
 		return $o;
 	}
 
 	function ProductsInStock($params)
 	{
 		$object =& $this->getObject($params);
 
 		if (!$object->GetDBField('InventoryStatus')) {
 			// unlimited count available
 			return false;
 		}
 
 		if ($object->GetDBField('InventoryStatus') == 2) {
 			$poc_table = $this->Application->getUnitOption('poc', 'TableName');
 			$sql = 'SELECT QtyInStock
 					FROM '.$poc_table.'
 					WHERE (ProductId = '.$object->GetDBField('ProductId').') AND (Availability = 1) AND (CombinationCRC = '.$object->GetDBField('OptionsSalt').')';
 			$ret = $this->Conn->GetOne($sql);
 		}
 		else {
 			$ret = $object->GetDBField('QtyInStock');
 		}
 
 		return $ret;
 	}
 
 	function PrintOptionValues($params)
 	{
 		$block_params['name'] = $params['render_as'];
 
 		$values = $this->Application->Parser->GetParam('value');
 		/* @var $values Array */
 
 		$prices = $this->Application->Parser->GetParam('price');
 		$price_types = $this->Application->Parser->GetParam('price_type');
 
 		$o = '';
 		$i = 0;
 		foreach ($values as $val) {
 			$i++;
 			$val = kUtil::unhtmlentities($val);
 			$block_params['value'] = htmlspecialchars($val);
 			if ($price_types[$val] == '$') {
 				$iso = $this->GetISO($params['currency']);
 				$value = $this->AddCurrencySymbol(sprintf("%.2f", $this->ConvertCurrency($prices[$val], $iso)), $iso, true); // true to force sign
 				$block_params['price'] = $value;
 				$block_params['price_type'] = '';
 				$block_params['sign'] = ''; // sign is included in the formatted value
 			}
 			else {
 				$block_params['price'] = $prices[$val];
 				$block_params['price_type'] = $price_types[$val];
 				$block_params['sign'] = $prices[$val] >= 0 ? '+' : '-';
 			}
 			$block_params['is_last'] = $i == count($values);
 			$o.= $this->Application->ParseBlock($block_params, 1);
 		}
 		return $o;
 	}
 
 	/*function ConvertKey($key, &$object)
 	{
 		static $mapping = null;
 		if (is_null($mapping) || !isset($mapping[$object->GetDBField('ProductId')])) {
 			$table = TABLE_PREFIX.'ProductOptions';
 			$sql = 'SELECT * FROM '.$table.' WHERE ProductId = '.$object->GetDBField('ProductId');
 			$mapping[$object->GetDBField('ProductId')] = $this->Conn->Query($sql, 'ProductOptionId');
 		}
 		return $mapping[$object->GetDBField('ProductId')][$key];
 	}*/
 
 	function PrintList($params)
 	{
 		$list =& $this->GetList($params);
 		$id_field = $this->Application->getUnitOption($this->Prefix, 'IDField');
 
 		$list->Query();
 		$o = '';
 		$list->GoFirst();
 
-		$block_params=$this->prepareTagParams($params);
+		$block_params = $this->prepareTagParams($params);
 		$block_params['name'] = $this->SelectParam($params, 'render_as,block');
 		$block_params['pass_params'] = 'true';
 
-		$product_object =& $this->Application->recallObject('p', 'p', Array('skip_autoload' => true));
+		$product_object =& $this->Application->recallObject('p', 'p', Array ('skip_autoload' => true));
 		/* @var $product_object kCatDBItem */
 
 		$i = 0;
 		$product_id = $product_object->GetID();
 		$product_id_get = $this->Application->GetVar('p_id');
 
 		while (!$list->EOL()) {
 			// load product used in orderitem
-			$this->Application->SetVar( $this->getPrefixSpecial().'_id', $list->GetDBField($id_field) ); // for edit/delete links using GET
+			$this->Application->SetVar($this->getPrefixSpecial() . '_id', $list->GetDBField($id_field)); // for edit/delete links using GET
 			$this->Application->SetVar('p_id', $list->GetDBField('ProductId'));
-			$product_object->Load( $list->GetDBField('ProductId') );	// correct product load
+			$product_object->Load($list->GetDBField('ProductId')); // correct product load
 
 			$this->Application->SetVar('m_cat_id', $product_object->GetDBField('CategoryId'));
 
 			$block_params['is_last'] = ($i == $list->GetSelectedCount() - 1);
 
-			$o.= $this->Application->ParseBlock($block_params, 1);
+			$o .= $this->Application->ParseBlock($block_params, 1);
 			$list->GoNext();
 			$i++;
 		}
 
 		// restore IDs used in cycle
 		$this->Application->SetVar('p_id', $product_id_get);
-		$this->Application->DeleteVar($this->getPrefixSpecial().'_id');
-		$product_object->Load($product_id);
+		$this->Application->DeleteVar($this->getPrefixSpecial() . '_id');
+
+		if ( $product_id ) {
+			$product_object->Load($product_id);
+		}
 
 		return $o;
 	}
 
 	function DisplayOptionsPricing($params)
 	{
 		$object =& $this->getObject($params);
 		/* @var $object kDBItem */
 
 		if ( $object->GetDBField('OptionsSelectionMode') == 1 ) {
 			return false;
 		}
 
 		$item_data = unserialize($object->GetDBField('ItemData'));
 		if ( !is_array($item_data) ) {
 			return false;
 		}
 
 		$options = getArrayValue($item_data, 'Options');
 		$helper =& $this->Application->recallObject('kProductOptionsHelper');
 		/* @var $helper kProductOptionsHelper */
 
 		$crc = $helper->OptionsSalt($options, true);
 
 		$sql = 'SELECT COUNT(*)
 				FROM ' . TABLE_PREFIX . 'ProductOptionCombinations
 				WHERE CombinationCRC = ' . $crc . ' AND ProductId = ' . $object->GetDBField('ProductId') . ' AND (Price != 0 OR (PriceType = 1 AND Price = 0))';
 
 		return $this->Conn->GetOne($sql) == 0; // no overriding combinations found
 	}
 
 	function RowIndex($params)
 	{
 		$object =& $this->getObject($params);
 		/* @var $object kDBItem */
 
 		return $object->GetDBField('ProductId') . ':' . $object->GetDBField('OptionsSalt') . ':' . $object->GetDBField('BackOrderFlag');
 	}
 
 	function FreePromoShippingAvailable($params)
 	{
 		$object =& $this->getObject($params);
 		/* @var $object kDBItem */
 
 		$order_helper =& $this->Application->recallObject('OrderHelper');
 		/* @var $order_helper OrderHelper */
 
 		return $order_helper->eligibleForFreePromoShipping($object);
 	}
 }
\ No newline at end of file