diff --git a/README b/README deleted file mode 100644 index 020453c..0000000 --- a/README +++ /dev/null @@ -1,25 +0,0 @@ -WP_Query_Multisite is a subclass of WP_Query, WordPress' post querying class. The class does everything behind the scenes, so the only change you make to query multisite is the in the class declaration expression. - -Example usage: - -$query = new WP_Query_Multisite( array('post_type' => 'post' ) ); -while($query->have_posts()) : $query->the_post(); - echo $blog_id . get_the_title() . "
"; -endwhile; -wp_reset_postdata(); - -To modify what sites are queried, create a 'sites' element in the $args in the constructor parameter, with a sub-element of either 'sites__in' or 'sites__not_in', which will be an array similar to 'posts__in' in the WP_Query object. - -EX: - -$args = array( - 'post_type' => 'post', - 'sites' => array( - 'sites__in' => array( 1, 2, 3, 5) - ) -); -$query = new WP_Query_Multisite( $args ); -while($query->have_posts()) : $query->the_post(); - echo $blog_id . get_the_title() . "
"; -endwhile; -wp_reset_postdata(); \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..ca32ba0 --- /dev/null +++ b/README.md @@ -0,0 +1,44 @@ +# WordPress Query Multisite + +This is a custom version of [WP_Query_Multisite](https://github.com/ericandrewlewis/WP_Query_Multisite), by [ericandrewlewis](https://github.com/ericandrewlewis), to support multisite post queries but without changing the class declaration, we will use the good ol' **WP_Query**. Just by entering the custom query var **multisite => 1** on your query args and your query is now global. + +----------------- + +## Example usage + +```php +$query = new WP_Query( array('multisite' => '1' ) ); +while($query->have_posts()) : $query->the_post(); + echo $blog_id . get_the_title() . "
"; +endwhile; +wp_reset_postdata(); +``` + +To modify what sites are queried, create a 'sites' element in the $args in the constructor parameter, with a sub-element of either 'sites__in' or 'sites__not_in', which will be an array similar to 'posts__in' in the WP_Query object. + +```php +$args = array( + 'multisite' => 1, + 'sites__in' => array( 1, 2, 3, 5) +); +$query = new WP_Query( $args ); +while($query->have_posts()) : $query->the_post(); + echo $blog_id . get_the_title() . "
"; +endwhile; +wp_reset_postdata(); +``` + +### Automatic multisite search example + +On your functions.php: + +```php +include_once(TEMPLATEPATH . '/path/to/multisite-query.php'); + +function my_multisite_search($query) { + if(!is_admin() && $query->is_main_query() && $query->is_search) { + $query->set('multisite', 1); + } +} +add_action('pre_get_posts', 'my_multisite_search'); +``` \ No newline at end of file diff --git a/index.php b/index.php index 328d192..2369319 100644 --- a/index.php +++ b/index.php @@ -1,100 +1,123 @@ args = $args; - $this->parse_multisite_args(); - $this->add_filters(); - $this->query($args); - $this->remove_filters(); +class WP_Query_Multisite { - } - - function parse_multisite_args() { - global $wpdb; - - $site_IDs = $wpdb->get_col( "select blog_id from $wpdb->blogs" ); - - if ( isset( $this->args['sites']['sites__not_in'] ) ) - foreach($site_IDs as $key => $site_ID ) - if (in_array($site_ID, $this->args['sites']['sites__not_in']) ) unset($site_IDs[$key]); - - if ( isset( $this->args['sites']['sites__in'] ) ) - foreach($site_IDs as $key => $site_ID ) - if ( ! in_array($site_ID, $this->args['sites']['sites__in']) ) - unset($site_IDs[$key]); - - - $site_IDs = array_values($site_IDs); - $this->sites_to_query = $site_IDs; + function __construct() { + add_filter('query_vars', array($this, 'query_vars')); + add_action('pre_get_posts', array($this, 'pre_get_posts'), 100); + add_filter('posts_clauses', array($this, 'posts_clauses'), 10, 2); + add_filter('posts_request', array($this, 'posts_request'), 10, 2); + add_action('the_post', array($this, 'the_post')); + add_action('loop_end', array($this, 'loop_end')); } - function add_filters() { - - add_filter('posts_request', array(&$this, 'create_and_unionize_select_statements') ); - add_filter('posts_fields', array(&$this, 'add_site_ID_to_posts_fields') ); - add_action('the_post', array(&$this, 'switch_to_blog_while_in_loop')); - + function query_vars($vars) { + $vars[] = 'multisite'; + $vars[] = 'sites__not_in'; + $vars[] = 'sites__in'; + return $vars; } - function remove_filters() { - remove_filter('posts_request', array(&$this, 'create_and_unionize_select_statements') ); - remove_filter('posts_fields', array(&$this, 'add_site_ID_to_posts_fields') ); + function pre_get_posts($query) { + if($query->get('multisite')) { + + global $wpdb, $blog_id; + + $this->loop_end = false; + $this->blog_id = $blog_id; + + $site_IDs = $wpdb->get_col( "select blog_id from $wpdb->blogs" ); + + if ( $query->get('sites__not_in') ) + foreach($site_IDs as $key => $site_ID ) + if (in_array($site_ID, $query->get('sites__not_in')) ) unset($site_IDs[$key]); + + if ( $query->get('sites__in') ) + foreach($site_IDs as $key => $site_ID ) + if ( ! in_array($site_ID, $query->get('sites__in')) ) + unset($site_IDs[$key]); + + $site_IDs = array_values($site_IDs); + + $this->sites_to_query = $site_IDs; + } } - function create_and_unionize_select_statements($sql) { - global $wpdb; - - $root_site_db_prefix = $wpdb->prefix; - - $page = $this->args['paged'] ? $this->args['paged'] : 1; - $posts_per_page = $this->args['posts_per_page'] ? $this->args['posts_per_page'] : 10; - - foreach ($this->sites_to_query as $key => $site_ID) : - - switch_to_blog($site_ID); - - $new_sql_select = str_replace($root_site_db_prefix, $wpdb->prefix, $sql); - $new_sql_select = preg_replace("/ LIMIT ([0-9]+), ".$posts_per_page."/", "", $new_sql_select); - $new_sql_select = str_replace("SQL_CALC_FOUND_ROWS ", "", $new_sql_select); - $new_sql_select = str_replace("# AS site_ID", "'$site_ID' AS site_ID", $new_sql_select); - $new_sql_select = preg_replace( '/ORDER BY ([A-Za-z0-9_.]+)/', "", $new_sql_select); - $new_sql_select = str_replace(array("DESC", "ASC"), "", $new_sql_select); - - $new_sql_selects[] = $new_sql_select; - restore_current_blog(); - - endforeach; - - if ( $posts_per_page > 0 ) { - $skip = ( $page * $posts_per_page ) - $posts_per_page; - $limit = "LIMIT $skip, $posts_per_page"; - } else { - $limit = ''; - } - $orderby = "tables.post_date DESC"; - $new_sql = "SELECT SQL_CALC_FOUND_ROWS tables.* FROM ( " . implode(" UNION ", $new_sql_selects) . ") tables ORDER BY $orderby " . $limit; - - return $new_sql; + function posts_clauses($clauses, $query) { + if($query->get('multisite')) { + global $wpdb; + + // Start new mysql selection to replace wp_posts on posts_request hook + $this->ms_select = array(); + + $root_site_db_prefix = $wpdb->prefix; + foreach($this->sites_to_query as $site_ID) { + + switch_to_blog($site_ID); + + $ms_select = $clauses['join'] . ' WHERE 1=1 '. $clauses['where']; + + if($clauses['groupby']) + $ms_select .= ' GROUP BY ' . $clauses['groupby']; + + $ms_select = str_replace($root_site_db_prefix, $wpdb->prefix, $ms_select); + $ms_select = " SELECT $wpdb->posts.*, '$site_ID' as site_ID FROM $wpdb->posts $ms_select "; + + $this->ms_select[] = $ms_select; + + restore_current_blog(); + + } + + // Clear join, where and groupby to populate with parsed ms select on posts_request hook; + $clauses['join'] = ''; + $clauses['where'] = ''; + $clauses['groupby'] = ''; + + // Orderby for tables (not wp_posts) + $clauses['orderby'] = str_replace($wpdb->posts, 'tables', $clauses['orderby']); + + } + return $clauses; } - - function add_site_ID_to_posts_fields($sql) { - $sql_statements[] = $sql; - $sql_statements[] = "# AS site_ID"; - return implode(', ', $sql_statements); + + function posts_request($sql, $query) { + + if($query->get('multisite')) { + + global $wpdb; + + // Clean up remanescent WHERE request + $sql = str_replace('WHERE 1=1', '', $sql); + + // Multisite request + $sql = str_replace("$wpdb->posts.* FROM $wpdb->posts", 'tables.* FROM ( ' . implode(" UNION ", $this->ms_select) . ' ) tables', $sql); + + } + + return $sql; } - - function switch_to_blog_while_in_loop($post) { + + function the_post($post) { global $blog_id; - if($post->site_ID && $blog_id != $post->site_ID ) + + if( isset( $this->loop_end ) && !$this->loop_end && $post->site_ID && $blog_id !== $post->site_ID) { switch_to_blog($post->site_ID); - else - restore_current_blog(); + } + + } + + function loop_end($query) { + global $switched; + if($query->get('multisite')) { + $this->loop_end = true; + if($switched) { + switch_to_blog($this->blog_id); + } + } } } +new WP_Query_Multisite(); + ?>