diff options
Diffstat (limited to 'system/libraries/Cart.php')
-rw-r--r-- | system/libraries/Cart.php | 292 |
1 files changed, 142 insertions, 150 deletions
diff --git a/system/libraries/Cart.php b/system/libraries/Cart.php index da47b5a19..c442f88da 100644 --- a/system/libraries/Cart.php +++ b/system/libraries/Cart.php @@ -1,44 +1,89 @@ -<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); +<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); /** * CodeIgniter * - * An open source application development framework for PHP 5.1.6 or newer + * An open source application development framework for PHP 5.2.4 or newer + * + * NOTICE OF LICENSE + * + * Licensed under the Open Software License version 3.0 + * + * This source file is subject to the Open Software License (OSL 3.0) that is + * bundled with this package in the files license.txt / license.rst. It is + * also available through the world wide web at this URL: + * http://opensource.org/licenses/OSL-3.0 + * If you did not receive a copy of the license and are unable to obtain it + * through the world wide web, please send an email to + * licensing@ellislab.com so we can send you a copy immediately. * * @package CodeIgniter - * @author ExpressionEngine Dev Team - * @copyright Copyright (c) 2006 - 2012, EllisLab, Inc. - * @license http://codeigniter.com/user_guide/license.html + * @author EllisLab Dev Team + * @copyright Copyright (c) 2006 - 2012, EllisLab, Inc. (http://ellislab.com/) + * @license http://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0) * @link http://codeigniter.com * @since Version 1.0 * @filesource */ -// ------------------------------------------------------------------------ - /** * Shopping Cart Class * * @package CodeIgniter * @subpackage Libraries * @category Shopping Cart - * @author ExpressionEngine Dev Team + * @author EllisLab Dev Team * @link http://codeigniter.com/user_guide/libraries/cart.html */ class CI_Cart { - // These are the regular expression rules that we use to validate the product ID and product name - var $product_id_rules = '\.a-z0-9_-'; // alpha-numeric, dashes, underscores, or periods - var $product_name_rules = '\.\:\-_ a-z0-9'; // alpha-numeric, dashes, underscores, colons or periods + /** + * These are the regular expression rules that we use to validate the product ID and product name + * alpha-numeric, dashes, underscores, or periods + * + * @var string + */ + public $product_id_rules = '\.a-z0-9_-'; + + /** + * These are the regular expression rules that we use to validate the product ID and product name + * alpha-numeric, dashes, underscores, colons or periods + * + * @var string + */ + public $product_name_rules = '\.\:\-_ a-z0-9'; + + /** + * only allow safe product names + * + * @var bool + */ + public $product_name_safe = TRUE; + + // -------------------------------------------------------------------------- + // Protected variables. Do not change! + // -------------------------------------------------------------------------- - // Private variables. Do not change! - var $CI; - var $_cart_contents = array(); + /** + * Reference to CodeIgniter instance + * + * @var object + */ + protected $CI; + /** + * Contents of the cart + * + * @var array + */ + protected $_cart_contents = array(); /** * Shopping Class Constructor * * The constructor loads the Session class, used to store the shopping cart contents. + * + * @param array + * @return void */ public function __construct($params = array()) { @@ -46,31 +91,20 @@ class CI_Cart { $this->CI =& get_instance(); // Are any config settings being passed manually? If so, set them - $config = array(); - if (count($params) > 0) - { - foreach ($params as $key => $val) - { - $config[$key] = $val; - } - } + $config = is_array($params) ? $params : array(); // Load the Sessions class $this->CI->load->library('session', $config); - // Grab the shopping cart array from the session table, if it exists - if ($this->CI->session->userdata('cart_contents') !== FALSE) - { - $this->_cart_contents = $this->CI->session->userdata('cart_contents'); - } - else + // Grab the shopping cart array from the session table + $this->_cart_contents = $this->CI->session->userdata('cart_contents'); + if ($this->_cart_contents === FALSE) { // No cart exists so we'll set some base values - $this->_cart_contents['cart_total'] = 0; - $this->_cart_contents['total_items'] = 0; + $this->_cart_contents = array('cart_total' => 0, 'total_items' => 0); } - log_message('debug', "Cart Class Initialized"); + log_message('debug', 'Cart Class Initialized'); } // -------------------------------------------------------------------- @@ -78,14 +112,13 @@ class CI_Cart { /** * Insert items into the cart and save it to the session table * - * @access public * @param array * @return bool */ - function insert($items = array()) + public function insert($items = array()) { // Was any cart data passed? No? Bah... - if ( ! is_array($items) OR count($items) == 0) + if ( ! is_array($items) OR count($items) === 0) { log_message('error', 'The insert method must be passed an array containing data.'); return FALSE; @@ -108,7 +141,7 @@ class CI_Cart { { foreach ($items as $val) { - if (is_array($val) AND isset($val['id'])) + if (is_array($val) && isset($val['id'])) { if ($this->_insert($val)) { @@ -119,7 +152,7 @@ class CI_Cart { } // Save the cart data if the insert was successful - if ($save_cart == TRUE) + if ($save_cart === TRUE) { $this->_save_cart(); return isset($rowid) ? $rowid : TRUE; @@ -133,14 +166,13 @@ class CI_Cart { /** * Insert * - * @access private * @param array * @return bool */ - function _insert($items = array()) + protected function _insert($items = array()) { // Was any cart data passed? No? Bah... - if ( ! is_array($items) OR count($items) == 0) + if ( ! is_array($items) OR count($items) === 0) { log_message('error', 'The insert method must be passed an array containing data.'); return FALSE; @@ -149,7 +181,7 @@ class CI_Cart { // -------------------------------------------------------------------- // Does the $items array contain an id, quantity, price, and name? These are required - if ( ! isset($items['id']) OR ! isset($items['qty']) OR ! isset($items['price']) OR ! isset($items['name'])) + if ( ! isset($items['id'], $items['qty'], $items['price'], $items['name'])) { log_message('error', 'The cart array must contain a product ID, quantity, price, and name.'); return FALSE; @@ -157,10 +189,8 @@ class CI_Cart { // -------------------------------------------------------------------- - // Prep the quantity. It can only be a number. Duh... - $items['qty'] = trim(preg_replace('/([^0-9])/i', '', $items['qty'])); - // Trim any leading zeros - $items['qty'] = trim(preg_replace('/(^[0]+)/i', '', $items['qty'])); + // Prep the quantity. It can only be a number. Duh... also trim any leading zeros + $items['qty'] = (float) $items['qty']; // If the quantity is zero or blank there's nothing for us to do if ( ! is_numeric($items['qty']) OR $items['qty'] == 0) @@ -173,7 +203,7 @@ class CI_Cart { // Validate the product ID. It can only be alpha-numeric, dashes, underscores or periods // Not totally sure we should impose this rule, but it seems prudent to standardize IDs. // Note: These can be user-specified by setting the $this->product_id_rules variable. - if ( ! preg_match("/^[".$this->product_id_rules."]+$/i", $items['id'])) + if ( ! preg_match('/^['.$this->product_id_rules.']+$/i', $items['id'])) { log_message('error', 'Invalid product ID. The product ID can only contain alpha-numeric characters, dashes, and underscores'); return FALSE; @@ -183,7 +213,7 @@ class CI_Cart { // Validate the product name. It can only be alpha-numeric, dashes, underscores, colons or periods. // Note: These can be user-specified by setting the $this->product_name_rules variable. - if ( ! preg_match("/^[".$this->product_name_rules."]+$/i", $items['name'])) + if ($this->product_name_safe && ! preg_match('/^['.$this->product_name_rules.']+$/i', $items['name'])) { 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'); return FALSE; @@ -191,10 +221,8 @@ class CI_Cart { // -------------------------------------------------------------------- - // Prep the price. Remove anything that isn't a number or decimal point. - $items['price'] = trim(preg_replace('/([^0-9\.])/i', '', $items['price'])); - // Trim any leading zeros - $items['price'] = trim(preg_replace('/(^[0]+)/i', '', $items['price'])); + // Prep the price. Remove leading zeros and anything that isn't a number or decimal point. + $items['price'] = (float) $items['price']; // Is the price a valid number? if ( ! is_numeric($items['price'])) @@ -215,9 +243,9 @@ class CI_Cart { // Internally, we need to treat identical submissions, but with different options, as a unique product. // Our solution is to convert the options array to a string and MD5 it along with the product ID. // This becomes the unique "row ID" - if (isset($items['options']) AND count($items['options']) > 0) + if (isset($items['options']) && count($items['options']) > 0) { - $rowid = md5($items['id'].implode('', $items['options'])); + $rowid = md5($items['id'].serialize($items['options'])); } else { @@ -230,20 +258,14 @@ class CI_Cart { // -------------------------------------------------------------------- // Now that we have our unique "row ID", we'll add our cart items to the master array + // grab quantity if it's already there and add it on + $old_quantity = isset($this->_cart_contents[$rowid]['qty']) ? (int) $this->_cart_contents[$rowid]['qty'] : 0; - // let's unset this first, just to make sure our index contains only the data from this submission - unset($this->_cart_contents[$rowid]); - - // Create a new index with our new row ID - $this->_cart_contents[$rowid]['rowid'] = $rowid; - - // And add the new items to the cart array - foreach ($items as $key => $val) - { - $this->_cart_contents[$rowid][$key] = $val; - } + // Re-create the entry, just to make sure our index contains only the data from this submission + $items['rowid'] = $rowid; + $items['qty'] += $old_quantity; + $this->_cart_contents[$rowid] = $items; - // Woot! return $rowid; } @@ -257,15 +279,13 @@ class CI_Cart { * changes to the quantity before checkout. That array must contain the * product ID and quantity for each item. * - * @access public * @param array - * @param string * @return bool */ - function update($items = array()) + public function update($items = array()) { // Was any cart data passed? - if ( ! is_array($items) OR count($items) == 0) + if ( ! is_array($items) OR count($items) === 0) { return FALSE; } @@ -275,9 +295,9 @@ class CI_Cart { // determine the array type is by looking for a required array key named "id". // If it's not found we assume it's a multi-dimensional array $save_cart = FALSE; - if (isset($items['rowid']) AND isset($items['qty'])) + if (isset($items['rowid'], $items['qty'])) { - if ($this->_update($items) == TRUE) + if ($this->_update($items) === TRUE) { $save_cart = TRUE; } @@ -286,9 +306,9 @@ class CI_Cart { { foreach ($items as $val) { - if (is_array($val) AND isset($val['rowid']) AND isset($val['qty'])) + if (is_array($val) && isset($val['rowid'], $val['qty'])) { - if ($this->_update($val) == TRUE) + if ($this->_update($val) === TRUE) { $save_cart = TRUE; } @@ -297,7 +317,7 @@ class CI_Cart { } // Save the cart data if the insert was successful - if ($save_cart == TRUE) + if ($save_cart === TRUE) { $this->_save_cart(); return TRUE; @@ -316,20 +336,19 @@ class CI_Cart { * changes to the quantity before checkout. That array must contain the * product ID and quantity for each item. * - * @access private * @param array * @return bool */ - function _update($items = array()) + protected function _update($items = array()) { // Without these array indexes there is nothing we can do - if ( ! isset($items['qty']) OR ! isset($items['rowid']) OR ! isset($this->_cart_contents[$items['rowid']])) + if ( ! isset($items['qty'], $items['rowid'], $this->_cart_contents[$items['rowid']])) { return FALSE; } // Prep the quantity - $items['qty'] = preg_replace('/([^0-9])/i', '', $items['qty']); + $items['qty'] = (float) $items['qty']; // Is the quantity a number? if ( ! is_numeric($items['qty'])) @@ -337,13 +356,6 @@ class CI_Cart { return FALSE; } - // Is the new quantity different than what is already saved in the cart? - // If it's the same there's nothing to do - if ($this->_cart_contents[$items['rowid']]['qty'] == $items['qty']) - { - return FALSE; - } - // Is the quantity zero? If so we will remove the item from the cart. // If the quantity is greater than zero we are updating if ($items['qty'] == 0) @@ -363,38 +375,26 @@ class CI_Cart { /** * Save the cart array to the session DB * - * @access private * @return bool */ - function _save_cart() + protected function _save_cart() { - // Unset these so our total can be calculated correctly below - unset($this->_cart_contents['total_items']); - unset($this->_cart_contents['cart_total']); - // Lets add up the individual prices and set the cart sub-total - $total = 0; - $items = 0; + $this->_cart_contents['total_items'] = $this->_cart_contents['cart_total'] = 0; foreach ($this->_cart_contents as $key => $val) { // We make sure the array contains the proper indexes - if ( ! is_array($val) OR ! isset($val['price']) OR ! isset($val['qty'])) + if ( ! is_array($val) OR ! isset($val['price'], $val['qty'])) { continue; } - $total += ($val['price'] * $val['qty']); - $items += $val['qty']; - - // Set the subtotal + $this->_cart_contents['cart_total'] += ($val['price'] * $val['qty']); + $this->_cart_contents['total_items'] += $val['qty']; $this->_cart_contents[$key]['subtotal'] = ($this->_cart_contents[$key]['price'] * $this->_cart_contents[$key]['qty']); } - // Set the cart total and total items. - $this->_cart_contents['total_items'] = $items; - $this->_cart_contents['cart_total'] = $total; - - // Is our cart empty? If so we delete it from the session + // Is our cart empty? If so we delete it from the session if (count($this->_cart_contents) <= 2) { $this->CI->session->unset_userdata('cart_contents'); @@ -416,10 +416,9 @@ class CI_Cart { /** * Cart Total * - * @access public - * @return integer + * @return int */ - function total() + public function total() { return $this->_cart_contents['cart_total']; } @@ -427,14 +426,31 @@ class CI_Cart { // -------------------------------------------------------------------- /** + * Remove Item + * + * Removes an item from the cart + * + * @param int + * @return bool + */ + public function remove($rowid) + { + // unset & save + unset($this->_cart_contents[$rowid]); + $this->_save_cart(); + return TRUE; + } + + // -------------------------------------------------------------------- + + /** * Total Items * * Returns the total item count * - * @access public - * @return integer + * @return int */ - function total_items() + public function total_items() { return $this->_cart_contents['total_items']; } @@ -446,12 +462,13 @@ class CI_Cart { * * Returns the entire cart array * - * @access public + * @param bool * @return array */ - function contents() + public function contents($newest_first = FALSE) { - $cart = $this->_cart_contents; + // do we want the newest first? + $cart = ($newest_first) ? array_reverse($this->_cart_contents) : $this->_cart_contents; // Remove these so they don't create a problem when showing the cart table unset($cart['total_items']); @@ -468,17 +485,12 @@ class CI_Cart { * Returns TRUE if the rowid passed to this function correlates to an item * that has options associated with it. * - * @access public - * @return array + * @param mixed + * @return bool */ - function has_options($rowid = '') + public function has_options($rowid = '') { - if ( ! isset($this->_cart_contents[$rowid]['options']) OR count($this->_cart_contents[$rowid]['options']) === 0) - { - return FALSE; - } - - return TRUE; + return (isset($this->_cart_contents[$rowid]['options']) && count($this->_cart_contents[$rowid]['options']) !== 0); } // -------------------------------------------------------------------- @@ -488,17 +500,12 @@ class CI_Cart { * * Returns the an array of options, for a particular product row ID * - * @access public + * @param int * @return array */ - function product_options($rowid = '') + public function product_options($rowid = '') { - if ( ! isset($this->_cart_contents[$rowid]['options'])) - { - return array(); - } - - return $this->_cart_contents[$rowid]['options']; + return isset($this->_cart_contents[$rowid]['options']) ? $this->_cart_contents[$rowid]['options'] : array(); } // -------------------------------------------------------------------- @@ -508,20 +515,12 @@ class CI_Cart { * * Returns the supplied number with commas and a decimal point. * - * @access public - * @return integer + * @param float + * @return string */ - function format_number($n = '') + public function format_number($n = '') { - if ($n == '') - { - return ''; - } - - // Remove anything that isn't a number or decimal point. - $n = trim(preg_replace('/([^0-9\.])/i', '', $n)); - - return number_format($n, 2, '.', ','); + return ($n === '') ? '' : number_format( (float) $n, 2, '.', ','); } // -------------------------------------------------------------------- @@ -531,22 +530,15 @@ class CI_Cart { * * Empties the cart and kills the session * - * @access public - * @return null + * @return void */ - function destroy() + public function destroy() { - unset($this->_cart_contents); - - $this->_cart_contents['cart_total'] = 0; - $this->_cart_contents['total_items'] = 0; - + $this->_cart_contents = array('cart_total' => 0, 'total_items' => 0); $this->CI->session->unset_userdata('cart_contents'); } - } -// END Cart Class /* End of file Cart.php */ /* Location: ./system/libraries/Cart.php */
\ No newline at end of file |