WordPress save_post 这个钩子有三个参数分别是:$post_ID$post$update,本篇对第三个参数 $update 总结一下。

$update 的定义

$update 是一个布尔型参数,它要么是 true,要么是 false,WordPress 开发文档对 $update 参数的定义是:

"Whether this is an existing post being updated."

字面上理解理解这句话:是否是对现有日志的更新。

上述定义带有一定的歧义和误导,事实上在日志编辑界面,并不是点更新按钮 $update 就是 true,点保存或发布按钮 $update 就是 false 。 WordPress 是根据编辑界面的标题或内容字段(仅限这两个字段)较上一次保存的版本是否发生变更来确定 $update 其值的:不管点什么按钮,只要标题或内容这两个字段有变更,$update 就是 false,否则,如果未发生变更,不管点什么按钮,点多少次,$update 的值都是 true 。

有趣的是当 $update 为 true 时,会生成修订版本,否则不生成修订版本。因此,推断 $update 这个字段可能是用来判断是否生成修订版本的。

简单一句话总结 $update 参数: 标题或内容无变动时, 点操作按钮(保存草稿/发布/更新)$update 为 true; 反之 $update 为 false 。

save_post 的触发时机

关于 save_post 这个钩子在什么情况下会触发,WordPress 开发文档给的解释如下:

save_post is an action triggered whenever a post or page is created or updated, which could be from an import, post/page edit form, xmlrpc, or post by email

大意是当我们通过编辑界面、 xmlrpc(如 wordpress APP)、 email 、导入工具,创建或更新日志或页面时,就会触发 save_post 钩子。

通过实验总结,以上解释也不是很具体。以发布一篇日志为例,从创建、保存、发布、更新,期间会多次触发 save_post 这个钩子,在此总结一下(可能不全,甚至有误)。

  1. 点 “写文章”,生成 $post_id,并立即触发 save_post 钩子,$update 值是 false
  2. 撰写新文章界面,不填任何内容, 直接点保存草稿/发布,均不触发 save_post, 发布不会成功
  3. 自动保存不触发 save_post
  4. 除以上情况,手动点保存草稿/发布/更新,都将触发 save_post

总结

如果希望借助 save_post 钩子做很细的控制操作,仅仅凭借 $update 一个参数是不够的,可能还需要通过 wp_get_post_parent_id() 借助 $post_ID 判断是否为修订版本,甚至是 save_post 第二个参数 $post 中的 post_datepost_statuspost_modified 来辅助。

wp_get_post_parent_id()会返回当前日志的父 ID,如果当前日志是修订版本,wp_get_post_parent_id() 返回它所附属日志的 post_id(大于 0);否则,返回 0 。下面结合编辑界面的按钮动作将 $update 和 wp_get_post_parent_id() 的对应值做一下总结,简短起见且将 wp_get_post_parent_id() 的返回结果命名为 parent_id

有变更 动作 $update parent_id
/ 新建 false 0
保存 true 0
发布 true 0
更新 true 0
保存 false >0
发布 false >0
更新 false >0

一直想将自己在用的主题分享出来,只因有一些私人信息不好处理,一直作罢。最近一段时间,将主题里相关的配置信息剥离出来,统一放到配置文件中,使得分享得以实现,等于现在我只需要维护一个私有的配置文件即可。现在将主题托管在了 GitHub 上,点这里直接下载。

功能介绍

  • 响应式布局;
  • 自动暗黑模式;
  • 支持 schemas 标记;
  • 支持部分 web app 特性;
  • 日志和评论支持无限滚动加载;
  • 标准(standard)格式支持视频背景;
  • 状态(status)格式支持喜欢按钮、 支持地理位置坐标;
  • 日志、评论自动记录发布者终端设备信息;
  • 上传附件附加随机字符串的安全机制;
  • 相对完善的垃圾评论抑制机制;
  • 丰富多样的参数化配置;
  • 原生 JavaScript 支持;
  • 支持代码高亮。

前天晚间博客遭受了一波垃圾评论攻击,攻击者大概是看了我之前的一篇介绍在用的防垃圾评论的日志,知道我这里评论文本框的名字叫 little_star,因此哥们一夜一间就制造了几百条垃圾评论。真是出乎意料,我一直觉得没人会对我的无名小站感兴趣,没想到这一天还是来了。

因此,这两天对在用的防垃圾评论机制进行了一些改进,总体思路是生成动态的评论文本框名称。方法大概入如下:
在主题 function.php 文件中加入以下几个函数

// 生成随机字符串
function get_brave_hash($hash_length = NULL) {
	$hash_length = !is_int($hash_length) ? rand(8,14) : abs($hash_length);
	return substr(str_shuffle("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890"), -$hash_length);
}

session_start(); // 开启 session

// 生成评论框名称
function get_comment_text_name() {
	$comment_text_name = 'real_comment';
	$comment_text_name_hash = get_array_key('_SESSION', $comment_text_name);
	if ( isset($comment_text_name_hash) ) {
		// session 里存在时直接返回 $_SESSION 中存储的值
		return $comment_text_name_hash;
	}
	$sep = '_';
	$hash_length = 8; // 8 位长度
	$comment_text_name_hash = $comment_text_name . $sep . get_brave_hash($hash_length);
	// 加入到 session
	$_SESSION[$comment_text_name] = $comment_text_name_hash;
	return $comment_text_name_hash;
}

