k-isabelle
5/31/2018 - 4:29 PM

Order WP_Query by taxonomy

Order WP_Query by taxonomy


/* --------------------------------- */
/*  Order WP_Query By Taxonomy
/* --------------------------------- */

/*

*** Note: THIS MAY BREAK if used with a WP_Query containing a taxonomy query ***

Usage:

$args = array(
  'post_type'      => 'custom_post_type',
  'posts_per_page' => -1,
  'meta_key'       => '_EventStartDate',
  'orderby'        => 'taxonomy.taxonomy_cat meta_value',
  'ordertax'       => 'ASC',
  'order'          => 'DESC'
);

add_filter( 'posts_clauses', 'orderby_tax_clauses', 10, 2 );
$the_query = new WP_Query( $args );
remove_filter( 'posts_clauses', 'orderby_tax_clauses', 10, 2 );

*/

function orderby_tax_clauses( $clauses, $wp_query ) {
  $orderby_arg = $wp_query->get('orderby');
  if ( ! empty( $orderby_arg ) && substr_count( $orderby_arg, 'taxonomy.' ) ) {
    global $wpdb;
    $bytax = "GROUP_CONCAT({$wpdb->terms}.name ORDER BY name ASC)";
    $array = explode( ' ', $orderby_arg ); 
    if ( ! isset( $array[1] ) ) {
      $array = array( $bytax, "{$wpdb->posts}.post_date" );
      $taxonomy = str_replace( 'taxonomy.', '', $orderby_arg );
    } else {
      foreach ( $array as $i => $t ) {
        if ( substr_count( $t, 'taxonomy.' ) )  {
          $taxonomy = str_replace( 'taxonomy.', '', $t );
          $array[$i] = $bytax;
        } elseif ( $t === 'meta_value' || $t === 'meta_value_num' ) {
          $cast = ( $t === 'meta_value_num' ) ? 'SIGNED' : 'CHAR';
          $array[$i] = "CAST( {$wpdb->postmeta}.meta_value AS {$cast} )";
        } else {
          $array[$i] = "{$wpdb->posts}.{$t}";
        }
      }
    }
    $order = strtoupper( $wp_query->get('order') ) === 'ASC' ? ' ASC' : ' DESC';
    $ot = strtoupper( $wp_query->get('ordertax') );
    $ordertax = $ot === 'DESC' || $ot === 'ASC' ? " $ot" : " $order";
    $clauses['orderby'] = implode(', ',
      array_map( function($a) use ( $ordertax, $order ) {
        return ( strpos($a, 'GROUP_CONCAT') === 0 ) ? $a . $ordertax : $a . $order;
      }, $array )
    );
    $clauses['join'] .= " LEFT OUTER JOIN {$wpdb->term_relationships} ";
    $clauses['join'] .= "ON {$wpdb->posts}.ID = {$wpdb->term_relationships}.object_id";
    $clauses['join'] .= " LEFT OUTER JOIN {$wpdb->term_taxonomy} ";
    $clauses['join'] .= "USING (term_taxonomy_id)";
    $clauses['join'] .= " LEFT OUTER JOIN {$wpdb->terms} USING (term_id)";
    $clauses['groupby'] = "object_id";
    $clauses['where'] .= " AND (taxonomy = '{$taxonomy}' OR taxonomy IS NULL)";
  }
  return $clauses;
}

/* 

Additional Note:

'orderby' => 'taxonomy.taxonomy_cat meta_value',
'ordertax' => 'DESC'
'order' => 'ASC'

means "ORDERBY taxonomy_cat DESC, meta_value ASC"

'orderby' => 'taxonomy.taxonomy_cat meta_value',
'order' => 'ASC'

means "ORDERBY taxonomy_cat ASC, meta_value ASC"


/* Source: http://wordpress.stackexchange.com/questions/137208/order-posts-by-taxonomy-and-meta-value */