The logic for the shopping cart for anon users fails. This is because the check for !$product_count happens in one instance, but not another.

The display logic should be:

        // Build the block array for display based on cache settings.
        if ($cachable && !$product_count) {
          // Caching is turned on and the user is not logged in, so we should
          // deliver a block that is safe for caching.
          $block = array(
            'subject' => theme('uc_cart_block_title', $title, $icon_class, $collapsible),
            'content' => theme('uc_cart_block_content_cachable'),
          );
        }

Alternately, $cachable should be reset based on $product_count.

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

longwave’s picture

Status: Active » Postponed (maintainer needs more info)

We must output the cache-safe cart block if $cachable is TRUE, no matter whether any products are in the cart. Otherwise, this can result in "ghost carts" being stored in the Drupal page cache, where subsequent users may see the cart contents of a previous user. Unless I'm missing something?

agentrickard’s picture

What I don't understand is that I get different output of this block for anon users in different contexts. Even if they have items in the cart, they get served the cached block (e.g. 'View your cart') in _some_ cases but not others (when they see an itemized cart block).

Isn't there session handling involved in the $product_count logic that accounts for this?

longwave’s picture

I am not sure this has anything to do with sessions, $product_count is simply the number of items in the cart.

        $cachable = !$user->uid && variable_get('cache', CACHE_DISABLED) != CACHE_DISABLED;
        $product_count = count(uc_cart_get_contents());

Perhaps the global $conf['cache'] is being overridden by another module sometimes, to avoid caching particular pages, so the variable_get() test is fooled? Can you identify particular cases where the block is shown to anon users?

agentrickard’s picture

FileSize
537.46 KB

uc_cart_get_contents() depends on uc_cart_get_id(), which sets and reads a unique session variable to distinguish between users (including anonymous users).

We're not doing anything odd to the cache. Settings are:

-- Page cache: Normal
-- Block cache: Off

The problem isn't that the block is _shown_ to anon users. It's that the block is not shown _consistently_ to anon users, as the doc attached tries to explain.

I suppose it is possible that Views is interfering in some odd way, since /store is a View path and may be confusing core cache because of how menu items are handled. But I doubt that.

longwave’s picture

The problem isn't that the block is _shown_ to anon users.

This is a problem, when page caching is enabled. Scenario:

1. The page cache is cleared.
2. An anonymous user adds an item to their cart.
3. The same user views an uncached (but cachable) page. The page is cached, including their cart block.
4. Another anonymous user (with an empty, or at least different, cart) visits the same page, and is shown the cached page, which contains the previous user's cart block.

The cache-safe cart block exists to avoid this "ghost cart" problem; anonymous users should always see "View your shopping cart" when page caching is enabled. But this does not explain the inconsistency in your example!

If you do want to show the cart contents block to anonymous users, you must either disable the page cache, or use the Ajax cart module to replace the cart block after the page is loaded. Back in D5, Ubercart used cache_clear_all() in several places to avoid this, but as it is a huge performance hit it was removed; see #309394: Excessive use of cache_clear_all().

#449122: Hide block if cart is empty. is related, though somewhat confusing to follow.

agentrickard’s picture

I'm thinking this might be a Pressflow variant issue. Perhaps Pressflow is disabling the page cache when $SESSION is not empty.

Investigating.

longwave’s picture

agentrickard’s picture

Title: Anonymous cart block cache broken » Anonymous cart block cache broken with Pressflow
Category: bug » support
Status: Postponed (maintainer needs more info) » Active

Right, so in the Pressflow world, it appears that drupal_page_is_cacheable() returns FALSE to anon users because Ubercart sets the cart $_SESSION variable.

That means that the page isn't being served from cache at all, which explains the difference.

Changing title to reflect that. Moving to 'support' request, since this can't be considered an UC bug.

[EDIT]: drupal_page_is_cacheable() is a Pressflow-specific function.

agentrickard’s picture

I wonder if anon users should use a cookie rather than a session_id for cart identification here, since cookies wouldn't break the behavior?

We could set the cookie IFF an item is in the cart.

Testing AJAX Cart.

agentrickard’s picture

Status: Active » Closed (duplicate)

Looks like AJAX Cart solves this problem. Marking as duplicate.

