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.
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.
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.
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.
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
}
}