## 更多资源

- [如何使用服务器端过滤器修改 theme.json 数据](https://developer.wordpress.org/news/2023/07/05/how-to-modify-theme-json-data-using-server-side-filters/)（WordPress 开发者博客）
- [通过客户端过滤器定制编辑器体验](https://developer.wordpress.org/news/2023/05/24/curating-the-editor-experience-with-client-side-filters/)（WordPress 开发者博客）

## 客户端（编辑器）过滤器

WordPress 6.2 引入了一个全新的客户端过滤器，允许您在编辑器渲染前修改区块层级的 [theme.json 设置](/docs/reference-guides/theme-json-reference/theme-json-living.md#settings)。

该过滤器名为 `blockEditor.useSetting.before`，可通过以下方式在 JavaScript 代码中使用：

```js
import { addFilter } from '@wordpress/hooks';

/**
 * 将栏目区块的间距选项限制为像素单位。
 */
addFilter(
	'blockEditor.useSetting.before',
	'example/useSetting.before',
	( settingValue, settingName, clientId, blockName ) => {
		if ( blockName === 'core/column' && settingName === 'spacing.units' ) {
			return [ 'px' ];
		}
		return settingValue;
	}
);
```

此示例将把栏目区块的可用间距单位限制为仅像素单位。如前所述，类似的限制也可以通过 theme.json 过滤器或直接在主题的 theme.json 文件中使用区块层级设置来实现。

但 `blockEditor.useSetting.before` 过滤器的独特之处在于，它允许您根据区块位置、相邻区块、当前用户角色等条件动态修改设置，定制可能性极为丰富。

下面这个示例展示了当标题区块被放置在「媒体与文本」区块内部时，会自动禁用其文字颜色控制功能：

```js
import { select } from  '@wordpress/data';
import { addFilter } from '@wordpress/hooks';

/**
 * 当标题区块置于媒体与文本区块内时，禁用其文字颜色控制功能。
 */
addFilter(
	'blockEditor.useSetting.before',
	'example/useSetting.before',
	( settingValue, settingName, clientId, blockName ) => {
		if ( blockName === 'core/heading' ) {
			const { getBlockParents, getBlockName } = select( 'core/block-editor' );
			const blockParents = getBlockParents( clientId, true );
			const inMediaText = blockParents.some( ( ancestorId ) => getBlockName( ancestorId ) === 'core/media-text' );

			if ( inMediaText && settingName === 'color.text' ) {
			    return false;
			}
		}

		return settingValue;
	}
);
```

## 区块过滤器

除了优化编辑器界面外，您还可以通过多种方式修改单个区块。比如禁用特定区块支持功能（如背景色），或定义特定区块默认显示的设置项。

其中最常用的过滤器之一是 [`block_type_metadata`](https://developer.wordpress.org/reference/hooks/block_type_metadata/)。当区块类型在服务器端通过 PHP 注册时，该过滤器允许您拦截从区块 `block.json` 文件加载的原始元数据。

该过滤器接收一个参数：

- `$metadata` (`array`) – 从 `block.json` 加载的区块类型注册元数据。

`$metadata` 数组包含您可能需要了解的所有区块信息，从描述和[属性](https://developer.wordpress.org/block-editor/reference-guides/block-api/block-attributes/)到区块[支持功能](https://developer.wordpress.org/block-editor/reference-guides/block-api/block-supports/)。

以下示例演示了如何禁用标题区块的背景色与渐变支持：

```php
function example_disable_heading_background_color_and_gradients( $metadata ) {

    // 仅对标题区块应用此过滤器
    if ( ! isset( $metadata['name'] ) || 'core/heading' !== $metadata['name'] ) {
        return $metadata;
    }

    // 检查是否存在支持功能配置
    if ( isset( $metadata['supports'] ) && isset( $metadata['supports']['color'] ) ) {

        // 移除背景色与渐变支持
        $metadata['supports']['color']['background'] = false;
        $metadata['supports']['color']['gradients']  = false;
    }

    return $metadata;
}
add_filter( 'block_type_metadata', 'example_disable_heading_background_color_and_gradients' );
```

您可以通过[区块过滤器文档](https://developer.wordpress.org/block-editor/reference-guides/filters/block-filters/)了解更多可用过滤器。

# 过滤器与钩子

编辑器提供了丰富的过滤器和钩子，让您可以自定义编辑体验。以下列举部分功能：

## 编辑器设置

最常见的编辑器修改方式是通过 [`block_editor_settings_all`](https://developer.wordpress.org/reference/hooks/block_editor_settings_all/) PHP 过滤器，该过滤器会在设置发送到初始化编辑器之前生效。

`block_editor_settings_all` 钩子会向回调函数传递两个参数：

- `$settings` - 编辑器[可配置设置](https://developer.wordpress.org/block-editor/reference-guides/filters/editor-filters/#editor-settings)的数组
- `$context` - [`WP_Block_Editor_Context`](https://developer.wordpress.org/reference/classes/wp_block_editor_context/) 实例，包含当前编辑器信息的对象

以下示例将为无法激活插件的用户（管理员除外）禁用代码编辑器。将此代码添加到插件或主题的 `functions.php` 文件中进行测试：

```php
add_filter( 'block_editor_settings_all', 'example_restrict_code_editor' );

function example_restrict_code_editor( $settings ) {
	$can_active_plugins = current_user_can( 'activate_plugins' );

	// 对无法激活插件的用户禁用代码编辑器
	if ( ! $can_active_plugins ) {
		$settings[ 'codeEditingEnabled' ] = false;
	}

	return $settings;
}
```

更多示例请参阅[编辑器钩子](https://developer.wordpress.org/block-editor/reference-guides/filters/editor-filters/)文档，包含以下用例：

- [设置默认图片尺寸](https://developer.wordpress.org/block-editor/reference-guides/filters/editor-filters/#set-a-default-image-size)
- [禁用 Openverse](https://developer.wordpress.org/block-editor/reference-guides/filters/editor-filters/#disable-openverse)
- [禁用字体库](https://developer.wordpress.org/block-editor/reference-guides/filters/editor-filters/#disable-the-font-library)
- [禁用区块检查器标签页](https://developer.wordpress.org/block-editor/reference-guides/filters/editor-filters/#disable-block-inspector-tabs)

## 服务端 theme.json 过滤器

theme.json 文件是控制界面选项的重要方式，但它仅支持全局或区块层级的修改，在某些场景下可能受限。

例如在前述章节中，我们使用 theme.json 全局禁用了颜色和版式控制。但假设您需要为管理员用户启用颜色设置。

为提供更灵活的配置，WordPress 6.1 引入了服务端过滤器，允许在四个数据层自定义 theme.json 数据：

- [`wp_theme_json_data_default`](https://developer.wordpress.org/reference/hooks/wp_theme_json_data_default/) - 挂钩 WordPress 提供的默认数据
- [`wp_theme_json_data_blocks`](https://developer.wordpress.org/reference/hooks/wp_theme_json_data_blocks/) - 挂钩区块提供的数据
- [`wp_theme_json_data_theme`](https://developer.wordpress.org/reference/hooks/wp_theme_json_data_theme/) - 挂钩当前主题提供的数据
- [`wp_theme_json_data_user`](https://developer.wordpress.org/reference/hooks/wp_theme_json_data_user/) - 挂钩用户提供的数据

以下示例使用 `wp_theme_json_data_theme` 过滤器更新当前主题的 theme.json 数据。如果当前用户是管理员，则会恢复颜色控制功能：

```php
// 为除管理员外的所有用户禁用颜色控制
function example_filter_theme_json_data_theme( $theme_json ){
    $is_administrator = current_user_can( 'edit_theme_options' );

    if ( $is_administrator ) {
        $new_data = array(
            'version'  => 2,
            'settings' => array(
                'color' => array(
                    'background'       => true,
                    'custom'           => true,
                    'customDuotone'    => true,
                    'customGradient'   => true,
                    'defaultGradients' => true,
                    'defaultPalette'   => true,
                    'text'             => true,
                ),
            ),
        );
    }

	return $theme_json->update_with( $new_data );
}
add_filter( 'wp_theme_json_data_theme', 'example_filter_theme_json_data_theme' );
```

该过滤器会接收到包含对应数据层数据的 `WP_Theme_JSON_Data` 类实例。随后您需要向 `update_with( $new_data )` 方法传入符合 theme.json 规范的新数据。注意 `$new_data` 中必须包含 theme.json 版本号。