Ditched the POS Session class in favor of just interacting with the session directly. Added more to the store / cart.

git-svn-id: http://svn.cleancode.org/svn/pickles@56 4d10bc64-7434-11dc-a737-d2d0f8310089
This commit is contained in:
Josh Sherman 2008-09-23 02:21:55 +00:00
parent 1784514696
commit 5390e37612
12 changed files with 165 additions and 155 deletions

View file

@ -41,11 +41,9 @@ class Config extends Singleton {
* @return An instace of the Config class
*/
public static function getInstance() {
$session = Session::getInstance();
$class = __CLASS__;
if (isset($session->$class)) {
if (isset($_SESSION['objects'][$class])) {
self::$instance = Singleton::thaw($class);
}
else if (!self::$instance instanceof $class) {
@ -75,7 +73,6 @@ class Config extends Singleton {
}
}
$load = true;
if ($load) {
if (file_exists($file)) {
$this->file = $file;

View file

@ -21,7 +21,6 @@ class Controller extends Object {
*/
private $model = null;
private $viewer = null;
private $session = null;
/*
protected $config = null;
@ -41,8 +40,13 @@ class Controller extends Object {
public function __construct($file = '../config.xml', $controller = 'Web') {
parent::__construct();
// Establish the session
$this->session = Session::getInstance();
// Start the session if it's not started already
/**
* @todo Need to make the session not so mandatory.
*/
if (ini_get('session.auto_start') == 0) {
session_start();
}
// Load the config for the site passed in
$this->config = Config::getInstance();

View file

@ -53,11 +53,9 @@ class DB extends Singleton {
* @return object An instace of the DB class
*/
public static function getInstance() {
$session = Session::getInstance();
$class = __CLASS__;
if (isset($session->$class)) {
if (isset($_SESSION['objects'][$class])) {
self::$instance = Singleton::thaw($class);
}
else if (!self::$instance instanceof $class) {
@ -75,6 +73,7 @@ class DB extends Singleton {
*
* @return boolean Based on the success or failure of mysql_connect()
* @todo Remove the error supressing @ from mysql_connect()
* @todo Currently the DBO is not being cached in the object, since it stores the password, it's a security issue.
*/
public function open() {
if (!is_resource($this->connection)) {

View file

@ -1,136 +0,0 @@
<?php
/**
* Session wrapper class
*
* Basic functions to ensure that interaction with the $_SESSION super global is
* done in a consistent manner.
*
* @package PICKLES
* @author Joshua Sherman <josh@phpwithpickles.org>
* @copyright 2007-2008 Joshua Sherman
* @todo Make the SQL less specific, right now you have to use a table
* named users, and use the email as the username. I will need to
* move this to the configuration and allow the user to specify which
* table to authenticate against, and what column names to use for the
* username and password.
*/
class Session extends Singleton {
/**
* Private instance of the Session class
*/
private static $instance;
/**
* Session ID
*/
public static $id = null;
/**
* Private constructor
*
* Checks if session.auto_start is not enabled and if not, it will start the
* session and then grabs the session ID.
*
* @todo Need to look into whether or not sessions can be disabled
* indefinately. If so, this may need to be rethought.
*/
private function __construct() {
if (ini_get('session.auto_start') == 0) {
session_start();
}
$this->id = session_id();
}
/**
* Gets an instance of the Session class
*/
public static function getInstance() {
if (!self::$instance instanceof Session) {
self::$instance = new Session();
}
return self::$instance;
}
/**
* Destroys the session
*
* Loops through all the $_SESSION variables and session_unregister()s them.
* After the unregistering session_destory() is called
*/
public function destroy() {
// foreach ($_SESSION as $variable => $value)
foreach (array_keys($_SESSION) as $variable) {
session_unregister($variable);
}
session_destroy();
}
/**
* Clone function
*
* Triggers a PHP error as the Session class cannot be cloned because it
* extends the Singleton class.
*
* @todo The Config and Session (and any other Singleton classes) need to
* have this function. I think it can be added to the Singleton class
* directly, then the child classes will have it via inheritance. Wait
* just remembered that class inheritance with static classes is a bit
* screwy so every class may need the function directly.
*/
public function __clone() {
trigger_error('Clone is not allowed for ' . __CLASS__, E_USER_ERROR);
}
/**
* Gets a session variable
*
* @param string $var Name of the variable to be returned
* @return Value of the requested variable
* @todo Returns null if the variable isn't set. Not sure if this is as
* drastic as returning false, we'll see.
*/
public function __get($var) {
if (!isset($_SESSION[$var])) {
$_SESSION[$var] = null;
}
return $_SESSION[$var];
}
/**
* Sets a session variable
*
* @param string $var Name of the variable to set
* @param mixed $val Value to be assigned to the passed variable
* @return boolean The returned status of assigning the variable.
*/
function __set($var, $val) {
return ($_SESSION[$var] = $val);
}
/**
* Checks if a session variable is set
*
* @param string $var Name of the variable to be checked
* @return boolean Whether or not the passed variable is set
*/
public function __isset($var) {
return isset($_SESSION[$var]) || isset($this->$var);
}
/**
* Destructor
*
* Closes out the session.
*/
public function __destruct() {
session_write_close();
}
}
?>

View file

@ -68,10 +68,9 @@ class Singleton {
* @todo Needs to return the status for error tracking.
*/
public function freeze() {
$session = Session::getInstance();
$this->timestamp = time();
$class = get_class($this);
$session->$class = serialize($this);
$_SESSION['objects'][$class] = serialize($this);
}
/**
@ -88,8 +87,7 @@ class Singleton {
public static function thaw($class) {
__autoload($class);
$session = Session::getInstance();
return unserialize($session->$class);
return unserialize($_SESSION['objects'][$class]);
}
}

View file

@ -5,6 +5,25 @@ class store extends Model {
public function __construct() {
parent::__construct();
// Loads up the cart in case we need it
if (!isset($_SESSION['cart'])) {
$_SESSION['cart'] = array();
$_SESSION['cart'] = array('count' => 0, 'products' => null);
}
else {
$count = 0;
if (is_array($_SESSION['cart']['products'])) {
foreach ($_SESSION['cart']['products'] as $product_id => $product_info) {
$count += $product_info['quantity'];
}
}
$_SESSION['cart']['count'] = $count;
}
$this->data['cart'] = $_SESSION['cart'];
// Loads the navigation
$config = Config::getInstance();
$this->data['subnav'] = $config->get('store', 'sections');

23
models/store/cart.php Normal file
View file

@ -0,0 +1,23 @@
<?php
/**
* Store cart view
*
* Displays the contents of the shopping cart and gives the user the
* ability to update quantities, remove items, apply discount codes and
* proceed to the checkout.
*
* @package PICKLES
* @subpackage store
* @author Joshua Sherman <josh@phpwithpickles.org>
* @copyright 2007-2008 Joshua Sherman
*/
class store_cart extends store {
public function __default() {
//session_destroy();
}
}
?>

64
models/store/cart/add.php Normal file
View file

@ -0,0 +1,64 @@
<?php
/**
* Adds an item to the cart
*
* Adds the passed item to the cart with a quantity of 1.
*
* @package PICKLES
* @subpackage store
* @author Joshua Sherman <josh@phpwithpickles.org>
* @copyright 2007-2008 Joshua Sherman
*/
class store_cart_add extends store {
/**
* @todo Add handling for an invalid product
*/
public function __default() {
if ($this->db->getField('SELECT COUNT(id) FROM products WHERE id = "' . $_REQUEST['id'] . '";') != 1) {
}
else {
// References the product in the cart
$product =& $_SESSION['cart']['products'][$_REQUEST['id']];
// If the data is not set then grab it and set it
if (!isset($product['name'], $product['sku'], $product['price'])) {
$data = $this->db->getRow('SELECT name, sku, price FROM products WHERE id ="' . $_REQUEST['id'] . '";');
$product['name'] = $data['name'];
$product['sku'] = $data['sku'];
$product['price'] = $data['price'];
}
// Increment the quantity and update the total
$product['quantity']++;
$product['total'] = number_format($product['price'] * $product['quantity'], 2);
unset($product);
// References the cart as a whole
$cart =& $_SESSION['cart'];
$subtotal = 0;
// Loops through the products and totals them up
if (is_array($cart['products'])) {
foreach ($cart['products'] as $product) {
$subtotal += $product['total'];
}
}
// Set the subtotal in the cart
$cart['subtotal'] = $subtotal;
unset($cart);
// Redirect to the cart
header('Location: /store/cart');
exit();
}
}
}
?>

35
templates/store/cart.tpl Normal file
View file

@ -0,0 +1,35 @@
<div class="content-left">
{include file="../../pickles/templates/store/navigation.tpl"}<br /><br />
{include file="../../pickles/templates/store/categories.tpl"}
</div>
<div class="content-right store-cart">
<div class="your-cart">
<h1>Your Cart</h1>
</div>
{if is_array($cart.products)}
<table class="product-list">
<tr>
<th class="product-quantity">Qty.</th>
<th class="product-sku">SKU</th>
<th class="product-description">Product Description</th>
<th class="product-price">Price</th>
<th class="product-total">Total</th>
</tr>
{foreach from=$cart.products item=product}
<tr>
<td class="product-quantity"><input type="text" class="product-quantity" value="{$product.quantity}" /></td>
<td class="product-sku">{$product.sku}</td>
<td class="product-description">{$product.name}</td>
<td class="product-price">${$product.price}</td>
<td class="product-total">${$product.total}</td>
{/foreach}
<tr>
<td colspan="5">
</td>
</tr>
</table>
{else}
You have no items in your shopping cart.
{/if}
<div>

View file

@ -1,7 +1,10 @@
<img src="/images/products/{$featured.id}/medium.{$featured.image}" class="float-right" style="padding-right: 20px; height: 155px;" />
<div id="store-featured-product">
<div class="store-featured-product">
<h1>Featured Product</h1>
<h2>{$featured.name}</h2><br />
{$featured.teaser}<br /><br />
<img src="/images/store/add_to_cart.gif" />&nbsp;&nbsp;<img src="/images/store/more_info.gif" />
<ul>
<li><a href="/store/cart/add/{$featured.id}" class="add-to-cart"><span>Add to Cart</span></a></li>
<li><a href="/store/product/{$featured.id}" class="more-information"><span>More Information</span></a></li>
</ul>
</div>

View file

@ -1,8 +1,8 @@
<div id="content-left">
<div name="content-left">
{include file="../../pickles/templates/store/navigation.tpl"}<br /><br />
{include file="../../pickles/templates/store/categories.tpl"}
</div>
<div id="content-right">
<div name="content-right">
{include file="../../pickles/templates/store/featured_product.tpl"}<br /><br />
{include file="../../pickles/templates/store/top_sellers.tpl"}
</div>

View file

@ -1,7 +1,11 @@
<div id="store-subnav">
<ol id="subnav">
{foreach from=$subnav key=link item=label}
<li {if $model == 'store/'|cat:$link}class="selected"{/if}><a href="/{$section}/{$link}" class="{$link}">{$label}</a></li>
<li {if $model == 'store/'|cat:$link}class="selected"{/if}>
<a href="/{$section}/{$link}" class="{$link}">
{$label}{if $link == 'cart' && $cart.count != 0} ({$cart.count}){/if}
</a>
</li>
{/foreach}
</ol>
</div>