+/**
+ * Retrieve HTML content for reply to comment link.
+ *
+ * @since 2.7.0
+ *
+ * @param array $args {
+ * Optional. Override default arguments.
+ *
+ * @type string $add_below The first part of the selector used to identify the comment to respond below.
+ * The resulting value is passed as the first parameter to addComment.moveForm(),
+ * concatenated as $add_below-$comment->comment_ID. Default 'comment'.
+ * @type string $respond_id The selector identifying the responding comment. Passed as the third parameter
+ * to addComment.moveForm(), and appended to the link URL as a hash value.
+ * Default 'respond'.
+ * @type string $reply_text The text of the Reply link. Default 'Reply'.
+ * @type string $login_text The text of the link to reply if logged out. Default 'Log in to Reply'.
+ * @type int $depth' The depth of the new comment. Must be greater than 0 and less than the value
+ * of the 'thread_comments_depth' option set in Settings > Discussion. Default 0.
+ * @type string $before The text or HTML to add before the reply link. Default empty.
+ * @type string $after The text or HTML to add after the reply link. Default empty.
+ * }
+ * @param int $comment Comment being replied to. Default current comment.
+ * @param int|WP_Post $post Post ID or WP_Post object the comment is going to be displayed on.
+ * Default current post.
+ * @return null|false|string Link to show comment form, if successful. False, if comments are closed.
+ */
+function get_comment_reply_link( $args = array(), $comment = null, $post = null ) {
+
+ $defaults = array(
+ 'add_below' => 'comment',
+ 'respond_id' => 'respond',
+ 'reply_text' => __( 'Reply' ),
+ 'reply_to_text' => __( 'Reply to %s' ),
+ 'login_text' => __( 'Log in to Reply' ),
+ 'depth' => 0,
+ 'before' => '',
+ 'after' => ''
+ );
+
+ $args = wp_parse_args( $args, $defaults );
+
+ if ( 0 == $args['depth'] || $args['max_depth'] <= $args['depth'] ) {
+ return;
+ }
+
+ $comment = get_comment( $comment );
+
+ if ( empty( $post ) ) {
+ $post = $comment->comment_post_ID;
+ }
+
+ $post = get_post( $post );
+
+ if ( ! comments_open( $post->ID ) ) {
+ return false;
+ }
+
+ /**
+ * Filter the comment reply link arguments.
+ *
+ * @since 4.1.0
+ *
+ * @param array $args Comment reply link arguments. See {@see get_comment_reply_link()}
+ * for more information on accepted arguments.
+ * @param object $comment The object of the comment being replied to.
+ * @param WP_Post $post The {@see WP_Post} object.
+ */
+ $args = apply_filters( 'comment_reply_link_args', $args, $comment, $post );
+
+ if ( get_option( 'comment_registration' ) && ! is_user_logged_in() ) {
+ $link = sprintf( '<a rel="nofollow" class="comment-reply-login" href="%s">%s</a>',
+ esc_url( wp_login_url( get_permalink() ) ),
+ $args['login_text']
+ );
+ } else {
+ $onclick = sprintf( 'return addComment.moveForm( "%1$s-%2$s", "%2$s", "%3$s", "%4$s" )',
+ $args['add_below'], $comment->comment_ID, $args['respond_id'], $post->ID
+ );
+
+ $link = sprintf( "<a class='comment-reply-link' href='%s' onclick='%s' aria-label='%s'>%s</a>",
+ esc_url( add_query_arg( 'replytocom', $comment->comment_ID ) ) . "#" . $args['respond_id'],
+ $onclick,
+ esc_attr( sprintf( $args['reply_to_text'], $comment->comment_author ) ),
+ $args['reply_text']
+ );
+ }
+ /**
+ * Filter the comment reply link.
+ *
+ * @since 2.7.0
+ *
+ * @param string $link The HTML markup for the comment reply link.
+ * @param array $args An array of arguments overriding the defaults.
+ * @param object $comment The object of the comment being replied.
+ * @param WP_Post $post The WP_Post object.
+ */
+ return apply_filters( 'comment_reply_link', $args['before'] . $link . $args['after'], $args, $comment, $post );
+}
+
+/**
+ * Displays the HTML content for reply to comment link.
+ *
+ * @since 2.7.0
+ *
+ * @see get_comment_reply_link()
+ *
+ * @param array $args Optional. Override default options.
+ * @param int $comment Comment being replied to. Default current comment.
+ * @param int|WP_Post $post Post ID or WP_Post object the comment is going to be displayed on.
+ * Default current post.
+ * @return mixed Link to show comment form, if successful. False, if comments are closed.
+ */
+function comment_reply_link($args = array(), $comment = null, $post = null) {
+ echo get_comment_reply_link($args, $comment, $post);
+}
+
+/**
+ * Retrieve HTML content for reply to post link.
+ *
+ * @since 2.7.0
+ *
+ * @param array $args {
+ * Optional. Override default arguments.
+ *
+ * @type string $add_below The first part of the selector used to identify the comment to respond below.
+ * The resulting value is passed as the first parameter to addComment.moveForm(),
+ * concatenated as $add_below-$comment->comment_ID. Default is 'post'.
+ * @type string $respond_id The selector identifying the responding comment. Passed as the third parameter
+ * to addComment.moveForm(), and appended to the link URL as a hash value.
+ * Default 'respond'.
+ * @type string $reply_text Text of the Reply link. Default is 'Leave a Comment'.
+ * @type string $login_text Text of the link to reply if logged out. Default is 'Log in to leave a Comment'.
+ * @type string $before Text or HTML to add before the reply link. Default empty.
+ * @type string $after Text or HTML to add after the reply link. Default empty.
+ * }
+ * @param int|WP_Post $post Optional. Post ID or WP_Post object the comment is going to be displayed on.
+ * Default current post.
+ * @return false|null|string Link to show comment form, if successful. False, if comments are closed.
+ */
+function get_post_reply_link($args = array(), $post = null) {
+ $defaults = array(
+ 'add_below' => 'post',
+ 'respond_id' => 'respond',
+ 'reply_text' => __('Leave a Comment'),
+ 'login_text' => __('Log in to leave a Comment'),
+ 'before' => '',
+ 'after' => '',
+ );
+
+ $args = wp_parse_args($args, $defaults);
+
+ $post = get_post($post);
+
+ if ( ! comments_open( $post->ID ) ) {
+ return false;
+ }
+
+ if ( get_option('comment_registration') && ! is_user_logged_in() ) {
+ $link = sprintf( '<a rel="nofollow" href="%s">%s</a>',
+ wp_login_url( get_permalink() ),
+ $args['login_text']
+ );
+ } else {
+ $onclick = sprintf( 'return addComment.moveForm( "%1$s-%2$s", "0", "%3$s", "%2$s" )',
+ $args['add_below'], $post->ID, $args['respond_id']
+ );
+
+ $link = sprintf( "<a rel='nofollow' class='comment-reply-link' href='%s' onclick='%s'>%s</a>",
+ get_permalink( $post->ID ) . '#' . $args['respond_id'],
+ $onclick,
+ $args['reply_text']
+ );
+ }
+ $formatted_link = $args['before'] . $link . $args['after'];
+ /**
+ * Filter the formatted post comments link HTML.
+ *
+ * @since 2.7.0
+ *
+ * @param string $formatted The HTML-formatted post comments link.
+ * @param int|WP_Post $post The post ID or WP_Post object.
+ */
+ return apply_filters( 'post_comments_link', $formatted_link, $post );
+}
+
+/**
+ * Displays the HTML content for reply to post link.
+ *
+ * @since 2.7.0
+ *
+ * @see get_post_reply_link()
+ *
+ * @param array $args Optional. Override default options,
+ * @param int|WP_Post $post Post ID or WP_Post object the comment is going to be displayed on.
+ * Default current post.
+ * @return string|bool|null Link to show comment form, if successful. False, if comments are closed.
+ */
+function post_reply_link($args = array(), $post = null) {
+ echo get_post_reply_link($args, $post);
+}
+
+/**
+ * Retrieve HTML content for cancel comment reply link.
+ *
+ * @since 2.7.0
+ *
+ * @param string $text Optional. Text to display for cancel reply link. Default empty.
+ */
+function get_cancel_comment_reply_link( $text = '' ) {
+ if ( empty($text) )
+ $text = __('Click here to cancel reply.');
+
+ $style = isset($_GET['replytocom']) ? '' : ' style="display:none;"';
+ $link = esc_html( remove_query_arg('replytocom') ) . '#respond';
+
+ $formatted_link = '<a rel="nofollow" id="cancel-comment-reply-link" href="' . $link . '"' . $style . '>' . $text . '</a>';
+ /**
+ * Filter the cancel comment reply link HTML.
+ *
+ * @since 2.7.0
+ *
+ * @param string $formatted_link The HTML-formatted cancel comment reply link.
+ * @param string $link Cancel comment reply link URL.
+ * @param string $text Cancel comment reply link text.
+ */
+ return apply_filters( 'cancel_comment_reply_link', $formatted_link, $link, $text );
+}
+
+/**
+ * Display HTML content for cancel comment reply link.
+ *
+ * @since 2.7.0
+ *
+ * @param string $text Optional. Text to display for cancel reply link. Default empty.
+ */
+function cancel_comment_reply_link( $text = '' ) {
+ echo get_cancel_comment_reply_link($text);
+}
+
+/**
+ * Retrieve hidden input HTML for replying to comments.
+ *
+ * @since 3.0.0
+ *
+ * @param int $id Optional. Post ID. Default current post ID.
+ * @return string Hidden input HTML for replying to comments
+ */
+function get_comment_id_fields( $id = 0 ) {
+ if ( empty( $id ) )
+ $id = get_the_ID();
+
+ $replytoid = isset($_GET['replytocom']) ? (int) $_GET['replytocom'] : 0;
+ $result = "<input type='hidden' name='comment_post_ID' value='$id' id='comment_post_ID' />\n";
+ $result .= "<input type='hidden' name='comment_parent' id='comment_parent' value='$replytoid' />\n";
+
+ /**
+ * Filter the returned comment id fields.
+ *
+ * @since 3.0.0
+ *
+ * @param string $result The HTML-formatted hidden id field comment elements.
+ * @param int $id The post ID.
+ * @param int $replytoid The id of the comment being replied to.
+ */
+ return apply_filters( 'comment_id_fields', $result, $id, $replytoid );
+}
+
+/**
+ * Output hidden input HTML for replying to comments.
+ *
+ * @since 2.7.0
+ *
+ * @param int $id Optional. Post ID. Default current post ID.
+ */
+function comment_id_fields( $id = 0 ) {
+ echo get_comment_id_fields( $id );
+}
+
+/**
+ * Display text based on comment reply status.
+ *
+ * Only affects users with JavaScript disabled.
+ *
+ * @since 2.7.0
+ *
+ * @param string $noreplytext Optional. Text to display when not replying to a comment.
+ * Default false.
+ * @param string $replytext Optional. Text to display when replying to a comment.
+ * Default false. Accepts "%s" for the author of the comment
+ * being replied to.
+ * @param string $linktoparent Optional. Boolean to control making the author's name a link
+ * to their comment. Default true.
+ */
+function comment_form_title( $noreplytext = false, $replytext = false, $linktoparent = true ) {
+ global $comment;
+
+ if ( false === $noreplytext ) $noreplytext = __( 'Leave a Reply' );
+ if ( false === $replytext ) $replytext = __( 'Leave a Reply to %s' );
+
+ $replytoid = isset($_GET['replytocom']) ? (int) $_GET['replytocom'] : 0;
+
+ if ( 0 == $replytoid )
+ echo $noreplytext;
+ else {
+ $comment = get_comment($replytoid);
+ $author = ( $linktoparent ) ? '<a href="#comment-' . get_comment_ID() . '">' . get_comment_author() . '</a>' : get_comment_author();
+ printf( $replytext, $author );
+ }
+}
+
+/**
+ * HTML comment list class.
+ *
+ * @uses Walker
+ * @since 2.7.0
+ */
+class Walker_Comment extends Walker {
+ /**
+ * What the class handles.
+ *
+ * @see Walker::$tree_type
+ *
+ * @since 2.7.0
+ * @var string
+ */
+ public $tree_type = 'comment';
+
+ /**
+ * DB fields to use.
+ *
+ * @see Walker::$db_fields
+ *
+ * @since 2.7.0
+ * @var array
+ */
+ public $db_fields = array ('parent' => 'comment_parent', 'id' => 'comment_ID');
+
+ /**
+ * Start the list before the elements are added.
+ *
+ * @see Walker::start_lvl()
+ *
+ * @since 2.7.0
+ *
+ * @param string $output Passed by reference. Used to append additional content.
+ * @param int $depth Depth of comment.
+ * @param array $args Uses 'style' argument for type of HTML list.
+ */
+ public function start_lvl( &$output, $depth = 0, $args = array() ) {
+ $GLOBALS['comment_depth'] = $depth + 1;
+
+ switch ( $args['style'] ) {
+ case 'div':
+ break;
+ case 'ol':
+ $output .= '<ol class="children">' . "\n";
+ break;
+ case 'ul':
+ default:
+ $output .= '<ul class="children">' . "\n";
+ break;
+ }
+ }
+
+ /**
+ * End the list of items after the elements are added.
+ *
+ * @see Walker::end_lvl()
+ *
+ * @since 2.7.0
+ *
+ * @param string $output Passed by reference. Used to append additional content.
+ * @param int $depth Depth of comment.
+ * @param array $args Will only append content if style argument value is 'ol' or 'ul'.
+ */
+ public function end_lvl( &$output, $depth = 0, $args = array() ) {
+ $GLOBALS['comment_depth'] = $depth + 1;
+
+ switch ( $args['style'] ) {
+ case 'div':
+ break;
+ case 'ol':
+ $output .= "</ol><!-- .children -->\n";
+ break;
+ case 'ul':
+ default:
+ $output .= "</ul><!-- .children -->\n";
+ break;
+ }
+ }
+
+ /**
+ * Traverse elements to create list from elements.
+ *
+ * This function is designed to enhance Walker::display_element() to
+ * display children of higher nesting levels than selected inline on
+ * the highest depth level displayed. This prevents them being orphaned
+ * at the end of the comment list.
+ *
+ * Example: max_depth = 2, with 5 levels of nested content.
+ * 1
+ * 1.1
+ * 1.1.1
+ * 1.1.1.1
+ * 1.1.1.1.1
+ * 1.1.2
+ * 1.1.2.1
+ * 2
+ * 2.2
+ *
+ * @see Walker::display_element()
+ * @see wp_list_comments()
+ *
+ * @since 2.7.0
+ *
+ * @param object $element Data object.
+ * @param array $children_elements List of elements to continue traversing.
+ * @param int $max_depth Max depth to traverse.
+ * @param int $depth Depth of current element.
+ * @param array $args An array of arguments.
+ * @param string $output Passed by reference. Used to append additional content.
+ * @return null Null on failure with no changes to parameters.
+ */
+ public function display_element( $element, &$children_elements, $max_depth, $depth, $args, &$output ) {
+
+ if ( !$element )
+ return;
+
+ $id_field = $this->db_fields['id'];
+ $id = $element->$id_field;
+
+ parent::display_element( $element, $children_elements, $max_depth, $depth, $args, $output );
+
+ // If we're at the max depth, and the current element still has children, loop over those and display them at this level
+ // This is to prevent them being orphaned to the end of the list.
+ if ( $max_depth <= $depth + 1 && isset( $children_elements[$id]) ) {
+ foreach ( $children_elements[ $id ] as $child )
+ $this->display_element( $child, $children_elements, $max_depth, $depth, $args, $output );
+
+ unset( $children_elements[ $id ] );
+ }
+
+ }
+
+ /**
+ * Start the element output.
+ *
+ * @since 2.7.0
+ *
+ * @see Walker::start_el()
+ * @see wp_list_comments()
+ *
+ * @param string $output Passed by reference. Used to append additional content.
+ * @param object $comment Comment data object.
+ * @param int $depth Depth of comment in reference to parents.
+ * @param array $args An array of arguments.
+ */
+ public function start_el( &$output, $comment, $depth = 0, $args = array(), $id = 0 ) {
+ $depth++;
+ $GLOBALS['comment_depth'] = $depth;
+ $GLOBALS['comment'] = $comment;
+
+ if ( !empty( $args['callback'] ) ) {
+ ob_start();
+ call_user_func( $args['callback'], $comment, $args, $depth );
+ $output .= ob_get_clean();
+ return;
+ }
+
+ if ( ( 'pingback' == $comment->comment_type || 'trackback' == $comment->comment_type ) && $args['short_ping'] ) {
+ ob_start();
+ $this->ping( $comment, $depth, $args );
+ $output .= ob_get_clean();
+ } elseif ( 'html5' === $args['format'] ) {
+ ob_start();
+ $this->html5_comment( $comment, $depth, $args );
+ $output .= ob_get_clean();
+ } else {
+ ob_start();
+ $this->comment( $comment, $depth, $args );
+ $output .= ob_get_clean();
+ }
+ }
+
+ /**
+ * Ends the element output, if needed.
+ *
+ * @since 2.7.0
+ *
+ * @see Walker::end_el()
+ * @see wp_list_comments()
+ *
+ * @param string $output Passed by reference. Used to append additional content.
+ * @param object $comment The comment object. Default current comment.
+ * @param int $depth Depth of comment.
+ * @param array $args An array of arguments.
+ */
+ public function end_el( &$output, $comment, $depth = 0, $args = array() ) {
+ if ( !empty( $args['end-callback'] ) ) {
+ ob_start();
+ call_user_func( $args['end-callback'], $comment, $args, $depth );
+ $output .= ob_get_clean();
+ return;
+ }
+ if ( 'div' == $args['style'] )
+ $output .= "</div><!-- #comment-## -->\n";
+ else
+ $output .= "</li><!-- #comment-## -->\n";
+ }
+
+ /**
+ * Output a pingback comment.
+ *
+ * @access protected
+ * @since 3.6.0
+ *
+ * @see wp_list_comments()
+ *
+ * @param object $comment The comment object.
+ * @param int $depth Depth of comment.
+ * @param array $args An array of arguments.
+ */
+ protected function ping( $comment, $depth, $args ) {
+ $tag = ( 'div' == $args['style'] ) ? 'div' : 'li';
+?>
+ <<?php echo $tag; ?> id="comment-<?php comment_ID(); ?>" <?php comment_class(); ?>>
+ <div class="comment-body">
+ <?php _e( 'Pingback:' ); ?> <?php comment_author_link(); ?> <?php edit_comment_link( __( 'Edit' ), '<span class="edit-link">', '</span>' ); ?>
+ </div>
+<?php
+ }
+
+ /**
+ * Output a single comment.
+ *
+ * @access protected
+ * @since 3.6.0
+ *
+ * @see wp_list_comments()
+ *
+ * @param object $comment Comment to display.
+ * @param int $depth Depth of comment.
+ * @param array $args An array of arguments.
+ */
+ protected function comment( $comment, $depth, $args ) {
+ if ( 'div' == $args['style'] ) {
+ $tag = 'div';
+ $add_below = 'comment';
+ } else {
+ $tag = 'li';
+ $add_below = 'div-comment';
+ }