<!---
Filename: ShoppingCart.cfc
Created by: Nate Weiss (NMW)
Additions by: Nick Sweeney Big Fat Designs LLC
Todd Gasall
Purpose: Creates a CFC called ShoppingCart
--->
<CFCOMPONENT>
<!--- Initialize the cart's contents --->
<!--- Because this is outside of any <CFFUNCTION>
tag, --->
<!--- it only occurs when the CFC is first created --->
<CFSET This.CartArray = ArrayNew(1)>
<!--- *** ADD Method *** --->
<CFFUNCTION
NAME="Add"
HINT="Adds an item to the shopping cart">
<!--- Two Arguments: MerchID and Quantity --->
<CFARGUMENT NAME="MerchID" TYPE="numeric" REQUIRED="Yes">
<CFARGUMENT NAME="Quantity" TYPE="numeric" REQUIRED="No" DEFAULT="1">
<CFARGUMENT NAME="Options" TYPE="struct" REQUIRED="No">
<CFARGUMENT NAME="Choices" TYPE="struct" REQUIRED="No">
<!--- Get the Further Info for Cart Item --->
<cfquery name="qryGetCartWeight" datasource="#Application.DSN#" username="#Application.username#" password="#Application.password#">
SELECT MerchID, MerchShipWeight
FROM Merchandise
WHERE MerchID = <cfqueryparam cfsqltype="cf_sql_integer" value="#Arguments.MerchID#">
</cfquery>
<!--- Get structure that represents this item in cart, --->
<!--- then set its quantity to the specified quantity --->
<CFSET CartItem = GetCartItem(MerchID,Options,Choices)>
<CFSET CartItem.Quantity = CartItem.Quantity + Arguments.Quantity>
<CFSET CartItem.Weight = #qryGetCartWeight.MerchShipWeight# * CartItem.Quantity>
<CFSET CartItem.Options = #Arguments.Options#>
<CFSET CartItem.Choices = #Arguments.Choices#>
</CFFUNCTION>
<!--- *** UPDATE Method *** --->
<CFFUNCTION
NAME="Update"
HINT="Updates an item's quantity in the shopping cart">
<!--- Two Arguments: MerchID and Quantity --->
<CFARGUMENT NAME="MerchID" TYPE="numeric" REQUIRED="Yes">
<CFARGUMENT NAME="Quantity" TYPE="numeric" REQUIRED="Yes">
<!--- If the new quantity is greater than zero --->
<CFIF Quantity GT 0>
<!--- Get the Further Info for Cart Item --->
<cfquery name="qryGetCartWeight" datasource="#Application.DSN#" username="#Application.username#" password="#Application.password#">
SELECT MerchID, MerchShipWeight
FROM Merchandise
WHERE MerchID = <cfqueryparam cfsqltype="cf_sql_integer" value="#Arguments.MerchID#">
</cfquery>
<!--- Get structure that represents this item in cart, --->
<!--- then set its quantity to the specified quantity --->
<CFSET CartItem = GetCartItem(MerchID)>
<CFSET CartItem.Quantity = Arguments.Quantity>
<CFSET CartItem.Weight = #qryGetCartWeight.MerchShipWeight# * CartItem.Quantity>
<!--- If new quantity is zero, remove the item from cart --->
<CFELSE>
<CFSET This.Remove(MerchID)>
</CFIF>
</CFFUNCTION>
<!--- *** REMOVE Method *** --->
<CFFUNCTION
NAME="Remove"
HINT="Removes an item from the shopping cart">
<!--- One Argument: MerchID --->
<CFARGUMENT NAME="MerchID" TYPE="numeric" REQUIRED="Yes">
<!--- What position is this item occupying in the cart? --->
<CFSET CartPos = GetCartPos(MerchID)>
<!--- Assuming the item was found, remove it from cart --->
<CFIF CartPos GT 0>
<CFSET ArrayDeleteAt(This.CartArray, CartPos)>
</CFIF>
</CFFUNCTION>
<!--- *** EMPTY Method *** --->
<CFFUNCTION
NAME="Empty"
HINT="Removes all items from the shopping cart">
<!--- Empty the cart by clearing the This.CartArray array --->
<CFSET ArrayClear(This.CartArray)>
</CFFUNCTION>
<!--- *** LIST Method *** --->
<CFFUNCTION
NAME="List"
HINT="Returns a query object containing all items in shopping cart. The query object has two columns: MerchID and Quantity."
RETURNTYPE="query">
<!--- Create a query, to return to calling process --->
<CFSET q = QueryNew("MerchID,Quantity,Weight,Options,Choices")>
<!--- For each item in cart, add row to query --->
<CFLOOP FROM="1" TO="#ArrayLen(This.CartArray)#" INDEX="i">
<CFSET QueryAddRow(q)>
<CFSET QuerySetCell(q, "MerchID", This.CartArray[i].MerchID)>
<CFSET QuerySetCell(q, "Quantity", This.CartArray[i].Quantity)>
<CFSET QuerySetCell(q, "Weight", This.CartArray[i].Weight)>
<CFSET QuerySetCell(q, "Options", This.CartArray[i].Options)>
<CFSET QuerySetCell(q, "Choices", This.CartArray[i].Choices)>
</CFLOOP>
<!--- Return completed query --->
<CFRETURN q>
</CFFUNCTION>
<!--- Internal GetCartPos() Method --->
<CFFUNCTION
NAME="GetCartPos"
RETURNTYPE="numeric"
ACCESS="private">
<!--- Argument: MerchID --->
<CFARGUMENT NAME="MerchID" TYPE="numeric" REQUIRED="Yes">
<CFARGUMENT NAME="Options" TYPE="struct" REQUIRED="No" default="#StructNew()#">
<CFARGUMENT NAME="Choices" TYPE="struct" REQUIRED="No" default="#StructNew()#">
<!--- Get position, if any, of MerchID in cart query --->
<CFSET CurrentArrayPos = 0>
<CFLOOP FROM="1" TO="#ArrayLen(This.CartArray)#" INDEX="i">
<cfset OptionsMatch = "TRUE">
<cfset ChoicesMatch = "TRUE">
<CFIF This.CartArray[i].MerchID EQ Arguments.MerchID>
<!--- Need to compare both Options Struct AND Choice Struct --->
<cfif StructCount(Arguments.Options) GT 0>
<cfset CartItemOptions = This.CartArray[i].Options>
<!--- Loop over Option Items to find similar value --->
<cfloop collection="#Arguments.Options#" item="o">
<cfset PassedOptionItemID = #StructFind(Arguments.Options, o)# >
<cfset CurrentOptionItemID = #StructFind(CartItemOptions, o)# >
<!--- If the values match - remove from temp list --->
<cfif PassedOptionItemID EQ CurrentOptionItemID>
<cfset DeleteRow = StructDelete(CartItemOptions, "#o#", "True")>
<cfelse>
<!--- If they don't match - set to FALSE and break loop --->
<cfset OptionsMatch = "FALSE">
<CFBREAK>
</cfif>
</cfloop>
</cfif>
<cfif StructCount(Arguments.Choices) GT 0>
<cfset CartItemChoices = This.CartArray[i].Choices>
<!--- Loop over Option Items to find similar value --->
<cfloop collection="#Arguments.Choices#" item="c">
<cfset PassedChoiceItemID = #StructFind(Arguments.Choices, c)# >
<cfset CurrentChoiceItemID = #StructFind(CartItemChoices, c)# >
<!--- If the values match - remove from temp list --->
<cfif PassedChoiceItemID EQ CurrentChoiceItemID>
<cfset DeleteRow = StructDelete(CartItemChoices, "#c#", "True")>
<cfelse>
<!--- If they don't match - set to FALSE and break loop --->
<cfset ChoicesMatch = "FALSE">
<CFBREAK>
</cfif>
</cfloop>
</cfif>
<!--- Check size of CartItemOptions - if anything left - the two do NOT match--->
<cfif OptionsMatch EQ "TRUE" AND ChoicesMatch EQ "TRUE">
<cfif StructCount(CartItemOptions) EQ 0 AND StructCount(CartItemChoices) EQ 0>
<CFSET CurrentArrayPos = i>
</cfif>
</cfif>
<CFBREAK>
</CFIF>
</CFLOOP>
<!--- Return the position --->
<CFRETURN CurrentArrayPos>
</CFFUNCTION>
<!--- Internal GetCartItem() Method --->
<CFFUNCTION
NAME="GetCartItem"
RETURNTYPE="struct"
ACCESS="private">
<!--- One Argument: MerchID --->
<CFARGUMENT NAME="MerchID" TYPE="numeric" REQUIRED="Yes">
<CFARGUMENT NAME="Options" TYPE="struct" REQUIRED="no">
<CFARGUMENT NAME="Choices" TYPE="struct" REQUIRED="no">
<!--- Get the position of the item in This.CartArray --->
<CFSET CartPos = GetCartPos(MerchID,Options,Choices)>
<!--- If item for this MerchID was found, we will return it --->
<CFIF CartPos GT 0>
<CFSET CartItem = This.CartArray[CartPos]>
<!--- If item was not found, create new one and add to cart --->
<CFELSE>
<CFSET CartItem = StructNew()>
<CFSET CartItem.MerchID = Arguments.MerchID>
<CFSET CartItem.Quantity = 0>
<CFSET CartItem.Weight = 0>
<CFSET CartItem.Options = StructNew()>
<CFSET CartItem.Choices = StructNew()>
<CFSET ArrayAppend(This.CartArray, CartItem)>
</CFIF>
<!--- In either case, return the item --->
<CFRETURN CartItem>
</CFFUNCTION>
</CFCOMPONENT>