8

I'm trying to find away to retrive a dynamic sidebar from one blog and print it on another blog in the same install of Wordpress Multisite. I have tried

switch_to_blog($blog_id);
dynamic_sidebar($sidebar_name);
restore_current_blog();

But nothing is returned.

I also tired to retrive the sidebar through get_blog_option($blog_id, 'sidebar_widgets') but I was only able to retrive an array identify what widgets were used by the sidebar, but I couldn't find away to process the array into a sidebar.

5 Answers 5

7

Unfortunately, the switch_to_blog() method isn't going to work for this purpose. switch_to_blog() is really only a partial switch - it makes some modifications to $wpdb that help with database queries. But it's not a complete switch in the way you might imagine.

In particular, dynamic_sidebar() depends on global called $wp_registered_sidebars. This global is populated by register_sidebar(), which is generally called from a theme file like functions.php. But functions.php, and the rest of the theme setup process, is not re-run by switch_to_blog(). That is to say: if you're running Twenty Eleven on the current blog, it'll register its own sidebars during startup; using switch_to_blog() to a blog running Twenty Ten will not tell Twenty Ten to set up its sidebars. You could try forcing it (by loading the switched-blog's functions.php manually) but this is almost certain to lead to disaster, due to issues with duplicate function names, load order, etc etc etc.

You might try a somewhat different tack: On the blog with the sidebar that you want, build a function that will print the contents of the sidebar into the output buffer, and then before printing it to the screen, stash it in a site_option. Then you can grab the sidebar (or a static version of it, at least) from any site on the network. This won't work if you absolutely need a totally dynamic sidebar, but for most purposes you probably don't.

Another method (which may be easier) is to render the sidebar with a function in an mu-plugins file or something like that, and then call the function manually in your themes (or hook it to a common sidebar hook). It might take some work to abstract the content out of the WP_Widget architecture, but on the other hand it would be a truly dynamic solution to the problem at hand.

2
  • Thanks those other two methods sound like great ideas, I was already thinking about try the first one, but could you flesh out the second Idea a bit. I think I was trying to do something like this by using get_blog_option('1','sidebars_widgets'); to get a list of widgets but I couldn't find anyway to process the data into a sidebar. Apr 20, 2012 at 19:39
  • I think it's going to be more trouble than it's worth to stick with WP's actual widget infrastructure. Instead, abstract the widget markup/PHP into a separate function, which you will then call directly in a template file (or hook to an appropriate action). Apr 20, 2012 at 20:00
2

Ran into the same problem and kind of figured out a solution. What i'm doing is the following:

1.) Whenever something is changed on blog 1's sidebar, save an array of those widgets and their settings as a sitewide transient, that outdates after 24 hours.

2.) On all child-blogs, put some code into sidebar.php that grabs this sitewide transient and displays the widgets.

Sounds pretty easy, but was very hard to figure out … and still is far from perfect.

Let's dig into some Code:

function antwortzeit_cache_widgets() {
    if ( false === ( $widgets = get_site_transient( 'antwortzeit_widgets' ) ) ) {
        global $wp_registered_sidebars, $wp_registered_widgets;

        foreach ( (array) $wp_registered_sidebars as $key => $value ) {
            if ( sanitize_title($value['name']) == sanitize_title('Breite Spalte') ) {
                $index = $key;
                break;
            }
        }

        $sidebars_widgets = wp_get_sidebars_widgets();
        if ( empty( $sidebars_widgets ) )
            return false;

        if ( empty($wp_registered_sidebars[$index]) || !array_key_exists($index, $sidebars_widgets) || !is_array($sidebars_widgets[$index]) || empty($sidebars_widgets[$index]) )
            return false;

        $sidebar = $wp_registered_sidebars[$index];
        foreach ( (array) $sidebars_widgets[$index] as $id ) {
            if ( !isset($wp_registered_widgets[$id]) ) continue;

            $params = array_merge(
                array( array_merge( $sidebar, array('widget_id' => $id, 'widget_name' => $wp_registered_widgets[$id]['name']) ) ),
                (array) $wp_registered_widgets[$id]['params']
            );

            // Substitute HTML id and class attributes into before_widget
            $classname_ = '';
            foreach ( (array) $wp_registered_widgets[$id]['classname'] as $cn ) {
                if ( is_string($cn) )
                    $classname_ .= '_' . $cn;
                elseif ( is_object($cn) )
                    $classname_ .= '_' . get_class($cn);
            }
            $classname_ = ltrim($classname_, '_');
            $params[0]['before_widget'] = sprintf($params[0]['before_widget'], $id, $classname_);

            $params = apply_filters( 'dynamic_sidebar_params', $params );

            $widgets[] = array(
                'callback'  => $wp_registered_widgets[$id]['callback'],
                'base'      => $wp_registered_widgets[$id]['callback'][0]->id_base,
                'id'        => $wp_registered_widgets[$id]['callback'][0]->id,
                'params'    => $params,
            );
        }
        set_site_transient( 'antwortzeit_widgets', $widgets, 60 * 60 * 24 );
    }
}
add_action( 'init', 'antwortzeit_cache_widgets');

This belongs into blog 1's functions.php (or better, a plugin alltogether) and saves the widgets into the bespoke transient every 24 hours.

function antwortzeit_widgetbruecke( $instance, $new_instance ) {
    delete_site_transient('antwortzeit_widgets');
    antwortzeit_cache_widgets();
    return $instance;
}
add_filter( 'widget_update_callback', 'antwortzeit_widgetbruecke', 10, 2 );

This also belongs into blog 1's functions.php and renews the transient every time the widgets are updated.

And finally for the other blogs drop into sidebar.php:

global $blog_id;

if($blog_id !== 1) {
switch_to_blog(1);
    $widgets = get_site_transient( 'antwortzeit_widgets' );
    if($widgets) :
        foreach($widgets as $widget) :
        if ( is_callable($widget['callback']) ) {
            call_user_func_array($widget['callback'], $widget['params']);
        }
        endforeach; 
    endif;
restore_current_blog();
}

Hope, this can help somebody out. If one has any improvements, they'll be very welcome.

1

Make sure you have the exact same sidebars registration code running on both sites during widgets_init. That should populate $wp_registered_sidebars and solve the problem that Boone highlighted. Haven't tried this myself.

0

This 'might' point you in the right direction.

Xtreme One - Theme Framework - http://marketpress.com/product/xtreme/

Check the video - http://vimeo.com/52479425

Basic concept is when adding a sidebar to a network site, you can also assign it as a global sidebar.

1
  • Interesting, I wonder how he is doing it. Probably modified widget_update_callback to check and see if its global and then executing a query to add it to all child blogs of the current site. May 25, 2012 at 19:44
-1

Are you using global $switched;?

global $switched;
switch_to_blog($blog_id);
dynamic_sidebar($sidebar_name);
restore_current_blog();
4
  • The $switched global is called from within switch_to_blog(). You don't need to declare it in the global namespace. Apr 6, 2012 at 17:58
  • Good to know. I'm using an outdated WPMU method. So is it just sidebars you're not able to access? What about menus? Apr 6, 2012 at 18:02
  • I would need to test it, but I'm guessing that menus might work in a switch_to_blog() context, because they don't need to be registered by the theme before being called (the registration data is stored in the database). Apr 6, 2012 at 19:41
  • I can confirm that menus work. See what the result of using is_active_sidebar($sidebar_name) is. Apr 6, 2012 at 19:46

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.