source: tags/1.0.0/lib/Cart.inc.php @ 1

Last change on this file since 1 was 1, checked in by scdev, 19 years ago

Initial import.

File size: 10.7 KB
Line 
1<?php
2/**
3 * Cart.inc.php
4 * Code by Strangecode :: www.strangecode.com :: This document contains copyrighted information
5 */
6
7class Cart {
8    var $items;         // array of items
9    var $subtotals;     // array of subtotals
10    var $errors;        // array of errors
11    var $total;         // total of the cart
12    var $weight;        // total weight of the cart
13    var $tax;           // tax, a percentage of the total
14    var $delivery;      // delivery price, it depends on the weight
15    var $final_price;   // $final_price = $total + $tax + $delivery
16   
17    var $we_charge_tax;             // bool
18    var $taxrate;                   // array, key is location identifyer (state, etc) val is the percentage (7.25, etc)
19    var $default_delivery_method;   // string, an identifyer for default shipping
20    var $default_delivery_zone;     // integer, the default world zone for calculating shipping before the customer specifies actual
21    var $shiprate;                  // array, shipping rates. See below.
22   
23    /* Shipping rates are built upon a threshold algorithm. The lowest array (0) is tested first,
24     * and if the actual weight and price are lower, we continue, otherwise that rate is used.
25     * When the weight and price are not lower, we take the last matched delivery cost.
26     * Examples: */
27     
28    /* 100g */
29    // $this->shiprate["French_Postal"][1][0]["maxweight"]  = 100;
30    // $this->shiprate["French_Postal"][1][0]["cost"]       = 1.04;
31    // $this->shiprate["French_Postal"][2][0]["maxweight"]  = 100;
32    // $this->shiprate["French_Postal"][2][0]["cost"]       = 1.14;
33   
34    /* 200g */
35    // $this->shiprate["French_Postal"][1][1]["maxweight"]  = 200;
36    // $this->shiprate["French_Postal"][1][1]["cost"]       = 1.98;
37    // $this->shiprate["French_Postal"][2][1]["maxweight"]  = 200;
38    // $this->shiprate["French_Postal"][2][1]["cost"]       = 2.06;
39   
40    function Cart()
41    {
42        $this->init();
43    }
44   
45    /**
46     * initialize (and reset) a shopping cart
47     */
48    function init()
49    {
50        $this->items = array();
51        $this->subtotals = array();
52        $this->total = 0;
53        $this->weight = 0;
54        $this->tax = 0;
55        $this->delivery = 0;
56        $this->final_price = 0;
57    }
58   
59    /**
60     * Checks item quantity in stock to make sure there are enough. Returns
61     * the total number of items in stock.
62     *
63     * @param  mixed $product_id   id of the item to check
64     *
65     * @return int   the number of items in stock, 0 if none
66     */
67    function inventory($product_id)
68    {
69        $qid = dbQuery("SELECT qty_in_stock FROM product_tbl WHERE product_id = '$product_id'");
70        $in_stock = mysql_fetch_row($qid);
71        return $in_stock[0];
72    }
73   
74    /**
75     * Add $qty items to the shopping cart, adding to the number already selected.
76     * If there are not enough items in stock, the total number of items in stock are set.
77     * Returns the quantity it was set to.
78     *
79     * @param  mixed $product_id   the id of the item to add
80     * @param  int   $qty         the quantity of items to add
81     *
82     * @return int    the number of items that were added. May not be the
83     *                same number as were requested if not enough are available
84     */
85    function addItem(&$product_id, $qty)
86    {
87        $in_stock = $this->inventory($product_id);
88        $new_qty = $this->items[$product_id] + $qty;
89        if ($new_qty <= $in_stock && isset($product_id)) {
90            /* If there are enough items in stock and the product id is specified, we add them to the cart */
91            $this->items[$product_id] = $new_qty;
92        } else {
93            /* Otherwise we set the qty to the actual number of items in stock */
94            $new_qty = $in_stock;
95            $this->items[$product_id] = $new_qty;
96        }
97        return $new_qty;
98    }
99   
100    /**
101     * Set the quantity of a product in the cart to a specified value.
102     * Returns the quantity it was set to.
103     *
104     * @param  mixed $product_id   the id of the item to set
105     * @param  int   $new_qty      the quantity of items to set
106     *
107     * @return int    the number of items that the cart was set to. May not be the
108     *                same number as were requested if not enough are available
109     */
110    function setItemQty(&$product_id, $new_qty)
111    {
112        $in_stock = $this->inventory($product_id);
113        if ($new_qty <= $in_stock && isset($product_id)) {
114            $this->items[$product_id] = (int) $new_qty;
115        } else {
116            $new_qty = $in_stock;
117            $this->items[$product_id] = $new_qty;
118        }
119        return $new_qty;
120    }
121   
122    /**
123     * this function will remove a given product from the cart
124     *
125     * @param  mixed $product_id   item id to remove
126     */
127    function removeItem(&$product_id)
128    {
129        if (isset($product_id)) {
130            unset($this->items[$product_id]);
131        }
132    }
133   
134    /**
135     * this function will clean up the cart, removing items with invalid product
136     * id's (non-numeric ones) and products with quantities less than 1.
137     */
138    function cleanup()
139    {
140        foreach ($this->items as $product_id => $qty) {
141            if ($qty < 1) {
142                unset($this->items[$product_id]);
143            }
144        }
145    }
146   
147    /**
148     * Returns the total number of individual items in the shopping cart
149     * (note, this takes into account the quantities of the items as well).
150     * If a product_id is specified, returns the count of just that item.
151     *
152     * @param  mixed $product_id   optional id of item to count
153     *
154     * @return int      the number of items in the cart
155     */
156    function itemCount($product_id='')
157    {
158        $count = 0;
159       
160        if (empty($product_id)) {
161            foreach ($this->items as $item => $qty) {
162                $count += $qty;
163            }
164        } else {
165            foreach ($this->items as $item => $qty) {
166                if ($product_id == $item) {
167                    $count += $qty;
168                }
169            }
170        }
171   
172        return $count;
173    }
174   
175    /**
176     * Return a comma delimited list of all the products in the cart, this will
177     * be used for queries, eg. SELECT id, price FROM products WHERE id IN ...
178     *
179     * @return string    a comma delimited list of the item ids in the cart
180     */
181    function getProductidList()
182    {
183        $comma = '';
184        foreach ($this->items as $product_id => $qty) {
185            $product_id_list .= $comma . "'" . $product_id . "'";
186            $comma = ',';
187        }
188        return $product_id_list;
189    }
190   
191    /**
192     * return an array of all the items in the shopping cart
193     *
194     * @return array    a 2-dimentional array, containing the result set of the query
195     */
196    function getCartItems()
197    {   
198        $in_clause = $this->getProductidList();
199        if (empty($in_clause)) {
200            return array();
201        }
202        $qid = dbQuery("
203            SELECT *
204            FROM product_tbl
205            WHERE product_id IN ($in_clause)
206        ");
207        while ($row = mysql_fetch_assoc($qid)) {
208            $ret[] = $row;
209        }
210        return $ret;
211    }
212   
213    /**
214     * recalculate the total for the shopping cart, we will also do some cleanup
215     * and remove invalid items from the cart.  we have to query the database to
216     * get the prices, so instead of making one query for each product in the
217     * basket, we will gather up all the ID's we are interested in and run one
218     * query to get all the products we care about (using $in_clause).
219     *
220     * @return bool true on success, false on failure
221     */
222    function recalculateTotal()
223    {
224        $this->total = 0;
225        $this->weight = 0;
226        $this->tax = 0;
227        $this->delivery = 0;
228        $this->final_price = 0;
229   
230        $in_clause = $this->getProductidList();
231        if (empty($in_clause)) {
232            return;
233        }
234   
235        $qid = dbQuery("SELECT product_id, retail_price, weight FROM product_tbl WHERE product_id IN ($in_clause)");
236        while ($product = mysql_fetch_object($qid)) {
237            $this->subtotals[$product->product_id] = $this->items[$product->product_id] * $product->retail_price;
238            $this->total += $this->subtotals[$product->product_id];
239            $this->weight += $this->items[$product->product_id] * $product->weight;
240        }
241       
242        $this->delivery = $this->getDeliveryCost($this->weight);
243        $this->tax = $this->getTaxCost($this->total);
244   
245        $this->final_price = $this->total + $this->tax + $this->delivery;
246    }
247   
248    /**
249     * Returns the cost of delivery based on the supplied variables.
250     *
251     * @param  float  $total_weight   weight of all items combined
252     *
253     * @param  string $delivery_type  optional delivery type to return the cost
254     *                                for this type of delivery. could be used
255     *                                to show a price for each method available.
256     *                               
257     * @param  string $zone           optional zone for getting a specific price
258     *
259     * @return float  the cost of delivery
260     */
261    function getDeliveryCost($total_weight, $delivery_type='', $zone='')
262    {
263        global $_SESSION;
264       
265        if ($total_weight == 0) {
266            return 0;
267        }
268       
269        setDefault($_SESSION['app']['orderinfo']['delivery_type'], $this->default_delivery_method);
270        if (empty($delivery_type)) { $delivery_type = $_SESSION['app']['orderinfo']['delivery_type']; }
271       
272        setDefault($_SESSION['app']['orderinfo']['delivery_zone'], $this->default_delivery_zone);
273        if (empty($zone)) { $zone = $_SESSION['app']['orderinfo']['delivery_zone']; }
274       
275        if ($zone == 0) { $zone = $this->default_delivery_zone; }
276        for ($i=sizeof($this->shiprate[$delivery_type][$zone]); $i>=0; $i--) {
277            if ($total_weight <= $this->shiprate[$delivery_type][$zone][$i]['maxweight']) { // && $this->total <= $this->shiprate[$delivery_type][$zone][$i]['maxprice']
278                $delivery_cost = $this->shiprate[$delivery_type][$zone][$i]['cost'];
279            }
280        }
281       
282        return $delivery_cost;
283    }
284   
285    /**
286     * Returns the cost of tax based on the default US billing state. CA is set here.
287     *
288     * @param  float $total   the total cost of this order before tax or shipping
289     *
290     * @return float    the cost of the tax
291     */
292    function getTaxCost($total)
293    {
294        global $_SESSION;
295       
296        if (!$this->we_charge_tax) {
297            return 0;
298        }
299       
300        setDefault($_SESSION['app']['orderinfo']['bill_state'], 'CA');
301       
302        foreach ($this->taxrate as $state => $rate) {
303            if (eregi($state, $_SESSION['app']['orderinfo']['bill_state'])) {
304                $tax = ($rate / 100) * $total;
305                break;
306            } else {
307                $tax = 0;
308            }
309        }
310       
311        return $tax;
312    }
313}
314
315?>
Note: See TracBrowser for help on using the repository browser.