增强 WordPress Shortcode 检测和判断能力,实现 doing_shortcode() 和 current_shortcode() 函数

我们之前详细介绍过 WordPress 的简码功能:Shortcode / 简码是什么?有什么用?一文详解 WordPress Shortcode

这里再简单介绍一下,简码(Shortcode)指的是使用[]包含的简码或者短代码,WordPress 会识别这些代码并根据它们定义的回调函数输出相应的内容,使用它可以给日志内容添加各种功能,并且它的接口非常容易使用,并且功能非常强大。

为什么需要正在处理的 Shortcode 查询和判断函数

但是使用过程中,发现简码功能没有提供 了 doing_filter()和 current_filter()来追踪当前正在执行的过滤器和过滤器名称的函数,其实我们也需要 current_shortcode()doing_shortcode($tag)函数,用于正在处理的 Shortcode 来获取和判断当前正在执行的短代码。。

我们先看看 WordPress Hook 的检测和判断函数有什么用处,current_filter()doing_filter($hook_name=null),或者 current_action()doing_action($hook_name=null)。他们分别用于返回正在的执行的 Hook,和某个特定的 Hook $hook_name 是否正在执行,具体怎么用呢?

比如我的文章目录扩展在文章开头加上目录的代码:

add_filter('the_content', function($content){
	if(!doing_filter('get_the_excerpt') && is_single(get_the_ID())){
		// 在文章前面加上目录
	}

	return $content;
});

我们是通过 the_content 这个 filter 实现的,但是很多时候,如果文章没有摘要,那么获取摘要的函数通过 get_the_excerpt 会调用 get_the_content() 函数来获取内容,然后再生成摘要,这样就会使得生成目录的代码被调用两次,所以我们通过 doing_filter('get_the_excerpt') 来判断这时候是在处理摘要,而不是内容,来实现文章目录只调用一次。

同样我们在 shortcode 处理函数的时候,可能有些时候也需要有同样的判断,比如我的内容模板插件,在实现密码保护的时候,再实现 password shortcode 时候,判断当前文章密码保护是不是需要的时候,就存在在外面和在执行 shortcode 回调的时候不同。

add_filter('post_password_required', function($required, $post){
	if($required){
		return doing_shortcode('password') ? true : !has_shortcode($post->post_content, 'password')
	}

	return $required;
}, 10, 2);

如何实现正在处理的 Shortcode 查询和判断函数

那么如何实现 current_shortcodedoing_shortcode($tag) 这两个函数呢?

Shortcode 的实际处理函数 do_shortcode_tag 有两个 filter,开始处理之前的 pre_do_shortcode_tag 和处理完成之后的 do_shortcode_tag,我们可以创建一个全局数组变量,用于存储正在处理的 Shorttag 的栈,在处理 Shortcode 之前推入当前,处理完成则推出。

//初始化队列
global $wp_current_shortcode;

if(!isset($wp_current_shortcode)){
	$wp_current_shortcode	= [];
}

// 处理之前,推入队列
add_filter('pre_do_shortcode_tag', function($pre, $tag){
	global $wp_current_shortcode;

	$wp_current_shortcode[]	= $tag;

	return $pre;
}, 1, 2);

add_filter('do_shortcode_tag', function($output, $tag){
	global $wp_current_shortcode;

	array_pop($wp_current_shortcode);

	return $output;
}, 999, 2)

// 获取当前的 Shortcode
if(!function_exists('current_shortcode')){
	function current_shortcode(){
		global $wp_current_shortcode;

		return end($wp_current_shortcode);
	}
}

// 判断当前的 Shortcode 
if(!function_exists('doing_shortcode')){
	function doing_shortcode($tag=null){
		global $wp_current_shortcode;

		return null === $tag ? !empty($wp_current_shortcode) : in_array($tag, $wp_current_shortcode, true);
	}
}

WPJAM Basic 插件中已经整合了这两个函数,可以直接使用。😎 也可以参考这个思路在自己的项目中实现类似的功能。


©我爱水煮鱼,本站推荐使用的主机:阿里云,国外主机建议使用BlueHost

本站长期承接 WordPress 优化建站业务,请联系微信:「chenduopapa」。