Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 0 additions & 25 deletions README

This file was deleted.

44 changes: 44 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -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() . "<BR>";
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() . "<BR>";
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');
```
189 changes: 106 additions & 83 deletions index.php
Original file line number Diff line number Diff line change
@@ -1,100 +1,123 @@
<?php

class WP_Query_Multisite extends WP_Query{


var $args;

function __construct( $args = array() ) {
$this->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();

?>