<?php
if( basename(__FILE__) == basename($_SERVER['SCRIPT_FILENAME']) )
die();
class QueryInterceptorBase_RS {
var $scoper;
function QueryInterceptorBase_RS() {
$this->scoper =& $GLOBALS['scoper'];
add_filter('posts_where', array(&$this, 'flt_defeat_publish_filter'), 40); // have to run this filter before QueryInterceptor_RS::flt_objects_where
add_filter('objects_listing_rs', array(&$this, 'flt_objects_listing'), 50, 4);
$arg_str = '$a';
foreach ( $this->scoper->data_sources->get_all() as $src_name => $src ) {
if ( isset($src->query_hooks->listing) ) {
// Call our abstract handlers with a lambda function that passes in original hook name
// In effect, make WP pass the hook name so multiple hooks can be registered to a single handler
$rs_args = "'$src_name', '', '' ";
$func = "return apply_filters( 'objects_listing_rs', $arg_str , $rs_args );";
add_filter( $src->query_hooks->listing, create_function( $arg_str, $func ), 50, 1 );
//d_echo ("adding filter: $original_hook -> $func <br />");
}
} //foreach data_sources
}
// Eliminate a primary plugin incompatibility by replacing front-end status='publish' requirement with scoped equivalent
// (i.e. include private posts/pages that this user has access to via RS role assignment).
//
// Also defeats status requirement imposed by WP core when query includes a custom taxonomy requirement
function flt_defeat_publish_filter($where) {
$post_type = cr_find_post_type();
$post_type_obj = get_post_type_object( $post_type );
$object_id = scoper_get_object_id( 'post', $post_type );
// don't alter the query if RS query filtering is disabled, or if this maneuver has been disabled via constant
// note: for non-administrators, QueryInterceptor_RS::flt_objects_where will convert the publish requirement to publish OR private, if the user's blog role or RS-assigned roles grant private access
if ( ! is_content_administrator_rs() || defined('SCOPER_RETAIN_PUBLISH_FILTER') || defined('DISABLE_QUERYFILTERS_RS') )
return $where;
global $wp_query;
if ( is_admin() && ! empty( $wp_query->query['post_status'] ) ) // if a specific status was requested by URI, don't force inclusion of others
return $where;
// don't alter the where clause if in wp-admin and not filtering by taxonomy
if ( is_admin() ) {
global $wp_query;
if ( empty($wp_query) && empty($wp_query->is_tax) )
return $where;
}
global $wpdb, $current_user;
// don't alter the where clause for anonymous users
if ( empty( $current_user->ID ) )
return $where;
$where = preg_replace( "/$wpdb->posts.post_status\s*=\s*'publish'/", "($wpdb->posts.post_status = 'publish' OR $wpdb->posts.post_status = 'private')", $where);
$where = preg_replace( "/p2.post_status\s*=\s*'publish'/", "(p2.post_status = 'publish' OR p2.post_status = 'private')", $where);
$where = preg_replace( "/p.post_status\s*=\s*'publish'/", "(p.post_status = 'publish' OR p.post_status = 'private')", $where);
return $where;
}
// can't do this from posts_results or it will throw off found_rows used for admin paging
function flt_objects_listing($results, $src_name, $object_types, $args = array()) {
global $wpdb;
// it's not currently necessary or possible to log listed revisions from here
//if ( isset($wpdb->last_query) && strpos( $wpdb->last_query, "post_type = 'revision'") )
// return $results;
// if currently listed IDs are not already in post_cache, make our own equivalent memcache
// ( create this cache for any data source, front end or admin )
if ( 'post' == $src_name )
global $wp_object_cache;
$listed_ids = array();
//if ( ('post' != $src_name) || empty($wp_object_cache->cache['posts']) ) {
if ( empty($this->scoper->listed_ids[$src_name]) ) {
if ( $col_id = $this->scoper->data_sources->member_property( $src_name, 'cols', 'id' ) ) {
$listed_ids = array();
// In edit.php, WP forces all objects into recordset for hierarchical post types. But for perf enchancement, we need to know IDs of items which are actually listed
if ( 'edit.php' == $GLOBALS['pagenow'] ) {
$post_type = ( ! empty( $_GET['post_type'] ) ) ? $_GET['post_type'] : 'post';
$determine_listed_ids = ! is_content_administrator_rs() && is_post_type_hierarchical( $post_type ) && ! empty( $GLOBALS['query_interceptor']->last_request[$src_name] ) && ! strpos( $GLOBALS['query_interceptor']->last_request[$src_name], 'LIMIT ' );
if ( $determine_listed_ids ) {
// mimic recordset paging used in edit.php
$pagenum = isset( $_GET['paged'] ) ? absint( $_GET['paged'] ) : 0;
if ( empty($pagenum) )
$pagenum = 1;
$edit_per_page = 'edit_' . $post_type . '_per_page';
$per_page = (int) get_user_option( $edit_per_page );
if ( empty( $per_page ) || $per_page < 1 )
$per_page = 20;
$per_page = apply_filters( $edit_per_page, $per_page );
$per_page = apply_filters( 'edit_posts_per_page', $per_page, $post_type );
if ( count($results) <= $per_page )
$determine_listed_ids = false;
}
} else
$determine_listed_ids = false;
if ( $determine_listed_ids ) {
// Construct and execute a secondary query (for IDs only) which includes the paging clause that would be used if edit.php did not defeat it
$pgstrt = ($pagenum - 1) * $per_page . ', ';
$limits = ' LIMIT ' . $pgstrt . $per_page;
global $wpdb;
$qry = $GLOBALS['query_interceptor']->last_request[$src_name] . $limits;
$qry = str_replace ( "$wpdb->posts.*", "$wpdb->posts.ID", $qry );
$_results = scoper_get_results( $qry );
foreach ( $_results as $row ) {
if ( isset($row->$col_id) )
$listed_ids [$row->$col_id] = true;
}
} else {
// No secondary query, just buffer all IDs in the results set
foreach ( $results as $row )
if ( isset($row->$col_id) )
$listed_ids [$row->$col_id] = true;
}
if ( empty($this->scoper->listed_ids) )
$this->scoper->listed_ids = array();
$this->scoper->listed_ids[$src_name] = $listed_ids;
}
} else
return $results;
//}
// now determine what restrictions were in place on these results
// (currently only for post data source, front end or manage posts/pages)
//
// possible todo: support other data sources, WP role type
if ( 'edit.php' == $GLOBALS['pagenow'] ) {
if ( scoper_get_otype_option('restrictions_column', 'post') || scoper_get_otype_option('term_roles_column', 'post') || scoper_get_otype_option('object_roles_column', 'post') ) {
global $scoper_role_usage;
require_once( dirname(__FILE__).'/role_usage_rs.php' );
$scoper_role_usage = new Role_Usage_RS();
$scoper_role_usage->determine_role_usage_rs( 'post', $listed_ids );
}
}
return $results;
}
} // end class
?>