剖析 WordPress `use_block_editor_for_post()` 函数的源码:如何为特定文章启用或禁用区块编辑器。

各位观众老爷,大家好!我是今天的主讲人,咱们今天来聊聊 WordPress 里面那个有点神秘的 use_block_editor_for_post() 函数。 别看名字长,作用可不小,它决定了你的文章是用古老的经典编辑器,还是用现在流行的区块编辑器(Gutenberg)。

前言:经典编辑器 vs. 区块编辑器,一场旷日持久的战争(误)

在 WordPress 的世界里,编辑器之争堪比 Android 和 iOS 的操作系统之争(当然,没那么激烈)。曾经的经典编辑器简单直接,但功能略显单薄;后来的区块编辑器功能强大,所见即所得,但上手难度稍微高一些。

那么,问题来了:如何让不同的文章使用不同的编辑器呢? 比如,我有些老文章,用经典编辑器编辑得好好的,不想迁移到区块编辑器;又有些新文章,我想尝鲜,用区块编辑器来排版。 这时候,use_block_editor_for_post() 函数就派上用场了。

揭秘 use_block_editor_for_post() 函数

use_block_editor_for_post() 函数的主要作用是:根据一定的规则,判断给定的文章是否应该使用区块编辑器。它的定义位于 wp-includes/block-editor.php 文件中。

源码看起来有点长,我们先分解一下:

/**
 * Determines whether the block editor should be used for a given post.
 *
 * @since 5.0.0
 *
 * @param WP_Post|int $post Post object or ID.
 * @return bool Whether the block editor should be used.
 */
function use_block_editor_for_post( $post ) {
    $post = get_post( $post );

    if ( ! $post ) {
        return false;
    }

    /**
     * Filters whether the block editor should be used for the given post.
     *
     * Returning a non-null value will short-circuit the function, effectively
     * short-circuiting the decision on whether the block editor is used for the
     * given post.
     *
     * @since 5.0.0
     *
     * @param bool|null $use_block_editor Whether the block editor should be used.
     *                                    Default null.
     * @param WP_Post   $post             Post object.
     */
    $use_block_editor = apply_filters( 'use_block_editor_for_post', null, $post );

    if ( null !== $use_block_editor ) {
        return (bool) $use_block_editor;
    }

    if ( 'attachment' === $post->post_type ) {
        return false;
    }

    if ( post_type_supports( $post->post_type, 'editor' ) ) {
        if ( function_exists( 'gutenberg_can_edit_post_type' ) && ! gutenberg_can_edit_post_type( $post->post_type ) ) {
            return false;
        }
        return true;
    }

    return false;
}

源码解析:一步一步来

  1. 获取文章对象:

    $post = get_post( $post );
    if ( ! $post ) {
        return false;
    }

    首先,函数接收一个 $post 参数,它可以是文章对象,也可以是文章 ID。 如果 $post 为空或者无效,就直接返回 false,表示不使用区块编辑器。

  2. 过滤器大法:

    $use_block_editor = apply_filters( 'use_block_editor_for_post', null, $post );
    if ( null !== $use_block_editor ) {
        return (bool) $use_block_editor;
    }

    这是 WordPress 强大的插件机制的体现。 apply_filters() 函数允许我们通过插件或主题来修改 use_block_editor_for_post() 函数的返回值。 如果某个插件或主题通过过滤器设置了 $use_block_editor 的值(不是 null),那么就直接使用这个值,不再往下执行。 这给了我们极大的灵活性,可以根据自己的需求来控制编辑器的使用。

  3. 附件排除:

    if ( 'attachment' === $post->post_type ) {
        return false;
    }

    如果文章类型是 attachment(附件),那么就直接返回 false,表示不使用区块编辑器。 附件通常不需要复杂的排版,所以默认不使用区块编辑器。

  4. 文章类型支持:

    if ( post_type_supports( $post->post_type, 'editor' ) ) {
        if ( function_exists( 'gutenberg_can_edit_post_type' ) && ! gutenberg_can_edit_post_type( $post->post_type ) ) {
            return false;
        }
        return true;
    }

    这里涉及到两个函数:

    • post_type_supports( $post->post_type, 'editor' ): 判断文章类型是否支持编辑器(包括经典编辑器和区块编辑器)。 如果支持,就继续往下判断。
    • gutenberg_can_edit_post_type( $post->post_type ): 这个函数是 Gutenberg 插件提供的,判断文章类型是否明确支持区块编辑器。 只有当文章类型既支持编辑器,又明确支持区块编辑器时,才会返回 true。 但是,如果gutenberg_can_edit_post_type函数不存在,则直接返回true。
  5. 默认值:

    return false;

    如果以上条件都不满足,那么就返回 false,表示不使用区块编辑器。

总结:use_block_editor_for_post() 函数的判断流程

可以用一个表格来总结一下:

步骤 条件 结果
1 $post 为空或无效 返回 false (不使用区块编辑器)
2 插件或主题通过 use_block_editor_for_post 过滤器设置了非 null 的值 返回过滤器设置的值
3 文章类型为 attachment 返回 false (不使用区块编辑器)
4 文章类型支持编辑器 (post_type_supports( $post->post_type, 'editor' ) 返回 true) 并且 Gutenberg 明确支持该文章类型 (gutenberg_can_edit_post_type( $post->post_type ) 返回 true) 返回 true (使用区块编辑器)
5 其他情况 返回 false (不使用区块编辑器)

