WSOD when viewing an orders details - logs show an error of undefined function uc_price on line 1437 of uc_order.module

rc6 and below uc_order_get_total() didn't use uc_price() to sum the order total.
rc7 reworked uc_order_get_total() to sum cart prices using the price alterer and uc_price.

The strange thing is at first glance this simply should be an issue because uc_store_init() includes uc_price.inc - hook_init() by defenition happens before most other processing.

I can't replicate this problem on a fresh drupal/ubercart install. However a number of our existing sites are generating this error. Even stranger is that for these existing site's modifying uc_store's weight in the system table to be -1 gets rid of the error. These sites are in a multisite install, some with differing versions/locations for ubercart.

Solved for the moment with this at the start of uc_order_get_total()

require_once(drupal_get_path('module', 'uc_store') . '/includes/uc_price.inc');

However this really isn't solving the issue long term.

Does uc_store module need a weight of -1?

CommentFileSizeAuthor
#21 587572_uc_price.patch1.22 KBlongwave
Support from Acquia helps fund testing for Drupal Acquia logo

Comments

domesticat’s picture

One of my users is reporting something similar enough that I think it belongs here. Her email to me after we upgraded to rc7 this morning:

I was trying to manually add an order through the store admin and I received the error below. The regular ordering seems fine b/c I decided to enter in the order directly through the store and it worked.

Fatal error: Call to undefined function uc_price() in /var/www/sites/all/modules/ubercart/uc_order/uc_order.module on line 1437

xecstasyx’s picture

i have the same issue here on two of my webs, i cant even see orders as admin. and im getting the same code
Fatal error: Call to undefined function uc_price() in /var/www/web/sites/all/modules/ubercart/uc_order/uc_order.module on line 1437

torgosPizza’s picture

Fenstrat and others, I've found that if you set uc_store (in the "system" database table) to have a weight of -1 (or in my case, -10) it will work. The issue is that uc_store is being loaded after the other modules which require uc_price. I've mentioned this to Lyle (Island Usurper) and he's aware of the issue, but it's more of a Drupal issue than anything. See my comments here: http://www.ubercart.org/issue/10820/call_undefined_function_uc_price_uc_...

xecstasyx’s picture

yay you're right, if you set weight to -1 it works, thanks a lot!

Island Usurper’s picture

While setting uc_store's module weight does make the error go away, I feel like it's only masking the real problem. I've just looked at all of the hook_init()s in Ubercart, and none of them look like they are using functions they shouldn't. As further evidence, I have no problems when creating an order in the admin.

I suspect there is some contrib module that's doing something that used to work in hook_init().

torgosPizza’s picture

Yeah, and my guess there are probably several Contrib modules that can lead to this. Soon as I can I'll set the weight back to 0, see if I can reproduce the error, and then start disabling contribs until I get it to stop.

BenK’s picture

Hey everyone,

I'm getting the same error, but I think I know the module causing the problem in my setup.... the Secure Pages module. I'm currently running Secure Pages 6.x-1.7-beta2, so I'm not sure if upgrading to a later version would fix this.

The reason I know this is that I didn't experience the error on my test server at all. The only difference between my test server and my production server is that Secure Pages is turned off on my test server. I also confirmed on my production server that turning off Secure Pages caused the problem to go away (and for the order details page to be visible).

Any ideas on what could be causing the problem in the Secure Pages module? For those with the issue, what version of Secure Pages are you running?

--Ben

BenK’s picture

I've confirmed that Secure Pages module was the culprit for me. Upgrading to the latest dev version of Secure Pages solved the issue.

Hope this helps,
Ben

torgosPizza’s picture

Interesting! I had disabled SP but not uninstalled it. I'll reset my module weights and see if this has an effect on my install.

domesticat’s picture

Unfortunately, I'm not running Secure Pages on the install that has the problem. So something's getting fixed, but not everything.

torgosPizza’s picture

Yeah it's probably another module that does something in hook_init(), at least, based on my reading here - that'd be my guess. One way to see would be to check out the admin/settings/performance page. I think the modules listed as "not compatible with aggressive mode" use hook_init to do some kind of pre-processing. Enabling/disabling those modules one by one should yield a good result.

