如何通过 WordPress REST API 添加一个带有未来发布日期的 post?

How to add a post via WordPress REST API with publish date in the future?

我想使用 WordPress 4.7 REST API 和 bashcurl 向 WordPress 网站添加新的 post 并设置发布日期以及客户端的 JSON-Tool“jq”。我已将 basic-auth 插件添加到 WordPress,以便我可以使用这种类型的身份验证。

我最初上传 posting 是这样的:

curl -s --location --basic --user 'name:password' \
     --url "https://<server>/wp-json/wp/v2/posts" \
     -d "title=Testpost" -d "content=This is a new post." | \
jq -r '"id: \(.id), date: \(.date), status: \(.status), title: \(.title.raw)"'

> id: 45, date: 2017-02-07T10:10:31, status: draft, title: Testpost

好的,这符合预期。让我们看看更改 post 是否有效:

curl -s --location --basic --user 'name:password' \
     --url "https://<server>/wp-json/wp/v2/posts/45" \
     -d "title=Other title" | \
jq -r '"date: \(.date), status: \(.status), title: \(.title.raw)"'

> date: 2017-02-07T10:20:32, status: draft, title: Other title

好的,有效。

现在我想在下午 3 点发布 post(“curl”参数缩小,因为它们没有改变):

curl ... "/wp-json/wp/v2/posts/45" \
     -d "date=2017-02-07T15:00:00" | \
jq -r '"id: \(.id), date: \(.date), status: \(.status)"'

> id: 45, date: 2017-02-07T10:29:32, status: draft

没有。日期更改为发出请求的时间,不是请求的发布日期。好的,也许状态 "pending"?

curl ... "/wp-json/wp/v2/posts/45" \
     -d "status=pending" -d "date=2017-02-07T15:00:00" | \
jq -r '"id: \(.id), date: \(.date), status: \(.status)"'

> id: 45, date: 2017-02-07T10:36:24, status: pending

嗯,状态设置为"pending",但是日期还是不对。也许明确地将状态设置为 "future"?

curl ... "/wp-json/wp/v2/posts/45" \
     -d "status=future" -d "date=2017-02-07T15:00:00" | \
jq -r '"id: \(.id), date: \(.date), status: \(.status)"'

> id: 45, date: 2017-02-07T10:36:48, status: publish

什么??? 这里发生了什么?现在,post 以当前日期发布。正是我不想拥有的。

但如果我现在用已发布的post重新发出相同的请求

curl ... "/wp-json/wp/v2/posts/45" \
     -d "status=future" -d "date=2017-02-07T15:00:00" | \
jq -r '"id: \(.id), date: \(.date), status: \(.status)"'

> id: 45, date: 2017-02-07T16:00:00, status: future

...它完成了工作 - 至少在某种程度上。不知何故,时间被解释为 UTC,但最终 post 被正确设置为 "future" 状态。

问题 1:如何让 post 进入这种状态 而不是 首先发布它?

问题 2:为什么日期被解释为 UTC?那不是“date_gmt”吗?

我在这里错过了什么?

好的,我想我得到了状态信息(问题 1)。

解法:

您可以通过中间将 post 状态设置为 private 来将发布日期更改为将来的日期。以下两个命令将草稿的发布日期更改为未来某个时间点而不会过早发布:

curl ... "/wp/v2/posts/45" -d "status=private"
curl ... "/wp/v2/posts/45" -d "status=future" -d "date=2017-02-07T15:00:00"

解释:

好的,这是为什么呢?这是 WordPress 核心的一项功能,可阻止预期的操作。让我们深入了解一下:

REST API 在 wp-includes/rest-api/endpoints 下面实现。对于处理 posts,代码是 class-wp-rest-posts-controller.php。更新 post 由 update_item() 从第 670 行开始(在 WP 4.7.2 中)处理。

那个函数做的不多。主要是,它在 WordPress 核心中调用 wp_update_post()。该方法在 wp-includes/post.php 中实现,从第 3534 行开始(原文如此!)。

在方法开始后不远处,我们发现了麻烦的代码行:

// Drafts shouldn't be assigned a date unless explicitly done so by the user.
if ( isset( $post['post_status'] ) &&
     in_array($post['post_status'], array('draft', 'pending', 'auto-draft')) &&
     empty($postarr['edit_date']) &&
     ('0000-00-00 00:00:00' == $post['post_date_gmt']) )
        $clear_date = true;
else
        $clear_date = false;

这就是问题所在:这里检查的所有数据都是已经存储的post信息。即使我通过 REST API 和我的更新请求一起传输新状态 future,也不会在这个地方进行评估。 $clear_date 仅根据数据库中的信息设置。由于我们的 post 作为草稿插入并且所有其他条件也匹配,因此它将始终是 true,这导致该方法进一步删除对日期字段的所有更新。因此,只要 post 的状态是 draftpendingauto-draft 之一,就无法更改 post 的发布日期.核心只是用它感觉的 "right".

覆盖对发布日期的所有预期更改

如本回复开头所述,解决方案是将 post 的状态中间更改为 private。该状态既不会触发任何发布操作,也不会出现在 wp_update_posts() 的 "special handling list" 上。因此,我们可以在第二步更改日期 - 然后更新状态,以便 post 将被发布。

我觉得这毕竟是个bug。在我看来,wp_update_post() 的关键部分应该考虑更新的新 post 状态,如果新状态(至少)是 published 之一,则保持新日期不变或 future.