Как отключить отдельные Гутенберг блоки в WordPress

WordPress из коробки предоставляет огромный набор блоков, некоторые из которых вам могут быть просто не нужны на сайте. Чтобы они не мешались при создании и редактировании постов, отдельные блоки можно отключить.

Деактивировать блоки можно разными способами с помощью PHP, JavaScript или через настройки пользователя. Выбор зависит от конкретной задачи. Например, использование JavaScript для ограничения блоков может быть удобным, если вы уже используете его для других задач. С другой стороны, PHP предлагает решение на стороне сервера, которое легко добавить к существующим плагинам и темам.

Ниже рассмотрим все возможные варианты удалить конкретные блоки из редактора блоков Гутенберг.

Отключение блоков для текущего пользователя (настройки)

Вы можете скрыть определенные блоки, используя панель настроек редактора.

Для этого в редакторе или редакторе сайта:

  • Щелкните на меню опций в правом верхнем углу экрана (три вертикальные точки).
  • Выберите пункт "Настройки".
  • Во всплывающем окне перейдите в раздел "Блоки".
  • Отметьте те, которые хотите скрыть (в списке зарегистрированных блоков).

Эти настройки сохраняются для пользователя, т.е. блоки не удаляются, а просто скрываются для вашего пользователя и при этом будут доступны остальным пользователям.

Отключение блоков через PHP

Для этого будем использовать хук allowed_block_types_all. Коллбэк хука принимает два параметра:

  • $allowed_block_types – Массив слагов типов блоков или логическое значение для включения или отключения всех блоков.
  • $block_editor_context – Текущий контекст редактора блоков.

Важно отметить, что при использовании этого хука любые паттерны блоков (block patterns), составленные из отключенных блоков, также станут недоступными для пользователя.

Важно! Чтобы блок можно было отключить через PHP, он должен регистрироваться также через PHP (а не через js). Поэтому рекомендуется регистрировать блоки через файл block.json или функцию register_block_type().

Белый список (разрешенные блоки)

Простой пример, который позволит пользователям вставлять только блоки Заголовок, Список, Изображение и Параграф. Это можно рассматривать как "список разрешенных блоков".

Чтобы протестировать следующий код, добавьте его в файл functions.php темы или включите его в плагин.

// Удаление всех блоков кроме указанных
add_filter( 'allowed_block_types_all', 'example_allowed_block_types', 10, 2 );

/**
 * @param array|bool $allowed_block_types Array of block type slugs, or boolean to enable/disable all.
 * @param object     $block_editor_context The current block editor context.
 *
 * @return array The array of allowed block types.
 */
function example_allowed_block_types( $allowed_block_types, $block_editor_context ) {

	$allowed_block_types = array(
		'core/heading',     // Heading block
		'core/image',       // Image block
		'core/list',        // List block
		'core/paragraph',   // Paragraph block
	);

	return $allowed_block_types;
}

Использование условий

Давайте сделаем этот пример немного более реалистичным.

Когда нужно ограничить авторов доступом только к определенным блокам, но предоставить редакторам и администраторам доступ ко всем. Для этого вы можете использовать функцию current_user_can():

// Удаление всех блоков кроме указанных
add_filter( 'allowed_block_types_all', 'example_allowed_block_types', 10, 2 );

/**
 * @param array|bool $allowed_block_types Array of block type slugs, or boolean to enable/disable all.
 * @param object     $block_editor_context The current block editor context.
 *
 * @return array The array of allowed block types.
 */
function example_allowed_block_types( $allowed_block_types, $block_editor_context ) {

	// Если у текущего пользователя нет нужных прав, ограничьте блокировку.
	if ( ! current_user_can( 'publish_pages' ) ) {
		$allowed_block_types = array(
			'core/heading',     // Heading block
			'core/image',       // Image block
			'core/list',        // List block
			'core/paragraph',   // Paragraph block
		);

		return $allowed_block_types;
	}

	// разрешим все блоки
	return true;
}

Полный список ролей и возможностей смотрите здесь.

Использование параметра $block_editor_context

Параметр $block_editor_context расширяет возможности условий при которых нужно отключать блоки. Например можно получить тип редактируемой записи, узнать работает ли пользователь в редакторе или в редакторе сайта, и т.д.

Давайте изменить код, чтобы ограничить блоки только если редактируется пост и разрешить все блоки есть редактируется сайт. Т.е. оставим определенный список блоков только для записей типа post.

Такой подход может быть полезен, если на вашем сайте используются пользовательские типы постов, предназначенные для размещения только определенных типов контента.

// Удаление всех блоков кроме указанных
add_filter( 'allowed_block_types_all', 'example_allowed_block_types', 10, 2 );

/**
 * @param array|bool $allowed_block_types Array of block type slugs, or boolean to enable/disable all.
 * @param object     $block_editor_context The current block editor context.
 *
 * @return array The array of allowed block types.
 */
function example_allowed_block_types( $allowed_block_types, $block_editor_context ) {

	// Применяется только в редакторе при редактировании постов.
	if (
		'core/edit-post' === $block_editor_context->name
		&& 'post' === ( $block_editor_context->post->post_type ?? '' )
	) {
		$allowed_block_types = array(
			'core/heading',     // Heading block
			'core/image',       // Image block
			'core/list',        // List block
			'core/paragraph',   // Paragraph block
		);

		return $allowed_block_types;
	}

	// разрешим все блоки
	return true;
}

$block_editor_context->name может содержать:

  • core/edit-post – Редактор
  • core/edit-site – Редактор сайта
  • core/widgets – Редактор виджетов
  • core/customize-widgets – Редактор виджетов в настраиваемом интерфейсе

Черный список (запрещенные блоки)

Выше мы разрешали блоки. Но если у вас сотни блоков, то удобнее указать только те, которые нужно запретить.

Чтобы этого добиться, мы можем указать ненужные блоки в массиве, затем программно получить весь список существующих блоков и исключить из них указанные.

Для получения всего списка блоков используем метод WP_Block_Type_Registery::get_all_registered().

Рассмотрим пример отключения блоков Навигации и Запроса для пользователей, у которых нет разрешения на edit_theme_options (обычно это право администратора).

add_filter( 'allowed_block_types_all', 'wpkama_disable_gutenberg_blocks', 30, 2 );
function wpkama_disable_gutenberg_blocks( $allowed_blocks, $block_editor_context ) {

	$disable_blocks = [
		'core/calendar',
		'core/comment-author-name',
		'core/comment-content',
		'core/comment-date',
		'core/comment-edit-link',
		'core/comment-reply-link',
		'core/comment-template',
		'core/comments',
		'core/comments-pagination',
		'core/comments-pagination-next',
		'core/comments-pagination-numbers',
		'core/comments-pagination-previous',
		'core/comments-title',
		'core/embed',
	];

	// Get all registered blocks if $allowed_block_types is not already set.
	if( ! is_array( $allowed_blocks ) || empty( $allowed_blocks ) ){
		$registered_blocks = WP_Block_Type_Registry::get_instance()->get_all_registered();
		$allowed_blocks = array_keys( $registered_blocks );
	}

	foreach( $allowed_blocks as $index => $block_id ){
		if( in_array( $block_id, $disable_blocks, true ) ){
			unset( $allowed_blocks[ $index ] );
		}
	}

	return array_values( $allowed_blocks ); // note: array list required
}

Отключение блоков через JavaScript

Реализация ограничений блоков с помощью JavaScript требует создание и подключение JavaScript-файла в редакторе.

Для примера ниже код скрипта будет лежать в файле темы (путь до файла скрипта будем указывать относительно темы).

  1. Создадим файл restrict-blocks.js (имя произвольное) и разместим его в папке assets/js темы.

  2. Подключим этот файл, используя хук enqueue_block_editor_assets и стандартную функцию wp_enqueue_script().
add_action( 'enqueue_block_editor_assets', 'example_enqueue_block_restrictions' );
function example_enqueue_block_restrictions() {
	wp_enqueue_script(
		'example-enqueue-block-variations',
		get_template_directory_uri() . '/assets/js/restrict-blocks.js',
		array( 'wp-blocks', 'wp-dom-ready' ),
		wp_get_theme()->get( 'Version' ),
		false
	);
}

Обратите внимание, на зависимости wp-blocks и wp-dom-ready. Они нужны для ограничений в примерах ниже.

Белый список (разрешенные блоки)

Тут логика отличается от варианта с PHP выше.

Чтобы оставить только несколько блоков, сначала нужно получить список всех существующих блоков с помощью функции wp.blocks.getBlockTypes(). Затем перебрать список и отключить все блоки которые не указаны в белом (разрешенном) списке.

Блоки отменяются с помощью метода wp.blocks.unregisterBlockType(), который принимает имя блока. Этот метод поставляется вместе с зависимостью wp-blocks (указывался при регистрации скрипта).

wp.domReady( () => {

	// Разрешить только блоки Heading, Image, List и Paragraph.
	const allowedBlocks = [
		'core/heading',
		'core/image',
		'core/list',
		'core/paragraph',
	];

	wp.blocks.getBlockTypes().forEach( blockType =>  {
		if ( allowedBlocks.indexOf( blockType.name ) === -1 ) {
			wp.blocks.unregisterBlockType( blockType.name );
		}
	} );
} );

Обязательно нужно использовать wp.domReady при отмене блоков. В противном случае функция может сработать слишком рано и не удалит блок.

Использование условий

Так же, как и в методах PHP, можно добавить условия. Например, метод canUser() из пакета @wordpress/data-core позволяет получать разрешения, а пакет @wordpress/data-core-editor предоставляет удобный метод getCurrentPostType().

Эти методы позволяет определить текущий тип записи и узнать, может ли пользователь обновлять настройки.

wp.domReady( () => {
	const { canUser } = wp.data.select( 'core' );
	const { getCurrentPostType } = wp.data.select( 'core/editor' );

	// Проверить разрешения пользователя и получить текущий тип записи.
	const canUserUpdateSettings = canUser( 'update', 'settings' );
	const currentPostType = getCurrentPostType();

	const allowedBlocks = [
		'core/heading',
		'core/image',
		'core/list',
		'core/paragraph',
	];

	if ( ! canUserUpdateSettings && currentPostType === 'post' ) {
		wp.blocks.getBlockTypes().forEach( blockType => {
			if ( allowedBlocks.indexOf( blockType.name ) === -1 ) {
				wp.blocks.unregisterBlockType( blockType.name );
			}
		} );
	}
} );

Черный список (запрещенные блоки)

Когда нужно отключить только несколько блоков, удобнее использовать следующих код. Например, нам нужно удалить два блока core/navigation и core/query в этом случае не нужно получать список всех блоков, а можно просто отключить ненужные блоки:

wp.domReady( () => {
	wp.blocks.unregisterBlockType( 'core/navigation' );
	wp.blocks.unregisterBlockType( 'core/query' );
} );

Если нужны условия, то также как и в примере до этого, используем методы пакетов core и core/editor:

wp.domReady( () => {
	const { canUser } = wp.data.select( 'core' );
	const { getCurrentPostType } = wp.data.select( 'core/editor' );

	if ( ! canUser( 'update', 'settings' ) && getCurrentPostType() === 'post' ) {
		wp.blocks.unregisterBlockType( 'core/navigation' );
		wp.blocks.unregisterBlockType( 'core/query' );
	}
} );

Вариант с JavaScript пожалуй более предпочтительный, потому что в итоге регистрация блоков делается как раз в JavaScript и в поэтому в этом случае у нас больше возможностей. Например, если мы регистрировали блок через JS, то в PHP этот блок просто не будет виден, тогда как в JS он будет существовать.

Отключение вариаций блоков

Часто вариации блоков (block variations) могут быть приняты за отдельные блоки, но это не так.

Простыми словами, вариации блоков - это один блок у которого есть разные варианты и каждый из вариантов выглядит в редакторе как отдельный блок.

Например встраивания (embed):

Все эти блоки - это один блок core/embed и если мы отлючим этот блок используя примеры выше, то мы отключим все вариации этого блока. Поэтому их нельзя отключить, используя ранее описанные методы. Но иногда бывает нужно отключить именно вариацию, при этом оставить остальные вариации.

Другой пример вариации это группы (group):