domesticat’s picture

@torgosPizza: I will be of limited help here. Our error was on a production site, and we had to downgrade to rc6 immediately because the bug killed a critical function for us.

However, I did check admin/settings/performance. The following modules are listed: ldapauth, notifications, og, persistent_login, statistics, uc_cart, uc_store

LightFromArt’s picture

Thank you very much, fenstrat for posting a solution:
require_once(drupal_get_path('module', 'uc_store') . '/includes/uc_price.inc');
in the beginning of uc_order_get_total() in uc_order.module.
It worked for me.
You made my day! Because none of other recommendation including setting weight to -1 or even -10 worked for me. Have a great day.

fenstrat’s picture

Ok, I've had a moment to spend with this one.

hook_init() in other modules does appear to be the culprit, specifically menu_breadcrumb (although it looks like globalredirect could be affected as well).

Disabling menu_breadcrumb fixes the error on my sites.

menu_breadcrumb_init() call's menu_get_item() (in both 1.1 and 1.x-dev) and that's where things go pear shape. Very interesting is a code comment in globalredirect_init()
"Use of menu_get_item should be optional as it appears in some situations it causes WSOD's..."

No more time to trace this further, but for others with affected sites does disabling menu_breadcrumb and/or globalredirect solve this undefined uc_price issue?

DrupalYedi’s picture

#14 disable menu_breadcrump works for me too.

longwave’s picture

I'm running into the same issue, but in my case the culprit is Organic Groups. The call stack is as follows:

og_init()
og_determine_context()
menu_get_item()
_menu_translate()
_menu_load_objects()
uc_order_load()
uc_order_load_line_items()
uc_line_item_subtotal()
uc_order_get_total()

I am not that well versed in Organic Groups but it seems like that code can't be moved anywhere else, as it's possible for OG to change the current site theme and language at that point depending on the group context, and any other hook would probably be too late to do this.

Changing the weight of uc_store in the system table to -1 fixed this problem, as discussed above I guess this will be necessary for Ubercart to work with any other module that calls menu_get_item() in hook_init(). As uc_store_init() only includes three files, adds a stylesheet and sets i18n variables, I can't see this change really causing any issues with any other modules.

longwave’s picture

In fact the OG code needs to use a workaround in og_is_group_member() where it needs to reload the global $user object if og_init() has not yet been called:

    global $user;
    // Adventurous modules can cause us to arrive here before og_init() has fired.
    // See http://drupal.org/node/285696
    if (!isset($user->og_groups)) {
      $user = user_load(array('uid' => $user->uid));  
    }

Ironically moshe mentions the exact problem in http://drupal.org/node/285696#comment-1018711:

The problem is globalredirect module. It is doing a menu_get_item() during hook_init() which is wreaking some havoc. I could fix this particular problem in OG but I'd rather see of GR could do things differently.

It looks like uc_order_load() will always be in the call stack as this issue is caused by to Drupal attempting to autoload any path data objects, so perhaps that could be responsible for loading uc_price.inc if the function is not yet defined?

Island Usurper’s picture

I'm kind of thinking of moving the require_once() call out of the uc_store_init() and putting it in the main part of the module file. All of the .module files are loaded before hook_init() is called, so uc_price would then be available whenever any module could use it.

The only thing that's really stopping me is that we can't use drupal_get_path() at that point, and I think there is some server (but not Apache) that does something unexpected with relative paths:

  require_once 'includes/uc_price.inc';

It might have something to do with PHP's include path setting as well.

longwave’s picture

Is this portable?

require_once(dirname(__FILE__) .'/includes/uc_price.inc');

Also while we're looking at this function, shouldn't the require_once calls inside uc_store_init() be replaced with module_load_include()?

fenstrat’s picture

+1 to moving out of uc_store_init to the top of uc_store.module as it looks like a sound solution. It's also used by filefield, imagefield, install_profile_api and jquery_ui (among others) in this exact context:

include_once dirname(__FILE__) . '/imagefield_file.inc';

So it'd become:

require_once dirname(__FILE__) .'/includes/uc_price.inc';

