剖析 WordPress `get_block_editor_settings()` 函数的源码:如何获取并应用所有区块编辑器的配置。

各位观众老爷,晚上好!今天咱们不聊风花雪月,来点硬核的:扒一扒 WordPress 区块编辑器的底裤,啊不,源码。具体来说,就是那个神秘的 get_block_editor_settings() 函数,看看它到底是怎么把区块编辑器的配置一股脑儿塞给你的。

准备好了吗?系好安全带,发车了!

第一节:开胃小菜 – get_block_editor_settings() 是个啥?

简单来说,get_block_editor_settings() 是 WordPress 用来获取区块编辑器(也就是古腾堡编辑器)配置信息的函数。它返回一个包含各种设置的大数组,这些设置控制了编辑器如何工作,包括允许哪些区块、编辑器样式、各种面板设置等等。

想象一下,你开了一家装修公司,get_block_editor_settings() 就像你的配置清单,上面详细列出了:

  • 允许使用的建材(区块)
  • 装修风格(编辑器样式)
  • 各种工具(面板设置)

有了这份清单,你的设计师(区块编辑器)才能按照你的要求进行装修。

第二节:追根溯源 – 源码在哪里?

get_block_editor_settings() 的源码位于 wp-admin/includes/template.php 文件中。打开这个文件,你就能看到它的真面目。

第三节:庖丁解牛 – 源码分析

接下来,咱们一点一点地剖析 get_block_editor_settings() 的源码。

