Skip to content

Instantly share code, notes, and snippets.

@elivz
Created July 22, 2012 20:27
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save elivz/3160987 to your computer and use it in GitHub Desktop.
Save elivz/3160987 to your computer and use it in GitHub Desktop.
Exp:resso Store discount extension
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
/**
* Store Discount Extension
*
* @package ExpressionEngine
* @subpackage Addons
* @category Extension
* @author Eli Van Zoeren
* @link http://elivz.com
*/
class Store_discount_ext {
public $settings = array();
public $description = 'Apply quantity-based discounts to Exp:resso Store';
public $docs_url = 'http://elivz.com';
public $name = 'Store Discount';
public $settings_exist = 'n';
public $version = '1.0';
private $EE;
/**
* Constructor
*
* @param mixed Settings array or empty string if none exist.
*/
public function __construct($settings = '')
{
$this->EE =& get_instance();
$this->settings = $settings;
}
// ----------------------------------------------------------------------
/**
* Activate Extension
*
* This function enters the extension into the exp_extensions table
*
* @see http://codeigniter.com/user_guide/database/index.html for
* more information on the db class.
*
* @return void
*/
public function activate_extension()
{
// Setup custom settings in this array.
$this->settings = array();
// Add hooks
$data = array(
'class' => __CLASS__,
'method' => 'update_cart',
'hook' => 'store_cart_update_end',
'settings' => serialize($this->settings),
'priority' => 10,
'version' => $this->version,
'enabled' => 'y'
);
$this->EE->db->insert('extensions', $data);
}
// ----------------------------------------------------------------------
/**
* Disable Extension
*
* This method removes information from the exp_extensions table
*
* @return void
*/
function disable_extension()
{
$this->EE->db->where('class', __CLASS__);
$this->EE->db->delete('extensions');
}
// ----------------------------------------------------------------------
/**
* Update Extension
*
* This function performs any necessary db updates when the extension
* page is visited
*
* @return mixed void on update / false if none
*/
function update_extension($current = '')
{
if ($current == '' OR $current == $this->version)
{
return FALSE;
}
$this->EE->db->where('class', __CLASS__);
$this->EE->db->update(
'extensions',
array('version' => $this->version)
);
}
// ----------------------------------------------------------------------
/**
* Responds to the store_cart_update_end hook in Exp:resso Store
* to apply a discount to each product, as needed
*
* @return array of cart items
*/
function update_cart($cart_contents)
{
$this->EE->load->helper(array('store'));
// Get the number of products currently in the user's cart
$count = count($cart_contents['items']);
// Only apply the discount if there is more than one item
if ($count > 1)
{
// Take $10 off all but the first product
// This calculation can easily be adjusted as needed
$discount = ($count - 1) * 10;
// Add the quantity discount to any existing discount (promo code)
$cart_contents['order_discount_val'] += $discount;
// Make sure we don't end up with a negative total
if ($cart_contents['order_discount_val'] > $cart_contents['order_subtotal_val'])
{
$cart_contents['order_discount_val'] = $cart_contents['order_subtotal_val'];
}
$cart_contents['order_discount'] = store_format_currency($cart_contents['order_discount_val']);
// Update the cart total to reflect the new discount
$cart_contents['order_total_val'] = $cart_contents['order_subtotal_val'] - $cart_contents['order_discount_val'];
$cart_contents['order_total'] = store_format_currency($cart_contents['order_total_val']);
}
return $cart_contents;
}
}
/* End of file ext.store_discount.php */
/* Location: /system/expressionengine/third_party/store_discount/ext.store_discount.php */
@since1976
Copy link

Eli thanks for the script exactly what I need for now.

However when I tried saving your file to my third_party dir and just get a blank page when visiting the extensions in the CP.

My third_party folder isn't in my system folder and is being linked to via a config var, would that make a difference?

Cheers
Dan

@since1976
Copy link

Looks like it has something to do with line 118
$count = count($cart_contents['items'];

If I comment that out the extension screen shows up just fine.

@elivz
Copy link
Author

elivz commented Jul 26, 2012

Daniel,

Yep, that's the problem. I somehow lost a closing parenthesis when I copied my code over. I just updated the Gist, or you can simply add a ")" at the end of that line, right before the semicolon.

@since1976
Copy link

Crap I should have seen that myself.
Thanks for the prompt reply.

@since1976
Copy link

Is there anything special I need to put in the template to get this to work?
Cant seem to see any discounts being applied. Have emptied the cart and added new product, but still no result.

@amacneil
Copy link

Thanks Eli, this looks great!

Daniel, looking at this code out of the box it will only apply a discount if you have more than one separate line item in your cart. So you may need to add two different products before you see anything. Also make sure you are templating {order_discount} somewhere in your checkout.

@elivz
Copy link
Author

elivz commented Jul 26, 2012

Daniel- Did Adrian's suggestion work for you? He's right, you need to have more than one item in the cart before a discount will show up. (Of course, you can edit the update_cart() function to apply any discount logic you want... that's just an example.) If it still doesn't work with two products in the cart, it's possible that there is a bug in my code. I haven't tested it extensively beyond my particular situation.

@since1976
Copy link

Thanks for the response guys.
I was trying with one product, opposed to multiple products. What I require is when a user orders 3 of the same product they would receive a discount.

I don't know PHP at all so don't really know what needs to be changed to achieve the above. I think I probably need to change line 118 somehow in order to get the quantity of items, instead of the items themselves.

@elivz
Copy link
Author

elivz commented Jul 26, 2012

The way it currently works, every product after the first one gets a $10 discount. If you wanted the discount to only apply to multiples of the SAME product, you would need to add some slightly more complex logic to loop through $cart_contents['items'], checking the SKU number of each product. You have a lot of leeway with how you calculate the discount... the point of this code is just to give people a boilerplate so they don't need to track down the correct hook and figure out which variables to update after the discount is calculated.

@since1976
Copy link

Ha, okay so it is a little more complicated than I just outlined. Shows I know nothing about development.

@elivz
Copy link
Author

elivz commented Jul 26, 2012

Right... this is a starting point for developing your own discount extension. If you need a click-and-play interface for discounts, you'll probably need to wait until Exp:resso adds it to Store, or use a different e-commerce add-on (CartThrob has very flexible discounting, although at the expense of a more complex system all around).

@since1976
Copy link

Yeah I really should start learning as it will make things a lot easier.
Thanks for this extension Eli it will work as a great starting point. I will ask a mate of mine to have a look and show me how we can extend the code to what I need. I will gist the result when it is done.

Cheers
Dan

@amacneil
Copy link

Dan.. try something like this (untested, may be some slight errors):

foreach ($cart_contents['items'] as $item)
{
    if ($item['item_qty'] >= 3)
    {
         $cart_contents['order_discount_val'] += 10;
    }
}

then add the rest of the code from above:

        if ($cart_contents['order_discount_val'] > $cart_contents['order_total_val'])
            $cart_contents['order_discount_val'] = $cart_contents['order_total_val'];
        $cart_contents['order_discount'] = store_format_currency($cart_contents['order_discount_val']);

        // Update the cart total to reflect the new discount
        $cart_contents['order_total_val'] = $cart_contents['order_subtotal_val'] - $cart_contents['order_discount_val'];
        $cart_contents['order_total'] = store_format_currency($cart_contents['order_total_val']);

        return $cart_contents;

That should add a $10 discount for every item which has qty >= 3. Notice all the variables are exactly the same as what you use in the template (item_qty, order_total etc).

@since1976
Copy link

Works great thanks guys.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment