bueltge
8/17/2014 - 7:57 PM

post-type--not-in.php

<?php

$query = new WP_Query( array(
  'post_type__not_in' => array( 'page', 'post' ),
));
<?php
/**
 * This class will cause WP_Query to ignore a 'post_type' parameter when 'post_type__not_in' is set.
 * 
 * Class Post_Type__Not_In
 */
class Post_Type__Not_In {

  /**
   *
   */
  static function on_load() {
    add_action( 'pre_get_posts', array( __CLASS__, '_pre_get_posts' ) );
    add_filter( 'posts_where', array( __CLASS__, '_posts_where' ), 10, 2 );
    add_filter( 'posts_where_paged', array( __CLASS__, '_posts_where' ), 10, 2 );
  }


  /**
   * @param WP_Query $query
   */
  static function _pre_get_posts( $query ) {
    if ( $post_type__not_in = $query->get( 'post_type__not_in' ) ) {
      $query->set( 'post_type', 'any' );
    }
  }

  /**
   * @param string $where
   * @param WP_Query $query
   * @return string
   */
  static function _posts_where( $where, $query ) {
    if ( $post_type__not_in = $query->get( 'post_type__not_in' ) ) {
      global $wpdb;
      preg_match( "#(AND {$wpdb->posts}.post_type IN) \('([^)]+)'\)#", $where, $matches );
      if( 3 == count( $matches ) ) {
        $post_types = explode( "', '", $matches[2] );
        if ( ! is_array( $post_type__not_in ) ) {
          $post_type__not_in = array( $post_type__not_in );
        }
        $post_type__not_in = array_map( 'esc_sql', $post_type__not_in );
        $post_types = implode( "','", array_diff( $post_types, $post_type__not_in ) );
        $new_sql = "{$matches[1]} ('{$post_types}')";
        $where = str_replace( $matches[0], $new_sql, $where );
      }
    }
    return $where;
  }

}
Post_Type__Not_In::on_load();