After adding my own implementation of hook_cart_item() in a custom module I am writing, it seems I am unable to empty or update cart items. However commenting out my implementation of the hook I have no problems updating the cart.

/*
 * Implementation of hook_cart_item
 */

function ticketing_cart_item($op, &$item) {
	switch($op) {
		case 'load':
			if (is_ticketable($item->nid)) {
				// Append date to SKU
				$item->model		= ticket_sku($item->model, $item->data['ticketing_date']);
				$item->shippable 	= 0;

				if ($item->data['level']) {
					$item->data['model'] = $item->model.'-'.$item->data['level'];
					$item->price = ticketing_load_pricing($item->nid, $item->data['level']);
				}
			}
	}
}

Comments

checker’s picture

I have the same problem. If you change $item->data via hook_cart_item() there are different values in database and on the frontend. If you remove or change qty of products the query is using serialize($item->data) in where clause. So it never hit a record because you altered $item->data via hook_cart_item() and it is not the same data like in the database.

interestingaftermath’s picture

So what's the solution? I'm having this same problem. Is this a possible option for modifying item->data?

Here's my code:

/**
 * Implementation of hook_cart_item().
 *
 * This module checks the items weight and if '1' it marks the item as shippable. If '0' marks as non-shippable.
 */
function uc_nonshippable_cart_item($op, &$item) {
	switch ($op) {
	case 'load':
		if($item->weight != 1) {
			$item->data['shippable'] = '0';
			//serialize($item->data);
		}
		break;
	}
}

I tried adding serialize($item->data); (commented out above) but it doesn't fix the issue. I cannot remove items from the cart that match that if test.

checker’s picture

I'm using hook_add_to_cart_data() instead of hook_cart_item().

interestingaftermath’s picture

Ok, that helps. Would you mind pasting in your code so I can see how you're using it in relation to this topic?

freelock’s picture

Category: support » bug
Status: Active » Needs work

I'm changing this to a bug, because I think the real problem is in uc_cart_remove_item().

The problem is this: if any hook_cart_item changes anything in $item->data, this function cannot find the cart item to delete.

And the fix is really simple, because the {uc_cart_products} table has a primary key that is already loaded into the $item, as $item->cart_item_id .

So the correct fix for this is to simply change line 1591 in uc_cart.module from:

  db_query("DELETE FROM {uc_cart_products} WHERE cart_id = '%s' AND nid = %d AND data = '%s'", $cart_id, $nid, serialize($data));

to...

  db_query("DELETE FROM {uc_cart_products} WHERE cart_id = '%s' AND cart_item_id = %d", $item->cart_id, $item->cart_item_id);

.
A similar change should be made in uc_product.module, uc_product_update_cart_item(), for the update part -- change the query to use the cart_item_id instead of the serialized $item->data.

But... until the maintainers address this, you shouldn't hack these files directly. Instead, just change your code above to add a 'remove' operation, and do the delete yourself:

function uc_nonshippable_cart_item($op, &$item) {
    switch ($op) {
    case 'load':
        if($item->weight != 1) {
            $item->data['shippable'] = '0';
            //serialize($item->data);
        }
        break;
    case 'remove':
      db_query("DELETE FROM {uc_cart_products} WHERE cart_id = '%s' AND cart_item_id = %d", $item->cart_id, $item->cart_item_id);
    }
}

... as a workaround...

longwave’s picture

Status: Needs work » Closed (works as designed)

Old issue, this is an unfortunate design decision in the way cart items work, and we are unable to change this now. As noted in #3 you should use hook_add_to_cart_data() to add data to the 'data' array of a cart item, rather than altering it in hook_cart_item('load').