Commits

nucklearproject  committed b57f7b3

Creando el componente SimpleCart basado en Cart de CI

  • Participants
  • Parent commits bd6c5ef

Comments (0)

Files changed (4)

File protected/components/SimpleCart.php

+<?php
+
+class SimpleCart  extends CApplicationComponent
+{
+	
+	/**
+	 * 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!
+	// --------------------------------------------------------------------------
+
+	/**
+	 * Reference to CodeIgniter instance
+	 *
+	 * @var object
+	 */
+	protected $YII;
+
+	/**
+	 * 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())
+	{
+		// Set the super object to a local variable for use later
+		//$this->CI =& get_instance();
+
+		// Are any config settings being passed manually?  If so, set them
+		$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
+		$this->_cart_contents = Yii::app()->session['cart_contents'];
+		
+		if ($this->_cart_contents === FALSE)
+		{
+			// No cart exists so we'll set some base values
+			$this->_cart_contents = array('cart_total' => 0, 'total_items' => 0);
+		}
+		
+		Yii::Trace('SimpleCart component Initialized');
+		//log_message('debug', 'Cart Class Initialized');
+	}
+
+	/**
+	 * Insert items into the cart and save it to the session table
+	 *
+	 * @param	array
+	 * @return	bool
+	 */
+	public function insert($items = array())
+	{
+		// Was any cart data passed? No? Bah...
+		if ( ! is_array($items) OR count($items) === 0)
+		{
+			Yii::log('The insert method must be passed an array containing data.', 'error');
+			return FALSE;
+		}
+
+		// You can either insert a single product using a one-dimensional array,
+		// or multiple products using a multi-dimensional one. The way we
+		// determine the array type is by looking for a required array key named "id"
+		// at the top level. If it's not found, we will assume it's a multi-dimensional array.
+
+		$save_cart = FALSE;
+		if (isset($items['id']))
+		{
+			if (($rowid = $this->_insert($items)))
+			{
+				$save_cart = TRUE;
+			}
+		}
+		else
+		{
+			foreach ($items as $val)
+			{
+				if (is_array($val) && isset($val['id']))
+				{
+					if ($this->_insert($val))
+					{
+						$save_cart = TRUE;
+					}
+				}
+			}
+		}
+
+		// Save the cart data if the insert was successful
+		if ($save_cart === TRUE)
+		{
+			$this->_save_cart();
+			return isset($rowid) ? $rowid : TRUE;
+		}
+
+		return FALSE;
+	}
+
+	// --------------------------------------------------------------------
+
+	/**
+	 * Insert
+	 *
+	 * @param	array
+	 * @return	bool
+	 */
+	protected function _insert($items = array())
+	{
+		// Was any cart data passed? No? Bah...
+		if ( ! is_array($items) OR count($items) === 0)
+		{
+			Yii::log('The insert method must be passed an array containing data.', 'error');
+			return FALSE;
+		}
+
+		// --------------------------------------------------------------------
+
+		// Does the $items array contain an id, quantity, price, and name?  These are required
+		if ( ! isset($items['id'], $items['qty'], $items['price'], $items['name']))
+		{
+			Yii::log('The cart array must contain a product ID, quantity, price, and name.', 'error');
+			return FALSE;
+		}
+
+		// --------------------------------------------------------------------
+
+		// 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)
+		{
+			return FALSE;
+		}
+
+		// --------------------------------------------------------------------
+
+		// 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']))
+		{
+			Yii::log('Invalid product ID.  The product ID can only contain alpha-numeric characters, dashes, and underscores', 'error');
+			return FALSE;
+		}
+
+		// --------------------------------------------------------------------
+
+		// 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 ($this->product_name_safe && ! preg_match('/^['.$this->product_name_rules.']+$/i', $items['name']))
+		{
+			Yii::log('An invalid name was submitted as the product name: '.$items['name'].' The name can only contain alpha-numeric characters, dashes, underscores, colons, and spaces', 'error');
+			return FALSE;
+		}
+
+		// --------------------------------------------------------------------
+
+		// 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']))
+		{
+			Yii::log('An invalid price was submitted for product ID: '.$items['id'], 'error');
+			return FALSE;
+		}
+
+		// --------------------------------------------------------------------
+
+		// We now need to create a unique identifier for the item being inserted into the cart.
+		// Every time something is added to the cart it is stored in the master cart array.
+		// Each row in the cart array, however, must have a unique index that identifies not only
+		// a particular product, but makes it possible to store identical products with different options.
+		// For example, what if someone buys two identical t-shirts (same product ID), but in
+		// different sizes?  The product ID (and other attributes, like the name) will be identical for
+		// both sizes because it's the same shirt. The only difference will be the size.
+		// 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']) && count($items['options']) > 0)
+		{
+			$rowid = md5($items['id'].serialize($items['options']));
+		}
+		else
+		{
+			// No options were submitted so we simply MD5 the product ID.
+			// Technically, we don't need to MD5 the ID in this case, but it makes
+			// sense to standardize the format of array indexes for both conditions
+			$rowid = md5($items['id']);
+		}
+
+		// --------------------------------------------------------------------
+
+		// 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;
+
+		// 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;
+
+		return $rowid;
+	}
+	
+	/**
+	 * Update the cart
+	 *
+	 * This function permits the quantity of a given item to be changed.
+	 * Typically it is called from the "view cart" page if a user makes
+	 * changes to the quantity before checkout. That array must contain the
+	 * product ID and quantity for each item.
+	 *
+	 * @param	array
+	 * @return	bool
+	 */
+	public function update($items = array())
+	{
+		// Was any cart data passed?
+		if ( ! is_array($items) OR count($items) === 0)
+		{
+			return FALSE;
+		}
+
+		// You can either update a single product using a one-dimensional array,
+		// or multiple products using a multi-dimensional one.  The way we
+		// 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'], $items['qty']))
+		{
+			if ($this->_update($items) === TRUE)
+			{
+				$save_cart = TRUE;
+			}
+		}
+		else
+		{
+			foreach ($items as $val)
+			{
+				if (is_array($val) && isset($val['rowid'], $val['qty']))
+				{
+					if ($this->_update($val) === TRUE)
+					{
+						$save_cart = TRUE;
+					}
+				}
+			}
+		}
+
+		// Save the cart data if the insert was successful
+		if ($save_cart === TRUE)
+		{
+			$this->_save_cart();
+			return TRUE;
+		}
+
+		return FALSE;
+	}
+
+	// --------------------------------------------------------------------
+
+	/**
+	 * Update the cart
+	 *
+	 * This function permits the quantity of a given item to be changed.
+	 * Typically it is called from the "view cart" page if a user makes
+	 * changes to the quantity before checkout. That array must contain the
+	 * product ID and quantity for each item.
+	 *
+	 * @param	array
+	 * @return	bool
+	 */
+	protected function _update($items = array())
+	{
+		// Without these array indexes there is nothing we can do
+		if ( ! isset($items['qty'], $items['rowid'], $this->_cart_contents[$items['rowid']]))
+		{
+			return FALSE;
+		}
+
+		// Prep the quantity
+		$items['qty'] = (float) $items['qty'];
+
+		// Is the quantity a number?
+		if ( ! is_numeric($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)
+		{
+			unset($this->_cart_contents[$items['rowid']]);
+		}
+		else
+		{
+			$this->_cart_contents[$items['rowid']]['qty'] = $items['qty'];
+		}
+
+		return TRUE;
+	}
+	
+		/**
+	 * Save the cart array to the session DB
+	 *
+	 * @return	bool
+	 */
+	protected function _save_cart()
+	{
+		// Lets add up the individual prices and set the cart sub-total
+		$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'], $val['qty']))
+			{
+				continue;
+			}
+
+			$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']);
+		}
+
+		// Is our cart empty? If so we delete it from the session
+		if (count($this->_cart_contents) <= 2)
+		{
+			unset(Yii::app()->session['cart_contents']);
+			//$this->CI->session->unset_userdata('cart_contents');
+
+			// Nothing more to do... coffee time!
+			return FALSE;
+		}
+
+		// If we made it this far it means that our cart has data.
+		// Let's pass it to the Session class so it can be stored
+		Yii::app()->session['cart_contents'] = $this->_cart_contents;
+		//$this->CI->session->set_userdata(array('cart_contents' => $this->_cart_contents));
+
+		// Woot!
+		return TRUE;
+	}
+
+
+
+}

