有时候有这样一个需求,如果用户输入了一段指定的评论,必须要求进行过滤的处理,有种处理方式就是白名单,白名单机制相当严格,但也非常有效。
需求是这样的,只允许用户输入自己的在列表中的链接地址才给显示,否者就不予显示。比如我的就可以只对loveyu.org下面的域名才进行超链接,如果不是的话直接显示为文本,这样处理也是很好的。看代码:
/**
* 过滤评论中的URL
* @param string $comment
* @return string
*/
function two_heart_comment_url_filter($comment){
$allow_domain = [
'loveyu.org',
'loveyu.net',
'loveyu.me',
'loveyu.info',
'baidu.com',
'google.com',
'stackoverflow.com',
'github.com',];
preg_match_all("/<a[\\s\\S]{1,}?href=["|']{1}([\\S]+?)["|']{1}[\\s\\S]+?>([\\S]+?)<\\/a>/", $comment, $matches, PREG_SET_ORDER);
foreach($matches as $v){
$is_match = false;
$host = explode(".", strtolower(parse_url($v[1], PHP_URL_HOST)));
$c = count($host);
foreach($allow_domain as $domain){
$host_v = explode(".", $domain);
$c_v = count($host_v);
if($c >= $c_v){
$flag = true;
for($i = 1; $i <= $c_v; $i++){
if($host_v[$c_v - $i] != $host[$c - $i]){
$flag = false;
break;
}
}
if($flag){
//匹配
$is_match = true;
break;
}
}
}
if($is_match){
continue;
}
if($v[1] == $v[2]){
//相同值过滤
$comment = str_replace($v[0], $v[1], $comment);
} else{
//不同值过滤
$comment = str_replace($v[0], $v[2] . ":" . $v[1], $comment);
}
}
return $comment;
}
* 过滤评论中的URL
* @param string $comment
* @return string
*/
function two_heart_comment_url_filter($comment){
$allow_domain = [
'loveyu.org',
'loveyu.net',
'loveyu.me',
'loveyu.info',
'baidu.com',
'google.com',
'stackoverflow.com',
'github.com',];
preg_match_all("/<a[\\s\\S]{1,}?href=["|']{1}([\\S]+?)["|']{1}[\\s\\S]+?>([\\S]+?)<\\/a>/", $comment, $matches, PREG_SET_ORDER);
foreach($matches as $v){
$is_match = false;
$host = explode(".", strtolower(parse_url($v[1], PHP_URL_HOST)));
$c = count($host);
foreach($allow_domain as $domain){
$host_v = explode(".", $domain);
$c_v = count($host_v);
if($c >= $c_v){
$flag = true;
for($i = 1; $i <= $c_v; $i++){
if($host_v[$c_v - $i] != $host[$c - $i]){
$flag = false;
break;
}
}
if($flag){
//匹配
$is_match = true;
break;
}
}
}
if($is_match){
continue;
}
if($v[1] == $v[2]){
//相同值过滤
$comment = str_replace($v[0], $v[1], $comment);
} else{
//不同值过滤
$comment = str_replace($v[0], $v[2] . ":" . $v[1], $comment);
}
}
return $comment;
}
上面的代码是过滤评论的代码,单独使用并没有什么异样,现在要做的就是与Wordpress结合起来,方法也很简单,一个钩子函数搞定一切。但要注意优先级的问题,如果优先级太低会导致执行顺序异常,最后过滤无效。
/**
* 添加评论内容过滤器
*/
add_action('comment_text', 'two_heart_comment_url_filter', 50);
* 添加评论内容过滤器
*/
add_action('comment_text', 'two_heart_comment_url_filter', 50);
再看看默认的过滤器列表,就会发现一些特点,过滤器干了很多事,实际上不一定要在最后添加一个过滤器,直接修改make_clickable这个函数也是可以的,当然你看了这个函数后就不会再有这样的想法了,正则看了眼晕。另一种方法是移除这个过滤器,然后自己写个,和上一个方法等价,也不值得推荐,最合适的就是我的做法了,所有事情处理完后再过滤一遍完事。
上面的代码并不是最漂亮的,还有其他的方式去处理,比如说用个非常优雅的正则去替换我写的循环匹配,不得不说循环只是不好看而已,但效率绝对足够。正则好看,但效率低。其实这只是我自我安慰的,因为没想出合适的正则的借口罢了,不过问题已解决,请听下回分解。
这个挺好的,一般保留评论者昵称那里有链接就可以了,内容上不需要有链接的
是的,同时保证部分安全连接还是可行的
这种小数据量,循环足够了
啥意思 没有链接怎么回访
我只看我右边的最近访客,如果不在列表上就主动忽略,还有头像旁边也有链接的啊