* @copyright 2009 Deon George * @link http://osb.leenooks.net * * @link http://www.agileco.com/ * @copyright 2004-2008 Agileco, LLC. * @license http://www.agileco.com/agilebill/license1-4.txt * @author Tony Landis * @package AgileBill * @subpackage Module:Cart */ /** * The main AgileBill Module Cart Class * * @package AgileBill * @subpackage Module:Cart */ class cart extends OSB_module { var $account_id; var $session_id; /** * How many associated product levels to check for products to grant? * * @var int */ var $module='cart'; /** * Admin View Cart Contents */ function admin_view($VAR) { if(!empty($VAR['account_id'])) { $this->account_id = $VAR['account_id']; } else { return false; } $this->admin_view = true; $this->user_view($VAR,$this); } /** * Admin Add Cart Contents */ function admin_add($VAR) { if(!empty($VAR['account_id'])) { $this->account_id = $VAR['account_id']; $db = &DB(); $rs = $db->Execute(sqlSelect($db,"session","id","account_id=$this->account_id")); if($rs && $rs->RecordCount()) { $this->session_id = $rs->fields['id']; } else { $this->session_id = SESS; } } else { return false; } $this->add($VAR,$this); } /** * Admin change cart qty */ function admin_changeqty($VAR) { if(!empty($VAR['account_id'])) { $this->account_id = $VAR['account_id']; } else { return false; } $this->admin = true; $this->changeqty($VAR,$this); } /** * Change the quantity of an item */ function changeqty($VAR) { if(empty($this->account_id)) $this->account_id = SESS_ACCOUNT; if(empty($this->session_id)) $this->session_id = SESS; @$id = $VAR['id']; @$qty = $VAR['qty']; if ($id <= 0 ) return; $db = &DB(); if ($qty == '0') { # Product Plugin Level deletion $cartid = & $db->Execute($sql=sqlSelect($db,"cart","*","id=::{$id}:: AND session_id = ::{$this->session_id}::")); if($cartid) $product = & $db->Execute($sql=sqlSelect($db,"product","*","id=::{$cartid->fields['product_id']}::")); if(!empty($product->fields['prod_plugin']) && !empty($product->fields['prod_plugin_data'])) { $prodplgfile = PATH_PLUGINS.'product/'. $product->fields['prod_plugin_file'] . '.php'; if(is_file($prodplgfile)) { include_once(PATH_PLUGINS.'product/'. $product->fields['prod_plugin_file'] . '.php'); eval('$prodplg = new plgn_prov_'. $product->fields['prod_plugin_file'] .';'); if(is_object($prodplg)) { if(is_callable(array($prodplg,'delete_cart'))) { $prodplg->delete_cart($VAR,$cartid->fields); } } } } # delete main cart items & subitems: $sql=''; if(empty($this->admin)) $sql = "AND session_id = ::{$this->session_id}::"; $rs = & $db->Execute($sql=sqlDelete($db,"cart","(id=::{$id}:: OR cart_parent_id=::{$id}:: ) $sql")); global $smarty; $smarty->assign('js',false); return false; } # update the quantity: if(!eregi("^[0-9]{1,5}$",$qty)) $qty = 1; if($qty < 1) $qty = 1; if(!$this->admin) $sql_extra = " AND session_id=::$this->session_id::"; else $sql_extra=''; if($VAR["type"] == 1) { $fields=Array('quantity'=>$qty); $db->Execute($sql=sqlUpdate($db,"cart",$fields,"id=::$id:: $sql_extra")); } else if ($VAR["type"] == 2) { $fields=Array('recurr_schedule'=>$VAR["schedule"]); $db->Execute($sql=sqlUpdate($db,"cart",$fields,"id=::$id:: $sql_extra")); } else if ($VAR["type"] == 3) { # change domain term $fields=Array('domain_term'=>$VAR["term"]); $db->Execute($sql=sqlUpdate($db,"cart",$fields,"id=::$id:: $sql_extra")); } # get the product id: $result = $db->Execute(sqlSelect($db,"cart","*","id=$id $sql_extra","cart_type,date_orig")); # get the product details: $product = $db->Execute(sqlSelect($db,"product","*","id={$result->fields["product_id"]}")); if($result->fields["cart_type"] == "2") { # domain name, get pricing include_once(PATH_MODULES.'host_tld/host_tld.inc.php'); $tldObj=new host_tld; $tldprice = $tldObj->price_tld_arr($result->fields['domain_tld'],$result->fields['host_type'],false,false,false,$this->account_id); $qty = $result->fields['domain_term']; $base_price = $tldprice[$qty]; $setup_price = 0; } else if($result->fields["cart_type"] == "3") { # ad-hoc, get price $base_price = $result->fields["ad_hoc_amount"] * $result->fields["quantity"]; $setup_price = $result->fields["ad_hoc_setup"] * $result->fields["quantity"]; } else { include_once(PATH_MODULES.'product/product.inc.php'); $productObj=new product; # get pricing for this product: $prod_price = $productObj->price_prod($product->fields,$result->fields["recurr_schedule"],$this->account); $setup_price = $prod_price["setup"] * $result->fields["quantity"]; $base_price = $prod_price["base"] * $result->fields["quantity"]; # get pricing for any attributes: $attr_price = $productObj->price_attr($product->fields,$result->fields["product_attr"],$result->fields["recurr_schedule"],$this->account); $setup_price += ($attr_price["setup"] * $result->fields["quantity"]); $base_price += ($attr_price["base"] * $result->fields["quantity"]); # get the qty $qty = $result->fields["quantity"]; } # set the smarty fields: global $smarty; $smarty->assign('qty',$qty); $smarty->assign('base',$base_price); $smarty->assign('setup',$setup_price); $smarty->assign('js',true); return; } /** * Get cart contents and return adodb rs */ public function get_contents() { $db = &DB(); $sql = sprintf('SELECT DISTINCT c.* FROM %scart as c',AGILE_DB_PREFIX); if (! empty($this->account_id)) { $sql .= sprintf(' LEFT JOIN %ssession AS s ON (s.site_id=%s AND s.account_id=%s) WHERE (c.account_id=%s OR c.session_id=s.id) ', AGILE_DB_PREFIX,DEFAULT_SITE,$this->account_id,$this->account_id); } else { $sql .= sprintf(' WHERE c.session_id=%s',$db->qstr(SESS)); $this->account_id = SESS_ACCOUNT; } $sql .= sprintf(' AND c.site_id=%s AND (c.cart_parent_id=0 OR c.cart_parent_id IS NULL) ORDER BY c.cart_type,c.date_orig',DEFAULT_SITE); $result = $db->Execute($sql); return $result; } /** * Convert cart contents into invoice object & get smarty data */ public function put_contents_invoice(&$result,&$invoice) { $db = &DB(); # get parent cart items $i = 0; $smart = array(); while (! $result->EOF) { $id = $result->fields['id']; $this->addInvoiceItem($id,$result,$invoice,$smart,$i); switch ($result->fields['cart_type']) { # AD HOC case 3: $smart[$i]['price'] = $invoice->invoice_item[$id]['total_amt']; break; # Domain case 2: $smart[$i]['price'] = $invoice->invoice_item[$id]['total_amt']; $smart[$i]['tld_arr'] = $invoice->tld_arr[$id]; $smart[$i]['sku'] = sprintf('DOMAIN-%s',strtoupper($result->fields['host_type'])); break; # Product default: @$smart[$i]['price'] = $invoice->price_arr[$id]; } # Get the product attributes $smart[$i]['attr'] = ''; if (! empty($invoice->invoice_item[$id]['product_attr_cart'])) { @$attrib = explode("\r\n",$invoice->invoice_item[$id]['product_attr_cart']); foreach($attrib as $attr) { $attributei = explode('==',$attr); if (! empty($attributei[0]) && !empty($attributei[1])) $smart[$i]['attr'] .= sprintf('%s : %s
',$attributei[0],$attributei[1]); } } # Get all children of this item $ii = 0; $resultassoc = $db->Execute(sqlSelect($db,'cart','*',sprintf('cart_parent_id=%s AND id !=%s',$result->fields['id'],$result->fields['id']))); if ($resultassoc && $resultassoc->RecordCount()) { while (!$resultassoc->EOF) { $id = $resultassoc->fields['id']; $this->addInvoiceItem($id,$resultassoc,$invoice,$smart,$i,$ii,true); # Domain if ($resultassoc->fields['cart_type'] == 2 ) { $smart[$i]['assoc'][$ii]['price'] = $invoice->invoice_item[$id]['total_amt']; $smart[$i]['assoc'][$ii]['tld_arr'] = $invoice->tld_arr[$id]; $smart[$i]['assoc'][$ii]['sku'] = sprintf('DOMAIN-%s',strtoupper($result->fields['host_type'])); } $resultassoc->MoveNext(); } } $result->MoveNext(); $i++; } return $smart; } /** * View Cart Contents */ public function user_view($VAR) { global $smarty; # Get cart contents RS $result = $this->get_contents(); if (! $result || $result->RecordCount() == 0) { $smarty->assign('result','0'); return false; } // init invoice object include_once(PATH_MODULES.'invoice/invoice.inc.php'); $invoice = new invoice; $invoice->initNew(0); $invoice->taxable=false; $invoice->discount=false; $smart = $this->put_contents_invoice($result,$invoice); $smarty->assign('results',count($invoice->invoice_item)); $smarty->assign('cart',$smart); } /** * Run a cart item through the invoice class to retrieve totals, discounts, taxes, attributes, etc. * * @param int $id * @param array $result * @param object $invoice * @param array $smart * @param int $i * @param int $assoc */ private function addInvoiceItem($id,&$result,&$invoice,&$smart,$i,$ii=false,$assoc=false) { $invoice->addItem( $id, $result ); if (! $assoc) { @$smart[$i] = $result->fields; @$smart[$i]['product'] = $invoice->product[$id]; @$smart[$i]['price_base'] = $invoice->invoice_item[$id]['price_base']; @$smart[$i]['price_setup'] = $invoice->invoice_item[$id]['price_setup']; } else { @$smart[$i]['assoc'][$ii] = $result->fields; @$smart[$i]['assoc'][$ii]['product'] = $invoice->product[$id]; @$smart[$i]['assoc'][$ii]['price_base'] = $invoice->invoice_item[$id]['price_base']; @$smart[$i]['assoc'][$ii]['price_setup'] = $invoice->invoice_item[$id]['price_setup']; } } /** * Start add to cart process */ public function add($VAR) { # Set the current account if (empty($this->account_id)) $this->account_id = SESS_ACCOUNT; if (empty($this->session_id)) $this->session_id = SESS; # Determine the type to be added to the domain: (domain or product) if (! empty($VAR['product_id'])) { if ($this->validate_product($VAR,$VAR['product_id'],$this->account_id)) { # Add hosting / domain if (! empty($VAR['domain_type'])) $this->product_add_host($VAR); # Standard product (no hosting or domain) else $this->product_add($VAR); return true; } } elseif (! empty($VAR['domain_name']) && ! empty($VAR['domain_tld'])) { # Add Domain only: # @todo Remove the is_array test, and have 1 set of code if (is_array($VAR['domain_name'])) { for ($i=0;$ivalidate_domain($VAR['domain_name'][$i],$VAR['domain_tld'][$i])) { $this->domain_add($VAR['domain_name'][$i],$VAR['domain_tld'][$i],@$VAR['host_type'][$i],@$VAR['domain_term'][$i]); } } } else { if($this->validate_domain($VAR['domain_name'],$VAR['domain_tld'])) { $this->domain_add($VAR['domain_name'],$VAR['domain_tld'],@$VAR['host_type'],@$VAR['domain_term']); } } } } /** * Add a domain name to cart * * @param string $domain * @param string $tld * @param int $type * @param int $term */ private function domain_add($domain,$tld,$type,$term=false) { if (empty($type)) return false; $db = &DB(); if (! $term || empty($term) || ! is_numeric($term)) { # Get the default term for this domain: $rs = $db->Execute(sqlSelect($db,'host_tld','default_term_new',array('name'=>$tld))); if ($rs === false || empty($rs->fields['default_term_new'])) $term = 1; else $term = $rs->fields['default_term_new']; } # Insert into cart $fields =array( 'date_orig' => time(), 'session_id' => $this->session_id, 'account_id' => $this->account_id, 'cart_type' => 2, 'host_type' => $type, 'domain_term' => $term, 'domain_name' => $domain, 'domain_tld' => $tld); $db->Execute(sqlInsert($db,'cart',$fields)); } /** * Add an ad-hoc line item to the cart */ public function ad_hoc($VAR) { $db = &DB(); if (! empty($VAR['account_id'])) { $rs = $db->Execute(sqlSelect($db,'session','id',array('account_id'=>$VAR['account_id']))); if ($rs && $rs->RecordCount() ==1) $this->session_id = $rs->fields['id']; else $this->session_id = SESS; } else { return false; } if (empty($VAR['ad_hoc_sku']) || empty($VAR['ad_hoc_name']) || $VAR['ad_hoc_amount'] == '') { global $C_debug,$C_translate; $C_debug->alert($C_translate->translate('ad_hoc_err','cart','')); return false; } if (empty($VAR['quantity'])) $qty = 1; else $qty = $VAR['quantity']; if (empty($VAR['ad_hoc_taxable'])) $VAR['ad_hoc_taxable'] = 0; # Attribs: (ad_hoc_attr_var & ad_hoc_attr_val) foreach ($VAR['ad_hoc_attr_var'] as $key => $value) if ($value && $VAR['ad_hoc_attr_val'][$key]) $attr[$value] = $VAR['ad_hoc_attr_val'][$key]; if (count($attr)) $attrib = serialize($attr); else $attrib = ''; # Create the record $fields = array( 'date_orig' => time(), 'session_id' => $this->session_id, 'account_id' => $VAR['account_id'], 'product_attr' => $attrib, 'cart_type' => 3, 'quantity' => $qty, 'ad_hoc_sku' => $VAR['ad_hoc_sku'], 'ad_hoc_name' => $VAR['ad_hoc_name'], 'ad_hoc_amount' => $VAR['ad_hoc_amount'], 'ad_hoc_taxable' => $VAR['ad_hoc_taxable']); $db->Execute(sqlInsert($db,'cart',$fields)); } /** * Add a product to the cart */ private function product_add($VAR) { if (empty($VAR['quantity'])) $qty = 1; else $qty = $VAR['quantity']; if (!empty($VAR['attr'])) @$attr = serialize($VAR['attr']); else $attr = ''; # Create the Main DB Record: $db = &DB(); $fields = array( 'date_orig' => time(), 'session_id' => $this->session_id, 'account_id' => @$VAR['account_id'], 'product_attr' => $attr, 'cart_type' => 0, 'quantity' => $qty, 'product_id' => $VAR['product_id'], 'recurr_schedule' => @$VAR['recurr_schedule'], 'service_id' => @$VAR['service_id']); $db->Execute(sqlInsert($db,'cart',$fields)); } /** * Add an assoc required product * * @param int $product_id * @todo Unused, calling code is commented out. */ private function product_req_add($product_id) { $db = &DB(); $fields = array( 'date_orig' => time(), 'session_id' => $this->session_id, 'account_id' => $this->account_id, 'cart_type' => 0, 'quantity' => 1, 'product_id' => $product_id); $db->Execute(sqlInsert($db,'cart',$fields)); } /** * Add a product to the cart */ private function product_add_host($VAR) { if (! empty($VAR['attr'])) @$attr = serialize($VAR['attr']); else $attr = serialize(array('')); $db = &DB(); $fields = array( 'date_orig' => time(), 'session_id' => $this->session_id, 'account_id' => @$VAR['account_id'], 'product_attr' => $attr, 'cart_type' => 1, 'quantity' => 1, 'product_id' => $VAR['product_id'], 'recurr_schedule' => @$VAR['recurr_schedule'], 'service_id' => @$VAR['service_id'], 'host_type' => $VAR['domain_type'], 'domain_name' => $VAR['domain_name'], 'domain_tld' => $VAR['domain_tld']); $id = sqlGenID($db,'cart'); $db->Execute(sqlInsert($db,'cart',$fields,$id)); # Get the default domain registration length: if ($VAR['domain_type'] == 'transfer' || $VAR['domain_type'] == 'register') { $domain_term = 1; $result = $db->Execute(sqlSelect($db,'host_tld','default_term_new',array('name'=>$VAR['domain_tld']))); if ($result && ! empty($result->fields['default_term_new'])) $domain_term = $result->fields['default_term_new']; # Add child domain if register or transfer $fields = array( 'date_orig' => time(), 'session_id' => $this->session_id, 'account_id' => @$VAR['account_id'], 'product_attr' => $attr, 'cart_type' => 2, 'quantity' => 1, 'host_type' => $VAR['domain_type'], 'domain_name' => $VAR['domain_name'], 'domain_tld' => $VAR['domain_tld'], 'domain_term' => $domain_term, 'cart_parent_id' => $id); $db->Execute(sqlInsert($db,'cart',$fields)); } } /** * Validate A Domain * * @param string $domain * @param string $tld * @return bool */ private function validate_domain($domain,$tld) { # Check that it is not already in the user's cart: $db = &DB(); $result = $db->Execute(sqlSelect($db,'cart','id',sprintf("(session_id=::%s:: OR account_id=) AND domain_name=:: AND domain_tld=::%s::", $this->session_id,SESS_ACCOUNT,$tld))); if ($result && $result->RecordCount()) { global $C_debug,$C_translate; $C_debug->alert($C_translate->translate('err_prod_already','cart','')); return false; } else { return true; } } /** * Validate A Product * * @param array $VAR * @param int $product_id * @param int $account_id * @return bool */ private function validate_product($VAR,$product_id,$account_id) { global $C_translate,$C_debug,$C_auth; $db = &DB(); # Can user add inactive items if ($C_auth->auth_method_by_name('invoice','add')) $active = array(); else $active = array('active'=>1); # Validate that product exists $result = $db->Execute(sqlSelect($db,'product','*',array_merge(array('id'=>$product_id),$active))); if (! $result || $result->RecordCount() == 0) { $C_debug->alert($C_translate->translate('err_no_prod','cart','')); return false; } # Check that product is not already in cart if ($result->fields['cart_multiple'] != '1' && empty($VAR['service_id'])) { $rs = $db->Execute(sqlSelect($db,'cart','id',array('product_id'=>$product_id,'session_id'=>$this->session_id))); if(! $rs || $rs->RecordCount() > 0) { $C_debug->alert($C_translate->translate('err_prod_already','cart','')); return false; } } # Validate groups: $groups = unserialize($result->fields['group_avail']); $auth = false; for ($ii=0; $iiauth_group_by_id($groups[$ii])) { $auth = true; break; } } if (! $auth) return false; # Validate any required products: if (! empty($result->fields['assoc_req_prod'])) $reqarr = unserialize($result->fields["assoc_req_prod"]); else $reqarr = false; $reqtype = $result->fields['assoc_req_prod_type']; $assoc = true; if (is_array($reqarr) && ! empty($reqarr[0])) { /* if($reqtype == 0 && is_array($reqarr)) { # ALL are required for($i=0; $iassoc_prod($reqarr[$i])) { $assoc = false; # Add the required product: $this->product_req_add($reqarr[$i]); } } elseif ($reqtype == 1 && is_array($reqarr)) { # ONE is required $assoc = false; for($i=0; $iassoc_prod($reqarr[$i])) { $assoc = true; $i = count( $reqarr ); } else { # add the required product: $this->product_req_add($reqarr[$i]); } } }*/ if(! SESS_LOGGED) { $C_debug->alert($C_translate->translate('err_assoc_login','cart','')); return false; } $items='
'; foreach ($reqarr as $prod_id) { $prodrs = $db->Execute(sqlSelect($db,'product_translate','*',array('product_id'=>$prod_id,'language_id'=>SESS_LANGUAGE))); if ($prodrs && $prodrs->RecordCount()) $items .= sprintf('- %s
',$prod_id,$prodrs->fields['name']); } $C_translate->value('cart','items',$items); $msg = $C_translate->translate('err_assoc_req','cart',''); if ($reqtype == 0) $C_debug->alert(sprintf('%s %s',$msg,$C_translate->translate('assoc_all','cart',''))); else $C_debug->alert(sprintf('%s %s',$msg,$C_translate->translate('assoc_one','cart',''))); return false; } # Product Plugin Level Validation $product = $result; if (! empty($product->fields['prod_plugin']) && !empty($product->fields['prod_plugin_data'])) { $prodplgfile = sprintf('%sproduct/%s.php',PATH_PLUGINS,$product->fields['prod_plugin_file']); if (is_file($prodplgfile)) { include_once($prodplgfile); eval('$prodplg = new plgn_prov_'.$product->fields['prod_plugin_file'].';'); if (is_object($prodplg)) { if (is_callable(array($prodplg,'validate_cart'))) { $result = $prodplg->validate_cart($VAR,$product); if (! $result) { $C_debug->alert($result); return false; } } } } } # Service upgrade if (! empty($VAR['service_id'])) { # Validate account logged in if (SESS_LOGGED == false) return false; $dbm = new CORE_database; # Validate account owns service, service is modifyable, active, not canceled, and exists $rs = $db->Execute(sqlSelect($db,'service','*',sprintf('recur_modify=1 AND active=1 AND (suspend_billing IS NULL OR suspend_billing=0) AND account_id=%s AND id=%s', SESS_ACCOUNT,$VAR['service_id']))); if (! $rs || $rs->RecordCount() == 0) return false; # Validate selected product_id is in allowed modify array for selected service if (empty($rs->fields['product_id'])) return false; $product_id = $rs->fields['product_id']; $prod = $db->Execute(sqlSelect($db,'product','*',array('id'=>$product_id))); if (! $prod || $prod->RecordCount() == 0) return false; $arr = unserialize($prod->fields['modify_product_arr']); if (! is_array($arr) || count($arr) == 0 || empty($arr[0])) return false; $do = false; foreach ($arr as $pid) if ($pid == $VAR['product_id']) { $do = true; break; } if (!$do) return false; # Make sure this service is not in the cart $sql = 'DELETE FROM ' . AGILE_DB_PREFIX . 'cart WHERE site_id='.$db->qstr(DEFAULT_SITE).' AND service_id='.$db->qstr($VAR['service_id']) ; echo '
';print_r(array($sql=>$sql,'q'=>sqlDelete($db,'cart',array('service_id'=>$VAR['service_id']))));die();
			$rs = $db->Execute($sql);

			# Make sure this service has no outstanding invoices:
			$p = AGILE_DB_PREFIX;
			$sql = "SELECT DISTINCT {$p}invoice.id, {$p}invoice_item.id
	            		FROM {$p}invoice,{$p}invoice_item
	            		WHERE {$p}invoice.site_id = ".DEFAULT_SITE." AND {$p}invoice_item.site_id = ".DEFAULT_SITE."
	            		AND {$p}invoice_item.service_id = ".$db->qstr($VAR['service_id'])."
	            		AND {$p}invoice_item.invoice_id = {$p}invoice.id  AND {$p}invoice.billing_status != 1";
			$rs = $db->Execute($sql);
			if ($rs && $rs->RecordCount() > 0) {
				echo "Invoice(s) in unpaid status for selected service ID {$VAR['service_id']}, cannot upgrade";
				return false;
			}
		}

		return true;
	}

	/**
	 * Validate Associated Prod Req.
	 *
	 * @param int $product_id
	 * @return bool
	 * @todo Unused, calling code is commented out.
	 */
	function assoc_prod($product_id) {
		# check if required assoc product is in cart
		$db = &DB();
		$p 	= AGILE_DB_PREFIX;
		$rs = $db->Execute(sqlSelect($db,"cart","*","product_id=::$product_id:: AND session_id=::".SESS."::"));
		if($rs->RecordCount() > 0) {
			return true;
		} else if (SESS_LOGGED) {
			# check if required assoc product has been purchased
			$sql ="SELECT {$p}invoice.account_id, {$p}invoice_item.product_id
                FROM {$p}invoice_item LEFT JOIN {$p}invoice ON {$p}invoice_item.invoice_id = {$p}invoice.id
                WHERE   {$p}invoice.account_id       = " . $db->qstr(SESS_ACCOUNT) . "
                AND     {$p}invoice_item.product_id  = " . $db->qstr( $product_id ) . "
                AND     {$p}invoice.process_status   = " . $db->qstr( "1" ) . "
                AND     {$p}invoice.site_id          = " . $db->qstr(DEFAULT_SITE) . "
                AND     {$p}invoice_item.site_id     = " . $db->qstr(DEFAULT_SITE);
			$rs = $db->Execute($sql);
			$rs->RecordCount();
			if($rs->RecordCount() > 0)  return true;
		}
		return false;
	}
}
?>