Freigeben dynamischer Seitenleisten in Blogs mit mehreren Standorten

8

Ich versuche herauszufinden, ob ich eine dynamische Seitenleiste aus einem Blog abrufen und in einem anderen Blog in derselben Installation von Wordpress Multisite drucken kann. Ich habe versucht

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

Es wird aber nichts zurückgegeben.

Ich war es auch leid, die Seitenleiste abzurufen, get_blog_option($blog_id, 'sidebar_widgets')aber ich konnte nur ein Array abrufen, um festzustellen, welche Widgets von der Seitenleiste verwendet wurden, aber ich konnte nicht herausfinden, wie ich das Array in eine Seitenleiste verarbeiten konnte.

Timothy Wallis
quelle

Antworten:

7

Leider wird die switch_to_blog()Methode für diesen Zweck nicht funktionieren. switch_to_blog()ist wirklich nur ein Teilwechsel - es werden einige Änderungen an $wpdbdieser Hilfe bei Datenbankabfragen vorgenommen. Aber es ist kein vollständiger Wechsel, wie Sie es sich vorstellen können.

Hängt insbesondere dynamic_sidebar()von global aufgerufen ab $wp_registered_sidebars. Diese globale wird von gefüllt register_sidebar(), die im Allgemeinen aus einer Themendatei wie functions.php aufgerufen wird. Aber functions.php und der Rest des Theme-Setup-Prozesses werden von nicht erneut ausgeführt switch_to_blog(). Das heißt: Wenn Sie Twenty Eleven im aktuellen Blog ausführen, werden beim Start eigene Seitenleisten registriert. Wenn Sie switch_to_blog()ein Blog verwenden, in dem Twenty Ten ausgeführt wird , wird Twenty Ten nicht angewiesen , seine Seitenleisten einzurichten . Sie könnten versuchen, es zu erzwingen (indem Sie die Datei functions.php des Switched-Blogs manuell laden), aber dies führt mit ziemlicher Sicherheit zu einer Katastrophe, da Probleme mit doppelten Funktionsnamen, Ladereihenfolge usw. usw. auftreten.

Sie könnten einen etwas anderen Ansatz ausprobieren: Erstellen Sie im Blog mit der gewünschten Seitenleiste eine Funktion, mit der der Inhalt der Seitenleiste in den Ausgabepuffer gedruckt wird, und speichern Sie ihn vor dem Drucken auf dem Bildschirm in einer site_option. Dann können Sie die Seitenleiste (oder zumindest eine statische Version davon) von jedem Standort im Netzwerk abrufen. Dies funktioniert nicht, wenn Sie unbedingt eine vollständig dynamische Seitenleiste benötigen , für die meisten Zwecke jedoch wahrscheinlich nicht.

Eine andere Methode (die möglicherweise einfacher ist) besteht darin, die Seitenleiste mit einer Funktion in einer Mu-Plugins-Datei oder ähnlichem zu rendern und die Funktion dann manuell in Ihren Designs aufzurufen (oder sie an einen allgemeinen Seitenleisten-Hook anzuhängen). Es könnte einige Arbeit erfordern, um den Inhalt aus der WP_WidgetArchitektur zu abstrahieren , aber andererseits wäre es eine wirklich dynamische Lösung für das vorliegende Problem.

Boone Gorges
quelle
Dank dieser beiden anderen Methoden klingen die Ideen großartig. Ich habe bereits darüber nachgedacht, die erste zu versuchen, aber könnten Sie die zweite Idee ein wenig ausarbeiten? Ich glaube, ich habe versucht, so etwas zu tun, indem get_blog_option('1','sidebars_widgets');ich eine Liste von Widgets abgerufen habe, aber ich konnte sowieso keine finden, um die Daten in einer Seitenleiste zu verarbeiten.
Timothy Wallis
Ich denke, es wird mehr Ärger geben, als es sich lohnt, an der tatsächlichen Widget-Infrastruktur von WP festzuhalten. Abstrahieren Sie stattdessen das Widget-Markup / PHP in eine separate Funktion, die Sie dann direkt in einer Vorlagendatei aufrufen (oder mit einer geeigneten Aktion verknüpfen).
Boone Gorges
2

Bin auf das gleiche Problem gestoßen und habe eine Lösung gefunden. Was ich tue, ist das Folgende:

1.) Wenn in der Seitenleiste von Blog 1 etwas geändert wird, speichern Sie ein Array dieser Widgets und ihrer Einstellungen als vorübergehenden Übergang, der nach 24 Stunden veraltet ist.

2.) Fügen Sie in allen untergeordneten Blogs Code in sidebar.php ein, der diesen standortweiten Übergang erfasst und die Widgets anzeigt.

Klingt ziemlich einfach, war aber sehr schwer herauszufinden… und ist immer noch alles andere als perfekt.

Lassen Sie uns einen Code untersuchen:

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');

Dies gehört in die functions.php von Blog 1 (oder besser ein Plugin insgesamt) und speichert die Widgets alle 24 Stunden in dem maßgeschneiderten Transienten.

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 );

Dies gehört auch in die Datei functions.php von Blog 1 und erneuert den Übergang jedes Mal, wenn die Widgets aktualisiert werden.

Und schließlich für die anderen Blogs in 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();
}

Hoffe, das kann jemandem helfen. Wenn man Verbesserungen hat, sind sie sehr willkommen.

Christian Jung
quelle
1

Stellen Sie sicher, dass auf beiden Websites während widgets_init genau derselbe Registrierungscode für die Seitenleisten ausgeführt wird. Das sollte $ wp_registered_sidebars füllen und das von Boone hervorgehobene Problem lösen. Ich habe es selbst nicht versucht.

Kovshenin
quelle
0

Dieses "könnte" Sie in die richtige Richtung weisen.

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

Überprüfen Sie das Video - http://vimeo.com/52479425

Das Grundkonzept besteht darin, dass Sie beim Hinzufügen einer Seitenleiste zu einer Netzwerksite diese auch als globale Seitenleiste zuweisen können.

Shawn
quelle
Interessant, ich frage mich, wie er es macht. Wahrscheinlich hat widget_update_callback geändert, um zu überprüfen, ob es global ist, und dann eine Abfrage auszuführen, um es allen untergeordneten Blogs der aktuellen Site hinzuzufügen.
Timothy Wallis
-1

Sind Sie mit global $switched;?

global $switched;
switch_to_blog($blog_id);
dynamic_sidebar($sidebar_name);
restore_current_blog();
Entwicklung
quelle
Das $switchedGlobale wird von innen aufgerufen switch_to_blog(). Sie müssen es nicht im globalen Namespace deklarieren.
Boone Gorges
Gut zu wissen. Ich verwende eine veraltete WPMU-Methode. Sind es also nur Seitenleisten, auf die Sie nicht zugreifen können? Was ist mit Menüs?
Entwicklung
Ich müsste es testen, aber ich vermute, dass Menüs in einem switch_to_blog()Kontext funktionieren könnten , da sie vor dem Aufruf nicht vom Thema registriert werden müssen (die Registrierungsdaten werden in der Datenbank gespeichert).
Boone Gorges
Ich kann bestätigen, dass Menüs funktionieren. Sehen Sie, was das Ergebnis der Verwendung is_active_sidebar($sidebar_name)ist.
Entwicklung