サポート » 使い方全般 » comment_textフックに登録した関数内でget_comment_type()を実行するとエラー

  • 解決済 developer

    (@6flat)


    functions.phpに追加した次のコードでコメントを出力する前にエスケープしているのですが、コメントの新規投稿時にエラーが出てしまいました。

    function escape_comment_html( $s ) {
      if ( get_comment_type() === 'comment' ) {
        $s = esc_html( $s );
      }
      return $s;
    }
    add_filter( 'comment_text', 'escape_comment_html', 9 );

    エラー内容

    Warning: Creating default object from empty value in ...\wp-includes\comment-template.php on line 1015
    
    Warning: Cannot modify header information - headers already sent by (output started at ...\wp-includes\comment-template.php:1015) in ...\wp-includes\comment.php on line 517
    
    Warning: Cannot modify header information - headers already sent by (output started at ...\wp-includes\comment-template.php:1015) in ...\wp-includes\comment.php on line 518
    
    Warning: Cannot modify header information - headers already sent by (output started at ...\wp-includes\comment-template.php:1015) in ...\wp-includes\comment.php on line 519
    
    Warning: Cannot modify header information - headers already sent by (output started at ...\wp-includes\comment-template.php:1015) in ...\wp-includes\pluggable.php on line 1171

    comment-template.phpの該当箇所を次のようにするとエラーは出なくなったのですが、これはWordPressの不具合なのでしょうか?
    それとも、私がフィルターに登録した関数がまずかったのでしょうか?

    function get_comment_type( $comment_ID = 0 ) {
    	$comment = get_comment( $comment_ID );
    	if ( '' == $comment->comment_type ) {
    		$comment = new stdClass();
    		$comment->comment_type = 'comment';
    	}
    
    	/**
    	 * Filter the returned comment type.
    	 *
    	 * @since 1.5.0
    	 * @since 4.1.0 The <code>$comment_ID</code> and <code>$comment</code> parameters were added.
    	 *
    	 * @param string     $comment_type The type of comment, such as 'comment', 'pingback', or 'trackback'.
    	 * @param int 	     $comment_ID   The comment ID.
    	 * @param WP_Comment $comment      The comment object.
    	 */
    	return apply_filters( 'get_comment_type', $comment->comment_type, $comment->comment_ID, $comment );
    }

    また、コアファイルを編集せずに対処する方法があればそちらも知りたいです。
    よろしくお願い致します。

7件の返信を表示中 - 1 - 7件目 (全7件中)
  • フィルター comment_text は同じ名前で2種類ありますが、escape_comment_html はどちらへフックさせるものですか?
    https://developer.wordpress.org/reference/hooks/comment_text/

    wp-includes/comment-template.php#L939
    function comment_text の中で

    echo apply_filters( 'comment_text', $comment_text, $comment, $args );

    wp-includes/comment.php#L39
    function check_comment の中で

    $comment = apply_filters( 'comment_text', $comment );

    トピック投稿者 developer

    (@6flat)

    gblsmさん、ご回答ありがとうございます。

    初めて知りましたが、同名のフィルターが2つあるんですね。
    私の認識ではfunction comment_textにフックさせているつもりです。
    また、現在コメントを承認制にしておらず、またその予定もないのでcheck_commentの方にフックさせるつもりはありません。

    もしかするとフック先がおかしかったのでしょうか?

    いいえ、フック先がおかしいというわけではありません。そもそも同じ名前で引数が違うフィルターがあること自体がちょっと変だなと思ってお尋ねしただけです。

    新規コメントを入れた直後は、承認が必要なコメントかどうか判定するために function check_comment の方が(function comment_text よりも先に)呼ばれます。その時点ではコメントがまだデータベースへ登録されていないので、get_comment_type() ではコメントの種類を取得できません。function get_comment_type の内部でいうと、get_comment から null(コメントオブジェクトが見つからない)が返されます。

    これはフィルターが呼び出されるタイミング上、止むを得ないと思います。ですので escape_comment_html のコードを次のように変えてはどうでしょう。

    function escape_comment_html( $s ) {
      $c = get_comment();   // 新規コメントは null が返される
    
      if ( empty( $c ) || get_comment_type( $c ) === 'comment' ) {
        $s = esc_html( $s );
      }
      return $s;
    }

    同名のフィルターがあるのは、フックする関数の方で対処が可能だそうです。探すと下記のtracチケットに例が載っていましたので、ご参考まで。
    #24913 (comment_text filter used differently in two places in core) — WordPress Trac

    トピック投稿者 developer

    (@6flat)

    確かに、同じ名前のフィルターというのは不可思議ですし、紛らわしいですね。

    書いて下さったコードを試みたところ、コアファイルを修正することなく無事コメントを投稿できるようになりました。
    ありがとうございます。
    新規の投稿であるかどうかをそのようにして条件に加えたら良かったのですね。

    ちなみに、最初にget_commentでコメント情報が取得できないのなら$sの中身(コメント)も存在しないのではと安直に考えてしまったのですが、これは関数の実行されるタイミングの問題と見て良いですか?(うまく言葉を整理出来ませんが…)

    同名のフィルターがあるのは、フックする関数の方で対処が可能だそうです。

    第二引数がnullならcheck_comment(DBに挿入されたとき?)、nullじゃなければcomment_text(表示するとき)というように対処するという事でしょうか…?

    最初にget_commentでコメント情報が取得できないのなら$sの中身(コメント)も存在しないのでは

    整理すると次のようになります。

    • 新規コメントは、データベースへ書き込む前に関数 check_comment で中身(テキストだけ)がチェックされます。このときにフィルター comment_text は引数が1つ、中身(コメントの文字列)だけが渡されます。
    • コメントを表示するときは関数 comment_text が使われます。これはデータベースへ保存済みのコメントが対象なので、フィルター comment_text に3つの引数(1番めの引数は フィルター comment_text 経由のときと同じくコメントのテキスト)が渡されます。

    第二引数がnullならcheck_comment(DBに挿入されたとき?)、nullじゃなければcomment_text(表示するとき)というように対処するという事でしょうか…?

    例えば:

    function escape_comment_html_new( $comment_text, $comment = null ) {
      if ( $comment !== null && get_comment_type( $comment ) === 'comment' ) {
        $comment_text = esc_html( $comment_text );
      }
      return $comment_text;
    }
    add_filter( 'comment_text', 'escape_comment_html_new', 9, 2 );
    トピック投稿者 developer

    (@6flat)

    処理の流れを踏まえた上で、結果的に第二引数が無ければデータベースに書き込む前(function check_comment)のコメント本文に、第二引数があればデータベースへ保存済み(function comment_text)のコメント本文にフックすることが可能というわけですね。

    function comment_text()に確実フックしたいときは、新しく書いて頂いたコードのように第二引数をチェックした方が良さそうですね。

    分かりやすく説明して下さり助かりました。
    ありがとうございます。

7件の返信を表示中 - 1 - 7件目 (全7件中)
  • トピック「comment_textフックに登録した関数内でget_comment_type()を実行するとエラー」には新たに返信することはできません。