function get_block_editor_settings( $settings = array() ) {
    global $post, $pagenow;

    $post_id = 0;
    if ( isset( $post ) ) {
        $post_id = $post->ID;
    }

    $available_block_types = WP_Block_Type_Registry::get_instance()->get_all_registered();

    $default_block_categories = array(
        array(
            'slug'  => 'common',
            'title' => _x( 'Common blocks', 'block category' ),
        ),
        array(
            'slug'  => 'formatting',
            'title' => _x( 'Formatting', 'block category' ),
        ),
        array(
            'slug'  => 'layout',
            'title' => _x( 'Layout elements', 'block category' ),
        ),
        array(
            'slug'  => 'widgets',
            'title' => _x( 'Widgets', 'block category' ),
        ),
        array(
            'slug'  => 'theme',
            'title' => _x( 'Theme', 'block category' ),
        ),
        array(
            'slug'  => 'embed',
            'title' => _x( 'Embeds', 'block category' ),
        ),
        array(
            'slug'  => 'reusable',
            'title' => __( 'Reusable blocks' ),
        ),
    );

    /**
     * Filters the default block categories.
     *
     * @since 5.0.0
     *
     * @param array[] $default_block_categories Array of block categories.
     */
    $block_categories = apply_filters( 'block_categories', $default_block_categories, $post );

    $settings = array_merge(
        array(
            'available_block_types'           => array_keys( $available_block_types ),
            'allowedBlockTypes'               => true, // Allows all block types by default.
            'block_categories'                => $block_categories,
            'disableCustomColors'             => get_theme_support( 'disable-custom-colors' ),
            'disableCustomFontSizes'          => get_theme_support( 'disable-custom-font-sizes' ),
            'disableCustomGradients'          => get_theme_support( 'disable-custom-gradients' ),
            'enableCustomLineHeight'          => get_theme_support( 'custom-line-height' ),
            'enableCustomSpacing'            => get_theme_support( 'custom-spacing' ),
            'enableCustomUnits'               => get_theme_support( 'custom-units' ),
            'enableCustomFontSize'            => get_theme_support( 'custom-font-size' ),
            'isRTL'                         => is_rtl(),
            'l10n'                          => array(
                'insert'            => __( 'Add block' ),
                'inserter'          => __( 'Add a block' ),
                'inserterMedia'     => __( 'Add media' ),
                'inserterText'      => __( 'Add text' ),
                'multiBlockSelected' => _n( '%d block selected', '%d blocks selected', 1 ),
                'noBlocksFound'      => __( 'No blocks found.' ),
                'noResultsFound'     => __( 'No results found.' ),
                'tryAgain'           => __( 'Try again.' ),
                'update'            => __( 'Update' ),
                'saved'             => __( 'Saved' ),
                'saving'            => __( 'Saving…' ),
                'default'           => __( 'Default' ),
                'ariaLabelMedia'    => __( 'Add media' ),
                'ariaLabelText'     => __( 'Add text' ),
                'block'             => __( 'Block' ),
                'categories'        => __( 'Categories' ),
                'close'             => __( 'Close' ),
                'confirmCancel'     => __( 'Are you sure you want to discard your changes?' ),
                'contentSelectedText' => __( '%d item selected' ),
                'copyAllBlocks'     => __( 'Copy all blocks' ),
                'createBlock'       => __( 'Create block' ),
                'createReusableBlock' => __( 'Create reusable block' ),
                'defaultBlock'       => __( 'Default block' ),
                'describeBlock'      => __( 'Describe block' ),
                'edit'              => __( 'Edit' ),
                'expandAll'         => __( 'Expand all' ),
                'finishDescription'  => __( 'Finish description' ),
                'focusBlock'        => __( 'Focus block' ),
                'insertBlock'       => __( 'Insert block' ),
                'inserterMenu'      => __( 'Add block' ),
                'leaveBlank'        => __( 'Leave blank' ),
                'mediaLibrary'      => __( 'Media Library' ),
                'moveDown'          => __( 'Move down' ),
                'moveUp'            => __( 'Move up' ),
                'navigation'        => __( 'Navigation' ),
                'noTitle'           => __( 'No title' ),
                'ok'                => __( 'OK' ),
                'options'           => __( 'Options' ),
                'ordinals'          => array(
                    __( 'First' ),
                    __( 'Second' ),
                    __( 'Third' ),
                    __( 'Fourth' ),
                    __( 'Fifth' ),
                    __( 'Sixth' ),
                    __( 'Seventh' ),
                    __( 'Eighth' ),
                    __( 'Ninth' ),
                    __( 'Tenth' ),
                ),
                'patterns'          => __( 'Patterns' ),
                'reusableBlocks'    => __( 'Reusable blocks' ),
                'reusableBlockSaved' => __( 'Reusable block saved.' ),
                'save'              => __( 'Save' ),
                'savedBlocks'       => __( 'Saved blocks' ),
                'search'            => __( 'Search' ),
                'selectAllBlocks'   => __( 'Select all blocks' ),
                'selectBlock'       => __( 'Select block' ),
                'settings'          => __( 'Settings' ),
                'showMoreSettings'  => __( 'Show more settings' ),
                'styles'            => __( 'Styles' ),
                'switchToHTML'      => __( 'Switch to HTML editor' ),
                'switchToVisual'    => __( 'Switch to the visual editor' ),
                'toolsPanelMore'    => __( 'Tools & options' ),
                'transformTo'       => __( 'Transform to' ),
                'tryBlockSearch'    => __( 'Try searching for a block' ),
                'updateBlock'       => __( 'Update block' ),
                'useReusableBlock'  => __( 'Use reusable block' ),
                'viewCode'          => __( 'View code' ),
                'visualEditor'      => __( 'Visual editor' ),
            ),
            'maxUploadFileSize'               => wp_max_upload_size(),
            'post'                          => get_default_post_to_edit( get_post_type(), true ),
            'styles'                        => array(),
            'template'                      => isset( $post->ID ) ? get_page_template_slug( $post->ID ) : '',
            'templateLock'                  => isset( $post->ID ) ? get_post_meta( $post->ID, '_wp_template_lock', true ) : '',
            '__experimentalBlockPatterns'    => WP_Block_Patterns_Registry::get_instance()->get_all_registered(),
            '__experimentalBlockPatternCategories' => WP_Block_Pattern_Categories_Registry::get_instance()->get_all_registered(),
        ),
        $settings
    );

    $editor_styles = array();

    if ( ! empty( $settings['styles'] ) ) {
        $editor_styles = $settings['styles'];
    }

    if ( current_theme_supports( 'editor-styles' ) ) {
        $editor_styles = array_merge( $editor_styles, get_editor_stylesheets() );
    }

    /**
     * Filters the editor styles.
     *
     * @since 5.0.0
     *
     * @param string[] $editor_styles Array of editor styles.
     */
    $editor_styles = apply_filters( 'editor_styles', $editor_styles );

    $settings['styles'] = $editor_styles;

    /**
     * Filters the settings passed to the block editor.
     *
     * @since 5.0.0
     *
     * @param array $settings Array of settings for the block editor.
     * @param WP_Post $post Post being edited.
     */
    return apply_filters( 'block_editor_settings', $settings, $post );
}

