diff options
Diffstat (limited to 'wp-includes/class-walker-comment.php')
-rw-r--r-- | wp-includes/class-walker-comment.php | 491 |
1 files changed, 491 insertions, 0 deletions
diff --git a/wp-includes/class-walker-comment.php b/wp-includes/class-walker-comment.php new file mode 100644 index 0000000..825a283 --- /dev/null +++ b/wp-includes/class-walker-comment.php @@ -0,0 +1,491 @@ +<?php +/** + * Comment API: Walker_Comment class + * + * @package WordPress + * @subpackage Comments + * @since 4.4.0 + */ + +/** + * Core walker class used to create an HTML list of comments. + * + * @since 2.7.0 + * + * @see Walker + */ +class Walker_Comment extends Walker { + + /** + * What the class handles. + * + * @since 2.7.0 + * @var string + * + * @see Walker::$tree_type + */ + public $tree_type = 'comment'; + + /** + * Database fields to use. + * + * @since 2.7.0 + * @var string[] + * + * @see Walker::$db_fields + * @todo Decouple this + */ + public $db_fields = array( + 'parent' => 'comment_parent', + 'id' => 'comment_ID', + ); + + /** + * Starts the list before the elements are added. + * + * @since 2.7.0 + * + * @see Walker::start_lvl() + * @global int $comment_depth + * + * @param string $output Used to append additional content (passed by reference). + * @param int $depth Optional. Depth of the current comment. Default 0. + * @param array $args Optional. Uses 'style' argument for type of HTML list. Default empty array. + */ + 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; + } + } + + /** + * Ends the list of items after the elements are added. + * + * @since 2.7.0 + * + * @see Walker::end_lvl() + * @global int $comment_depth + * + * @param string $output Used to append additional content (passed by reference). + * @param int $depth Optional. Depth of the current comment. Default 0. + * @param array $args Optional. Will only append content if style argument value is 'ol' or 'ul'. + * Default empty array. + */ + 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; + } + } + + /** + * Traverses 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 + * + * @since 2.7.0 + * + * @see Walker::display_element() + * @see wp_list_comments() + * + * @param WP_Comment $element Comment data object. + * @param array $children_elements List of elements to continue traversing. Passed by reference. + * @param int $max_depth Max depth to traverse. + * @param int $depth Depth of the current element. + * @param array $args An array of arguments. + * @param string $output Used to append additional content. Passed by reference. + */ + 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 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 ] ); + } + } + + /** + * Starts the element output. + * + * @since 2.7.0 + * @since 5.9.0 Renamed `$comment` to `$data_object` and `$id` to `$current_object_id` + * to match parent class for PHP 8 named parameter support. + * + * @see Walker::start_el() + * @see wp_list_comments() + * @global int $comment_depth + * @global WP_Comment $comment Global comment object. + * + * @param string $output Used to append additional content. Passed by reference. + * @param WP_Comment $data_object Comment data object. + * @param int $depth Optional. Depth of the current comment in reference to parents. Default 0. + * @param array $args Optional. An array of arguments. Default empty array. + * @param int $current_object_id Optional. ID of the current comment. Default 0. + */ + public function start_el( &$output, $data_object, $depth = 0, $args = array(), $current_object_id = 0 ) { + // Restores the more descriptive, specific name for use within this method. + $comment = $data_object; + + ++$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 ( 'comment' === $comment->comment_type ) { + add_filter( 'comment_text', array( $this, 'filter_comment_text' ), 40, 2 ); + } + + 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(); + } + + if ( 'comment' === $comment->comment_type ) { + remove_filter( 'comment_text', array( $this, 'filter_comment_text' ), 40 ); + } + } + + /** + * Ends the element output, if needed. + * + * @since 2.7.0 + * @since 5.9.0 Renamed `$comment` to `$data_object` to match parent class for PHP 8 named parameter support. + * + * @see Walker::end_el() + * @see wp_list_comments() + * + * @param string $output Used to append additional content. Passed by reference. + * @param WP_Comment $data_object Comment data object. + * @param int $depth Optional. Depth of the current comment. Default 0. + * @param array $args Optional. An array of arguments. Default empty array. + */ + public function end_el( &$output, $data_object, $depth = 0, $args = array() ) { + if ( ! empty( $args['end-callback'] ) ) { + ob_start(); + call_user_func( + $args['end-callback'], + $data_object, // The current comment object. + $args, + $depth + ); + $output .= ob_get_clean(); + return; + } + if ( 'div' === $args['style'] ) { + $output .= "</div><!-- #comment-## -->\n"; + } else { + $output .= "</li><!-- #comment-## -->\n"; + } + } + + /** + * Outputs a pingback comment. + * + * @since 3.6.0 + * + * @see wp_list_comments() + * + * @param WP_Comment $comment The comment object. + * @param int $depth Depth of the current 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( '', $comment ); ?>> + <div class="comment-body"> + <?php _e( 'Pingback:' ); ?> <?php comment_author_link( $comment ); ?> <?php edit_comment_link( __( 'Edit' ), '<span class="edit-link">', '</span>' ); ?> + </div> + <?php + } + + /** + * Filters the comment text. + * + * Removes links from the pending comment's text if the commenter did not consent + * to the comment cookies. + * + * @since 5.4.2 + * + * @param string $comment_text Text of the current comment. + * @param WP_Comment|null $comment The comment object. Null if not found. + * @return string Filtered text of the current comment. + */ + public function filter_comment_text( $comment_text, $comment ) { + $commenter = wp_get_current_commenter(); + $show_pending_links = ! empty( $commenter['comment_author'] ); + + if ( $comment && '0' == $comment->comment_approved && ! $show_pending_links ) { + $comment_text = wp_kses( $comment_text, array() ); + } + + return $comment_text; + } + + /** + * Outputs a single comment. + * + * @since 3.6.0 + * + * @see wp_list_comments() + * + * @param WP_Comment $comment Comment to display. + * @param int $depth Depth of the current 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'; + } + + $commenter = wp_get_current_commenter(); + $show_pending_links = isset( $commenter['comment_author'] ) && $commenter['comment_author']; + + if ( $commenter['comment_author_email'] ) { + $moderation_note = __( 'Your comment is awaiting moderation.' ); + } else { + $moderation_note = __( 'Your comment is awaiting moderation. This is a preview; your comment will be visible after it has been approved.' ); + } + ?> + <<?php echo $tag; ?> <?php comment_class( $this->has_children ? 'parent' : '', $comment ); ?> id="comment-<?php comment_ID(); ?>"> + <?php if ( 'div' !== $args['style'] ) : ?> + <div id="div-comment-<?php comment_ID(); ?>" class="comment-body"> + <?php endif; ?> + <div class="comment-author vcard"> + <?php + if ( 0 != $args['avatar_size'] ) { + echo get_avatar( $comment, $args['avatar_size'] ); + } + ?> + <?php + $comment_author = get_comment_author_link( $comment ); + + if ( '0' == $comment->comment_approved && ! $show_pending_links ) { + $comment_author = get_comment_author( $comment ); + } + + printf( + /* translators: %s: Comment author link. */ + __( '%s <span class="says">says:</span>' ), + sprintf( '<cite class="fn">%s</cite>', $comment_author ) + ); + ?> + </div> + <?php if ( '0' == $comment->comment_approved ) : ?> + <em class="comment-awaiting-moderation"><?php echo $moderation_note; ?></em> + <br /> + <?php endif; ?> + + <div class="comment-meta commentmetadata"> + <?php + printf( + '<a href="%s">%s</a>', + esc_url( get_comment_link( $comment, $args ) ), + sprintf( + /* translators: 1: Comment date, 2: Comment time. */ + __( '%1$s at %2$s' ), + get_comment_date( '', $comment ), + get_comment_time() + ) + ); + + edit_comment_link( __( '(Edit)' ), ' ', '' ); + ?> + </div> + + <?php + comment_text( + $comment, + array_merge( + $args, + array( + 'add_below' => $add_below, + 'depth' => $depth, + 'max_depth' => $args['max_depth'], + ) + ) + ); + ?> + + <?php + comment_reply_link( + array_merge( + $args, + array( + 'add_below' => $add_below, + 'depth' => $depth, + 'max_depth' => $args['max_depth'], + 'before' => '<div class="reply">', + 'after' => '</div>', + ) + ) + ); + ?> + + <?php if ( 'div' !== $args['style'] ) : ?> + </div> + <?php endif; ?> + <?php + } + + /** + * Outputs a comment in the HTML5 format. + * + * @since 3.6.0 + * + * @see wp_list_comments() + * + * @param WP_Comment $comment Comment to display. + * @param int $depth Depth of the current comment. + * @param array $args An array of arguments. + */ + protected function html5_comment( $comment, $depth, $args ) { + $tag = ( 'div' === $args['style'] ) ? 'div' : 'li'; + + $commenter = wp_get_current_commenter(); + $show_pending_links = ! empty( $commenter['comment_author'] ); + + if ( $commenter['comment_author_email'] ) { + $moderation_note = __( 'Your comment is awaiting moderation.' ); + } else { + $moderation_note = __( 'Your comment is awaiting moderation. This is a preview; your comment will be visible after it has been approved.' ); + } + ?> + <<?php echo $tag; ?> id="comment-<?php comment_ID(); ?>" <?php comment_class( $this->has_children ? 'parent' : '', $comment ); ?>> + <article id="div-comment-<?php comment_ID(); ?>" class="comment-body"> + <footer class="comment-meta"> + <div class="comment-author vcard"> + <?php + if ( 0 != $args['avatar_size'] ) { + echo get_avatar( $comment, $args['avatar_size'] ); + } + ?> + <?php + $comment_author = get_comment_author_link( $comment ); + + if ( '0' == $comment->comment_approved && ! $show_pending_links ) { + $comment_author = get_comment_author( $comment ); + } + + printf( + /* translators: %s: Comment author link. */ + __( '%s <span class="says">says:</span>' ), + sprintf( '<b class="fn">%s</b>', $comment_author ) + ); + ?> + </div><!-- .comment-author --> + + <div class="comment-metadata"> + <?php + printf( + '<a href="%s"><time datetime="%s">%s</time></a>', + esc_url( get_comment_link( $comment, $args ) ), + get_comment_time( 'c' ), + sprintf( + /* translators: 1: Comment date, 2: Comment time. */ + __( '%1$s at %2$s' ), + get_comment_date( '', $comment ), + get_comment_time() + ) + ); + + edit_comment_link( __( 'Edit' ), ' <span class="edit-link">', '</span>' ); + ?> + </div><!-- .comment-metadata --> + + <?php if ( '0' == $comment->comment_approved ) : ?> + <em class="comment-awaiting-moderation"><?php echo $moderation_note; ?></em> + <?php endif; ?> + </footer><!-- .comment-meta --> + + <div class="comment-content"> + <?php comment_text(); ?> + </div><!-- .comment-content --> + + <?php + if ( '1' == $comment->comment_approved || $show_pending_links ) { + comment_reply_link( + array_merge( + $args, + array( + 'add_below' => 'div-comment', + 'depth' => $depth, + 'max_depth' => $args['max_depth'], + 'before' => '<div class="reply">', + 'after' => '</div>', + ) + ) + ); + } + ?> + </article><!-- .comment-body --> + <?php + } +} |