剖析 WordPress `is_block_editor()` 函数源码:如何判断当前页面是否为区块编辑器。

各位观众老爷们,早上好!欢迎来到今天的“WordPress源码解剖课”。今天咱们要聊的是一个在WordPress开发中经常会用到的函数:is_block_editor()。这玩意儿就像个门卫,专门负责告诉你:嘿,哥们,现在是区块编辑器地盘儿,还是经典编辑器说了算?

废话不多说,直接上干货!

一、 is_block_editor() 的身世之谜

is_block_editor() 函数,顾名思义,就是用来判断当前页面是否正在使用区块编辑器(Gutenberg编辑器)。自从WordPress 5.0引入区块编辑器以来,它就成了区分新旧编辑器的关键。

二、 源码解剖:扒光 is_block_editor() 的衣服

要了解一个函数,最好的办法就是直接看它的源码。让我们一起潜入WordPress核心代码,找到 is_block_editor() 的真身。

(以下代码基于WordPress 6.4.2版本)

/**
 * Determines whether the current page is the block editor.
 *
 * @since 5.0.0
 *
 * @global WP_Screen $current_screen WordPress screen object.
 *
 * @return bool True if the current page is the block editor, false otherwise.
 */
function is_block_editor() {
    global $current_screen;

    if ( ! is_admin() ) {
        return false;
    }

    if ( ! function_exists( 'get_current_screen' ) ) {
        return false;
    }

    $screen = get_current_screen();

    if ( ! $screen ) {
        return false;
    }

    // The new widgets block editor screen.
    if ( 'widgets' === $screen->id && use_widgets_block_editor() ) {
        return true;
    }

    // The new customize block editor screen.
    if ( 'customize' === $screen->id && use_widgets_block_editor() ) {
        return true;
    }

    if ( method_exists( $screen, 'is_block_editor' ) && $screen->is_block_editor() ) {
        return true;
    }

    $post_types = get_post_types( array( 'show_in_rest' => true ) );
    if ( is_array( $post_types ) && in_array( $screen->post_type, $post_types, true ) ) {
        return true;
    }

    return false;
}

怎么样,是不是感觉有点像看天书?别怕,咱们一点点拆解。