Is uc_price.inc the only one that needs to be moved or will summaries.inc and tapir.inc also neeed to be moved?

As longwave pointed out if either of them stay in hook_init() they should change to:

module_load_include('inc', 'uc_store', 'summaries');
module_load_include('inc', 'uc_store', 'tapir');
longwave’s picture

Status: Active » Needs review
FileSize
1.22 KB

Patch attached which solves my conflict with Organic Groups while keeping the weight of uc_store module as 0. The form summary and TAPIr includes shouldn't need to be moved in the same way as far as I can see.

There are a number of other uses of require_once in Ubercart which should be replaced with module_load_include() but that should be dealt with in a separate issue.

Island Usurper’s picture

Ah yes. I keep forgetting about the magic constants. I think it's interesting that content.module doesn't use this technique because cck starts with C, which means that its hook_init() comes before most other modules.

I don't think summaries or tapir need to move since those functions are only used on specific pages. uc_price() can be called on any page that needs to load an order apparently, so it needs to be loaded as early as possible.

Update: Oh, yay. A patch. Before you get to changing all of the require_once()s, I just want to point out that the reason we didn't use module_load_include() there is because it runs drupal_get_path() each time. Maybe it's just a bit of unnecessary optimization, as I don't really know how expensive drupal_get_path() is. I'll probably commit the patch the way it's written.

longwave’s picture

drupal_get_path() calls drupal_get_filename() which internally caches previous lookups, so there shouldn't be a performance hit.

kevinquillen’s picture

Everytime this error happens to me, it comes back to nodewords.

Island Usurper’s picture

Is there any reason you used include_once() instead of require_once()? I think it makes sense to use the second one because Ubercart won't work very well without uc_price() loaded into memory, and that's what module_load_include() itself uses.

longwave’s picture

require and include are identical, except require will fail with a fatal error if the file doesn't exist. As the file in question will be distributed with the module I don't really think it makes any difference.

Chad_Dupuis’s picture

Patch appears to work for me with no weighting changes....

Island Usurper’s picture

Status: Needs review » Fixed

I think require is better in this case, because I'm absolutely certain that it'll fail for someone at some point. I'd rather the error message they get it is "could not load includes/uc_price.inc" instead of "uc_price() is undefined". The first one makes it easier to realize what the problem is and points to an obvious solution.

Committed with that change.

fenstrat’s picture

Agree with your reasoning Lyle.

Created a follow up: #599572: Standardise use of require_once()

mikeytown2’s picture

Status: Fixed » Closed (fixed)

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

freatida’s picture

Im getting this error (uc_price is undefined in uc_order_get_total()) using Ubercart 6x2.2, when I try to view an order. Disabling menu breadcrumb makes it go away. Was the patch committed supposed to fix this?

freatida’s picture

I also get this error when using custom breadcrumb module
Is there a fix for this problem?

freatida’s picture

Status: Closed (fixed) » Active

Reopening this because didn't get a reply and it's still a problem for me. Is this fixed for others?

TR’s picture

Status: Active » Closed (fixed)

Well, it didn't get a reply because you commented on a closed issue. No one looks at closed issues, so no one noticed your comments. Regardless, opening an old, fixed issue is not the way handle this. Please search for uc_price in this issue queue and read all the old issues first, then if none of them solve your problem open a new support request. If this is anything like the conflict with nodewords, the custom breadcrumb module is probably the thing that needs to be patched.

freatida’s picture

I reopened because I'm still having the issue described here. If I posted a new issue, wouldn't that just be a duplicate?
I asked in my last post whether anyone is still having the issue because it is marked as fixed, but isn't fixed for me. Sorry if you think I've done something wrong. I don't want to re-open and annoy you further, but I would appreciate knowing if the issue is supposed to be fixed (as #30 asks). That would help me sort out my problem.
Thanks.

Chad_Dupuis’s picture

The fix as I noted above (http://drupal.org/node/587572#comment-2128264) worked for me. I also use custom breadcrumbs on my site and everything works fine - although I don't use them in the store as the breadcrumbs that are there for the catalog serve my needs.