I have a hierarchical CPT with the following structure:

- parent item 1
   - child item 1
   - child item 2
   - child item 3
   - child item 4
   - child item 5
- parent item 2
   - child item 1
   - child item 2
   - child item 3
   - child item 4
   - child item 5

each child item has a meta key called “section_id” which is numeric and corresponds to it’s order within the parent. The date stamps are approx 5 minutes apart from each other.

what I want to accomplish is sorting each parent item in descending date order, THEN the child items in either ascending date order or by the meta section_id (either will work, since they will product the same results)

running a pre_get_posts or parse_query allow me to do one or the other, but not both. is it possible to do this?

note this is only for the admin post table, not the front end.

2 s
2

As I couldn’t find any filter to override the WP_Posts_List_Table class, I propose a quite hacky solution by doing this:

  1. Query only parents in pre_get_posts;
  2. Query their children on wp and change $wp_query->posts accordingly.

This might need some more work as I’m probably breaking pagination numbers or so.

// Use a query variable to control when to change the main admin query
add_filter( 'query_vars', 'custom_admin_list_query_vars', 10, 1 );
function custom_admin_list_query_vars( $vars ) {
    array_push( $vars, 'custom_admin_list_children' );
    return $vars;
}

add_action( 'pre_get_posts', 'custom_admin_pre_get_posts' );
function custom_admin_pre_get_posts( $query ) {

    global $post_type;

    // Change query only if it's a user-triggered query in admin
    if ( ! is_admin()
        || 'page' != $post_type
        || $query->get( 'custom_admin_list_children' ) )
        return false;

    // Query only parents in date order
    $query->set( 'post_parent', 0 );
    $query->set( 'orderby', 'post_date' );
    $query->set( 'order', 'desc' );

}

// Query the children of the parents above
add_action( 'wp', 'custom_admin_list_wp' );
function custom_admin_list_wp() {

    global $post_type, $wp_query;

    if ( ! is_admin() || 'page' != $post_type )
        return false;

    $args = array(
        'post_type' => 'page',
        'numberposts' => -1,
        'custom_admin_list_children' => true,
        'meta_key' => 'section_id',
        'orderby' => 'meta_value_num',
        'order' => 'asc'
    );

    // Get children
    $children = array();
    for( $i = 0; $i < count( $wp_query->posts ); $i++ ) {
        $args['post_parent'] = $wp_query->posts[ $i ]->ID;
        $children[ $i ] = get_posts( $args );
    }

    // Flag as a children with a '--' in front of the title
    foreach( $children as &$c ) {
        if ( !empty( $c->post_title ) )
            $c->post_title="&mdash;&nbsp;" . $c->post_title;
    }

    // Put everything together
    $posts = array();
    for( $i = 0; $i < count( $wp_query->posts ); $i++ ) {
        $posts[] = $wp_query->posts[ $i ];
        $posts = array_merge( $posts, $children[ $i ] );
    }

    $wp_query->posts = $posts;
    $wp_query->post_count = count( $posts );

}

Leave a Reply

Your email address will not be published. Required fields are marked *