Take the 2-minute tour ×
WordPress Development Stack Exchange is a question and answer site for WordPress developers and administrators. It's 100% free, no registration required.

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.

share|improve this question
    
Where precisely do you want to accomplish this? Post list table? –  Rarst Aug 29 '13 at 13:20
    
@Rarst correct. the front-end is all set and working as expected. right now, it's all in DESC order, which is good for the parent items, but backwards for the child items. –  Norcross Aug 29 '13 at 13:34
1  
For me there is no chance. WP_Posts_List_Table do not use query to accomplish hierachical post displaying, only foreach cycles on the retrieved post array that arrange post into two array: one for top level posts and one (two dimensional) for children posts. In addition there are no filter that permit to edit this arrays. –  G. M. Aug 29 '13 at 15:32
    
I'm seeing that myself. This was a 'nice to have' thing, so I'm bailing for now. –  Norcross Aug 30 '13 at 15:33
    
Ideea: if (git) patches aren't a big overhead for your project and you see them as an acceptable form of hacking the core, try adding a filter to _get_list_table() as a patch, so you can extend WP_Posts_List_Table afterwards –  Dan Ștefancu Sep 24 '13 at 20:04

2 Answers 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 );

}
share|improve this answer

If you want to sort hierarchical posts, then the straightforward way to do this is to use the "order" field. This will allow you to rearrange the order of the child posts in any way you like. Instead of 1,2,3,... I recommend you use 10,20,30,... leaving space for future changes.

It would be nice, of course, if Wordpress offered a drag and drop interface to make that task painless, but as far as I can see, there isn't one (or perhaps there's a plugin).

This isn't exactly what you asked for (the ability to do two kinds of sorting in one list), but hopefully it accomplishes your end goal.

share|improve this answer
    
thanks, but that wasn't what I was looking for. and a drag and drop can be built (I've done it) but this is over 1000 items, which would kill the admin. I realized it wasn't worth the headache. –  Norcross Sep 16 '13 at 5:12
1  
There are some decent drag-and-drop plugins out there for reordering pages/post types. I tend to like the Simple Page Ordering plugin myself. –  guiniveretoo Nov 26 '13 at 15:29

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.