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:
parent
1784514696
commit
5390e37612
12 changed files with 165 additions and 155 deletions
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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)) {
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
|
@ -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]);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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
23
models/store/cart.php
Normal 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
64
models/store/cart/add.php
Normal 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
35
templates/store/cart.tpl
Normal 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>
|
|
@ -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" /> <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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue