web-dev-qa-db-ja.com

保留中の投稿のフロントエンドプレビューページでコメントを有効にする

著者が共同で編集プロセスの一部になることを許可する過程にあります。保留中のすべての投稿のプレビューページにアクセスできます( not post-editページ)。

投稿が pending post_statusにあるときはいつでも、私はこれらのユーザが通常のコメントを投稿できるようにしたいです。

調査の結果、ここでは 包括的な解決策が掲載されています 。ただし、この解決策は編集後ページからのコメントのみ可能で、プレビューページではありません。にとって。

1

序文

投稿のプレビューがフロントエンドになると、コメントフォームはテーマの処理方法に依存します。この回答では、標準のcomment_form()関数を使用してコメントフォームが表示されると仮定します。

前の仮定では十分ではありません。実際、comment_formはおそらくWordPressコアのフックが多い関数です。ほとんどすべての行にフックがあります。そのため、ページに表示されるものは、プラグインまたはそれを変更できるテーマに大きく依存しています。

その後、comment_formを使用して、多くのフックを含むPOSTからwp-comment-post.phpへのコメントを保存します。そのため、私のソリューションがWPのVanillaインストールで動作する場合でもtwenty *テーマを使用すると、一部のプラグインまたはカスタムテーマでも動作することを保証できません。

ワークフロー

ですから、標準的なケースになると仮定すると、コメントフォームはajaxを使用せず、目的の結果を得るのに役立つ多くのフックがあるため、あなたが尋ねるのはリンクされたQ/Aより簡単です(序文でこの点のマイナス面について話しました)。

基本的に次のことを行う必要があります。

  1. 投稿のプレビューが保留中のときにコメントフォームにフィールドを追加すると、そのフォームからのコメントを認識できます。
  2. 保留中の投稿へのコメントを許可するためにWordPressのセキュリティチェックを解除する必要がある場合は、このチェックを別のチェックに置き換えることをお勧めします。ポイント1で非表示フィールドにnonceを使用するのは良い考えです。
  3. 追加のセキュリティチェックとして、登録ユーザーのみにコメントを有効にすることをお勧めします(ただし、登録ユーザーのみにプレビューアクセスを既に許可しているようです)。おそらく、ロールを制限することもお勧めです。
  4. このワークフローの中核部分は、break保留中および下書きの投稿に対するコメントを防ぐためにWordPressが行うチェックです。私のアイデアはtease WordPressであり、投稿が公開されたと信じておくだけです。私がやる方法は、コードを防ぐためにグローバル変数を避けるべき理由の例と考えることができます。誰かがからかいです。
  5. 最後に行う必要があるのは、コメントの作成後にリダイレクトをインターセプトすることです。これは、標準リダイレクトが標準ポストパーマリンクを指すため、ポストプレビューパーマリンクをポイントする必要があるためです。

コード

まず最初に、許可されたログに記録されたユーザーおよび投稿のプレビューでのみ、コメントフォームにナンスフィールドを追加する関数を作成しましょう。また、現在のユーザーが許可されているユーザーの1人であるかどうかを確認する関数を作成します。これにより、他のスコープで使用できます。この関数では、カスタムフィルターフックを配置します。この方法で、ロールalloewdを変更できます。

/**
 * Return true if user can comment on post preview
 */
function is_a_preview_commenter() {
  // change this roles according to your needs
  $roles = array('administrator', 'editor', 'author', 'contributor');
  $allowed_roles = apply_filters('preview_comment_allowed_roles', $roles);
  $user = wp_get_current_user();
  $inrole = array_intersect($user->roles, $allowed_roles);
  return ! empty( $inrole );
} 

/**
 * Add a nonce field for comment form in post preview for allowed users
 */
function additional_comment_fields() {
  if ( is_preview() && is_a_preview_commenter() ) {
    $nonce = wp_create_nonce('comment_preview');
    echo '<input type="hidden" name="check_the_preview" value="' . $nonce . '" />';
  }
}
add_action( 'comment_form_logged_in_after', 'additional_comment_fields');

それでは、WordPressをいじりましょう。 WPを使用して投稿のステータスをコメントするのが適切かどうかを確認する方法は、$status_obj = get_post_status_object($status)を呼び出すことです(ここで、$statusはコメントされている投稿のpost_statusフィールドです) $status_objprivateまたはpublicであるかどうかを確認してください。そうでない場合はwp_dieです。ただし、get_post_status_objectが行う唯一のことは、グローバル配列$wp_post_statuses(要求された投稿ステータスでキー設定されたもの)から値を返すことです。 Fakingグローバル変数は、get_post_status_objectを偽造することを意味するため、WordPressチェックを偽造することも意味します。

グローバル変数の変更は非常に簡単ですが、投稿が私たちから来ていることを確認するためにいくつかのチェックを行い(以前に追加されたノンス隠しフィールドのおかげ)、現在のユーザーが存在して許可されているかどうかも確認します:

/**
 * On 'wp_loaded', when the current page is wp-comments-post.php, check if the request
 * comes from post preview, if so and also the current user is allowed replace 
 * $GLOBALS['wp_post_statuses']['pending'] with $GLOBALS['wp_post_statuses']['publish']
 */
function fake_public_pending() {
  global $pagenow;
  if ( $pagenow === 'wp-comments-post.php' && is_a_preview_commenter() ) {
    $nonce = filter_input(INPUT_POST, 'check_the_preview', FILTER_SANITIZE_STRING);
    if ( empty($nonce) || ! wp_verify_nonce($nonce, 'comment_preview') ) return;
    global $wp_post_statuses;
    // let WordPress believe all pending posts are published post
    $wp_post_statuses['pending'] = $wp_post_statuses['publish'];
  }
}
add_action('wp_loaded', 'fake_public_pending');

投稿プレビューからコメントが挿入された後、プレビューを投稿するにはブラウザを再度リダイレクトする必要があります。いつものように、リクエストはプレビューの投稿からのものであり、現在のユーザーは許可されたロールの1つを持っている

/**
 * After a comment is inserted, redirect page to post preview when request come from
 * post preview. Also check if current user role is one of the allowed
 */
function redirect_to_preview( $comment, $user ) {
  if ( ! is_a_preview_commenter() ) return;
  $nonce = filter_input(INPUT_POST, 'check_the_preview', FILTER_SANITIZE_STRING);
  if ( empty($nonce) || ! wp_verify_nonce($nonce, 'comment_preview') ) return;
  $link = get_permalink($comment->comment_post_ID);
  $url = add_query_arg( array('preview' => 'true'), $link );
  wp_safe_redirect("{$url}#comment-{$comment->comment_ID}", 302);
  exit();
}
add_action('set_comment_cookies', 'redirect_to_preview', 9999, 2 );
5
gmazzap