三、 源码逐行解读:抽丝剥茧,还原真相

  1. function is_block_editor() {: 这行代码定义了函数 is_block_editor(),没有参数,返回一个布尔值(truefalse)。

  2. global $current_screen;: 声明使用全局变量 $current_screen。这个变量包含了当前屏幕(页面)的信息,比如ID、post type等等。

  3. if ( ! is_admin() ) { return false; }: 这一行很重要。is_admin() 函数判断当前是否在后台管理界面。如果不在后台,那肯定不是区块编辑器,直接返回 false。记住,区块编辑器只在后台使用。

  4. if ( ! function_exists( 'get_current_screen' ) ) { return false; }: 检查 get_current_screen() 函数是否存在。这个函数是用来获取 $current_screen 对象的。如果不存在,说明WordPress环境有问题,直接返回 false

  5. $screen = get_current_screen();: 获取 $current_screen 对象,并赋值给变量 $screen

  6. if ( ! $screen ) { return false; }: 检查 $screen 对象是否为空。如果为空,说明没有获取到屏幕信息,返回 false

  7. if ( 'widgets' === $screen->id && use_widgets_block_editor() ) { return true; }if ( 'customize' === $screen->id && use_widgets_block_editor() ) { return true; }: 这两行代码是针对小工具和自定义界面的区块编辑器。$screen->id 存储了当前屏幕的ID。如果ID是 'widgets''customize',并且 use_widgets_block_editor() 函数返回 true,则表示当前正在使用小工具或自定义界面的区块编辑器,返回 trueuse_widgets_block_editor() 函数会检查主题是否支持区块小工具。

  8. if ( method_exists( $screen, 'is_block_editor' ) && $screen->is_block_editor() ) { return true; }: 这行代码检查 $screen 对象是否存在 is_block_editor() 方法,如果存在并且调用该方法返回 true,则认为当前是区块编辑器。 这允许主题或插件更精细地控制区块编辑器的启用。

  9. $post_types = get_post_types( array( 'show_in_rest' => true ) );: 获取所有 show_in_resttrue 的 post types。 show_in_rest 参数决定了该 post type 是否支持 REST API,而区块编辑器正是基于 REST API 构建的。

  10. if ( is_array( $post_types ) && in_array( $screen->post_type, $post_types, true ) ) { return true; }: 如果 $post_types 是一个数组,并且当前屏幕的 post type ( $screen->post_type ) 存在于 $post_types 数组中,则认为当前是区块编辑器。 in_array(..., true) 使用严格比较,确保类型和值都相同。

  11. return false;: 如果以上所有条件都不满足,则最终返回 false,表示当前不是区块编辑器。

四、 逻辑梳理:拨开云雾见青天

让我们用更简洁的语言总结一下 is_block_editor() 函数的判断逻辑:

  1. 首先,确认当前是否在后台管理界面。 不在后台,肯定不是区块编辑器。
  2. 检查WordPress环境是否正常。 如果 get_current_screen() 函数不存在,或者 $current_screen 对象为空,说明环境有问题。
  3. 判断是否是小工具或自定义界面的区块编辑器。 通过检查 $screen->iduse_widgets_block_editor() 函数的返回值来判断。
  4. 检查 $screen 对象是否存在 is_block_editor() 方法,并调用该方法。
  5. 获取所有支持 REST API 的 post types。 如果当前屏幕的 post type 属于这些 post types,则认为是区块编辑器。
  6. 如果以上条件都不满足,则认为不是区块编辑器。

用表格的形式总结如下:

条件 返回值 说明
! is_admin() false 不在后台管理界面
! function_exists( 'get_current_screen' ) false get_current_screen() 函数不存在
! $screen false $current_screen 对象为空
'widgets' === $screen->id && use_widgets_block_editor() true 小工具界面的区块编辑器
'customize' === $screen->id && use_widgets_block_editor() true 自定义界面的区块编辑器
method_exists( $screen, 'is_block_editor' ) && $screen->is_block_editor() true $screen 对象存在 is_block_editor() 方法,且返回 true
in_array( $screen->post_type, $post_types, true ),其中 $post_typesshow_in_resttrue 的 post types 数组 true 当前 post type 支持 REST API
以上条件均不满足 false 不是区块编辑器

五、 实战演练: is_block_editor() 的应用场景

了解了 is_block_editor() 的原理,接下来看看它在实际开发中有什么用武之地。

  1. 加载不同的 CSS/JavaScript 文件:

    在主题或插件中,你可能需要根据编辑器类型加载不同的样式或脚本。

    function my_enqueue_scripts() {
        if ( is_block_editor() ) {
            wp_enqueue_style( 'my-block-editor-style', get_template_directory_uri() . '/css/block-editor.css' );
            wp_enqueue_script( 'my-block-editor-script', get_template_directory_uri() . '/js/block-editor.js', array( 'wp-blocks', 'wp-element' ), '1.0', true );
        } else {
            wp_enqueue_style( 'my-classic-editor-style', get_template_directory_uri() . '/css/classic-editor.css' );
            wp_enqueue_script( 'my-classic-editor-script', get_template_directory_uri() . '/js/classic-editor.js', array( 'jquery' ), '1.0', true );
        }
    }
    add_action( 'admin_enqueue_scripts', 'my_enqueue_scripts' );
  2. 执行不同的操作:

    有时候,你需要在区块编辑器和经典编辑器中执行不同的操作。

    function my_admin_notice() {
        if ( is_block_editor() ) {
            echo '<div class="notice notice-info is-dismissible"><p>欢迎使用区块编辑器!</p></div>';
        } else {
            echo '<div class="notice notice-info is-dismissible"><p>欢迎使用经典编辑器!</p></div>';
        }
    }
    add_action( 'admin_notices', 'my_admin_notice' );
  3. 控制 metabox 的显示:

    如果你的 metabox 与区块编辑器不兼容,可以只在经典编辑器中显示。

    function my_add_metabox() {
        if ( ! is_block_editor() ) {
            add_meta_box(
                'my_metabox',
                '我的 Metabox',
                'my_metabox_callback',
                'post',
                'normal',
                'default'
            );
        }
    }
    add_action( 'add_meta_boxes', 'my_add_metabox' );
  4. use_block_editor_for_post() 配合使用:

    use_block_editor_for_post() 函数用于判断特定 post type 是否使用区块编辑器。它可以与 is_block_editor() 结合使用,实现更精确的控制。

    function my_custom_editor_check( $use_block_editor, $post ) {
        // 只有 'product' 类型的 post 才使用区块编辑器
        if ( $post->post_type === 'product' ) {
            return true;
        } else {
            return false;
        }
    }
    add_filter( 'use_block_editor_for_post', 'my_custom_editor_check', 10, 2 );
    
    function my_conditional_action() {
        global $post;
        if ( is_block_editor() && $post && $post->post_type === 'product' ) {
            // 只在 product 类型的 post 的区块编辑器中执行
            echo '<script>console.log("Product Block Editor");</script>';
        }
    }
    add_action( 'admin_enqueue_scripts', 'my_conditional_action' );

六、 注意事项:避免踩坑

  1. 不要在前端使用 is_block_editor() is_block_editor() 函数只在后台管理界面有效。在前端使用它可能会导致不可预测的结果。
  2. 注意缓存问题: 如果你的网站使用了缓存插件,可能会导致 is_block_editor() 的返回值不正确。建议在必要时清理缓存。
  3. 主题兼容性: 有些主题可能对区块编辑器的支持不够完善,导致 is_block_editor() 的行为异常。

七、 总结:学以致用,融会贯通

今天,我们深入剖析了 is_block_editor() 函数的源码,了解了它的判断逻辑和应用场景。希望通过今天的学习,大家能够更加熟练地运用 is_block_editor() 函数,在WordPress开发中如鱼得水。

记住,理解源码不是目的,目的是更好地解决实际问题。希望大家能够把今天学到的知识应用到自己的项目中,创造出更优秀的作品。

今天的讲座就到这里,感谢大家的收听!下次有机会再和大家一起解剖其他的WordPress源码。祝大家编码愉快!

发表回复

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