代码有点长,咱们分段解读:

  1. 初始化
function get_block_editor_settings( $settings = array() ) {
    global $post, $pagenow;

    $post_id = 0;
    if ( isset( $post ) ) {
        $post_id = $post->ID;
    }

    $available_block_types = WP_Block_Type_Registry::get_instance()->get_all_registered();
  • 函数接收一个可选的 $settings 数组作为参数,允许你传入自定义设置。
  • 获取全局变量 $post (当前编辑的文章/页面) 和 $pagenow (当前管理页面)。
  • 获取当前文章/页面的 ID。
  • 通过 WP_Block_Type_Registry 获取所有已注册的区块类型。WP_Block_Type_Registry 是一个单例类,负责管理区块类型的注册和检索。get_all_registered() 返回一个包含所有已注册区块类型对象的数组。
  1. 默认区块分类
    $default_block_categories = array(
        array(
            'slug'  => 'common',
            'title' => _x( 'Common blocks', 'block category' ),
        ),
        array(
            'slug'  => 'formatting',
            'title' => _x( 'Formatting', 'block category' ),
        ),
        array(
            'slug'  => 'layout',
            'title' => _x( 'Layout elements', 'block category' ),
        ),
        array(
            'slug'  => 'widgets',
            'title' => _x( 'Widgets', 'block category' ),
        ),
        array(
            'slug'  => 'theme',
            'title' => _x( 'Theme', 'block category' ),
        ),
        array(
            'slug'  => 'embed',
            'title' => _x( 'Embeds', 'block category' ),
        ),
        array(
            'slug'  => 'reusable',
            'title' => __( 'Reusable blocks' ),
        ),
    );

    /**
     * Filters the default block categories.
     *
     * @since 5.0.0
     *
     * @param array[] $default_block_categories Array of block categories.
     */
    $block_categories = apply_filters( 'block_categories', $default_block_categories, $post );
  • 定义了一组默认的区块分类,例如 "Common blocks", "Formatting" 等。
  • 使用 apply_filters( 'block_categories', $default_block_categories, $post ) 允许开发者通过 block_categories 过滤器修改这些分类。 这是 WordPress 强大的扩展机制之一,你可以通过这个过滤器添加、删除或修改区块分类,从而定制区块编辑器的界面。
  1. 构建设置数组
    $settings = array_merge(
        array(
            'available_block_types'           => array_keys( $available_block_types ),
            'allowedBlockTypes'               => true, // Allows all block types by default.
            'block_categories'                => $block_categories,
            'disableCustomColors'             => get_theme_support( 'disable-custom-colors' ),
            'disableCustomFontSizes'          => get_theme_support( 'disable-custom-font-sizes' ),
            'disableCustomGradients'          => get_theme_support( 'disable-custom-gradients' ),
            'enableCustomLineHeight'          => get_theme_support( 'custom-line-height' ),
            'enableCustomSpacing'            => get_theme_support( 'custom-spacing' ),
            'enableCustomUnits'               => get_theme_support( 'custom-units' ),
            'enableCustomFontSize'            => get_theme_support( 'custom-font-size' ),
            'isRTL'                         => is_rtl(),
            'l10n'                          => array(
                'insert'            => __( 'Add block' ),
                'inserter'          => __( 'Add a block' ),
                // ...省略大量本地化字符串...
            ),
            'maxUploadFileSize'               => wp_max_upload_size(),
            'post'                          => get_default_post_to_edit( get_post_type(), true ),
            'styles'                        => array(),
            'template'                      => isset( $post->ID ) ? get_page_template_slug( $post->ID ) : '',
            'templateLock'                  => isset( $post->ID ) ? get_post_meta( $post->ID, '_wp_template_lock', true ) : '',
            '__experimentalBlockPatterns'    => WP_Block_Patterns_Registry::get_instance()->get_all_registered(),
            '__experimentalBlockPatternCategories' => WP_Block_Pattern_Categories_Registry::get_instance()->get_all_registered(),
        ),
        $settings
    );
  • 这是一个核心步骤,它构建了一个包含各种设置的数组。
  • available_block_types: 所有可用区块类型的键名数组。
  • allowedBlockTypes: 默认值为 true,表示允许所有区块类型。你可以将其设置为一个区块类型名称数组,只允许特定的区块类型。
  • block_categories: 前面获取的区块分类数组。
  • disableCustomColors, disableCustomFontSizes, disableCustomGradients, enableCustomLineHeight, enableCustomSpacing, enableCustomUnits, enableCustomFontSize: 这些选项控制了是否允许用户自定义颜色、字体大小、渐变、行高、间距和单位。它们的值取决于主题是否支持这些特性 (通过 add_theme_support() 函数声明)。
  • isRTL: 判断当前语言是否为从右向左书写。
  • l10n: 包含大量本地化字符串,用于区块编辑器的界面显示。
  • maxUploadFileSize: 允许上传的最大文件大小。
  • post: 当前文章/页面的默认数据,通过 get_default_post_to_edit() 获取。
  • styles: 编辑器样式表数组,稍后会进行处理。
  • template: 当前文章/页面使用的页面模板。
  • templateLock: 模板锁定设置,防止用户修改模板结构。
  • __experimentalBlockPatterns: 所有已注册的区块模式。
  • __experimentalBlockPatternCategories: 所有已注册的区块模式分类。
  • array_merge(): 将默认设置与传入的 $settings 数组合并。如果 $settings 中有相同的键,则 $settings 中的值会覆盖默认值。
  1. 处理编辑器样式
    $editor_styles = array();

    if ( ! empty( $settings['styles'] ) ) {
        $editor_styles = $settings['styles'];
    }

    if ( current_theme_supports( 'editor-styles' ) ) {
        $editor_styles = array_merge( $editor_styles, get_editor_stylesheets() );
    }

    /**
     * Filters the editor styles.
     *
     * @since 5.0.0
     *
     * @param string[] $editor_styles Array of editor styles.
     */
    $editor_styles = apply_filters( 'editor_styles', $editor_styles );

    $settings['styles'] = $editor_styles;
  • 首先,将 $settings['styles'] 中的样式表复制到 $editor_styles 数组中。
  • 如果主题支持 editor-styles 特性 (通过 add_theme_support( 'editor-styles' ) 声明),则通过 get_editor_stylesheets() 获取主题的编辑器样式表,并将其合并到 $editor_styles 数组中。
  • 使用 apply_filters( 'editor_styles', $editor_styles ) 允许开发者通过 editor_styles 过滤器修改编辑器样式表。
  • 最后,将处理后的 $editor_styles 数组赋值给 $settings['styles']
  1. 最终过滤和返回
    /**
     * Filters the settings passed to the block editor.
     *
     * @since 5.0.0
     *
     * @param array $settings Array of settings for the block editor.
     * @param WP_Post $post Post being edited.
     */
    return apply_filters( 'block_editor_settings', $settings, $post );
}
  • 使用 apply_filters( 'block_editor_settings', $settings, $post ) 允许开发者通过 block_editor_settings 过滤器修改最终的设置数组。 这是最后一个机会修改区块编辑器的配置,你可以通过这个过滤器添加、删除或修改任何设置。
  • 返回最终的设置数组。

