Ejemplo n.º 1
0
 function insert_role_restrictions($topic, $max_scope, $role_handle, $src_or_tx_name, $obj_or_term_id, $insert_restriction, $propagate_from_req_id, $args = array())
 {
     $defaults = array('inherited_from' => 0, 'is_auto_insertion' => false);
     // auto_insertion arg set for restriction propagation from parent objects
     $args = array_merge($defaults, (array) $args);
     extract($args);
     global $current_user, $wpdb;
     if (!($role_spec = scoper_explode_role_handle($role_handle))) {
         return;
     }
     // keep track of which objects from non-post data sources have ever had their roles/restrictions custom-edited
     if (!$is_auto_insertion && (TERM_SCOPE_RS == $max_scope || OBJECT_SCOPE_RS == $max_scope && 'post' != $src_or_tx_name)) {
         $custom_role_items = get_option("scoper_custom_{$src_or_tx_name}");
         if (!is_array($custom_role_items)) {
             $custom_role_items = array();
         }
     }
     // need object_type for permission check when modifying propagated object roles
     if (OBJECT_SCOPE_RS == $topic) {
         if ($role_attrib = $this->scoper->role_defs->get_role_attributes($role_handle)) {
             $object_type = $role_attrib->object_type;
         } else {
             $object_type = '';
         }
         // probably won't be able to propagate roles if this error occurs
     }
     // prepare hierarchy and object type data for subsequent propagation
     if ($propagate_from_req_id) {
         if (TERM_SCOPE_RS == $topic) {
             if (!($tx = $this->scoper->taxonomies->get($src_or_tx_name))) {
                 return;
             }
             if (!($src = $this->scoper->data_sources->get($tx->source))) {
                 return;
             }
         } elseif (!($src = $this->scoper->data_sources->get($src_or_tx_name))) {
             return;
         }
         if (empty($src->cols->parent)) {
             return;
         }
         $descendant_ids = awp_query_descendant_ids($src->table, $src->cols->id, $src->cols->parent, $obj_or_term_id);
         $remove_ids = array();
         foreach ($descendant_ids as $id) {
             if (TERM_SCOPE_RS == $topic) {
                 if (!$this->scoper_admin->user_can_admin_terms($src_or_tx_name, $id)) {
                     $remove_ids[] = $id;
                 }
             } else {
                 if (!$this->scoper_admin->user_can_admin_object($src_or_tx_name, $object_type, $id)) {
                     $remove_ids[] = $id;
                 }
             }
         }
         if ($remove_ids) {
             $descendant_ids = array_diff($descendant_ids, $remove_ids);
         }
     }
     // Before inserting a restriction, delete any overlooked old restriction.
     $qry_delete_base = "DELETE FROM {$wpdb->role_scope_rs}" . " WHERE topic = '{$topic}' AND max_scope = '{$max_scope}' AND src_or_tx_name = '{$src_or_tx_name}'" . " AND role_type = '{$role_spec->role_type}' AND role_name = '{$role_spec->role_name}'";
     $qry_select_base = "SELECT requirement_id AS assignment_id FROM {$wpdb->role_scope_rs}" . " WHERE topic = '{$topic}' AND max_scope = '{$max_scope}' AND src_or_tx_name = '{$src_or_tx_name}'" . " AND role_type = '{$role_spec->role_type}' AND role_name = '{$role_spec->role_name}'";
     $qry_insert_base = "INSERT INTO {$wpdb->role_scope_rs}" . " (src_or_tx_name, role_type, role_name, topic, max_scope, obj_or_term_id, require_for, inherited_from)" . " VALUES ('{$src_or_tx_name}', '{$role_spec->role_type}', '{$role_spec->role_name}', '{$topic}', '{$max_scope}',";
     // obj_or_term_id, propagate, inherited_from values must be appended
     if ($insert_restriction) {
         // before inserting the role, delete any other matching or conflicting assignments this user/group has for the same object
         scoper_query($qry_delete_base . " AND obj_or_term_id = '{$obj_or_term_id}';");
         // insert role for specified object and group(s)
         scoper_query($qry_insert_base . "'{$obj_or_term_id}', '{$insert_restriction}', '{$inherited_from}')");
         $inserted_req_id = (int) $wpdb->insert_id;
         // keep track of which objects have ever had their roles/restrictions custom-edited
         if (!$is_auto_insertion) {
             if (OBJECT_SCOPE_RS == $max_scope && 'post' == $src_or_tx_name) {
                 update_post_meta($obj_or_term_id, '_scoper_custom', true);
             } else {
                 $custom_role_items[$obj_or_term_id] = true;
             }
         }
     }
     // insert role for all descendant items
     if ($propagate_from_req_id) {
         if ($insert_restriction) {
             $propagate_from_req_id = $inserted_req_id;
         }
         // note: Propagated roles will be converted to direct-assigned roles if the parent object/term is deleted.
         //		 But if the parent setting is changed without deleting old object/term, inherited roles from the old parent remain.
         // TODO: 're-inherit parent roles' checkbox for object and term role edit UI
         foreach ($descendant_ids as $id) {
             // Don't overwrite an explicitly assigned object role with a propagated assignment
             if ($direct_assignment = scoper_get_var("{$qry_select_base} AND inherited_from = '0' AND obj_or_term_id = '{$id}' LIMIT 1")) {
                 continue;
             }
             // before inserting the role, delete any other propagated assignments this user/group has for the same object type
             scoper_query($qry_delete_base . " AND obj_or_term_id = '{$id}'");
             scoper_query($qry_insert_base . "'{$id}', 'both', '{$propagate_from_req_id}')");
         }
     }
     // keep track of which objects from non-post data sources have ever had their roles/restrictions custom-edited
     if (!empty($custom_role_items)) {
         update_option("scoper_custom_{$src_or_tx_name}", $custom_role_items);
     }
 }
