/lenasys/trunk

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/lenasys/trunk
20.1.1 by galaxyAbstractor
* Added an simple admin panel to the codeviewer-cmssy stuff
1
<?php  if ( ! defined('BASEPATH')) exit('No direct script access allowed');
2
/**
3
 * CodeIgniter
4
 *
5
 * An open source application development framework for PHP 5.1.6 or newer
6
 *
7
 * @package		CodeIgniter
8
 * @author		ExpressionEngine Dev Team
9
 * @copyright	Copyright (c) 2006 - 2012, EllisLab, Inc.
10
 * @license		http://codeigniter.com/user_guide/license.html
11
 * @link		http://codeigniter.com
12
 * @since		Version 1.0
13
 * @filesource
14
 */
15
16
// ------------------------------------------------------------------------
17
18
/**
19
 * Shopping Cart Class
20
 *
21
 * @package		CodeIgniter
22
 * @subpackage	Libraries
23
 * @category	Shopping Cart
24
 * @author		ExpressionEngine Dev Team
25
 * @link		http://codeigniter.com/user_guide/libraries/cart.html
26
 */
27
class CI_Cart {
28
29
	// These are the regular expression rules that we use to validate the product ID and product name
30
	var $product_id_rules	= '\.a-z0-9_-'; // alpha-numeric, dashes, underscores, or periods
31
	var $product_name_rules	= '\.\:\-_ a-z0-9'; // alpha-numeric, dashes, underscores, colons or periods
32
33
	// Private variables.  Do not change!
34
	var $CI;
35
	var $_cart_contents	= array();
36
37
38
	/**
39
	 * Shopping Class Constructor
40
	 *
41
	 * The constructor loads the Session class, used to store the shopping cart contents.
42
	 */
43
	public function __construct($params = array())
44
	{
45
		// Set the super object to a local variable for use later
46
		$this->CI =& get_instance();
47
48
		// Are any config settings being passed manually?  If so, set them
49
		$config = array();
50
		if (count($params) > 0)
51
		{
52
			foreach ($params as $key => $val)
53
			{
54
				$config[$key] = $val;
55
			}
56
		}
57
58
		// Load the Sessions class
59
		$this->CI->load->library('session', $config);
60
61
		// Grab the shopping cart array from the session table, if it exists
62
		if ($this->CI->session->userdata('cart_contents') !== FALSE)
63
		{
64
			$this->_cart_contents = $this->CI->session->userdata('cart_contents');
65
		}
66
		else
67
		{
68
			// No cart exists so we'll set some base values
69
			$this->_cart_contents['cart_total'] = 0;
70
			$this->_cart_contents['total_items'] = 0;
71
		}
72
73
		log_message('debug', "Cart Class Initialized");
74
	}
75
76
	// --------------------------------------------------------------------
77
78
	/**
79
	 * Insert items into the cart and save it to the session table
80
	 *
81
	 * @access	public
82
	 * @param	array
83
	 * @return	bool
84
	 */
85
	function insert($items = array())
86
	{
87
		// Was any cart data passed? No? Bah...
88
		if ( ! is_array($items) OR count($items) == 0)
89
		{
90
			log_message('error', 'The insert method must be passed an array containing data.');
91
			return FALSE;
92
		}
93
94
		// You can either insert a single product using a one-dimensional array,
95
		// or multiple products using a multi-dimensional one. The way we
96
		// determine the array type is by looking for a required array key named "id"
97
		// at the top level. If it's not found, we will assume it's a multi-dimensional array.
98
99
		$save_cart = FALSE;
100
		if (isset($items['id']))
101
		{
102
			if (($rowid = $this->_insert($items)))
103
			{
104
				$save_cart = TRUE;
105
			}
106
		}
107
		else
108
		{
109
			foreach ($items as $val)
110
			{
111
				if (is_array($val) AND isset($val['id']))
112
				{
113
					if ($this->_insert($val))
114
					{
115
						$save_cart = TRUE;
116
					}
117
				}
118
			}
119
		}
120
121
		// Save the cart data if the insert was successful
122
		if ($save_cart == TRUE)
123
		{
124
			$this->_save_cart();
125
			return isset($rowid) ? $rowid : TRUE;
126
		}
127
128
		return FALSE;
129
	}
130
131
	// --------------------------------------------------------------------
132
133
	/**
134
	 * Insert
135
	 *
136
	 * @access	private
137
	 * @param	array
138
	 * @return	bool
139
	 */
140
	function _insert($items = array())
141
	{
142
		// Was any cart data passed? No? Bah...
143
		if ( ! is_array($items) OR count($items) == 0)
144
		{
145
			log_message('error', 'The insert method must be passed an array containing data.');
146
			return FALSE;
147
		}
148
149
		// --------------------------------------------------------------------
150
151
		// Does the $items array contain an id, quantity, price, and name?  These are required
152
		if ( ! isset($items['id']) OR ! isset($items['qty']) OR ! isset($items['price']) OR ! isset($items['name']))
153
		{
154
			log_message('error', 'The cart array must contain a product ID, quantity, price, and name.');
155
			return FALSE;
156
		}
157
158
		// --------------------------------------------------------------------
159
160
		// Prep the quantity. It can only be a number.  Duh...
161
		$items['qty'] = trim(preg_replace('/([^0-9])/i', '', $items['qty']));
162
		// Trim any leading zeros
163
		$items['qty'] = trim(preg_replace('/(^[0]+)/i', '', $items['qty']));
164
165
		// If the quantity is zero or blank there's nothing for us to do
166
		if ( ! is_numeric($items['qty']) OR $items['qty'] == 0)
167
		{
168
			return FALSE;
169
		}
170
171
		// --------------------------------------------------------------------
172
173
		// Validate the product ID. It can only be alpha-numeric, dashes, underscores or periods
174
		// Not totally sure we should impose this rule, but it seems prudent to standardize IDs.
175
		// Note: These can be user-specified by setting the $this->product_id_rules variable.
176
		if ( ! preg_match("/^[".$this->product_id_rules."]+$/i", $items['id']))
177
		{
178
			log_message('error', 'Invalid product ID.  The product ID can only contain alpha-numeric characters, dashes, and underscores');
179
			return FALSE;
180
		}
181
182
		// --------------------------------------------------------------------
183
184
		// Validate the product name. It can only be alpha-numeric, dashes, underscores, colons or periods.
185
		// Note: These can be user-specified by setting the $this->product_name_rules variable.
186
		if ( ! preg_match("/^[".$this->product_name_rules."]+$/i", $items['name']))
187
		{
188
			log_message('error', 'An invalid name was submitted as the product name: '.$items['name'].' The name can only contain alpha-numeric characters, dashes, underscores, colons, and spaces');
189
			return FALSE;
190
		}
191
192
		// --------------------------------------------------------------------
193
194
		// Prep the price.  Remove anything that isn't a number or decimal point.
195
		$items['price'] = trim(preg_replace('/([^0-9\.])/i', '', $items['price']));
196
		// Trim any leading zeros
197
		$items['price'] = trim(preg_replace('/(^[0]+)/i', '', $items['price']));
198
199
		// Is the price a valid number?
200
		if ( ! is_numeric($items['price']))
201
		{
202
			log_message('error', 'An invalid price was submitted for product ID: '.$items['id']);
203
			return FALSE;
204
		}
205
206
		// --------------------------------------------------------------------
207
208
		// We now need to create a unique identifier for the item being inserted into the cart.
209
		// Every time something is added to the cart it is stored in the master cart array.
210
		// Each row in the cart array, however, must have a unique index that identifies not only
211
		// a particular product, but makes it possible to store identical products with different options.
212
		// For example, what if someone buys two identical t-shirts (same product ID), but in
213
		// different sizes?  The product ID (and other attributes, like the name) will be identical for
214
		// both sizes because it's the same shirt. The only difference will be the size.
215
		// Internally, we need to treat identical submissions, but with different options, as a unique product.
216
		// Our solution is to convert the options array to a string and MD5 it along with the product ID.
217
		// This becomes the unique "row ID"
218
		if (isset($items['options']) AND count($items['options']) > 0)
219
		{
220
			$rowid = md5($items['id'].implode('', $items['options']));
221
		}
222
		else
223
		{
224
			// No options were submitted so we simply MD5 the product ID.
225
			// Technically, we don't need to MD5 the ID in this case, but it makes
226
			// sense to standardize the format of array indexes for both conditions
227
			$rowid = md5($items['id']);
228
		}
229
230
		// --------------------------------------------------------------------
231
232
		// Now that we have our unique "row ID", we'll add our cart items to the master array
233
234
		// let's unset this first, just to make sure our index contains only the data from this submission
235
		unset($this->_cart_contents[$rowid]);
236
237
		// Create a new index with our new row ID
238
		$this->_cart_contents[$rowid]['rowid'] = $rowid;
239
240
		// And add the new items to the cart array
241
		foreach ($items as $key => $val)
242
		{
243
			$this->_cart_contents[$rowid][$key] = $val;
244
		}
245
246
		// Woot!
247
		return $rowid;
248
	}
249
250
	// --------------------------------------------------------------------
251
252
	/**
253
	 * Update the cart
254
	 *
255
	 * This function permits the quantity of a given item to be changed.
256
	 * Typically it is called from the "view cart" page if a user makes
257
	 * changes to the quantity before checkout. That array must contain the
258
	 * product ID and quantity for each item.
259
	 *
260
	 * @access	public
261
	 * @param	array
262
	 * @param	string
263
	 * @return	bool
264
	 */
265
	function update($items = array())
266
	{
267
		// Was any cart data passed?
268
		if ( ! is_array($items) OR count($items) == 0)
269
		{
270
			return FALSE;
271
		}
272
273
		// You can either update a single product using a one-dimensional array,
274
		// or multiple products using a multi-dimensional one.  The way we
275
		// determine the array type is by looking for a required array key named "id".
276
		// If it's not found we assume it's a multi-dimensional array
277
		$save_cart = FALSE;
278
		if (isset($items['rowid']) AND isset($items['qty']))
279
		{
280
			if ($this->_update($items) == TRUE)
281
			{
282
				$save_cart = TRUE;
283
			}
284
		}
285
		else
286
		{
287
			foreach ($items as $val)
288
			{
289
				if (is_array($val) AND isset($val['rowid']) AND isset($val['qty']))
290
				{
291
					if ($this->_update($val) == TRUE)
292
					{
293
						$save_cart = TRUE;
294
					}
295
				}
296
			}
297
		}
298
299
		// Save the cart data if the insert was successful
300
		if ($save_cart == TRUE)
301
		{
302
			$this->_save_cart();
303
			return TRUE;
304
		}
305
306
		return FALSE;
307
	}
308
309
	// --------------------------------------------------------------------
310
311
	/**
312
	 * Update the cart
313
	 *
314
	 * This function permits the quantity of a given item to be changed.
315
	 * Typically it is called from the "view cart" page if a user makes
316
	 * changes to the quantity before checkout. That array must contain the
317
	 * product ID and quantity for each item.
318
	 *
319
	 * @access	private
320
	 * @param	array
321
	 * @return	bool
322
	 */
323
	function _update($items = array())
324
	{
325
		// Without these array indexes there is nothing we can do
326
		if ( ! isset($items['qty']) OR ! isset($items['rowid']) OR ! isset($this->_cart_contents[$items['rowid']]))
327
		{
328
			return FALSE;
329
		}
330
331
		// Prep the quantity
332
		$items['qty'] = preg_replace('/([^0-9])/i', '', $items['qty']);
333
334
		// Is the quantity a number?
335
		if ( ! is_numeric($items['qty']))
336
		{
337
			return FALSE;
338
		}
339
340
		// Is the new quantity different than what is already saved in the cart?
341
		// If it's the same there's nothing to do
342
		if ($this->_cart_contents[$items['rowid']]['qty'] == $items['qty'])
343
		{
344
			return FALSE;
345
		}
346
347
		// Is the quantity zero?  If so we will remove the item from the cart.
348
		// If the quantity is greater than zero we are updating
349
		if ($items['qty'] == 0)
350
		{
351
			unset($this->_cart_contents[$items['rowid']]);
352
		}
353
		else
354
		{
355
			$this->_cart_contents[$items['rowid']]['qty'] = $items['qty'];
356
		}
357
358
		return TRUE;
359
	}
360
361
	// --------------------------------------------------------------------
362
363
	/**
364
	 * Save the cart array to the session DB
365
	 *
366
	 * @access	private
367
	 * @return	bool
368
	 */
369
	function _save_cart()
370
	{
371
		// Unset these so our total can be calculated correctly below
372
		unset($this->_cart_contents['total_items']);
373
		unset($this->_cart_contents['cart_total']);
374
375
		// Lets add up the individual prices and set the cart sub-total
376
		$total = 0;
377
		$items = 0;
378
		foreach ($this->_cart_contents as $key => $val)
379
		{
380
			// We make sure the array contains the proper indexes
381
			if ( ! is_array($val) OR ! isset($val['price']) OR ! isset($val['qty']))
382
			{
383
				continue;
384
			}
385
386
			$total += ($val['price'] * $val['qty']);
387
			$items += $val['qty'];
388
389
			// Set the subtotal
390
			$this->_cart_contents[$key]['subtotal'] = ($this->_cart_contents[$key]['price'] * $this->_cart_contents[$key]['qty']);
391
		}
392
393
		// Set the cart total and total items.
394
		$this->_cart_contents['total_items'] = $items;
395
		$this->_cart_contents['cart_total'] = $total;
396
397
		// Is our cart empty?  If so we delete it from the session
398
		if (count($this->_cart_contents) <= 2)
399
		{
400
			$this->CI->session->unset_userdata('cart_contents');
401
402
			// Nothing more to do... coffee time!
403
			return FALSE;
404
		}
405
406
		// If we made it this far it means that our cart has data.
407
		// Let's pass it to the Session class so it can be stored
408
		$this->CI->session->set_userdata(array('cart_contents' => $this->_cart_contents));
409
410
		// Woot!
411
		return TRUE;
412
	}
413
414
	// --------------------------------------------------------------------
415
416
	/**
417
	 * Cart Total
418
	 *
419
	 * @access	public
420
	 * @return	integer
421
	 */
422
	function total()
423
	{
424
		return $this->_cart_contents['cart_total'];
425
	}
426
427
	// --------------------------------------------------------------------
428
429
	/**
430
	 * Total Items
431
	 *
432
	 * Returns the total item count
433
	 *
434
	 * @access	public
435
	 * @return	integer
436
	 */
437
	function total_items()
438
	{
439
		return $this->_cart_contents['total_items'];
440
	}
441
442
	// --------------------------------------------------------------------
443
444
	/**
445
	 * Cart Contents
446
	 *
447
	 * Returns the entire cart array
448
	 *
449
	 * @access	public
450
	 * @return	array
451
	 */
452
	function contents()
453
	{
454
		$cart = $this->_cart_contents;
455
456
		// Remove these so they don't create a problem when showing the cart table
457
		unset($cart['total_items']);
458
		unset($cart['cart_total']);
459
460
		return $cart;
461
	}
462
463
	// --------------------------------------------------------------------
464
465
	/**
466
	 * Has options
467
	 *
468
	 * Returns TRUE if the rowid passed to this function correlates to an item
469
	 * that has options associated with it.
470
	 *
471
	 * @access	public
472
	 * @return	array
473
	 */
474
	function has_options($rowid = '')
475
	{
476
		if ( ! isset($this->_cart_contents[$rowid]['options']) OR count($this->_cart_contents[$rowid]['options']) === 0)
477
		{
478
			return FALSE;
479
		}
480
481
		return TRUE;
482
	}
483
484
	// --------------------------------------------------------------------
485
486
	/**
487
	 * Product options
488
	 *
489
	 * Returns the an array of options, for a particular product row ID
490
	 *
491
	 * @access	public
492
	 * @return	array
493
	 */
494
	function product_options($rowid = '')
495
	{
496
		if ( ! isset($this->_cart_contents[$rowid]['options']))
497
		{
498
			return array();
499
		}
500
501
		return $this->_cart_contents[$rowid]['options'];
502
	}
503
504
	// --------------------------------------------------------------------
505
506
	/**
507
	 * Format Number
508
	 *
509
	 * Returns the supplied number with commas and a decimal point.
510
	 *
511
	 * @access	public
512
	 * @return	integer
513
	 */
514
	function format_number($n = '')
515
	{
516
		if ($n == '')
517
		{
518
			return '';
519
		}
520
521
		// Remove anything that isn't a number or decimal point.
522
		$n = trim(preg_replace('/([^0-9\.])/i', '', $n));
523
524
		return number_format($n, 2, '.', ',');
525
	}
526
527
	// --------------------------------------------------------------------
528
529
	/**
530
	 * Destroy the cart
531
	 *
532
	 * Empties the cart and kills the session
533
	 *
534
	 * @access	public
535
	 * @return	null
536
	 */
537
	function destroy()
538
	{
539
		unset($this->_cart_contents);
540
541
		$this->_cart_contents['cart_total'] = 0;
542
		$this->_cart_contents['total_items'] = 0;
543
544
		$this->CI->session->unset_userdata('cart_contents');
545
	}
546
547
548
}
549
// END Cart Class
550
551
/* End of file Cart.php */
552
/* Location: ./system/libraries/Cart.php */