File protected/config/main.php

 
 	// preloading 'log' component
 	'preload'=>array('log'),
-
+	
+	
 	// autoloading model and component classes
 	'import'=>array(
 		'application.models.*',
 
 	// application components
 	'components'=>array(
+		
+		'session' => array (
+		'class' => 'system.web.CDbHttpSession',
+		'connectionID' => 'db',
+		'sessionTableName' => 'session',
+		),
+		
+		'cart' => array('class' => 'SimpleCart'),
+		
 		'user'=>array(
 			// enable cookie-based authentication
 			'allowAutoLogin'=>true,
 			'routes'=>array(
 				array(
 					'class'=>'CFileLogRoute',
-					'levels'=>'error, warning',
+					'levels'=>'trace, error, warning',
 				),
 				// uncomment the following to show log messages on web pages
 				/*

File protected/controllers/TestcartController.php

+<?php
+
+class TestcartController extends Controller {
+
+  /**
+   * @var string the default layout for the views. Defaults to '//layouts/column2', meaning
+   * using two-column layout. See 'protected/views/layouts/column2.php'.
+   */
+  public $layout = '//layouts/column2';
+  
+	public function actionIndex(){
+
+		$data = array(
+                'id'      => 'sku_123ABC',
+                'qty'     => 2,
+                'price'   => 39.00,
+                'name'    => 'T-Shirt',
+                'options' => array('Size' => 'L', 'Color' => 'Red')
+             );
+			 
+			 $data2 = array(
+                'id'      => 'sku_123ABCJJJ',
+                'qty'     => 1,
+                'price'   => 39.00,
+                'name'    => 'T-Shirt',
+                'options' => array('Size' => 'M', 'Color' => 'Red')
+             );
+	
+	$update = array(
+                'rowid' => '0256a32c98ce49afbe2a4eb8c96c5884',
+				'qty' => 5
+             );
+		//$cart = new SimpleCart();
+		Yii::app()->cart->insert($data);
+		Yii::app()->cart->insert($data2);
+
+
+//Yii::app()->session['uno'] = $data;
+//var_dump(Yii::app()->session['uno']);
+var_dump(Yii::app()->session['cart_contents']);
+
+Yii::app()->cart->update($update);
+var_dump(Yii::app()->session['cart_contents']);
+
+	}
+  
+  }

File protected/data/yii.db

Binary file modified.