Ejemplo n.º 2
0
 function merge_scoped_blogcaps()
 {
     global $scoper;
     // strip out any assignments for roles which are no longer defined (such as Revisionary roles after Revisionary is deactivated)
     foreach (array_keys($this->assigned_blog_roles) as $date_key) {
         $this->assigned_blog_roles[$date_key] = array_intersect_key($this->assigned_blog_roles[$date_key], $scoper->role_defs->role_caps);
     }
     foreach (array_keys($this->assigned_blog_roles[ANY_CONTENT_DATE_RS]) as $role_handle) {
         if (!is_array($scoper->role_defs->role_caps[$role_handle])) {
             continue;
         }
         $role_spec = scoper_explode_role_handle($role_handle);
         if (!empty($role_spec->role_type) && 'rs' == $role_spec->role_type && !empty($scoper->role_defs->role_caps[$role_handle])) {
             $this->allcaps = is_array($this->allcaps) ? array_merge($this->allcaps, $scoper->role_defs->role_caps[$role_handle]) : $scoper->role_defs->role_caps[$role_handle];
         }
     }
     $this->allcaps['is_scoped_user'] = true;
     // use this to detect when something tampers with scoped allcaps array
 }
 function objects_where_scope_clauses($src_name, $reqd_caps, $args)
 {
     // Optional Args (will be defaulted to meaningful values)
     // Note: ignore_restrictions affects Scoper::qualify_terms() output
     $defaults = array('taxonomies' => '', 'use_blog_roles' => true, 'terms_query' => false, 'qualifying_object_roles' => false, 'skip_objscope_check' => false, 'require_full_object_role' => false, 'objrole_revisions_clause' => false, 'ignore_restrictions' => false);
     // Required Args
     // NOTE: use_object_roles is a boolean for the single object_type in question, but use_term_roles is array[taxonomy] = true or false
     $required = array_fill_keys(array('user', 'object_type', 'qualifying_roles', 'otype_use_term_roles', 'otype_use_object_roles'), true);
     if ($missing = array_diff_key($required, $args)) {
         rs_notice(sprintf('Role Scoper Runtime Error (%1$s) - Missing argument(s): %2$s', 'objects_where_scope_clauses', implode(", ", array_keys($missing))));
         return ' 1=2 ';
     }
     $defaults = array_merge($defaults, $required);
     $args = array_merge($defaults, (array) $args);
     extract($args);
     if (!($src = $this->scoper->data_sources->get($src_name))) {
         rs_notice(sprintf('Role Scoper Config Error (%1$s): Data source (%2$s) is not defined.', 'objects_where_scope_clauses', $src_name));
         return ' 1=2 ';
     }
     $src_table = !empty($source_alias) ? $source_alias : $src->table;
     if ('group' == $src_name) {
         $otype_use_object_roles = true;
     } elseif (!empty($src->no_object_roles)) {
         $otype_use_object_roles = false;
     }
     // primary qualifying_roles array should contain only RS roles
     $qualifying_roles = $this->scoper->role_defs->filter($qualifying_roles, array('role_type' => 'rs'), 'names_as_key');
     if ($otype_use_object_roles) {
         // For object assignment, replace any "others" reqd_caps array.
         // Also exclude any roles which have never been assigned to any object
         if (!is_array($qualifying_object_roles)) {
             $qualifying_object_roles = $this->scoper->confirm_object_scope($qualifying_roles, $user);
         }
         if ($skip_objscope_check) {
             $objscope_objects = array();
         } else {
             $objscope_objects = $this->scoper->get_restrictions(OBJECT_SCOPE_RS, $src_name);
         }
         // this is buffered so redundant calling is not a concern
     }
     //---------------------------------------------------------------------------------
     //dump($qualifying_object_roles);
     //dump($objscope_objects);
     if ($otype_use_object_roles) {
         $user_qualifies_for_obj_roles = $user->ID || defined('SCOPER_ANON_METAGROUP');
     }
     $where = array();
     if ($terms_query) {
         $_taxonomies = $taxonomies;
     } elseif ($otype_use_term_roles && is_array($otype_use_term_roles)) {
         $_taxonomies = array_keys(array_intersect($otype_use_term_roles, array(1, '1', true)));
         // taxonomies arg is for limiting; default is to include all associated taxonomies in where clause
         if ($taxonomies) {
             $_taxonomies = array_intersect($_taxonomies, $taxonomies);
         }
     } else {
         $_taxonomies = array();
     }
     if ($_taxonomies && 'post' == $src_name) {
         $enabled_taxonomies = array_keys(array_intersect(scoper_get_option('use_taxonomies'), array(1, '1', true)));
         $_taxonomies = array_intersect($_taxonomies, $enabled_taxonomies);
     }
     $user_blog_roles = array('' => array());
     if ($use_blog_roles) {
         foreach (array_keys($user->blog_roles) as $date_key) {
             $user_blog_roles[$date_key] = array_intersect_key($user->blog_roles[$date_key], $qualifying_roles);
         }
         // Also include user's WP blogrole(s),
         // but via equivalent RS role(s) to support scoping requirements (strict (i.e. restricted) terms, objects)
         if ($wp_qualifying_roles = $this->scoper->role_defs->qualify_roles($reqd_caps, 'wp')) {
             if ($user_blog_roles_wp = array_intersect_key($user->blog_roles[ANY_CONTENT_DATE_RS], $wp_qualifying_roles)) {
                 // Credit user's qualifying WP blogrole via contained RS role(s)
                 // so we can also enforce "term restrictions", which are based on RS roles
                 $user_blog_roles_via_wp = $this->scoper->role_defs->get_contained_roles(array_keys($user_blog_roles_wp), false, 'rs');
                 $user_blog_roles_via_wp = array_intersect_key($user_blog_roles_via_wp, $qualifying_roles);
                 $user_blog_roles[ANY_CONTENT_DATE_RS] = array_merge($user_blog_roles[ANY_CONTENT_DATE_RS], $user_blog_roles_via_wp);
             }
         }
     }
     /*
     // --- optional hack to require read_private cap via blog role AND object role
     // if the required capabilities include a read_private cap but no edit caps
     $require_blog_and_obj_role = ( in_array('read_private_posts', $reqd_caps) || in_array('read_private_pages', $reqd_caps) )   &&    ( ! array_diff( $reqd_caps, array('read_private_posts', 'read_private_pages', 'read') ) );
     // --- end hack ---
     */
     //dump($qualifying_roles);
     //dump($objscope_objects);
     foreach (array_keys($qualifying_roles) as $role_handle) {
         //dump($role_handle);
         if ($otype_use_object_roles && empty($require_blog_and_obj_role)) {
             if (!empty($objscope_objects['restrictions'][$role_handle])) {
                 $objscope_clause = " AND {$src_table}.{$src->cols->id} NOT IN ('" . implode("', '", array_keys($objscope_objects['restrictions'][$role_handle])) . "')";
             } elseif (isset($objscope_objects['unrestrictions'][$role_handle])) {
                 if (!empty($objscope_objects['unrestrictions'][$role_handle])) {
                     $objscope_clause = " AND {$src_table}.{$src->cols->id} IN ('" . implode("', '", array_keys($objscope_objects['unrestrictions'][$role_handle])) . "')";
                 } else {
                     $objscope_clause = " AND 1=2";
                 }
                 // role is default-restricted for this object type, but objects are unrestrictions are set
             } else {
                 $objscope_clause = '';
             }
         } else {
             $objscope_clause = '';
         }
         //dump($objscope_clause);
         $all_terms_qualified = array();
         $all_taxonomies_qualified = array();
         if ($_taxonomies) {
             $args['return_id_type'] = COL_TAXONOMY_ID_RS;
             $strict_taxonomies = array();
             foreach ($_taxonomies as $taxonomy) {
                 if ($this->scoper->taxonomies->member_property($taxonomy, 'requires_term')) {
                     $strict_taxonomies[$taxonomy] = true;
                 }
             }
             foreach ($_taxonomies as $taxonomy) {
                 // we only need a separate clause for each role if considering object roles (and therefore considering that some objects might require some roles to be object-assigned)
                 if (!$otype_use_object_roles) {
                     $role_handle_arg = $qualifying_roles;
                 } else {
                     $role_handle_arg = array($role_handle => 1);
                 }
                 // If a taxonomy does not require objects to have a term, its term role assignments
                 // will be purely supplemental; there is no basis for ignoring blogrole assignments.
                 //
                 // So if none of the taxonomies require each object to have a term
                 // AND the user has a qualifying role via blog assignment, we can skip the taxonomies clause altogether.
                 // Otherwise, will consider current user's termroles
                 if (!$strict_taxonomies) {
                     if (array_intersect_key($role_handle_arg, $user->blog_roles[ANY_CONTENT_DATE_RS])) {
                         // User has a qualifying role by blog assignment, so term_id clause is not required
                         $all_taxonomies_qualified[ANY_CONTENT_DATE_RS] = true;
                         break;
                     }
                 }
                 // qualify_terms returns:
                 // terms for which current user has a qualifying role
                 // 		- AND -
                 // which are non-restricted (i.e. blend in blog assignments) for a qualifying role which the user has blog-wide
                 //
                 // note: $reqd_caps function arg is used; qualify_terms will ignore reqd_caps element in args array
                 if ($user_terms = $this->scoper->qualify_terms_daterange($reqd_caps, $taxonomy, $role_handle_arg, $args)) {
                     if (!isset($term_count[$taxonomy])) {
                         $term_count[$taxonomy] = $this->scoper->get_terms($taxonomy, UNFILTERED_RS, COL_COUNT_RS);
                     }
                     foreach (array_keys($user_terms) as $date_key) {
                         if (count($user_terms[$date_key])) {
                             // don't bother applying term requirements if user has cap for all terms in this taxonomy
                             if (count($user_terms[$date_key]) >= $term_count[$taxonomy] && $this->scoper->taxonomies->member_property($taxonomy, 'requires_term')) {
                                 // User is qualified for all terms in this taxonomy; no need for any term_id clauses
                                 $all_terms_qualified[$date_key][$taxonomy] = true;
                             } else {
                                 $where[$date_key][$objscope_clause][TERM_SCOPE_RS][$taxonomy] = isset($where[$date_key][$objscope_clause][TERM_SCOPE_RS][$taxonomy]) ? array_unique(array_merge($where[$date_key][$objscope_clause][TERM_SCOPE_RS][$taxonomy], $user_terms[$date_key])) : $user_terms[$date_key];
                             }
                         }
                         $all_taxonomies_qualified[$date_key] = !empty($all_terms_qualified[$date_key]) && count($all_terms_qualified[$date_key]) == count($strict_taxonomies);
                     }
                 }
             }
             // end foreach taxonomy
         }
         foreach (array_keys($user_blog_roles) as $date_key) {
             if (!empty($all_taxonomies_qualified[$date_key]) || !$_taxonomies && !empty($user_blog_roles[$date_key][$role_handle])) {
                 if ($date_key || $objscope_clause || !empty($require_blog_and_obj_role)) {
                     $where[$date_key][$objscope_clause][BLOG_SCOPE_RS] = "1=1";
                 } else {
                     return "1=1";
                     // no need to include other clause if user has a qualifying role blog-wide or in all terms, it is not date-limited, and that role does not require object assignment for any objects
                 }
             }
         }
         // if object roles should be applied, populatate array key to force inclusion of OBJECT_SCOPE_RS query clauses below
         if ($otype_use_object_roles && isset($qualifying_object_roles[$role_handle]) && $user_qualifies_for_obj_roles) {
             // want to apply objscope requirements for anon user, but not apply any obj roles
             if ($role_spec = scoper_explode_role_handle($role_handle)) {
                 $where[ANY_CONTENT_DATE_RS][NO_OBJSCOPE_CLAUSE_RS][OBJECT_SCOPE_RS][$role_spec->role_type][$role_spec->role_name] = true;
             }
         }
         // we only need a separate clause for each role if considering object roles (and therefore considering that some objects might require some roles to be object-assigned)
         if (!$otype_use_object_roles && !empty($where[ANY_CONTENT_DATE_RS])) {
             break;
         }
     }
     // end foreach role
     // also include object scope clauses for any roles which qualify only for object-assignment
     if ($otype_use_object_roles && isset($qualifying_object_roles) && $user_qualifies_for_obj_roles) {
         // want to apply objscope requirements for anon user, but not apply any obj roles
         if ($obj_only_roles = array_diff_key($qualifying_object_roles, $qualifying_roles)) {
             foreach (array_keys($obj_only_roles) as $role_handle) {
                 if ($role_spec = scoper_explode_role_handle($role_handle)) {
                     $where[ANY_CONTENT_DATE_RS][NO_OBJSCOPE_CLAUSE_RS][OBJECT_SCOPE_RS][$role_spec->role_type][$role_spec->role_name] = true;
                 }
             }
         }
     }
     // DB query perf enhancement: if any terms are included regardless of post ID, don't also include those terms in ID-specific clause
     foreach (array_keys($where) as $date_key) {
         foreach (array_keys($where[$date_key]) as $objscope_clause) {
             if ($objscope_clause && isset($where[$date_key][$objscope_clause][TERM_SCOPE_RS])) {
                 foreach ($where[$date_key][$objscope_clause][TERM_SCOPE_RS] as $taxonomy => $terms) {
                     if (!empty($terms) && !empty($where[$date_key][NO_OBJSCOPE_CLAUSE_RS][TERM_SCOPE_RS][$taxonomy])) {
                         $where[$date_key][$objscope_clause][TERM_SCOPE_RS][$taxonomy] = array_diff($where[$date_key][$objscope_clause][TERM_SCOPE_RS][$taxonomy], $where[$date_key][NO_OBJSCOPE_CLAUSE_RS][TERM_SCOPE_RS][$taxonomy]);
                         if (empty($where[$date_key][$objscope_clause][TERM_SCOPE_RS][$taxonomy])) {
                             unset($where[$date_key][$objscope_clause][TERM_SCOPE_RS][$taxonomy]);
                             // if we removed a taxonomy array, don't leave behind a term scope array with no taxonomies
                             if (empty($where[$date_key][$objscope_clause][TERM_SCOPE_RS])) {
                                 unset($where[$date_key][$objscope_clause][TERM_SCOPE_RS]);
                                 // if we removed a term scope array, don't leave behind an objscope array with no scopes
                                 if (empty($where[$date_key][$objscope_clause])) {
                                     unset($where[$date_key][$objscope_clause]);
                                 }
                             }
                         }
                     }
                 }
             }
         }
     }
     // since object roles are not pre-loaded prior to this call, role date limits are handled via subselect, within the date_key = '' iteration
     $object_roles_duration_clause = scoper_get_duration_clause();
     // implode the array of where criteria into a query as concisely as possible
     foreach ($where as $date_key => $objscope_clauses) {
         foreach ($objscope_clauses as $objscope_clause => $scope_criteria) {
             foreach (array_keys($scope_criteria) as $scope) {
                 switch ($scope) {
                     case BLOG_SCOPE_RS:
                         $where[$date_key][$objscope_clause][BLOG_SCOPE_RS] = $where[$date_key][$objscope_clause][BLOG_SCOPE_RS] . " {$objscope_clause}";
                         break;
                     case TERM_SCOPE_RS:
                         $taxonomy_clauses = array();
                         foreach ($scope_criteria[TERM_SCOPE_RS] as $taxonomy => $terms) {
                             $is_strict = !empty($strict_taxonomies[$taxonomy]);
                             if ($objscope_clause) {
                                 // Avoid " term_id IN (5) OR ( term_id IN (5) AND ID NOT IN (100) )
                                 // Otherwise this redundancy can occur when various qualifying roles require object role assignment for different objects
                                 if (!empty($where[$date_key][NO_OBJSCOPE_CLAUSE_RS][TERM_SCOPE_RS][$taxonomy])) {
                                     if (!($terms = array_diff($terms, $where[$date_key][NO_OBJSCOPE_CLAUSE_RS][TERM_SCOPE_RS][$taxonomy]))) {
                                         //unset($scope_criteria[TERM_SCOPE_RS][$taxonomy]);  // this doesn't affect anything (removed in v1.1)
                                         continue;
                                     }
                                 }
                             }
                             $terms = array_unique($terms);
                             if ($qvars = $this->scoper->taxonomies->get_terms_query_vars($taxonomy)) {
                                 if ($terms_query && !$otype_use_object_roles) {
                                     $qtv = $this->scoper->taxonomies->get_terms_query_vars($taxonomy, true);
                                     $taxonomy_clauses[false][] = "{$qtv->term->alias}.{$qtv->term->col_id} IN ('" . implode("', '", $terms) . "') {$objscope_clause}";
                                 } else {
                                     $this_tx_clause = "{$qvars->term->alias}.{$qvars->term->col_id} IN ('" . implode("', '", $terms) . "')";
                                     // Use a subselect rather than adding our own LEFT JOIN.
                                     $terms_subselect = "SELECT {$qvars->term->alias}.{$qvars->term->col_obj_id} FROM {$qvars->term->table} {$qvars->term->as} WHERE {$this_tx_clause}";
                                     if (defined('RVY_VERSION') && $objrole_revisions_clause) {
                                         $revision_clause = "OR ( {$src_table}.{$src->cols->type} = 'revision' AND {$src_table}.{$src->cols->parent} IN ( {$terms_subselect} ) )";
                                     } else {
                                         $revision_clause = '';
                                     }
                                     $taxonomy_clauses[$is_strict][] = "( {$src_table}.{$src->cols->id} IN ( {$terms_subselect} ) {$revision_clause} ) {$objscope_clause}";
                                 }
                             }
                         }
                         if ($taxonomy_clauses) {
                             // all taxonomy clauses concat: [taxonomy 1 clauses] [OR] [taxonomy 2 clauses] [OR] ...
                             //$where[$date_key][$objscope_clause][TERM_SCOPE_RS] = agp_implode(' ) OR ( ', $taxonomy_clauses, ' ( ', ' ) ');
                             // strict taxonomy clauses (if any are present, they must all be satisfied)
                             if (!empty($taxonomy_clauses[true])) {
                                 $where[$date_key][$objscope_clause][TERM_SCOPE_RS] = agp_implode(' ) AND ( ', $taxonomy_clauses[true], ' ( ', ' ) ');
                                 // non-strict taxonomy clauses
                             } elseif (!empty($taxonomy_clauses[false])) {
                                 $where[$date_key][$objscope_clause][TERM_SCOPE_RS] = agp_implode(' ) OR ( ', $taxonomy_clauses[false], ' ( ', ' ) ');
                             } else {
                                 $where[$date_key][$objscope_clause][TERM_SCOPE_RS] = '1=2';
                             }
                             // all taxonomy clauses concat: ( [strict taxonomy clause 1] [AND] [strict taxonomy clause 2]... ) [OR] [taxonomy 3 clauses] [OR] ...
                             //$where[$date_key][$objscope_clause][TERM_SCOPE_RS] = agp_implode(' ) OR ( ', $taxonomy_clauses, ' ( ', ' ) ');
                         }
                         break;
                     case OBJECT_SCOPE_RS:
                         // should only exist with nullstring objscope_clause
                         if ($user_qualifies_for_obj_roles) {
                             global $wpdb;
                             $u_g_clause = $user->get_user_clause('uro');
                             foreach (array_keys($scope_criteria[OBJECT_SCOPE_RS]) as $role_type) {
                                 //should be only one
                                 if ($scope_criteria[OBJECT_SCOPE_RS][$role_type]) {
                                     ksort($scope_criteria[OBJECT_SCOPE_RS][$role_type]);
                                 }
                                 // sort array for efficient membuffering of query results
                                 // Combine all qualifying (and applied) object roles into a single OR clause
                                 $role_in = "'" . implode("', '", array_keys($scope_criteria[OBJECT_SCOPE_RS][$role_type])) . "'";
                                 static $cache_obj_ids = array();
                                 if ('post.php' == $GLOBALS['pagenow'] && !empty($_REQUEST['action']) || did_action('save_post') || !empty($_GET['doaction'])) {
                                     $force_refresh = true;
                                 }
                                 $objrole_subselect = "SELECT DISTINCT uro.obj_or_term_id FROM {$wpdb->user2role2object_rs} AS uro WHERE uro.role_type = '{$role_spec->role_type}' AND uro.scope = 'object' AND uro.assign_for IN ('entity', 'both') AND uro.role_name IN ({$role_in}) AND uro.src_or_tx_name = '{$src_name}' {$object_roles_duration_clause} {$u_g_clause} ";
                                 if (!isset($cache_obj_ids[$objrole_subselect]) || !empty($force_refresh)) {
                                     $cache_obj_ids[$objrole_subselect] = scoper_get_col($objrole_subselect);
                                 }
                                 if ($cache_obj_ids[$objrole_subselect]) {
                                     $where[$date_key][$objscope_clause][OBJECT_SCOPE_RS] = "{$src_table}.{$src->cols->id} IN ( '" . implode("','", $cache_obj_ids[$objrole_subselect]) . "' )";
                                 } else {
                                     $where[$date_key][$objscope_clause][OBJECT_SCOPE_RS] = "1=2";
                                 }
                                 if (defined('RVY_VERSION') && $objrole_revisions_clause) {
                                     $where[$date_key][$objscope_clause][OBJECT_SCOPE_RS] = "( {$where[$date_key][$objscope_clause]['object']} OR ( {$src_table}.{$src->cols->type} = 'revision' AND {$src_table}.{$src->cols->parent} IN ( '" . implode("','", $cache_obj_ids[$objrole_subselect]) . "' ) ) )";
                                 }
                             }
                         }
                         break;
                 }
                 // end scope switch
             }
             // end foreach scope
             /*
             // --- optional hack to require read_private cap via blog role AND object role
             if ( ! empty($require_blog_and_obj_role) ) {
             	if ( ! isset($where[$date_key][''][BLOG_SCOPE_RS]) )
             		$where[$date_key][''][BLOG_SCOPE_RS] = '1=2';
             	
             	if ( ! isset($where[$date_key][''][TERM_SCOPE_RS]) )
             		$where[$date_key][''][TERM_SCOPE_RS] = '1=2';
             		
             	if ( ! isset($where[$date_key][''][OBJECT_SCOPE_RS]) )
             		$where[$date_key][''][OBJECT_SCOPE_RS] = '1=2';
             	
             	$where[$date_key][''] = "( ( {$where[$date_key]['']['blog']} ) OR ( {$where[$date_key]['']['term']} ) ) AND ( {$where[$date_key]['']['object']} )";
             } 
             else
             // --- end hack
             */
             // all scope clauses concat: [object roles] OR [term ids] OR [blogrole1 clause] [OR] [blogrole2 clause] [OR] ...
             // Collapse the array to a string even if it's empty
             $where[$date_key][$objscope_clause] = agp_implode(' ) OR ( ', $where[$date_key][$objscope_clause], ' ( ', ' ) ');
         }
         // end foreach objscope clause
         $date_clause = '';
         if ($date_key && is_serialized($date_key)) {
             $content_date_limits = unserialize($date_key);
             if ($content_date_limits->content_min_date_gmt) {
                 $date_clause .= " AND {$src_table}.{$src->cols->date} >= '" . $content_date_limits->content_min_date_gmt . "'";
             }
             if ($content_date_limits->content_max_date_gmt) {
                 $date_clause .= " AND {$src_table}.{$src->cols->date} <= '" . $content_date_limits->content_max_date_gmt . "'";
             }
         }
         foreach (array_keys($where[$date_key]) as $objscope_clause) {
             if (empty($where[$date_key][$objscope_clause])) {
                 unset($where[$date_key][$objscope_clause]);
             }
         }
         // all objscope clauses concat: [clauses w/o objscope] [OR] [objscope 1 clauses] [OR] [objscope 2 clauses]
         $where[$date_key] = agp_implode(' ) OR ( ', $where[$date_key], ' ( ', ' ) ');
         if ($date_clause && $where[$date_key]) {
             $where[$date_key] = "( {$where[$date_key]}{$date_clause} )";
         }
     }
     // end foreach datekey (set of content date limits for which role(s) apply)
     foreach (array_keys($where) as $date_key) {
         if (empty($where[$date_key])) {
             unset($where[$date_key]);
         }
     }
     // all date clauses concat: [clauses w/o content date limits] [OR] [content date range 1 clauses] [OR] [content date range 2 clauses]
     $where = agp_implode(' ) OR ( ', $where, ' ( ', ' ) ');
     if (empty($where)) {
         $where = '1=2';
     }
     return $where;
 }
 function get_all_groups($filtering = UNFILTERED_RS, $cols = COLS_ALL_RS, $args = array())
 {
     $defaults = array('include_norole_groups' => false, 'reqd_caps' => 'manage_groups', 'where' => '');
     $args = array_merge($defaults, (array) $args);
     extract($args);
     if ($filtering && is_user_administrator_rs()) {
         $filtering = 0;
     }
     if ($filtering) {
         $cache_flag = 'usergroups';
         global $current_rs_user;
         $cache = $current_rs_user->cache_get($cache_flag);
     } else {
         $cache_flag = 'all_usergroups';
         $cache_id = 'all';
         $cache = wpp_cache_get($cache_id, $cache_flag);
     }
     $ckey = md5($cols . $reqd_caps);
     if (!isset($cache[$ckey])) {
         global $wpdb;
         if ($filtering && !is_user_administrator_rs() && !cr_user_can($reqd_caps, 0, 0, array('skip_any_object_check' => true, 'skip_any_term_check' => true, 'skip_id_generation' => true))) {
             $duration_clause = scoper_get_duration_clause();
             global $scoper;
             $role_handles = $scoper->role_defs->qualify_roles($reqd_caps);
             $role_names = array();
             foreach (array_keys($role_handles) as $role_handle) {
                 $role = scoper_explode_role_handle($role_handle);
                 $role_names[] = $role->role_name;
             }
             $role_clause = "AND uro.role_name IN ('" . implode("','", $role_names) . "')";
             $join = "INNER JOIN {$wpdb->user2role2object_rs} AS uro" . " ON uro.obj_or_term_id = {$wpdb->groups_rs}.{$wpdb->groups_id_col}" . " AND uro.src_or_tx_name = 'group' AND uro.scope = 'object' {$role_clause} {$duration_clause}";
             $_where = "WHERE uro.user_id = {$current_rs_user->ID}";
         } else {
             $join = '';
             $_where = 'WHERE 1=1 ';
         }
         // append supplemental where clause, if any was passed in
         $_where .= $where;
         if (COL_ID_RS == $cols) {
             $query = "SELECT DISTINCT {$wpdb->groups_id_col} FROM {$wpdb->groups_rs} {$join} {$_where}";
         } else {
             $query = "SELECT DISTINCT {$wpdb->groups_id_col} AS ID, {$wpdb->groups_name_col} AS display_name, {$wpdb->groups_descript_col} as descript, {$wpdb->groups_meta_id_col} as meta_id" . " FROM {$wpdb->groups_rs} {$join} {$_where} ORDER BY {$wpdb->groups_name_col}";
         }
         if (COL_ID_RS == $cols) {
             $cache[$ckey] = scoper_get_col($query);
         } else {
             $cache[$ckey] = scoper_get_results($query);
         }
     }
     if ($filtering) {
         $current_rs_user->cache_set($cache, $cache_flag);
     } else {
         wpp_cache_set($cache_id, $cache, $cache_flag);
     }
     if (COLS_ALL_RS == $cols) {
         // strip out anon metagroup if we're not using it (have to do this after cache storage / retrieval)
         if (!defined('SCOPER_ANON_METAGROUP')) {
             foreach (array_keys($cache[$ckey]) as $key) {
                 if ('wp_anon' == $cache[$ckey][$key]->meta_id) {
                     unset($cache[$ckey][$key]);
                     break;
                 }
             }
         }
         // strip out groups that don't use roles, unless arg asked for them
         if (!$include_norole_groups) {
             foreach (array_keys($cache[$ckey]) as $key) {
                 if (strpos($cache[$ckey][$key]->meta_id, '_nr_')) {
                     unset($cache[$ckey][$key]);
                 }
             }
         }
     }
     if (!$cache[$ckey]) {
         $cache[$ckey] = array();
     }
     return $cache[$ckey];
 }