When og_init() reloads the global $user object, it wipes out $user properties from the sessions table that were initially set by sess_read() but are not set by user_load(). One missing $user property that is actually used (that I know of) is $user->cache. Without a $user->cache property, calling cache_get() results in PHP notice: Undefined property: stdClass::$cache in includes/cache.inc on line 42.

In this patch, I thought it would be a good idea to restore the other missing session properties as well: sid, hostname, timestamp, and session. It's a little ugly, maybe there's some nicer way to do this :)

CommentFileSizeAuthor
#11 og-load-subscriptions.patch1.25 KBmarcp
og-user-load.patch959 bytesmfb
Support from Acquia helps fund testing for Drupal Acquia logo

Comments

moshe weitzman’s picture

that strikes me as a bug in user_load(). or at least most uses that i have seen are $user = user_load(). perhaps user_load itself should retrieve these columns from sessions table. i'm not opposed to a fix like this for d6, but we need to decide what the right fix is for 7.

mfb’s picture

moshe weitzman’s picture

Does it make sense to actually get the properties form the DB. Thats kinda the point of doing a user_load() on the current user. It "refreshes" from storage.

mfb’s picture

Well, I'm not aware of a reason we need to reload from the sessions table. I do know that cache_clear_all() modifies $user->cache without writing to the sessions table. That doesn't happen until drupal_session_commit() in drupal_page_footer(). By reloading from the sessions table you might lose a modified $user->cache?

moshe weitzman’s picture

Well, maybe I am making a moot point. This is a good patch, AFAICT. Needs to go into D7 first though, no?

marcp’s picture

Maybe it's time for Drupal's bootstrapping code to just load up the global $user object (see #46551: problem with call to hook_user in custom module which was rejected long ago).

Since that's not going to happen, though, doesn't it make sense for contrib modules to just never load up the global $user object in hook_init()?

Since og_user('load', ...) just fills up $user->og_groups, can't you just do that same thing in og_init() instead of doing the full user_load() which winds up calling every module's hook_user() at init time? Seems a lot safer, and then when the user gets reloaded, you'll still end up going through og_user('load', ...) again.

moshe weitzman’s picture

Sure, og could fix the problem but it is simply a bug that user_load() is dangerous for the current user.

mfb’s picture

Well really replacing global $user is the dangerous part :) If it's ok to just add the og bits onto the original $user that seems best for now (I wasn't sure if some contrib module needed og to run the full user_load() or something..)

marcp’s picture

Replacing the global $user is definitely the dangerous part -- hopefully someday we won't be seeing global $user; littered throughout core and contrib.

In the meantime, OG probably should fix itself (or we can provide patches) knowing that core is flawed in this way.

@mfb - have you tried to add those bits into the original $user yet?

moshe weitzman’s picture

Status: Needs review » Fixed

Committed a fix. Can you guys look at http://cvs.drupal.org/viewvc.py/drupal/contributions/modules/og/og.modul... and confirm that this fixes any issues. Thanks.

marcp’s picture

Status: Fixed » Needs review
FileSize
1.25 KB

Moshe - Attached is a patch that does what I was thinking. It has the same effect as what you committed, but it is more future-proof in case hook_user() goes away and it helps nudge OG a little more towards providing an API.

Note that I haven't tested your fix or this one. This smacks for a simpletest.

moshe weitzman’s picture

Status: Needs review » Fixed

Thanks marcp. I actually prefer to call og_user(load) since we might add new bits one day that happen when loading a user.

marcp’s picture

Yeah, it's 6 of one half a dozen of the other.

I'd still prefer to pull out a separate og_load_user() and do everything (which is just 1 line for now) in there, leaving the 'load' part of hook_user() as a 1-line call to og_load_user(). Then, if we need to add new bits when loading a user, if there's specific code that should only happen in hook_user() the code would go in hook_user(). Any code that should always run when loading a new user would go in the generic load function.

The direct call to og_user() with the empty array() parameter just seems like it's going to come back to cause us (okay, you) an extra half hour of porting time when hook_user()'s footprint changes someday.

No big whoop either way -- just a nit that I've got with calling hook functions directly.

Move along!

Status: Fixed » Closed (fixed)

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