Support » Plugin: User Role Editor » improper usage of switch_to_blog

  • Yesterday we downloaded and installed URE into our WP multisite system. Within 24 hours we found some odd behavior. Our media urls changed. If disabled URE, the media urls were back to normal. There could have been other problems, but we have not re-enabled URE on our production system.

    Through debugging I found the problem. In the code it uses switch_to_blog() to the main site, later uses switch_to_blog() to go back to the current site. This is not correct! You should be using restore_current_blog() to go back to the current site. I found this method of switching in multiple sections in the code. IMO, this is a (simple) bug and should be fixed.

    http://codex.wordpress.org/Function_Reference/switch_to_blog

    http://wordpress.org/plugins/user-role-editor/

Viewing 5 replies - 1 through 5 (of 5 total)
  • Thread Starter jkhongusc

    (@jkhongusc)

    I am not sure if “improper” is the right word of the switch_to_blog() use in URE. But apparently not all things are switched correctly when returning to the original blog site.

    Plugin Author Vladimir Garagulya

    (@shinephp)

    Thanks for the information.

    At the end of the referenced Codex page you may find this code for multiple switching case:

    $original_blog_id = get_current_blog_id();
    foreach( $blog_ids as $blog_id ){
        switch_to_blog( $blog_id );
        //Do something
    }
    switch_to_blog( $original_blog_id );

    So, we see from here, that usage of switch_to_blog() for return to the original blog is quite correct, that is “proper” solution.

    The reason of the problem could be some other plugin which does not like blog switching…
    I ask you to try reproduce the problem at the test environment and share the details. I will try to find the solution then.

    Thread Starter jkhongusc

    (@jkhongusc)

    Vladmir –
    Thanks for responding. But wow, it took me a few hours to figure out why your code wasnt working properly for us – with URE enabled our media urls were wrong. It turns out that the codex code you referenced above is wrong! This is the right way:

    foreach( $blog_ids as $blog_id ){
        switch_to_blog( $blog_id );
        //Do stuff
        restore_current_blog_id();
     }

    I tell you why. You need to view the switch_to_blog() and restore_current_blog() code:
    http://wpseek.com/switch_to_blog/
    http://wpseek.com/restore_current_blog/

    You will see both functions push and pop blog information into $GLOBALS[‘_wp_switched_stack’]. The problem is if you keep pushing data using switch_to_blog, but never clear it doing a restore_current_blog every time, it never empties. WP internally notes when it is switched using this function ms_is_switched:
    http://wpseek.com/ms_is_switched/

    And finally the ms_is_switched affects wp_upload_dir():
    http://wpseek.com/wp_upload_dir/

    up_upload_dir thinks WP is switched and returns us the wrong media url.

    LOL, long explanation and I hope you understand. In short, everytime you do a switch_to_blog() you need to do a restore_current_blog() to clear the globals.

    Plugin Author Vladimir Garagulya

    (@shinephp)

    Hi jkhongusc,

    Thank you for this useful details. Of course I should take this into account, with little amendment though. If you do not need restore environment in the cycle to every previous blog, it is enough to clear globals only

    array_pop( $GLOBALS['_wp_switched_stack'] );
    $GLOBALS['switched'] = ! empty( $GLOBALS['_wp_switched_stack'] );

    without the rest overhead from restore_curren_blog_id(). It will work much quicker.
    I will add this code to the next version definitely.

    Thread Starter jkhongusc

    (@jkhongusc)

    Vladmir –
    Actually you have to be careful. Using switch_to_blog() affects multiple global variables, so just pop’ing $GLOBALS[‘_wp_switched_stack’] may not be enough; it depends on what APIs are called afterwards. You can read the details here – http://wordpress.stackexchange.com/questions/124064/restore-current-blog-vs-multiple-switch-to-blog-followed-by-removing-globa/124110#124110

    As I was debugging this URE problem, I found that I only had to fix one location of switch_to_blog() in URE, user-role-editor/includes/class-ure-lib.php There might be other places that need to be fixed, but I havent found anymore. init_options() had to be fixed because when URE is enabled, that function is called. init_options() does a switch_to_blog() which disrupts the WP global variables; and it definitely requires a restore_current_blog() here.

    protected function init_options($options_id) {
    
            global $wpdb;
    
            $current_blog = $wpdb->blogid;
            if ($this->multisite && $current_blog!=$this->main_blog_id) {
                switch_to_blog($this->main_blog_id);  // in order to get URE options from the main blog
            }
    
            $this->options_id = $options_id;
            $this->options = get_option($options_id);
    
            if ($this->multisite && $current_blog!=$this->main_blog_id) {
                // return back to the current blog
    -            switch_to_blog($current_blog); // remove this line
    +            restore_current_blog(); // add this line
            }
        }

Viewing 5 replies - 1 through 5 (of 5 total)
  • The topic ‘improper usage of switch_to_blog’ is closed to new replies.