Source
File: wp-includes/class-wp-comment-query.php
protected function fill_descendants( $comments ) {
global $wpdb;
$levels = array(
0 => wp_list_pluck( $comments, 'comment_ID' ),
);
$key = md5( serialize( wp_array_slice_assoc( $this->query_vars, array_keys( $this->query_var_defaults ) ) ) );
$last_changed = wp_cache_get_last_changed( 'comment' );
// Fetch an entire level of the descendant tree at a time.
$level = 0;
$exclude_keys = array( 'parent', 'parent__in', 'parent__not_in' );
do {
// Parent-child relationships may be cached. Only query for those that are not.
$child_ids = array();
$uncached_parent_ids = array();
$_parent_ids = $levels[ $level ];
foreach ( $_parent_ids as $parent_id ) {
$cache_key = "get_comment_child_ids:$parent_id:$key:$last_changed";
$parent_child_ids = wp_cache_get( $cache_key, 'comment' );
if ( false !== $parent_child_ids ) {
$child_ids = array_merge( $child_ids, $parent_child_ids );
} else {
$uncached_parent_ids[] = $parent_id;
}
}
if ( $uncached_parent_ids ) {
// Fetch this level of comments.
$parent_query_args = $this->query_vars;
foreach ( $exclude_keys as $exclude_key ) {
$parent_query_args[ $exclude_key ] = '';
}
$parent_query_args['parent__in'] = $uncached_parent_ids;
$parent_query_args['no_found_rows'] = true;
$parent_query_args['hierarchical'] = false;
$parent_query_args['offset'] = 0;
$parent_query_args['number'] = 0;
$level_comments = get_comments( $parent_query_args );
// Cache parent-child relationships.
$parent_map = array_fill_keys( $uncached_parent_ids, array() );
foreach ( $level_comments as $level_comment ) {
$parent_map[ $level_comment->comment_parent ][] = $level_comment->comment_ID;
$child_ids[] = $level_comment->comment_ID;
}
foreach ( $parent_map as $parent_id => $children ) {
$cache_key = "get_comment_child_ids:$parent_id:$key:$last_changed";
wp_cache_set( $cache_key, $children, 'comment' );
}
}
$level++;
$levels[ $level ] = $child_ids;
} while ( $child_ids );
// Prime comment caches for non-top-level comments.
$descendant_ids = array();
for ( $i = 1, $c = count( $levels ); $i < $c; $i++ ) {
$descendant_ids = array_merge( $descendant_ids, $levels[ $i ] );
}
_prime_comment_caches( $descendant_ids, $this->query_vars['update_comment_meta_cache'] );
// Assemble a flat array of all comments + descendants.
$all_comments = $comments;
foreach ( $descendant_ids as $descendant_id ) {
$all_comments[] = get_comment( $descendant_id );
}
// If a threaded representation was requested, build the tree.
if ( 'threaded' === $this->query_vars['hierarchical'] ) {
$threaded_comments = array();
$ref = array();
foreach ( $all_comments as $k => $c ) {
$_c = get_comment( $c->comment_ID );
// If the comment isn't in the reference array, it goes in the top level of the thread.
if ( ! isset( $ref[ $c->comment_parent ] ) ) {
$threaded_comments[ $_c->comment_ID ] = $_c;
$ref[ $_c->comment_ID ] = $threaded_comments[ $_c->comment_ID ];
// Otherwise, set it as a child of its parent.
} else {
$ref[ $_c->comment_parent ]->add_child( $_c );
$ref[ $_c->comment_ID ] = $ref[ $_c->comment_parent ]->get_child( $_c->comment_ID );
}
}
// Set the 'populated_children' flag, to ensure additional database queries aren't run.
foreach ( $ref as $_ref ) {
$_ref->populated_children( true );
}
$comments = $threaded_comments;
} else {
$comments = $all_comments;
}
return $comments;
}