• Resolved sj-xweb

    (@sj-xweb)


    Hi, we’re currently running the latest version of WP, Buddypress, BadgeOS, and BadgeOS Community.

    I noticed a weird bug: $blog_id gets messed up in a multisite installation in some scenarios. After tracing the issue I noticed that you’re polling for achievements in all the blogs(includes/user.php, line 389) by using switch_to_blog() in a loop, and then resetting to current blog by doing another switch_to_blog() after the loop.

    This apparently causes an issue with the latest version of Buddypress, because they added a new function bp_get_object_terms (buddypress/bp-core/bp-core-taxonomy.php, line 63) that gets called at some point. In that function, it calls restore_current_blog(), which sets the blog to before the last time switch_to_blog() was called. It it determines the last switch by looking at global variable $GLOBALS[‘_wp_switched_stack’], which just contains an array of all the previously switched blog ID’s, and popped off the last element.

    So in the case of site running BadgeOS, restore_current_blog() actually changes the current blog to the last polled blog.

    In our case, it causes issues with our custom template since WP/BP starts looking at the wrong directory for our custom template.

    I am not sure what the best solution is, but in our case by adding $GLOBALS[‘_wp_switched_stack’] = array(); after the last switch_to_blog() in badgeos_get_network_achievement_types_for_user() fixes the problem. However, that may not be the best solution because there might be legit reason why that switch stack should not be cleared out.

    Please let me know if you need me to clarify anything.

    https://wordpress.org/plugins/badgeos/

Viewing 6 replies - 1 through 6 (of 6 total)
  • Thread Starter sj-xweb

    (@sj-xweb)

    Or, to fix the issue, you can also just put the switch stack in a variable before polling, and then set it back afterwards, like how you’re doing with the blog id right now.

    Michael Beckwith

    (@tw2113)

    The BenchPresser

    Hi sj-xweb.

    Interesting findings, and I’m admittedly unsure exactly what the best solution is at the moment.

    From what I can see, we use badgeos_get_network_achievement_types_for_user one time in the Community Addon, and it’s for setting up members’ achievement tabs. It’s set to run regardless, but will only generate some parts of the menu if the specific achievement is set to be displayed. Thus no way to prevent it from running, as is.

    Could you try a test for me, and see if moving the switch_to_blog on the $cached_id inside the foreach loop helps at all. Essentially this will put the code back on the original site after each iteration.

    Not sure exactly what bp_get_object_terms() is used for at the moment, so I’d have to ask the BP core devs about it, or try to find its usage in the codebase. Hard to tell offhand how often it’s getting run within the context of our looping.

    Thread Starter sj-xweb

    (@sj-xweb)

    Hi Michael,

    Just tried, and that didn’t fix it. Further debugging showed that $GLOBALS[‘_wp_switched_stack’] has the following value before restore_current_blog() is called:

    Array (
    		[0] => 1
    		[1] => 1
    		[2] => 2
    		[3] => 1
    		[4] => 7
    		[5] => 1
    		[6] => 8
    		[7] => 1
    		[8] => 9
    	)

    restore_current_blog will then set the current blog to the blog ID in the last element.

    Michael Beckwith

    (@tw2113)

    The BenchPresser

    Not sure still then. The cached_id likely should be ID 1, and the final iteration over everything should put it back to 1. Are you generating this array while still in the loop? or directly after it? I don’t have the function open at the moment, but the last thing we do, as is, regarding site switching is switch back to $cached_id, which wouldn’t be part of that array.

    If you have a GitHub account, I’d appreciate as much detail as you can muster for this on our issue tracker https://github.com/opencredit/badgeos/issues

    Thread Starter sj-xweb

    (@sj-xweb)

    As far as I know, the $GLOBALS[‘_wp_switched_stack’] array is an internal WP variable that it uses to track all the blog switches done in a page lifecycle. You can see it being used in switch_to_blog() definition in ms-blogs.php.

    So every time switch_to_blog() is called, the old blog ID is appended to $GLOBALS[‘_wp_switched_stack’].

    Here’s a sequence of events of what happens:
    – BadgeOS stores current blogID into $cached_id (1)
    – Loop switch_to_blog() for all the blogs on the network
    – For every itereation, $GLOBALS[‘_wp_switched_stack’] is appended with the previous blogID
    – At the end of loop, last switch_to_blog() is called with $cached_id (1) as parameter. At this point, the last blogID (9) is appended to $GLOBALS[‘_wp_switched_stack’]
    – Buddypress runs its process, and calls restore_current_blog(), which changes the current blog to the last blog id (9) in the $GLOBALS[‘_wp_switched_stack’] array.

    I hope that clears it up a bit more.

    Michael Beckwith

    (@tw2113)

    The BenchPresser

    I saw the BuddyPress ticket show up and it’s already been patched in their trunk. Curious if trying out a trunk copy of BP with our stuff will solve the issues you were seeing. I think it’s probably best that BadgeOS look into reworking how we handle the network achievements fetching as well, just to be sure.

Viewing 6 replies - 1 through 6 (of 6 total)

The topic ‘Issue with switch_to_blog’ is closed to new replies.