: str_replace(): Passing null to parameter #2 ($replace) of type array|string is deprecated in
* @param string $link_url Cancel comment reply link URL.
* @param string $link_text Cancel comment reply link text.
return apply_filters( 'cancel_comment_reply_link', $cancel_comment_reply_link, $link_url, $link_text );
* Displays HTML content for cancel comment reply link.
* @param string $link_text Optional. Text to display for cancel reply link. If empty,
* defaults to 'Click here to cancel reply'. Default empty.
function cancel_comment_reply_link( $link_text = '' ) {
echo get_cancel_comment_reply_link( $link_text );
* Retrieves hidden input HTML for replying to comments.
* @since 6.2.0 Renamed `$post_id` to `$post` and added WP_Post support.
* @param int|WP_Post|null $post Optional. The post the comment is being displayed for.
* Defaults to the current global post.
* @return string Hidden input HTML for replying to comments.
function get_comment_id_fields( $post = null ) {
$post = get_post( $post );
$reply_to_id = _get_comment_reply_id( $post_id );
$comment_id_fields = "<input type='hidden' name='comment_post_ID' value='$post_id' id='comment_post_ID' />\n";
$comment_id_fields .= "<input type='hidden' name='comment_parent' id='comment_parent' value='$reply_to_id' />\n";
* Filters the returned comment ID fields.
* @param string $comment_id_fields The HTML-formatted hidden ID field comment elements.
* @param int $post_id The post ID.
* @param int $reply_to_id The ID of the comment being replied to.
return apply_filters( 'comment_id_fields', $comment_id_fields, $post_id, $reply_to_id );
* Outputs hidden input HTML for replying to comments.
* Adds two hidden inputs to the comment form to identify the `comment_post_ID`
* and `comment_parent` values for threaded comments.
* This tag must be within the `<form>` section of the `comments.php` template.
* @since 6.2.0 Renamed `$post_id` to `$post` and added WP_Post support.
* @see get_comment_id_fields()
* @param int|WP_Post|null $post Optional. The post the comment is being displayed for.
* Defaults to the current global post.
function comment_id_fields( $post = null ) {
echo get_comment_id_fields( $post );
* Displays text based on comment reply status.
* Only affects users with JavaScript disabled.
* @internal The $comment global must be present to allow template tags access to the current
* comment. See https://core.trac.wordpress.org/changeset/36512.
* @since 6.2.0 Added the `$post` parameter.
* @global WP_Comment $comment Global comment object.
* @param string|false $no_reply_text Optional. Text to display when not replying to a comment.
* @param string|false $reply_text Optional. Text to display when replying to a comment.
* Default false. Accepts "%s" for the author of the comment
* @param bool $link_to_parent Optional. Boolean to control making the author's name a link
* to their comment. Default true.
* @param int|WP_Post|null $post Optional. The post that the comment form is being displayed for.
* Defaults to the current global post.
function comment_form_title( $no_reply_text = false, $reply_text = false, $link_to_parent = true, $post = null ) {
if ( false === $no_reply_text ) {
$no_reply_text = __( 'Leave a Reply' );
if ( false === $reply_text ) {
/* translators: %s: Author of the comment being replied to. */
$reply_text = __( 'Leave a Reply to %s' );
$post = get_post( $post );
$reply_to_id = _get_comment_reply_id( $post->ID );
if ( 0 === $reply_to_id ) {
// Sets the global so that template tags can be used in the comment form.
$comment = get_comment( $reply_to_id );
$comment_author = sprintf(
'<a href="#comment-%1$s">%2$s</a>',
get_comment_author( $reply_to_id )
$comment_author = get_comment_author( $reply_to_id );
printf( $reply_text, $comment_author );
* Gets the comment's reply to ID from the $_GET['replytocom'].
* @param int|WP_Post $post The post the comment is being displayed for.
* Defaults to the current global post.
* @return int Comment's reply to ID.
function _get_comment_reply_id( $post = null ) {
$post = get_post( $post );
if ( ! $post || ! isset( $_GET['replytocom'] ) || ! is_numeric( $_GET['replytocom'] ) ) {
$reply_to_id = (int) $_GET['replytocom'];
* Bail out if it does not exist, is not approved, or its
* `comment_post_ID` does not match the given post ID.
$comment = get_comment( $reply_to_id );
! $comment instanceof WP_Comment ||
0 === (int) $comment->comment_approved ||
$post->ID !== (int) $comment->comment_post_ID
* Displays a list of comments.
* Used in the comments.php template to list comments for a particular post.
* @see WP_Query::$comments
* @global WP_Query $wp_query WordPress Query object.
* @global int $comment_alt
* @global int $comment_depth
* @global int $comment_thread_alt
* @global bool $overridden_cpage
* @global bool $in_comment_loop
* @param string|array $args {
* Optional. Formatting options.
* @type object $walker Instance of a Walker class to list comments. Default null.
* @type int $max_depth The maximum comments depth. Default empty.
* @type string $style The style of list ordering. Accepts 'ul', 'ol', or 'div'.
* 'div' will result in no additional list markup. Default 'ul'.
* @type callable $callback Callback function to use. Default null.
* @type callable $end-callback Callback function to use at the end. Default null.
* @type string $type Type of comments to list. Accepts 'all', 'comment',
* 'pingback', 'trackback', 'pings'. Default 'all'.
* @type int $page Page ID to list comments for. Default empty.
* @type int $per_page Number of comments to list per page. Default empty.
* @type int $avatar_size Height and width dimensions of the avatar size. Default 32.
* @type bool $reverse_top_level Ordering of the listed comments. If true, will display
* newest comments first. Default null.
* @type bool $reverse_children Whether to reverse child comments in the list. Default null.
* @type string $format How to format the comments list. Accepts 'html5', 'xhtml'.
* Default 'html5' if the theme supports it.
* @type bool $short_ping Whether to output short pings. Default false.
* @type bool $echo Whether to echo the output or return it. Default true.
* @param WP_Comment[] $comments Optional. Array of WP_Comment objects. Default null.
* @return void|string Void if 'echo' argument is true, or no comments to list.
* Otherwise, HTML list of comments.
function wp_list_comments( $args = array(), $comments = null ) {
global $wp_query, $comment_alt, $comment_depth, $comment_thread_alt, $overridden_cpage, $in_comment_loop;
'reverse_top_level' => null,
'reverse_children' => '',
'format' => current_theme_supports( 'html5', 'comment-list' ) ? 'html5' : 'xhtml',
$parsed_args = wp_parse_args( $args, $defaults );
* Filters the arguments used in retrieving the comment list.
* @see wp_list_comments()
* @param array $parsed_args An array of arguments for displaying comments.
$parsed_args = apply_filters( 'wp_list_comments_args', $parsed_args );
// Figure out what comments we'll be looping through ($_comments).
if ( null !== $comments ) {
$comments = (array) $comments;
if ( empty( $comments ) ) {
if ( 'all' !== $parsed_args['type'] ) {
$comments_by_type = separate_comments( $comments );
if ( empty( $comments_by_type[ $parsed_args['type'] ] ) ) {
$_comments = $comments_by_type[ $parsed_args['type'] ];
* If 'page' or 'per_page' has been passed, and does not match what's in $wp_query,
* perform a separate comment query and allow Walker_Comment to paginate.
if ( $parsed_args['page'] || $parsed_args['per_page'] ) {
$current_cpage = get_query_var( 'cpage' );
if ( ! $current_cpage ) {
$current_cpage = 'newest' === get_option( 'default_comments_page' ) ? 1 : $wp_query->max_num_comment_pages;
$current_per_page = get_query_var( 'comments_per_page' );
if ( $parsed_args['page'] != $current_cpage || $parsed_args['per_page'] != $current_per_page ) {
'post_id' => get_the_ID(),
'orderby' => 'comment_date_gmt',
if ( is_user_logged_in() ) {
$comment_args['include_unapproved'] = array( get_current_user_id() );
$unapproved_email = wp_get_unapproved_comment_author_email();
if ( $unapproved_email ) {
$comment_args['include_unapproved'] = array( $unapproved_email );
$comments = get_comments( $comment_args );
if ( 'all' !== $parsed_args['type'] ) {
$comments_by_type = separate_comments( $comments );
if ( empty( $comments_by_type[ $parsed_args['type'] ] ) ) {
$_comments = $comments_by_type[ $parsed_args['type'] ];
// Otherwise, fall back on the comments from `$wp_query->comments`.
if ( empty( $wp_query->comments ) ) {
if ( 'all' !== $parsed_args['type'] ) {
if ( empty( $wp_query->comments_by_type ) ) {
$wp_query->comments_by_type = separate_comments( $wp_query->comments );
if ( empty( $wp_query->comments_by_type[ $parsed_args['type'] ] ) ) {
$_comments = $wp_query->comments_by_type[ $parsed_args['type'] ];
$_comments = $wp_query->comments;
if ( $wp_query->max_num_comment_pages ) {
$default_comments_page = get_option( 'default_comments_page' );
$cpage = get_query_var( 'cpage' );
if ( 'newest' === $default_comments_page ) {
$parsed_args['cpage'] = $cpage;
* When first page shows oldest comments, post permalink is the same as
} elseif ( 1 == $cpage ) {
$parsed_args['cpage'] = '';
$parsed_args['cpage'] = $cpage;
$parsed_args['page'] = 0;
$parsed_args['per_page'] = 0;
if ( '' === $parsed_args['per_page'] && get_option( 'page_comments' ) ) {
$parsed_args['per_page'] = get_query_var( 'comments_per_page' );
if ( empty( $parsed_args['per_page'] ) ) {
$parsed_args['per_page'] = 0;
$parsed_args['page'] = 0;
if ( '' === $parsed_args['max_depth'] ) {
if ( get_option( 'thread_comments' ) ) {
$parsed_args['max_depth'] = get_option( 'thread_comments_depth' );
$parsed_args['max_depth'] = -1;
if ( '' === $parsed_args['page'] ) {
if ( empty( $overridden_cpage ) ) {
$parsed_args['page'] = get_query_var( 'cpage' );
$threaded = ( -1 != $parsed_args['max_depth'] );
$parsed_args['page'] = ( 'newest' === get_option( 'default_comments_page' ) ) ? get_comment_pages_count( $_comments, $parsed_args['per_page'], $threaded ) : 1;
set_query_var( 'cpage', $parsed_args['page'] );
$parsed_args['page'] = (int) $parsed_args['page'];
if ( 0 == $parsed_args['page'] && 0 != $parsed_args['per_page'] ) {
$parsed_args['page'] = 1;
if ( null === $parsed_args['reverse_top_level'] ) {
$parsed_args['reverse_top_level'] = ( 'desc' === get_option( 'comment_order' ) );
if ( empty( $parsed_args['walker'] ) ) {
$walker = new Walker_Comment();
$walker = $parsed_args['walker'];
$output = $walker->paged_walk( $_comments, $parsed_args['max_depth'], $parsed_args['page'], $parsed_args['per_page'], $parsed_args );
$in_comment_loop = false;
if ( $parsed_args['echo'] ) {
* Outputs a complete commenting form for use within a template.
* Most strings and form fields may be controlled through the `$args` array passed
* into the function, while you may also choose to use the {@see 'comment_form_default_fields'}
* filter to modify the array of default fields if you'd just like to add a new
* one or remove a single field. All fields are also individually passed through
* a filter of the {@see 'comment_form_field_$name'} where `$name` is the key used
* in the array of fields.
* @since 4.1.0 Introduced the 'class_submit' argument.
* @since 4.2.0 Introduced the 'submit_button' and 'submit_fields' arguments.
* @since 4.4.0 Introduced the 'class_form', 'title_reply_before', 'title_reply_after',
* 'cancel_reply_before', and 'cancel_reply_after' arguments.
* @since 4.5.0 The 'author', 'email', and 'url' form fields are limited to 245, 100,
* and 200 characters, respectively.
* @since 4.6.0 Introduced the 'action' argument.
* @since 4.9.6 Introduced the 'cookies' default comment field.
* @since 5.5.0 Introduced the 'class_container' argument.
* Optional. Default arguments and form fields to override.
* Default comment fields, filterable by default via the {@see 'comment_form_default_fields'} hook.
* @type string $author Comment author field HTML.
* @type string $email Comment author email field HTML.
* @type string $url Comment author URL field HTML.
* @type string $cookies Comment cookie opt-in field HTML.
* @type string $comment_field The comment textarea field HTML.
* @type string $must_log_in HTML element for a 'must be logged in to comment' message.
* @type string $logged_in_as The HTML for the 'logged in as [user]' message, the Edit profile link,
* @type string $comment_notes_before HTML element for a message displayed before the comment fields
* if the user is not logged in.
* Default 'Your email address will not be published.'.
* @type string $comment_notes_after HTML element for a message displayed after the textarea field.
* @type string $action The comment form element action attribute. Default '/wp-comments-post.php'.
* @type string $id_form The comment form element id attribute. Default 'commentform'.
* @type string $id_submit The comment submit element id attribute. Default 'submit'.
* @type string $class_container The comment form container class attribute. Default 'comment-respond'.
* @type string $class_form The comment form element class attribute. Default 'comment-form'.
* @type string $class_submit The comment submit element class attribute. Default 'submit'.
* @type string $name_submit The comment submit element name attribute. Default 'submit'.
* @type string $title_reply The translatable 'reply' button label. Default 'Leave a Reply'.
* @type string $title_reply_to The translatable 'reply-to' button label. Default 'Leave a Reply to %s',
* where %s is the author of the comment being replied to.
* @type string $title_reply_before HTML displayed before the comment form title.
* Default: '<h3 id="reply-title" class="comment-reply-title">'.
* @type string $title_reply_after HTML displayed after the comment form title.
* @type string $cancel_reply_before HTML displayed before the cancel reply link.
* @type string $cancel_reply_after HTML displayed after the cancel reply link.
* @type string $cancel_reply_link The translatable 'cancel reply' button label. Default 'Cancel reply'.
* @type string $label_submit The translatable 'submit' button label. Default 'Post a comment'.
* @type string $submit_button HTML format for the Submit button.
* Default: '<input name="%1$s" type="submit" id="%2$s" class="%3$s" value="%4$s" />'.
* @type string $submit_field HTML format for the markup surrounding the Submit button and comment hidden
* fields. Default: '<p class="form-submit">%1$s %2$s</p>', where %1$s is the
* submit button markup and %2$s is the comment hidden fields.
* @type string $format The comment form format. Default 'xhtml'. Accepts 'xhtml', 'html5'.
* @param int|WP_Post $post Optional. Post ID or WP_Post object to generate the form for. Default current post.
function comment_form( $args = array(), $post = null ) {
$post = get_post( $post );
// Exit the function if the post is invalid or comments are closed.
if ( ! $post || ! comments_open( $post ) ) {
* Fires after the comment form if comments are closed.
* For backward compatibility, this action also fires if comment_form()
* is called with an invalid post object or ID.
do_action( 'comment_form_comments_closed' );
$commenter = wp_get_current_commenter();
$user = wp_get_current_user();
$user_identity = $user->exists() ? $user->display_name : '';
$args = wp_parse_args( $args );
if ( ! isset( $args['format'] ) ) {
$args['format'] = current_theme_supports( 'html5', 'comment-form' ) ? 'html5' : 'xhtml';