Im Block-Editor können wiederverwendbare Blöcke erstellt werden. Diese Blöcke lassen sich dann wie Core- und Plugin-Blöcke normal einfügen. Sobald eine Instanz dieses Blocks bearbeitet wird, wird überall diese aktualisierte Version ausgespielt.

Ein nützlicher Anwendungsfall für diese wiederverwendbaren Blöcke ist beispielsweise die Darstellung von Team-Mitgliedern, wenn einzelne davon auch auf anderen Seiten als Ansprechpartnerinnen und Ansprechpartner angezeigt werden sollen. Hier zeige ich, wie sich diese Blöcke zwischen mehreren Sites einer Multisite synchronisieren lassen, um über das gesamte Netzwerk hinweg immer den aktuellen Stand anzuzeigen.

Vorüberlegung

Wiederverwendbare Blöcke werden im Hintergrund als Post-Type gespeichert. Diese Posts wollen wir zwischen verschiedenen Sites einer Multisite synchronisieren und aktualisieren, sobald einer der Blöcke auf irgendeiner der Sites verändert wird. Wir brauchen also eine Action in dem Moment, wenn ein Block veröffentlicht oder aktualisiert wird.

Dafür bietet sich die dynamische Action {$new_status}_{$post->post_type} an, die als publish_wp_block immer abgefeuert wird, wenn ein neuer Post vom Typ wp_block veröffentlicht oder ein bestehender aktualisiert wird.

Um bestehende Blöcke über die Sites hinweg aktualisieren zu können, werden wir beim initialen Erstellen eine ID als Meta-Wert speichern, um die Blöcke der unterschiedlichen Sites einander zuordnen zu können.

Der Code

Zunächst hier der komplette Code:

/**
 * Sync the reusable blocks between the sites of the multisite.
 * 
 * @param int $post_id The post id.
 * @param WP_Post $post The post object.
 */
add_action( 'publish_wp_block', 'slug_sync_reusable_blocks', 10, 2  );
function slug_sync_reusable_blocks( $post_id, $post ) {
	// Check if the post already has a sync_hash or create one.
	if ( get_post_meta( $post_id, 'sync_hash', true ) !== '' ) {
		$sync_hash = get_post_meta( $post_id, 'sync_hash', true );
	} else {
		$sync_hash = uniqid( $post->post_title );
		update_post_meta( $post_id, 'sync_hash', $sync_hash );
	}
	$current_site_id = get_current_blog_id();
	
	// Get the site IDs.
	$sites = get_sites(
		[
			'fields' => 'ids',
		]
	);
	
	remove_action( 'publish_wp_block', 'slug_sync_reusable_blocks', 10 );
	foreach ( $sites as $site_id ) {
		if ( $current_site_id !== $site_id ) {
			switch_to_blog( $site_id );
			// Check if we already synced the block and only need to update it.
			$existing_block_query = new WP_Query(
				[
					'post_type' => 'wp_block',
					'no_found_rows' => true,
					'update_post_meta_cache' => false,
					'update_post_term_cache' => false,
					'fields' => 'ids',
					'meta_key' => 'sync_hash',
					'meta_value' => $sync_hash,
					'posts_per_page' => 1,
				]
			);
			
			if ( $existing_block_query->have_posts() ) {
				// Update the post.
				$existing_post_id = $existing_block_query->posts[0];
				wp_update_post(
					[
						'ID' => $existing_block_query->posts[0],
						'post_content' => $post->post_content,
						'post_title' => $post->post_title,
						'post_status' => 'publish',
					]
				);
			} else {
				// Create the post if we do not have the block already.
				wp_insert_post(
					[
						'post_type' => 'wp_block',
						'post_content' => $post->post_content,
						'post_title' => $post->post_title,
						'post_status' => 'publish',
						'meta_input' =>
						[
							'sync_hash' => $sync_hash,
						],
					]
				);
			}
			restore_current_blog();
		}
	}
	add_action( 'publish_wp_block', 'slug_sync_reusable_blocks', 10, 2  ); 
}
Code-Sprache: PHP (php)

In Zeile 7 hängen wir unsere Funktion slug_sync_reusable_blocks an den publish_wp_block-Hook an. Im Anschluss kommt die Funktion, die als Parameter die Post-ID sowie das Post-Objekt erhält.

Innerhalb der Funktion prüfen wir zunächst, ob der Beitrag bereits einen Wert für den Meta-Eintrag sync_hash hat. Falls ja, weisen wir der Variablen $sync_hash diesen Wert zu, andernfalls erstellen wir eine eindeutige ID mit dem Beitragstitel als Präfix und speichern sie als Meta-Wert.

Nun holen wir für einen späteren Abgleich die ID der aktuellen Site und ermitteln die IDs aller Sites der Multisite. Danach müssen wir unsere in Zeile 7 angelegte Action entfernen, um beim Anlegen oder Aktualisieren von Blöcken keine Dauerschleife aus Funktionsaufrufen zu erzeugen, und durchlaufen danach das Site-ID-Array.

Folgende Schritte werden in der Schleife ausgeführt:

  1. Wir prüfen, ob die gerade durchlaufene ID mit $current_site_id übereinstimmt, also die ID der Site ist, auf der der wiederverwendbare Block angelegt oder aktualisiert wurde.
    1. Falls ja, wird für die Site keine Aktion ausgeführt und wir beginnen wieder bei 1.
    2. Falls es nicht dieselbe Site ist, wechseln wir mit switch_to_block( $site_id ); zu der Site.
  2. Wir prüfen, ob bereits ein Block mit dem Sync-Hash existiert.
    1. Falls ja, aktualisieren wir den Beitrag mit wp_update_post().
    2. Falls noch kein entsprechender Block existiert, legen wir über wp_insert_post() einen an.
  3. Wir stellen die Site wieder her, von der die Funktion ursprünglich aufgerufen wurde.

Nach der Schleife wird unsere Funktion wieder an den Action-Hook angehängt.

Damit stehen uns jetzt auf allen Sites neu angelegte wiederverwendbare Blöcke immer im aktuellsten Zustand zur Verfügung.