Рассмотрим пример с отключением вариации групп Row, Stack и вариацию встраивания YouTube.

wp.domReady( () => {
	wp.blocks.unregisterBlockVariation( 'core/group', 'group-row' );
	wp.blocks.unregisterBlockVariation( 'core/group', 'group-stack' );
	wp.blocks.unregisterBlockVariation( 'core/embed', 'youtube' );
} );

Для получения дополнительной информации о вариациях блоков обратитесь к статье "Введение в вариации блоков".

Атрибут allowedBlocks: Белый список блоков внутри блоков

Некоторые блоки могут содержать другие блоки. Назовём такие блоки - блоками контейнерами. Пример такого блока контейнера - это блок "Group". Иногда может понадобится ограничить список блоков, которые можно использовать внутри блока контейнера.

Для WordPress 6.4 атрибут allowedBlocks поддерживают четыре блока:

  • Column
  • Cover
  • Media & Text
  • Group - включает в себя вариации:
    • Row
    • Stack
    • Grid

Для этих блоков можно использовать атрибут allowedBlocks, чтобы указать список разрешенных блоков внутри контейнерного блока. Блоки, не включенные в этот список, будут недоступны для вставки внутри блока контейнера.

Например, если нужно разрешить только блоки "Заголовок" и "Параграф" внутри определенного контейнерного блока, следует использовать такой параметр настройки блока:

{"allowedBlocks":["core/heading","core/paragraph"]}

Посмотрим на другой параметр блокировки блока у которого есть визуальный интерфес:

Однако для атрибута allowedBlocks пользовательский интерфейс отсутствует. Поэтому, чтобы проиллюстрировать, как работает атрибут allowedBlocks, давайте рассмотрим шаблон "call-to-action" паттерна (с изображением справа) в теме Twenty Twenty-Four.

Шаблон структурирован следующим образом: состоит из блока "Group", служащего оберткой, которая содержит блок "Columns", разделенный на два отдельных блока "Column". Наша задача ограничить блоки, которые могут быть добавлены в каждую колонку.

Давайте сделаем так, чтобы в левую колонку можно было только добавить блоки: Кнопок, Заголовка, Списка и Параграфа. А в правую только блок "Изображеня".

Вот упрощенная версия шаблона, сфокусированная на разметке блока Columns с примененными атрибутами.

<!-- wp:column {"allowedBlocks":["core/buttons","core/heading","core/list","core/paragraph"],"verticalAlignment":"center","width":"50%"} -->
<div class="wp-block-column is-vertically-aligned-center" style="flex-basis:50%">[...]
</div>
<!-- /wp:column -->

<!-- wp:column {"allowedBlocks":["core/image"],"verticalAlignment":"center","width":"50%"} -->
<div class="wp-block-column is-vertically-aligned-center" style="flex-basis:50%">[...]
</div>
<!-- /wp:column -->

Разрешенные блоки в каждом блоке Columns теперь ограничены. Так, если использовать этот паттерн в контенте, блоки, которые могут быть вставлены в колонки, будут ограничены. Такой подход может быть полезен в проектах, где важна последовательность и предписанная структура контента.

Важно отметить, что поскольку этим ограничением блока управляет атрибут, пользователи теоретически могут переключиться в Редактор кода, удалить атрибут и затем добавить любые блоки, которые им нужны. Если и эту возможность нужно убрать, то можно ограничьте доступ к Редактору кода с помощью PHP.

Отключение доступа к редактору кода

Редактор кода позволяет просматривать базовую разметку блока для страницы или записи. Это может пригодится, но только если вы опытный пользователь, в противном случае вы можете случайно нарушить разметку блока, редактируя контент. Чтобы ограничить доступ пользователей к редактированию HTML кода, добавьте следующий код в ваш файл functions.php.

add_filter( 'block_editor_settings_all', 'example_restrict_code_editor_access', 10, 2 );
function example_restrict_code_editor_access( $settings, $context ) {
	$settings[ 'codeEditingEnabled' ] = false;

	return $settings;
}

Этот код предотвращает доступ к редактору кода для всех пользователей.

--

Источник: https://developer.wordpress.org/news/2024/01/29/how-to-disable-specific-blocks-in-wordpress/