uc_cart_get_contents and drupal_alter
mfer - December 22, 2008 - 13:20
| Project: | Ubercart |
| Version: | 6.x-2.0-beta3 |
| Component: | Code |
| Category: | feature request |
| Priority: | normal |
| Assigned: | rszrama |
| Status: | closed |
Description
Would it be possible to get a drupal_alter call in the function uc_cart_get_contents. It's nice to be able to add to each item but it would be great to alter what other modules have done or at a point after the entire care has been populated.
The code would look something like:
<?php
/**
* Grab the items in a shopping cart for a user.
*
* If $cid is not passed in, this function uses the uid of the person currently
* accessing this function.
*/
function uc_cart_get_contents($cid = NULL, $action = NULL) {
static $items = array();
$cid = $cid ? $cid : uc_cart_get_id();
if ($action == 'rebuild') {
$items = array();
}
if (!isset($items[$cid])) {
$items[$cid] = array();
$result = db_query("SELECT c.*, n.title, n.vid FROM {node} n INNER JOIN {uc_cart_products} c ON n.nid = c.nid WHERE c.cart_id = '%s'", $cid);
while ($item = db_fetch_object($result)) {
for ($i = 0; $i < count($items[$cid]); $i++) {
if ($items[$cid][$i]->nid == $item->nid && $items[$cid][$i]->data == $item->data) {
$items[$cid][$i]->qty += $item->qty;
continue 2;
}
}
$product = node_load($item->nid);
$item->cost = $product->cost;
$item->price = $product->sell_price;
$item->weight = $product->weight;
$item->data = unserialize($item->data);
$item->module = $item->data['module'];
$item->options = array();
$item->model = $product->model;
// Invoke hook_cart_item() with $op = 'load' in enabled modules.
foreach (module_implements('cart_item') as $module) {
$func = $module .'_cart_item';
$func('load', $item);
}
$items[$cid][] = $item;
}
drupal_alter('cart_item', $items);
}
return $items[$cid];
}
?>notice the drupal_alter call at the bottom.
This would be great if I want to alter the prices of items in the cart based on the contents of the cart. This is my use case but I'm sure there are many more.
Can we get this change in. If needed I'll roll a patch. It's just a one line change.

#1
Looking at this again I'd actually make the alter call read:
<?phpdrupal_alter('cart_items', $items);
?>
#2
Here's an interesting idea. I can see how this could make product kits a lot less complicated. Possibly. It may just move the complexity around to a different function. It's definitely worth another look.
My patch makes it call hook_uc_cart_alter(). It's really the entire cart that's being altered and not the individual item. Also, I'm only passing it the actual cart being returned by uc_cart_get_contents(). This keeps each module from modifying the cart more than once, and doesn't allow any kind of cross-contamination through faulty coding.
I'm going to mull it over for a while. I can think of a lot of different applications for this, but I'm not sure they're all going to sit well together.
#3
My use case is where I have two products. When one is purchased the other gets a discount if it is there as well. This is a lot simpler with a _alter call. I can imagine a number of other uses..... for example the uc discounts module which has to build a psuedo cart on it's own so it knows what's in the cart before it acts. That could possible be removed if it had the cart there.
#4
Lyle's patch in #3 seems good to me... unobtrusive and certainly useful. Maybe one day we'll have better cart support in general, but this is a good small step.
Will document this so people know implementations of this hook must receive the $items argument by reference.
#5
Automatically closed -- issue fixed for 2 weeks with no activity.