WordPressのコメントのエンドポイントは、home_url( ‘/wp-comments-post.php’ ) であり、これを使用する場合ある程度バリデーションなどを行ってくれたり、そもそもプラグインはこれを前提としているため、基本的にはこのエンドポイントを使用することを想定している。

ただ(フックを使ってある程度は調整できるものの)HTMLの編集性が高くないため、ある程度WordPressに理解がある人であれば、自前で用意したりすることもあるだろう。

今回はそういった方向けに、実装した(けど結局使わなかった)プログラムをメモとしてここに貼り付けておく。

// functions.php

// 投稿ではコメントの表示を常にON
add_filter('comments_open', function($open, $post_id) {
  if (get_post_type($post_id) === 'post') {
    // return $open; // デフォルトの状態を取得
    return true; // 強制的にコメントをON
  }
  return false; // 強制的にコメントをOFF
}, 10 , 2);

// コメントの名前を自由に変更できるようにする
add_filter('pre_comment_author_name', function ($name){
  $user = wp_get_current_user();
  if ($user->ID && isset($_POST['author'])) {
    $name = trim(strip_tags($_POST['author']));
  }
  return $name;
});

// コメントのURLを自由に変更できるようにする
add_filter('pre_comment_author_url', function ($url){
  $user = wp_get_current_user();
  if ($user->ID && isset($_POST['url'])) {
    $url = trim(strip_tags($_POST['url']));
  }
  return $url;
});

// コメントのメールアドレスを自由に変更できるようにする
add_filter('pre_comment_author_email', function ($email){
  $user = wp_get_current_user();
  if ($user->ID && isset($_POST['email'])) {
    $email = trim(strip_tags($_POST['email']));
  }
  return $email;
});

// コメントフォームのバリデーション
// わざわざ /wp-comments-post.php でやらなくても、このレベルあれば、wp_insert_commentを使用して自前でエンドポイントを用意しPOSTリダイレクトなどを使用したほうがよいかも
add_action('pre_comment_on_post', function ($comment_post_ID) {
  if (get_post_type($comment_post_ID) === 'post') {
    $nonce = (isset($_POST['nonce']) ? trim($_POST['nonce']) : null);
    if ( !$nonce || !wp_verify_nonce( $nonce, 'comment-nonce-' . $comment_post_ID ) ) {
      wp_die('不正な操作を検知しました。');
    }

    // コメントの返信の返信はできないようにする
    $parent = (int)$_POST['comment_parent'];
    if ($parent !== 0) {
      $comments = get_comments([
        'comment__in' => $parent,
      ]);
      $comment = $comments[0];
      if ( $comment->parent !== 0 ) {
        wp_die('不正な操作を検知しました。');
      }
    }

    // 文字数制限
    $comment_content = $_POST['comment'];
    if (mb_strlen($comment_content) > 1000) {
      wp_die('コメントは1000文字以内で入力してください。');
    }
  }
});

// コメントフォーム送信後のリダイレクト先
// これで http://localhost/2020-03/comment-page-2/#comment-18 みたいにURLにページ数がつかないようにする
add_action('comment_post', function($comment_ID, $comment_approved, $commentdata) {
  // ページIDを取得
  $comment = get_comment($comment_ID);
  $post_id = $comment->comment_post_ID;
  wp_safe_redirect(get_permalink($post_id) . '#comment-' . $comment_ID);
  exit;
}, 10, 3);

// コメントにHTMLタグを挿入できないようにする
add_filter('preprocess_comment', function($data) {
	global $allowedtags;
	$allowedtags = array();
	return $data;
});

// リンクタグの自動挿入削除
remove_filter('comment_text', 'make_clickable', 9);

// pタグの自動挿入削除
remove_filter( 'comment_text', 'wpautop', 30 );

// コメントにHTMLタグを使った際、そのまま表示
add_filter('comment_text', function($comment_content) {
	if ( get_comment_type() == 'comment' ) {
	  $comment_content = esc_html($comment_content);
    $comment_content = nl2br($comment_content);
	}
	return $comment_content;
}, 9);
// comments.php
// フォーム部分のみ抜粋

<div id="respond">
    <form action="<?php echo home_url( '/wp-comments-post.php' ); ?>" method="post">
        <?php if (isset($_GET['reply']) && $_GET['reply'] !== ''): // 返信の場合は replay パラメーターがつくかたち ?>
        <input type="hidden" name="comment_parent" value="<?php echo esc_attr($_GET['reply']); ?>" />
        <h3>
            <strong><?php echo get_comment(strip_tags($_GET['reply']))->comment_author; ?>さんへの返信</strong>
            &nbsp;
            <a class="link" href="<?php the_permalink(); ?>#respond">キャンセル</a>
        </h3>
        <?php else: ?>
        <input type="hidden" name="comment_parent" value="0" />
        <h3>コメントを書く</h3>
        <?php endif; ?>

        <div class="form">
        <p>コメントするとご登録のユーザー名が公開されます。<br />コメントは1000文字以内で入力してください。</p>
        <textarea name="comment" placeholder="コメントを書く"></textarea>
        </div>
        <div class="btn-outer">
        <button type="submit" class="btn">送信する</button>
        </div>

        <input type="hidden" name="comment_post_ID" value="<?php echo get_the_ID(); ?>" />
        <input type="hidden" name="author" value="<?php echo wp_get_current_user()->display_name; ?>" />
        <input type="hidden" name="email" value="<?php echo wp_get_current_user()->user_email; ?>" />
        <input type="hidden" name="url" value="<?php echo wp_get_current_user()->user_url; ?>" />
        <input type="hidden" name="nonce" value="<?php echo wp_create_nonce( 'comment-nonce-' . get_the_ID() ); ?>" />
    </form>
</div>

上記のHTMLでは nameが重要で、エンドポイントで処理してくれるようname属性は必ず同じように設定しなくてはならないことに注意。