第四节:深入细节 – 几个关键设置项

咱们来重点看看几个比较重要的设置项:

设置项 描述 示例
available_block_types 一个包含所有已注册区块类型名称的数组。 array( 'core/paragraph', 'core/image', 'core/heading' )
allowedBlockTypes 控制允许使用的区块类型。可以设置为 true (允许所有区块类型),也可以设置为一个包含允许的区块类型名称的数组。 true (允许所有区块), array( 'core/paragraph', 'core/image' ) (只允许段落和图片区块)
block_categories 一个包含区块分类信息的数组。每个分类包含 slug (分类的唯一标识符) 和 title (分类的显示名称)。 php array( array( 'slug' => 'common', 'title' => __( 'Common blocks' ) ), array( 'slug' => 'formatting', 'title' => __( 'Formatting' ) ) )
disableCustomColors 如果设置为 true,则禁用用户自定义颜色。主题可以通过 add_theme_support( 'disable-custom-colors' ) 来控制这个选项。 true (禁用自定义颜色), false (允许自定义颜色)
styles 一个包含编辑器样式表 URL 的数组。这些样式表会被加载到区块编辑器中,用于提供与主题风格一致的视觉效果。 array( 'https://example.com/wp-content/themes/my-theme/editor-style.css' )
template 当前文章/页面使用的页面模板。 page-templates/my-custom-template.php
templateLock 模板锁定设置。可以设置为 'all' (锁定所有区块) 或 'insert' (只允许插入新区块,不允许移动或删除现有区块)。 'all', 'insert'
__experimentalBlockPatterns 一个包含所有已注册区块模式的数组。 数组,每个元素代表一个区块模式

