Veröffentlicht am Schreib einen Kommentar

Gutenberg: Wiederverwendbare Blöcke und has_block()

Nutzt man wiederverwendbare Blöcke und möchte mit has_block() prüfen, ob ein bestimmter Block innerhalb eines Beitrags verwendet wird, so werden die Inhalte wiederverwendbare Blöcke dabei ignoriert. Dadurch kann es hierbei zu „false negatives“ führen, also falsch-negative Erkennungen.

Hintergrund ist, dass has_block(), das übrigens im WordPress Core mitgeliefert wird, den Quellcode des Beitrags verarbeitet. Soweit, so gut. Wiederverwendbare Blöcke sind innerhalb eines Beitrags jedoch nur eine Referenz auf einen ganzen Beitrag eines individuellen Inhaltstyps (wp_block) und sieht dabei beispielsweise folgendermaßen im Quellcode aus:

<!-- wp:block {"ref":1337} /-->

Dadurch erkennt has_block() hier nur einen Block mit dem generischen Typ block, aber nicht den eigentlichen Inhalt des wiederverwendbaren Blocks. Um dies anzupassen, sodass auch Inhalte der wiederverwendbaren Blöcke überprüft werden, muss man die Blöcke eines Beitrags zuerst selbst parsen, wiederverwendbare Blöcke innerhalb des Beitrags erkennen und über diese die Funktion has_block() laufen lassen.

Auf GitHub konnte ich dafür einen entsprechenden Issue finden und auch einen Workaround in Form einer eigenen Funktion, die genau das tut. Diese habe ich für mich noch etwas angepasst, sodass sie nun so aussieht:

/**
 * Check if a block is inside a post, even if it's a reusable one.
 * 
 * @param	string	$block_name Full Block type to look for
 * @param	bool	$id The post ID to look for
 * @return	bool True if the post contains this block, false otherwise
 */
function my_has_block( $block_name, $id = false ) {
	$id = ( $id ?: get_the_ID() );
	
	if ( has_block( $block_name, $id ) ) {
		return true;
	}
	
	if ( ! $id ) {
		return false;
	}
	
	// check reusable blocks
	if ( has_block( 'block', $id ) ) {
		$content = get_post_field( 'post_content', $id );
		$blocks = parse_blocks( $content );

		if ( ! is_array( $blocks ) || empty( $blocks ) ) {
			return false;
		}
		
		foreach ( $blocks as $block ) {
			if ( ! empty( $block['attrs']['ref'] ) && has_block( $block_name, $block['attrs']['ref'] ) ) {
				return true;
			}
		
			if ( ! empty( $block['innerBlocks'] ) ) {
				foreach ( $block['innerBlocks'] as $inner_block ) {
					if ( ! empty( $inner_block['attrs']['ref'] ) && has_block( $block_name, $inner_block['attrs']['ref'] ) ) {
						return true;
					}
				}
			}
		}
	}
	
	return false;
}

Dabei kann er genau so verwendet werden, wie has_block() auch, also in dem Fall beispielsweise so:
my_has_block( 'audio' )

Hinweis: Diese Funktion findet so keinen wiederverwendbaren Block innerhalb eines anderen wiederverwendbaren Blocks.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.