DivaVocals,
I'm not planning to submit and support an add-on but will show you what I did. Caution: while the following code appears to work for me, I suggest you thoroughly test this code on a development site before you go live with it.
1. Create a donation product - I called mine "Donation to <name of organization>". Replace <name of organization> with appropriate text. Set the price at $1.00. You can set the Product is Virtual to yes, or in my case I set it to no because of a free gift we provide for a donation. I set Always Free Shipping to yes (due to the free gift). I set up attributes for the donation product so that the customer can select which free gift they want. But you don't need to set up attributes for this code to work.
2. Modify includes/templates/<your_template>/templates/tpl_product_info_display.php to not display the donation unit price and change the "add to cart" text where you enter quantity. Replace <your_template> with the appropriate text for your template. Changes to sections of the file are indicated in red in the code snippets below.
Code:
<!--bof Product Price block -->
<h2 id="productPrices" class="productGeneral">
<?php
// base price
if ($show_onetime_charges_description == 'true') {
$one_time = '<span >' . TEXT_ONETIME_CHARGE_SYMBOL . TEXT_ONETIME_CHARGE_DESCRIPTION . '</span><br />';
} else {
$one_time = '';
}
if ((int)$_GET['products_id'] <> DONATION_PRODUCT_ID) {
echo $one_time . ((zen_has_product_attributes_values((int)$_GET['products_id']) and $flag_show_product_info_starting_at == 1) ? TEXT_BASE_PRICE : '') . zen_get_products_display_price((int)$_GET['products_id']);
}
?></h2>
<!--eof Product Price block -->
Code:
<!--bof Add to Cart Box -->
<?php
if (CUSTOMERS_APPROVAL == 3 and TEXT_LOGIN_FOR_PRICE_BUTTON_REPLACE_SHOWROOM == '') {
// do nothing
} else {
?>
<?php
if ($_GET['products_id'] <> DONATION_PRODUCT_ID) {
$display_qty = (($flag_show_product_info_in_cart_qty == 1 and $_SESSION['cart']->in_cart($_GET['products_id'])) ? '<p>' . PRODUCTS_ORDER_QTY_TEXT_IN_CART . $_SESSION['cart']->get_quantity($_GET['products_id']) . '</p>' : '');
} else {
$display_qty = (($flag_show_product_info_in_cart_qty == 1 and $_SESSION['cart']->in_cart($_GET['products_id'])) ? '<p>' . DONATION_ORDER_QTY_TEXT_IN_CART . $_SESSION['cart']->get_quantity($_GET['products_id']) . '</p>' : '');
}
if ($products_qty_box_status == 0 or $products_quantity_order_max== 1) {
// hide the quantity box and default to 1
$the_button = '<input type="hidden" name="cart_quantity" value="1" />' . zen_draw_hidden_field('products_id', (int)$_GET['products_id']) . zen_image_submit(BUTTON_IMAGE_IN_CART, BUTTON_IN_CART_ALT);
} else {
// show the quantity box
if ($_GET['products_id'] <> DONATION_PRODUCT_ID) {
$the_button = PRODUCTS_ORDER_QTY_TEXT . '<input type="text" name="cart_quantity" value="' . (zen_get_buy_now_qty($_GET['products_id'])) . '" maxlength="6" size="4" /><br />' . zen_get_products_quantity_min_units_display((int)$_GET['products_id']) . '<br />' . zen_draw_hidden_field('products_id', (int)$_GET['products_id']) . zen_image_submit(BUTTON_IMAGE_IN_CART, BUTTON_IN_CART_ALT);
} else {
$the_button = DONATION_ORDER_QTY_TEXT . '<input type="text" name="cart_quantity" value="' . (zen_get_buy_now_qty($_GET['products_id'])) . '" maxlength="6" size="4" /><br />' . zen_get_products_quantity_min_units_display((int)$_GET['products_id']) . '<br />' . zen_draw_hidden_field('products_id', (int)$_GET['products_id']) . zen_image_submit(BUTTON_IMAGE_IN_CART, BUTTON_IN_CART_ALT);
}
}
$display_button = zen_get_buy_now_button($_GET['products_id'], $the_button);
?>
<?php if ($display_qty != '' or $display_button != '') { ?>
<div id="cartAdd">
<?php
echo $display_qty;
echo $display_button;
?>
</div>
<?php } // display qty and button ?>
<?php } // CUSTOMERS_APPROVAL == 3 ?>
<!--eof Add to Cart Box-->
3. Be sure to define the constants DONATION_PRODUCT_ID, DONATION_ORDER_QTY_TEXT_IN_CART, and DONATION_ORDER_QTY_TEXT. In my case, I used 600, 'Donation in Cart: ', and 'Donation Amount: ' respectively. I included them in includes/languages/<your_template>/english.php in the section concerning cart contents. I'm certain there are other files where you can define these constants.
4. Set up an observer for the NOTIFIER_CART_GET_PRODUCTS_END event. Two files will need to be set up. First, includes/autoloaders/config.processDonationEntry.php
Code:
<?php
/**
* autoloader activation point for donation entry box processing
*
* @package initSystem
* @copyright Copyright 2003-2013 Zen Cart Development Team
* @license http://www.zen-cart.com/license/2_0.txt GNU Public License V2.0
* @version $Id: config.processDonationEntry.php $
*/
/**
* Autoloader to instantiate observer class
*/
$autoLoadConfig[203][] = array('autoType'=>'class',
'loadFile'=>'observers/class.processDonationEntry.php');
$autoLoadConfig[203][] = array('autoType'=>'classInstantiate',
'className'=>'processDonationEntry',
'objectName'=>'processDonationEntry');
Second, includes/classes/observers/class.processDonationEntry.php
Code:
<?php
/**
* observer class to process donation entry box
*
* @package classes
* @copyright Copyright 2003-2013 Zen Cart Development Team
* @license http://www.zen-cart.com/license/2_0.txt GNU Public License V2.0
* @version $Id: class.processDonationEntry.php $
*/
class processDonationEntry extends base {
/** constructor method !
*
* Attach observer class to the global $zco_notifier and watch for a single notifier event.
*/
function __construct() {
$this->attach($this, array('NOTIFIER_CART_GET_PRODUCTS_END'));
}
/** Actual Method that does the desired activity
*
* Called by observed class when any of the notifiable events occur
*
* @param object $class
* @param string $eventID
* @param array $paramsArray
*/
function update(&$class, $eventID, $paramsArray = array()) {
global $db, $products_array;
foreach ($products_array as &$product) {
if ($product['id'] == DONATION_PRODUCT_ID ) {
$product['price'] = $product['quantity'];
$product['final_price'] = $product['price'];
$product['quantity'] = 1;
}
} // end of foreach
unset($product); // break reference with the last element
// echo "<pre>"; print_r($products_array); echo "</pre>";
} // end of function update
} // end of class
5. Modify a core file (sorry) to allow the observer function access to a variable in file includes/classes/shopping_cart.php in function get_products.
Code:
/**
* Method to return details of all products in the cart
*
* @param boolean whether to check if cart contents are valid
* @return array
*/
function get_products($check_for_valid_cart = false) {
global $db, $products_array;
$this->notify('NOTIFIER_CART_GET_PRODUCTS_START');
6. Finally, include a file developed by lat9 to retain the customer entered donation if the quantity of another item in the cart is changed. This file is includes/extra_cart_actions/fix_donation_quantity.php
Code:
<?php
/**
* Edit to retain donation amount if the quantity of another item in the shopping cart is changed
* Code written and supplied by lat9 on the Zen Cart forum
*/
if (isset($_GET['action']) && $_GET['action'] == 'update_product') {
for ($i = 0, $n = sizeof($_POST['products_id']); $i < $n; $i++) {
if ($_POST['products_id'][$i] == DONATION_PRODUCT_ID) { // index $i added to LAT9 supplied code
if (! (in_array(DONATION_PRODUCT_ID, (is_array($_POST['cart_delete']) ? $_POST['cart_delete'] : array())) || $_POST['cart_quantity'][$i] == 0) ){
foreach ($_SESSION['cart']->contents as $uprid => $contents) {
if (((int)$uprid) == DONATION_PRODUCT_ID) {
$_POST['cart_quantity'][$i] = $contents['qty'];
break; // out of foreach
}
}
}
}
}
}
That should be all that is needed to implement a donation product where the quantity is 1 and the donation is the amount entered rather than seeing a quantity of 50 $1.00 donations in the shopping cart throughout the checkout process. Be sure to test your implementation. Good luck!
Dave
Bookmarks