第五节:实战演练 – 如何修改区块编辑器配置

现在,咱们来演示一下如何通过过滤器修改区块编辑器的配置。

场景 1:只允许使用段落和图片区块

add_filter( 'block_editor_settings', 'my_custom_block_editor_settings' );

function my_custom_block_editor_settings( $settings ) {
    $settings['allowedBlockTypes'] = array( 'core/paragraph', 'core/image' );
    return $settings;
}

这段代码使用了 block_editor_settings 过滤器,将 allowedBlockTypes 设置为一个包含 core/paragraphcore/image 的数组。这样,在区块编辑器中就只允许使用段落和图片区块了。

场景 2:添加自定义区块分类

add_filter( 'block_categories', 'my_custom_block_categories', 10, 2 );

function my_custom_block_categories( $categories, $post ) {
    return array_merge(
        $categories,
        array(
            array(
                'slug'  => 'my-custom-category',
                'title' => __( 'My Custom Category', 'my-theme' ),
                'icon'  => 'star-filled', // 可选,添加分类图标
            ),
        )
    );
}

这段代码使用了 block_categories 过滤器,添加了一个名为 "My Custom Category" 的自定义区块分类。icon 参数是可选的,你可以通过它为分类添加一个图标。

场景 3:添加自定义编辑器样式

add_filter( 'editor_styles', 'my_custom_editor_styles' );

function my_custom_editor_styles( $styles ) {
    $styles[] = 'https://example.com/wp-content/themes/my-theme/custom-editor-style.css';
    return $styles;
}

这段代码使用了 editor_styles 过滤器,添加了一个自定义编辑器样式表。

第六节:注意事项

  • 缓存: 修改区块编辑器配置后,可能需要清除浏览器缓存才能看到效果。
  • 主题支持: 一些设置项 (例如 disableCustomColors, disableCustomFontSizes) 取决于主题是否支持相应的特性。
  • 插件冲突: 其他插件可能会修改区块编辑器的配置,导致冲突。 调试时需要注意插件的加载顺序和代码逻辑。
  • 实验性特性:__experimental 开头的设置项是实验性的,可能会在未来的 WordPress 版本中发生变化。

第七节:总结

get_block_editor_settings() 函数是 WordPress 区块编辑器的核心,它负责获取并传递各种配置信息。 通过理解它的源码,你可以更好地定制区块编辑器的行为,使其更符合你的需求。 而通过使用 WordPress 提供的各种过滤器,你可以轻松地修改区块编辑器的配置,而无需修改 WordPress 核心代码。

今天的讲座就到这里,希望大家有所收获!下次有机会,咱们再来聊聊其他 WordPress 的黑科技。

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注