Wordpress最新版(6.8.3) PHP 8.3 で動作確認済。
実装
/**
* 公開予約記事のコメント投稿を許可する
* comment_on_draftアクションをフックして、コメント投稿処理を実行
*
* @param int $comment_post_ID 投稿ID
*/
function allow_comments_on_future_posts_handler($comment_post_ID)
{
// 公開予約記事かどうかを確認
$post = get_post($comment_post_ID);
if (!$post || $post->post_status !== 'future') {
return;
}
// コメント投稿処理を実行
do_action('pre_comment_on_post', $comment_post_ID);
// POSTデータからコメント情報を取得
$comment_author = isset($_POST['author']) ? trim(strip_tags($_POST['author'])) : '';
$comment_author_email = isset($_POST['email']) ? trim($_POST['email']) : '';
$comment_author_url = isset($_POST['url']) ? trim($_POST['url']) : '';
$comment_content = isset($_POST['comment']) ? trim($_POST['comment']) : '';
// ログインユーザーの場合
$user = wp_get_current_user();
if ($user->exists()) {
if (empty($user->display_name)) {
$user->display_name = $user->user_login;
}
$comment_author = wp_slash($user->display_name);
$comment_author_email = wp_slash($user->user_email);
$comment_author_url = wp_slash($user->user_url);
// フィルタリング権限のチェック
if (current_user_can('unfiltered_html')) {
if (!isset($_POST['_wp_unfiltered_html_comment']) ||
!wp_verify_nonce($_POST['_wp_unfiltered_html_comment'], 'unfiltered-html-comment_' . $comment_post_ID)) {
// kses なんとかは iframeタグを削除するとかのHTML無害化処理らしい
kses_remove_filters();
kses_init_filters();
}
}
} else {
// 非ログインユーザーの場合
if (get_option('comment_registration')) {
wp_die(__('Sorry, you must be logged in to post a comment.'));
}
}
$comment_type = '';
// 必須フィールドのチェック
if (get_option('require_name_email') && !$user->exists()) {
// 6 ... メールアドレスの理論上の最小値 a@b.co
if (6 > strlen($comment_author_email) || '' == $comment_author) {
wp_die(__('<strong>ERROR</strong>: please fill the required fields (name, email).'));
} elseif (!is_email($comment_author_email)) {
wp_die(__('<strong>ERROR</strong>: please enter a valid email address.'));
}
}
if ('' == $comment_content) {
wp_die(__('<strong>ERROR</strong>: please type a comment.'));
}
$comment_parent = isset($_POST['comment_parent']) ? absint($_POST['comment_parent']) : 0;
// コメントデータを構築
$commentdata = compact('comment_post_ID', 'comment_author', 'comment_author_email', 'comment_author_url', 'comment_content', 'comment_type', 'comment_parent', 'user_ID');
// コメントを投稿
$comment_id = wp_new_comment($commentdata);
$comment = get_comment($comment_id);
// クッキーを設定
//do_action('set_comment_cookies', $comment, $user);
// ログインユーザーの場合は自動承認
if ($user->exists()) {
wp_set_comment_status($comment_id, 'approve');
}
// リダイレクト先を決定
$location = empty($_POST['redirect_to']) ? get_comment_link($comment_id) : $_POST['redirect_to'] . '#comment-' . $comment_id;
$location = apply_filters('comment_post_redirect', $location, $comment);
// リダイレクト
wp_safe_redirect($location);
exit;
}
add_action('comment_on_draft', 'allow_comments_on_future_posts_handler');
はじめに
予約投稿記事にコメントする…?? 公開されていない記事に一般ユーザーがどうやって…???
私が持つ案件は予約投稿記事も一般公開するという特殊な事情があり、
予約投稿記事に未ログインユーザーでもコメントできる機能を提供する必要がありました。
なので、予約投稿というよりは、先行公開記事というイメージです。
(予約投稿記事を一般公開する方法は、説明と実装が大変なので割愛します)
上記の実装により、予約投稿記事でもコメントができるようになります。
一般ユーザーコメント、管理者コメント、返信、WP ULikeを用いたイイネができることを確認してあります。
予約投稿記事にコメントができない原因
通常、Wordpressは公開記事にしかコメントができません。
公開予約記事にコメントした場合、exitが走って強制的にコメント投稿が中止になります。
wp-comments-post.php の、L38行目で exit が走ります
// $_POST にはちゃんとコメントが入っていた
/*
array(9) {
["comment"]=>
string(36) "公開予約記事へのコメントテスト"
["author"]=>
string(18) "qwe001"
["email"]=>
string(18) "test@example.com"
["url"]=>
string(0) ""
["xo_security_captcha"]=>
string(12) "あいうえ"
["comment-form-bot-check"]=>
string(2) "OK"
["submit"]=>
string(6) "送信"
["comment_post_ID"]=>
string(6) "123456"
["comment_parent"]=>
string(1) "0"
}
*/
$comment = wp_handle_comment_submission( wp_unslash( $_POST ) ); // ここで int(0) になる
if ( is_wp_error( $comment ) ) { // $comment 変数が 0 なので、ここの条件分岐に入る
$data = (int) $comment->get_error_data();
if ( ! empty( $data ) ) {
wp_die(
'<p>' . $comment->get_error_message() . '</p>',
__( 'Comment Submission Failure' ),
array(
'response' => $data,
'back_link' => true,
)
);
} else {
exit; // ここに入り、強制終了になる
}
}
公開予約記事にコメントができないのは、記事の公開ステータスが 公開 or 非公開 以外のステータスの時、
下書きへのコメントとして処理するというフィルター comment_on_draft が動いているためです。
Wordpressコアファイル wp-includes/comment.php に、その実装がされています。
} elseif ( ! $status_obj->public && ! $status_obj->private ) {
/**
* Fires when a comment is attempted on a post in draft mode.
*
* @since 1.5.1
*
* @param int $comment_post_id Post ID.
*/
do_action( 'comment_on_draft', $comment_post_id );
if ( current_user_can( 'read_post', $comment_post_id ) ) {
return new WP_Error( 'comment_on_draft', __( 'Sorry, comments are not allowed for this item.' ), 403 );
} else {
return new WP_Error( 'comment_on_draft' );
}
}
予約投稿記事にコメントできるようにする方法
ということは、 comment_on_draft フィルターをなんかこう、イイ感じに調整すればコメントできるようになるのでは?
参考サイト
この投稿記事のおかげでなんとかなりました。神降臨あざす
kses_init_filters フィルターについて