// 获取数组键值
function get_array_key($array, $key) {
	if (is_string($array)) {
		global $$array;
		return array_key_exists($key, $$array) ? $$array[$key] : null;
	}
	return array_key_exists($key, $array) ? $array[$key] : null;
}

在主题评论文件中(我这里是 comments.php)调用 get_comment_text_name() 函数,生成动态的名称,用作评论文本框名称:

<?php
$comment_text_name = get_comment_text_name();
comment_form( array(
'fields' => array(
'author' => '<p class="commentform"><input type="text" name="author" id="author" class="inp cmt-input" placeholder="昵称 [必填]" aria-required="true" size="30" value="' . esc_attr( $commenter['comment_author'] ) . '"></p>',
'email' => '<p class="commentform"><input type="text" name="email" id="email" class="inp cmt-input" placeholder="邮箱 [必填·保密]" aria-required="true" size="30" value="' . esc_attr( $commenter['comment_author_email'] ) . '"></p>',
'url' => '<p class="commentform"><input type="text" name="url" id="url" class="inp cmt-input" placeholder="网址 [选填]" size="30" value="'.$comment_author_url.'"></p>',
'cookies' => '<p class="comment-form-cookies-consent"><input id="wp-comment-cookies-consent" name="wp-comment-cookies-consent" type="checkbox" value="yes"' . $consent . ' />' .
'<label for="wp-comment-cookies-consent" class="c4"> 记住我的个人信息</label></p>'
),
'comment_field' => '<textarea id="comment" name="comment"></textarea>
<textarea name= ' . '"' .$comment_text_name . '"' . ' class="inp text-bg comment-textarea" placeholder="添加评论..." aria-required="true" cols="45" rows="8"></textarea>',
'title_reply' => '发表评论',
'cancel_reply_link' => '取消回复',
'label_submit' => '发表评论',
'comment_notes_before' => '',
'comment_notes_after' => '',
'class_submit' => 'btn submit',
'action' => '/wp-stop-spam.php'
));
?>

在 wp-stop-spam.php 文件中通过 session 获取评论框名称,并进行置换

<?php
/** Sets up the WordPress Environment. */
require_once __DIR__ . '/wp-load.php';
nocache_headers();

$comment = trim($_POST['comment']);
if ( empty( $comment ) ) {
// 置换评论内容
$comment_text_name = get_comment_text_name();
$_POST['comment'] = trim($_POST[$comment_text_name]);
require_once( __DIR__ . '/wp-comments-post.php' );
}
if ( ! empty( $comment ) ) {
	// 返回错误
	wp_die('放过我吧!');
}

6:20我被父亲的电话惊醒,昨晚剃了头,整夜我都在被窝里尝试通过调整不同的位置让后脑勺不觉得那么冷,空调似乎变成了只能吹风的风扇,夜间第一次醒来发现灯没关,我料定起身再回来被窝就凉了,干脆蒙上头。

此时父亲电话叫我开门,外面很黑,没有光,迎面勉强看到父亲轮廓,除去铁门开合的声音,村子里寂静无声,我到外面小解,院外昨晚的软泥和着雨雪融水已被冻硬,踩上去咯咯作响,骤然间鸡鸣四起,父亲叫我回去睡觉,我躺下不一会便听到外面牛棚里牛儿们进食喉咙里发出的沉闷喘息声,夹着牛脖子上链绳的清脆碰击声,还有父亲的呵斥声。

大概是上周的某一天爱人通过平板将手机丢失的信息告诉我:午后使唤孩子到菜鸟驿站取快递,手机装在孩子上衣兜里,不巧就丢在了取快递的路上。孩子到了快递站发现手机丢了,调头找回来未果,我们这才知道手机不见了。

随后我陆续拨了几次丢失的手机,能拨通只是无人接听。尝试通过“查找我的手机”定位手机也未能成功,随后打电话给电信公司挂失了号码。

不久老婆又来了消息她自己亲自找了一遍,还去物业找人查了监控,也没有任何线索。此时已能断定手机是被人捡走了。我向孩子打听了一些细节,孩子告诉我去的路上遇见一个外卖员,问孩子“小朋友上几年级了”,孩子说这个外卖员不像什么好人。孩子在快递站发现手机丢失返回寻找。又遇到那个外卖员返回,这次外卖员说又遇到你了。

听了孩子的描述我觉得这个外卖员可疑,想到前几年一起手机失窃的例子,窃贼不仅转走了钱,甚至利用受害人身份开网贷借钱转走。觉得不能大意,先挂失了支付宝,接着出于预防进一步财产损失的目的,抱着试试看的心态拨了110报警。

至此我们已经接受手机丢失的现实,只是丢失的手机里有很多家庭照片和其他资料,还是非常希望能够找回。

回想我多年前捡过一个钱包,最后完璧归赵;也捡过手机,最后交给失主,怎么我就不能遇到一次这样的好运呢!

报警还是有用的,当晚回家警察出警过来处置,一起去物业找人查监控,最后发现手机在一个监控摄像头的可视区域正下方约半米左右的界内掉落在地,相隔不到半分钟被物业的一个清洁工人拾起。

次日上午拿回手机,手机里的资料保住了,同时又节约了一笔意外开支。当晚孩子从口袋里掏一张纸片,孩子告诉我这是取快递用的,以后取快递会把取件号码写在纸上,这样就不会再把妈妈手机弄丢了。至于为什么第一次查监控没能有结果,可能是操作者不同,对系统熟悉程度不同,也不排除警察来了他们查的比较上心。