实战演练:如何控制编辑器的使用

现在,我们来模拟几个场景,看看如何通过过滤器来控制编辑器的使用。

场景 1:禁用所有文章的区块编辑器

有时候,我们可能想彻底禁用区块编辑器,只使用经典编辑器。 可以通过以下代码来实现:

add_filter( 'use_block_editor_for_post', '__return_false' );

这段代码的意思是:无论什么文章,都返回 false,表示不使用区块编辑器。 __return_false 是 WordPress 内置的一个函数,它总是返回 false

场景 2:只允许特定文章类型的文章使用区块编辑器

假设我们只想让 post 类型的文章使用区块编辑器,其他类型的文章都使用经典编辑器。 可以这样写:

add_filter( 'use_block_editor_for_post', function( $use_block_editor, $post ) {
    if ( 'post' === $post->post_type ) {
        return true; // 允许 post 类型的文章使用区块编辑器
    }
    return false; // 其他类型的文章禁用区块编辑器
}, 10, 2 );

这段代码使用了匿名函数,接收两个参数:

  • $use_block_editor: 默认值,通常是 null
  • $post: 当前文章对象。

我们判断文章类型是否为 post,如果是,就返回 true,否则返回 false10 是优先级,2 是参数个数。

场景 3:根据文章 ID 来控制编辑器的使用

有时候,我们可能只想让特定的几篇文章使用区块编辑器。 可以这样写:

add_filter( 'use_block_editor_for_post', function( $use_block_editor, $post ) {
    $allowed_post_ids = array( 123, 456, 789 ); // 允许使用区块编辑器的文章 ID

    if ( in_array( $post->ID, $allowed_post_ids ) ) {
        return true; // 允许指定 ID 的文章使用区块编辑器
    }
    return false; // 其他文章禁用区块编辑器
}, 10, 2 );

这段代码定义了一个 $allowed_post_ids 数组,包含了允许使用区块编辑器的文章 ID。 然后,我们判断当前文章的 ID 是否在 $allowed_post_ids 数组中,如果是,就返回 true,否则返回 false

场景 4:根据自定义字段来控制编辑器的使用

这可能是最灵活的一种方式。 我们可以给文章添加一个自定义字段,比如 use_block_editor,如果这个字段的值为 true,就允许使用区块编辑器,否则禁用。

add_filter( 'use_block_editor_for_post', function( $use_block_editor, $post ) {
    $use_block_editor_meta = get_post_meta( $post->ID, 'use_block_editor', true );

    if ( 'true' === $use_block_editor_meta ) {
        return true; // 允许使用区块编辑器
    }
    return false; // 禁用区块编辑器
}, 10, 2 );

这段代码使用了 get_post_meta() 函数来获取文章的自定义字段 use_block_editor 的值。 如果这个值为 true,就返回 true,否则返回 false

代码部署:在哪里添加这些代码?

这些代码应该添加到你的主题的 functions.php 文件中,或者添加到自定义插件中。 建议使用自定义插件,这样即使更换主题,这些代码也不会丢失。

注意事项:

  • 优先级: add_filter() 函数的第三个参数是优先级,数字越小,优先级越高。 如果有多个过滤器修改了 use_block_editor_for_post 的返回值,那么优先级最高的过滤器会生效。
  • 缓存: 有些缓存插件可能会缓存 use_block_editor_for_post 的返回值,导致修改后的代码没有生效。 如果遇到这种情况,请清除缓存。
  • Gutenberg 插件: 如果安装了 Gutenberg 插件,可能会影响 use_block_editor_for_post 函数的行为。 建议禁用 Gutenberg 插件,或者仔细阅读 Gutenberg 插件的文档,了解其对编辑器的控制方式。

进阶:gutenberg_can_edit_post_type() 函数

前面提到过 gutenberg_can_edit_post_type() 函数,它是 Gutenberg 插件提供的,用于判断文章类型是否明确支持区块编辑器。 我们可以利用这个函数来更精确地控制编辑器的使用。

例如,我们可以只允许 Gutenberg 插件明确支持的文章类型使用区块编辑器:

add_filter( 'use_block_editor_for_post', function( $use_block_editor, $post ) {
    if ( function_exists( 'gutenberg_can_edit_post_type' ) && gutenberg_can_edit_post_type( $post->post_type ) ) {
        return true; // Gutenberg 插件明确支持,允许使用区块编辑器
    }
    return false; // 其他情况禁用区块编辑器
}, 10, 2 );

这段代码判断 gutenberg_can_edit_post_type() 函数是否存在,并且返回值为 true,才允许使用区块编辑器。

总结:灵活运用,掌控编辑器

use_block_editor_for_post() 函数是 WordPress 提供的一个强大的工具,可以让我们灵活地控制编辑器的使用。 通过过滤器,我们可以根据文章类型、文章 ID、自定义字段等条件来决定是否使用区块编辑器。 希望今天的讲解能够帮助大家更好地理解和使用这个函数,打造更个性化的 WordPress 网站!

好了,今天的讲座就到这里,感谢各位的观看! 记住,代码的世界是充满乐趣的,多尝试,多实践,你也能成为编程高手!

发表回复

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