@longwave Thanks for the support!

longwave’s picture

Status: Closed (duplicate) » Active

I wonder if the patch from #377798-47: Cart block always starts a session will help here, without the need for Ajax cart?

agentrickard’s picture

Let me try that.

agentrickard’s picture

Status: Active » Needs review
FileSize
1.05 KB

This version works as expected. I'm not sure why the second IF had !$cacheable as the first check. If empty we should always hide.

longwave’s picture

Good news, thanks for testing. Before committing I would like to test this myself, and would also like some comments above this new code to explain that it's for Pressflow support.

I think the second part should be left as-is, or needs a separate Pressflow workaround, again because of the ghost cart block problem. If we change the code as you suggest, it looks like that if all the following are true:
- site is not using Pressflow
- page caching is enabled
- user is anonymous
- "hide empty cart block" is enabled
- user has items in their cart
- user visits a previously uncached page
Then later, another anonymous user with an empty cart views the same page, the cache safe cart block will be displayed?

agentrickard’s picture

That makes sense to me. You need a revised patch?

Status: Needs review » Needs work

The last submitted patch, 1167276-anon-pressflow-uc-block.patch, failed testing.

longwave’s picture

If you have time, please do - not sure when I will get around to testing a Pressflow-enabled install, and any help here is welcome! There is also no need for the $cachable = TRUE; line in the patch.

agentrickard’s picture

Status: Needs work » Needs review
FileSize
1.1 KB

This just adds a logic check for $is_pressflow to the current patch.

Status: Needs review » Needs work

The last submitted patch, 1167276-anon-pressflow-uc-block-2.patch, failed testing.

wxman’s picture

I just tried this patch to see if it would get rid of the cart showing on all anon visitors. It works perfectly on my Pressflow install. The only weird thing is my copy didn't have
$uc_cart_path = drupal_get_path('module', 'uc_cart');

agentrickard’s picture

Status: Needs work » Needs review

Ignoring the testbot fail and marking NR.

mrP’s picture

#10 http://drupal.org/node/1167276#comment-4519590 (uc_ajax_cart) is a great workaround for pressflow + anonymous checkout issues. Thanks!

mrP’s picture

Version: 6.x-2.4 » 6.x-2.6

FYI, confirmed in UC 2.6 / Pressflow 6.22 as well.

TR’s picture

@pricejn2: So did you test the patch in #18?

mrP’s picture

Sorry no. I haven't tested the patch yet. Will get around to is ASAP.

mrP’s picture

FileSize
1.31 KB

I just tried the patch and it failed out. I don't have to patch very often so it could definitely be user error. Nonetheless, the .rej file is attached.

TR’s picture

FileSize
1.05 KB

Here's a re-roll of the patch from #18 against the current 6.x-2.x-dev.

Status: Needs review » Needs work

The last submitted patch, 1167276-reroll.patch, failed testing.

TR’s picture

Version: 6.x-2.6 » 6.x-2.x-dev

Lets try against HEAD, where this belongs.

TR’s picture

Status: Needs work » Needs review
TR’s picture

#27: 1167276-reroll.patch queued for re-testing.

TR’s picture

So the testbot likes the new patch, but that's only the first step. Now I need to know:
1) Does it fix the problem with Pressflow? Should be checked for both anonymous and authenticated cart blocks.
2) Does a non-Pressflow site still work properly with this patch? Again, should be checked for anonymous and authenticated.

Poieo’s picture

I can confirm this is working with Pressflow for anon and auth users.

I don't have a non-pressflow site to test with.

Stealth’s picture

#27: 1167276-reroll.patch queued for re-testing.

TR’s picture

Category: support » feature
lliss’s picture

I have tested this both on pressflow and on a fresh install of drupal 6.28. The pressflow version allows the cart to display with the number of items in the cart with caching enabled. The standard installation works exactly as it does without the patch. So I think it is safe to move forward with integrating this into the next release.

mrP’s picture

Status: Needs review » Reviewed & tested by the community

+1 RTBC

longwave’s picture

Status: Reviewed & tested by the community » Fixed

Committed #27.

Status: Fixed » Closed (fixed)

Automatically closed -- issue fixed for 2 weeks with no activity.