今天在网上逛到有些大佬的博客,发现他们有各种各样的表情包,特别是有 b 站的表情包,用起来真是亲切。而本站虽说有表情包功能,但我不太喜欢 Alu 表情包的这个风格,感觉辨识度太低了,都不知道每个表情是啥意思,而且表情数量也少,完全不能满足交流功能。于是我就想给博客加点其他表情,没想到这简简单单加个表情真是非常曲折,在这里分享下我的经验,可能能帮助到各位。
本站表情包用的是 WP Alu2Button 这个插件,原因是 MDx 主题对这个插件做了适配(现在回过头来看,好像也只是检测了个函数名,没啥特别的),用这个插件的话就能和主题的评论框完美融合。
所以我自然而然地想到直接魔改插件… 看了下插件的源码,很明显就能看出,表情列表就是靠这个函数来解决的,前面是表情码,后面是对应的图片,存在插件目录里面。
function alu_smilies_reset() { global $wpsmiliestrans, $wp_smiliessearch; if ( !get_option( 'use_smilies' ) ) return; $wpsmiliestrans = array( ':mrgreen:' => 'icon_mrgreen.gif', ':neutral:' => 'icon_neutral.gif', ':twisted:' => 'icon_twisted.gif', // ……略…… ':|' => 'icon_neutral.gif', ':!:' => 'icon_exclaim.gif', ':?:' => 'icon_question.gif', ); } add_action('init','alu_smilies_reset');
当我把我的表情按格式填入这个数组里后,表情列表确实出现了我新加入的表情,但是发送出去的表情码原封不动的是字符,没有成功替换成表情图片。我就纳闷了,表情列表都显示了新表情,怎么发出去之后却不行了?什么玩意。
然后就是折磨的开始了,四处搜寻资料,来回看了好多遍这插件的源码,甚至把主题适配插件的部分源码都看了下。虽说我是一点也不会 PHP,但是代码长得还挺像 Python 的,勉强能看懂在干啥。
搞了半天我发现一个特点,以前插件的表情码比如 :mrgreen:
我改成对应自己的表情图片是可以的,但是我自己没法添加新的表情码,这就离谱了。
然后我又去搜索 WordPress 表情的原理,然后发现了这插件用的表情码其实是 WordPress 内置好的,这个插件无非是把它对应的图片修改成了 Alu 表情包。这给我了点启发,难道是说只有 WordPress 内置表情码才能正确替换为表情包,而我不能新加表情码吗?
然后我就去翻 WordPress 的源代码,因为不知道这功能写到哪个文件里了,于是我就直接在 wp-includes 里面搜索了一波 :mrgreen:
这个表情码,因为你定义表情替换规则肯定有这个关键词。果不然在 functions.php 里面写了 smilies_init()
这个函数。
但是我一看,这函数的对应部分和插件那个函数一模一样,那这插件是哪里有问题了呢?我注意到这个函数的注释:
Plugins may override the default smiley list by setting the $wpsmiliestrans to an array, with the key the code the blogger types in and the value the image file.
好家伙,这注释都说明了插件是可以覆盖 WordPress 内置的表情的,并且插件的代码确实重写了 $wpsmiliestrans
这个数组啊,怎么却不能成功显示呢?再看下一行注释:
The $wp_smiliessearch global is for the regular expression and is set each time the function is called.
说的是 $wp_smiliessearch
是正则表达式,在每次调用该函数的时候会被设定。然后我就突然发现,这插件的代码调用覆盖表情的函数之后,重写了 $wpsmiliestrans
这个数组,所以表情列表可以正常显示,但是插件没有重新设定 $wp_smiliessearch
,导致替换表情的正则表达式仍然只匹配 WordPress 默认的表情码。
发现这个之后,我立马把 WordPress 源码的这个函数整个复制到插件里面,比原来的函数多了以下内容,然后改成插件对应的函数名,再把我的新表情列表塞进去,保存刷新,好家伙,果不然可以正常显示了。
$wpsmiliestrans = apply_filters( 'smilies', $wpsmiliestrans ); if ( count( $wpsmiliestrans ) == 0 ) { return; } krsort( $wpsmiliestrans ); $spaces = wp_spaces_regexp(); $wp_smiliessearch = '/(?<=' . $spaces . '|^)'; $subchar = ''; foreach ( (array) $wpsmiliestrans as $smiley => $img ) { $firstchar = substr( $smiley, 0, 1 ); $rest = substr( $smiley, 1 ); // New subpattern? if ( $firstchar != $subchar ) { if ( '' !== $subchar ) { $wp_smiliessearch .= ')(?=' . $spaces . '|$)'; $wp_smiliessearch .= '|(?<=' . $spaces . '|^)'; } $subchar = $firstchar; $wp_smiliessearch .= preg_quote( $firstchar, '/' ) . '(?:'; } else { $wp_smiliessearch .= '|'; } $wp_smiliessearch .= preg_quote( $rest, '/' ); } $wp_smiliessearch .= ')(?=' . $spaces . '|$)/m';
因为 WordPress 源码的这个函数每次运行会重新设定匹配规则,而插件的函数并不会重新设定匹配规则,导致只能用 WordPress 设定好的匹配规则。修改后,插件每次也会设定新的匹配规则,所以我再插件里加的表情包就能正常匹配并显示了。
发表回复