A mí me funciona

El blog de Ignacio Cruz
gutenberg-logo

Bloques de Gutenberg sólo para un tipo de post concreto

22 mar. 2021
·
  • Gutenberg
  • What is code
·
  • bloques
  • JavaScript
  • php

Si queremos registrar un bloque en Gutenberg para un tipo de post dado, hay que saber que tenemos dos modos para hacerlo. El primero es con puro JavaScript y el segundo utilizando PHP. El problema es que el enfoque con PHP trata de excluir bloques mediante un whitelisting, con lo que tendríamos que pasar a Gutenberg todos los bloques que queremos utilizar, por ejemplo:

add_filter( 'allowed_block_types', function( $allowed_blocks ) {
	if ( get_post_type() !== 'news' ) {
		return $allowed_blocks;
	}

	return [
		'core/paragraph',
		'core/embed-youtube',
		'core/image',
		'my/custom-block', // Aquí el bloque que quiero para news
	];
} );

Si el tipo de post es news, entonces sólo permitimos añadir párrafos, vídeos de Youtube embebidos, imágenes y el bloque que quiero registrar exclusivamente para ese tipo de post. Si lo que buscamos es sólo registrar my/custom-block en news, esto no nos vale. El problema es que cuando WordPress está cargando Gutenberg en el servidor, los bloques todavía no están registrados ya que esto se realiza desde el propio navegador con JS por lo que habría que buscar una solución ajustada a esta situación.

…Peeeero

Malas noticias, con JS tampoco mejora mucho la cosa y la recomendación inicial es, de nuevo, un whitelisting como aquí:

wp.domReady( function() {
	const postType = wp.data.select( 'core/editor' ).getCurrentPostType();
	if ( postType !== 'news' ) {
		return;
	}

	wp.blocks.unregisterBlockType( 'my/custom-block' );
} );

Traducción: Cuando el DOM esté cargado, comprueba si el tipo de post es news y elimina del registro el bloque que yo quiera.

Pues bien: Esto tampoco es posible porque resulta que getCurrentPostType() devuelve null cuando el DOM ha cargado. Hay que esperar un poco más a que Gutenberg rellene todos los stores, en este caso tendríamos esperar a que core/editor esté listo para usarse pero como hemos visto, no lo está.

Varias soluciones

Hay muchos posts que recomiendan soluciones alternativas al blacklisting, como este, que me parece rizar el rizo demasiado, o usar una whitelist algo mejorada. Yo quiero proponer otra que no he visto en ningún sitio y que tampoco es que sea muy bonita pero sí algo más simple que las anteriores.

if ( get_post_type() === 'news' ) {
	$script = <<<JS
	wp.domReady( function() {
		wp.blocks.unregisterBlockType( 'my/custom-block' );
	} );
JS;

	wp_add_inline_script(
		'wp-blocks',
		$script,
		'after'
	);
}

Este método mezcla JS y PHP, y hace uso de la función wp_add_inline_script, que recordemos hace poco hablamos de ella, para insertar un script en el cuerpo del HTML que eliminará el bloque que queramos si el tipo de post coincide con news. Todo esto se ejecutará si el script wp-blocks del editor se ha cargado, de otra manera no será necesario.