function attachment_access()
 {
     global $post, $wpdb;
     if (empty($post)) {
         global $wp_query;
         if (!empty($wp_query->query_vars['attachment_id'])) {
             $post = scoper_get_row("SELECT * FROM {$wpdb->posts} WHERE post_type = 'attachment' AND ID = '{$wp_query->query_vars['attachment_id']}'");
         } elseif (!empty($wp_query->query_vars['attachment'])) {
             $post = scoper_get_row("SELECT * FROM {$wpdb->posts} WHERE post_type = 'attachment' AND post_name = '{$wp_query->query_vars['attachment']}'");
         }
     }
     if (!empty($post)) {
         $object_type = scoper_get_var("SELECT post_type FROM {$wpdb->posts} WHERE ID = '{$post->post_parent}'");
         // default to 'post' object type if retrieval failed for some reason
         if (empty($object_type)) {
             $object_type = 'post';
         }
         if ($post->post_parent) {
             if (!current_user_can("read_{$object_type}", $post->post_parent)) {
                 if (scoper_get_otype_option('do_teaser', 'post')) {
                     if ($use_teaser_type = scoper_get_otype_option('use_teaser', 'post', $object_type)) {
                         AttachmentTemplate_RS::impose_post_teaser($post, $object_type, $use_teaser_type);
                     } else {
                         unset($post);
                     }
                 } else {
                     unset($post);
                 }
                 // WordPress generates 404 if teaser is not enabled
             }
         } elseif (defined('SCOPER_BLOCK_UNATTACHED_UPLOADS') && SCOPER_BLOCK_UNATTACHED_UPLOADS) {
             unset($post);
         }
     }
 }
function agp_return_file($file_path, $attachment_id = 0)
{
    require_once dirname(__FILE__) . '/uploads_rs.php';
    $uploads = scoper_get_upload_info();
    if (false === strpos($file_path, $uploads['basedir'])) {
        $file_path = untrailingslashit($uploads['basedir']) . "/{$file_path}";
    }
    $file_url = str_replace(untrailingslashit($uploads['basedir']), untrailingslashit($uploads['baseurl']), $file_path);
    //rs_errlog( "agp_return_file: $file_path" );
    if (!$attachment_id) {
        global $wpdb;
        // we've already confirmed that this user can read the file; if it is attached to more than one post any corresponding file key will do
        // Resized copies have -NNNxNNN suffix, but the base filename is stored as attachment.  Strip the suffix out for db query.
        $orig_file_url = preg_replace("/-[0-9]{2,4}x[0-9]{2,4}./", '.', $file_url);
        //rs_errlog( "orig_file_url: $orig_file_url" );
        if (!($attachment_id = scoper_get_var("SELECT ID FROM {$wpdb->posts} WHERE post_type = 'attachment' AND guid = '{$orig_file_url}' AND post_parent > 0 LIMIT 1"))) {
            return;
        }
    }
    if (!($key = get_post_meta($attachment_id, '_rs_file_key'))) {
        // The key was lost from DB, so regenerate it (and files / uploads .htaccess)
        require_once dirname(__FILE__) . '/rewrite-rules_rs.php';
        ScoperRewrite::resync_file_rules();
        // If the key is still not available, fail out to avoid recursion
        if (!($key = get_post_meta($attachment_id, '_rs_file_key'))) {
            exit(0);
        }
    } elseif (strpos($_SERVER['REQUEST_URI'], 'rs_file_key')) {
        // Apparantly, the .htaccess rules contain an entry for this file, but with invalid file key.  URL with this valid key already passed through RewriteRules.
        // Regenerate .htaccess file in uploads folder, but don't risk recursion by redirecting again.  Note that Firefox browser cache may need to be cleared following this error.
        $last_resync = get_option('scoper_last_htaccess_resync');
        if (!$last_resync || time() - $last_resync > 3600) {
            // prevent abuse (mismatched .htaccess keys should not be a frequent occurance)
            update_option('scoper_last_htaccess_resync', time());
            require_once dirname(__FILE__) . '/rewrite-rules_rs.php';
            ScoperRewrite::resync_file_rules();
        }
        exit(0);
        // If htaccess rewrite was instantaneous, we could just continue without this exit.  But settle for the one-time image access failure to avoid a redirect loop on delayed file update.
    }
    if (is_array($key)) {
        $key = reset($key);
    }
    if (IS_MU_RS) {
        $basedir = parse_url($uploads['basedir']);
        $baseurl = parse_url($uploads['baseurl']);
        global $base;
        $file_url = str_replace(ABSPATH, $baseurl['scheme'] . '://' . $baseurl['host'] . $base, $file_path);
        $file_url = str_replace('\\', '/', $file_url);
    }
    $redirect = $file_url . "?rs_file_key={$key}";
    //rs_errlog( "redirect: $redirect" );
    usleep(10);
    wp_redirect($redirect);
    exit(0);
}
 function flt_comments_clauses($clauses, &$qry_obj)
 {
     global $wpdb;
     if (is_admin() && defined('SCOPER_NO_COMMENT_FILTERING') && empty($GLOBALS['current_user']->allcaps['moderate_comments'])) {
         return $clauses;
     }
     if (empty($clauses['join'])) {
         $clauses['join'] = "JOIN {$wpdb->posts} ON {$wpdb->posts}.ID = {$wpdb->comments}.comment_post_ID";
     }
     // for WP 3.1 and any manual 3rd-party join construction (subsequent filter will expand to additional statuses as appropriate)
     $clauses['where'] = preg_replace("/ post_status\\s*=\\s*[']?publish[']?/", " {$wpdb->posts}.post_status = 'publish'", $clauses['where']);
     // performance enhancement: simplify comments query if there are no attachment comments to filter (TODO: cache this result)
     $qry_any_attachment_comments = "SELECT ID FROM {$wpdb->posts} AS p INNER JOIN {$wpdb->comments} AS c ON p.ID = c.comment_post_ID WHERE p.post_type = 'attachment' LIMIT 1";
     $post_type_arg = isset($qry_obj->query_vars['post_type']) ? $qry_obj->query_vars['post_type'] : '';
     $post_id = !empty($qry_obj->query_vars['post_id']) ? $qry_obj->query_vars['post_id'] : 0;
     $attachment_query = 'attachment' == $post_type_arg || $post_id && 'attachment' == get_post_field('post_type', $post_id);
     $args = array('skip_teaser' => true);
     if (is_admin()) {
         require_once 'admin/comments-interceptor-admin_rs.php';
         $args['force_reqd_caps'] = CommentsInterceptorAdmin_RS::get_reqd_caps();
     }
     // $attachment_query: current query is for attachment post type, or for a specific post which is an attachment
     // $post_id: current query is for a specific post
     // 	 NOTE: even if not $attachment_query, attachment comments are included by default along with comments on other post types (i.e. for Recent Comments sidebar)
     if (defined('SCOPER_NO_ATTACHMENT_COMMENTS') || !$attachment_query && ($post_id || !defined('SCOPER_ATTACHMENT_COMMENTS') && !scoper_get_var($qry_any_attachment_comments))) {
         $clauses['where'] = " AND " . $clauses['where'];
         $clauses['where'] = "1=1" . apply_filters('objects_where_rs', $clauses['where'], 'post', $post_type_arg, $args);
     } else {
         if (false === strpos($clauses['fields'], 'DISTINCT ')) {
             $clauses['fields'] = 'DISTINCT ' . $clauses['fields'];
         }
         if ($post_type_arg) {
             $post_types = (array) $post_type_arg;
         } else {
             $post_types = array_diff(get_post_types(array('public' => true)), array('attachment'));
         }
         $post_type_in = "'" . implode("','", $post_types) . "'";
         $clauses['join'] .= " LEFT JOIN {$wpdb->posts} as parent ON parent.ID = {$wpdb->posts}.post_parent AND parent.post_type IN ({$post_type_in}) AND {$wpdb->posts}.post_type = 'attachment'";
         $use_post_types = scoper_get_option('use_post_types');
         $where = array();
         foreach ($post_types as $type) {
             if (!empty($use_post_types[$type])) {
                 $where_post = apply_filters('objects_where_rs', '', 'post', $type, $args);
             } else {
                 $where_post = "AND 1=1";
             }
             $where[] = "{$wpdb->posts}.post_type = '{$type}' {$where_post}";
             $where[] = "{$wpdb->posts}.post_type = 'attachment' AND parent.post_type = '{$type}' " . str_replace("{$wpdb->posts}.", "parent.", $where_post);
         }
         $clauses['where'] = preg_replace("/\\s*AND\\s*{$wpdb->posts}.post_status\\s*=\\s*[']?publish[']?/", "", $clauses['where']);
         $clauses['where'] .= ' AND ( ' . agp_implode(' ) OR ( ', $where, ' ( ', ' ) ') . ' )';
     }
     return $clauses;
 }
 function flt_user_has_cap($wp_blogcaps, $orig_reqd_caps, $args)
 {
     if (empty($args[2])) {
         return $wp_blogcaps;
     }
     // Disregard caps which are not defined in Role Scoper config
     if (!($rs_reqd_caps = array_intersect($orig_reqd_caps, $this->scoper->cap_defs->get_all_keys()))) {
         return $wp_blogcaps;
     }
     $user_id = isset($args[1]) ? $args[1] : 0;
     global $current_rs_user;
     if ($user_id && $user_id != $current_rs_user->ID) {
         $user = rs_get_user($user_id);
     } else {
         $user = $current_rs_user;
     }
     $object_id = (int) $args[2];
     if (!($post_type = get_post_field('post_type', $object_id))) {
         return $wp_blogcaps;
     }
     global $wpdb;
     $use_term_roles = scoper_get_otype_option('use_term_roles', 'post', $post_type);
     $use_object_roles = empty($src->no_object_roles) ? scoper_get_otype_option('use_object_roles', 'post', $post_type) : false;
     $this_args = array('object_type' => $post_type, 'user' => $user, 'otype_use_term_roles' => $use_term_roles, 'otype_use_object_roles' => $use_object_roles, 'skip_teaser' => true);
     $where = $this->query_interceptor->objects_where_role_clauses('post', $rs_reqd_caps, $this_args);
     if ($where) {
         $where = "AND ( {$where} )";
     }
     $id_ok = scoper_get_var("SELECT {$wpdb->posts}.ID FROM {$wpdb->posts} WHERE 1=1 {$where} AND {$wpdb->posts}.ID = '{$object_id}' LIMIT 1");
     $rs_reqd_caps = array_fill_keys($rs_reqd_caps, true);
     if (!$id_ok) {
         //d_echo("object_id $object_id not okay!" );
         //rs_errlog( "object_id $object_id not okay!" );
         return array_diff_key($wp_blogcaps, $rs_reqd_caps);
         // required caps we scrutinized are excluded from this array
     } else {
         if ($restore_caps = array_diff($orig_reqd_caps, array_keys($rs_reqd_caps))) {
             $rs_reqd_caps = $rs_reqd_caps + array_fill_keys($restore_caps, true);
         }
         //rs_errlog( 'RETURNING:' );
         //rs_errlog( serialize(array_merge($wp_blogcaps, $rs_reqd_caps)) );
         return array_merge($wp_blogcaps, $rs_reqd_caps);
     }
 }
 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);
     }
 }
 /**
  * Checks if a group with a given name exists
  *
  * @param string $name - Name of the group to test
  * @return boolean True if the group exists, false otherwise.
  **/
 function groupExists($name)
 {
     global $wpdb;
     $query = "SELECT COUNT(*) FROM {$wpdb->groups_rs} WHERE {$wpdb->groups_name_col} = '{$name}'";
     $results = scoper_get_var($query);
     return $results != 0;
 }
 function flt_users_where($where, $reqd_caps = '', $object_src_name = '', $object_id = '', $args = array())
 {
     if (!USER_ROLES_RS && !GROUP_ROLES_RS) {
         return $where;
     }
     global $wpdb;
     static $stored_owner_id;
     if (!isset($stored_owner_id)) {
         $stored_owner_id = array();
     }
     $defaults = array('use_term_roles' => 1, 'use_blog_roles' => 1, 'skip_object_roles' => 0, 'querying_groups' => 0, 'ignore_group_roles' => false, 'ignore_user_roles' => false, 'object_type' => '', 'objscope_roles' => '', 'preserve_or_clause' => '', 'enforce_duration_limits' => true, 'enforce_content_date_limits' => true);
     $args = array_merge($defaults, (array) $args);
     extract($args);
     // Default to not honoring custom user caps, but support option
     $custom_user_blogcaps = SCOPER_CUSTOM_USER_BLOGCAPS;
     // if reqd_caps are missing, try to determine context from URI
     if (!$reqd_caps) {
         return $where;
     }
     // no basis for filtering without required caps
     $reqd_caps = (array) $reqd_caps;
     // if rolenames are intermingled with caps in reqd_caps array, convert them to caps
     $reqd_caps = $this->scoper->role_defs->role_handles_to_caps($reqd_caps, true);
     //arg: also check for unprefixed WP rolenames
     if ($object_id && !$object_src_name) {
         $object_id = 0;
     }
     if ($object_id) {
         foreach ($reqd_caps as $cap_name) {
             if ($meta_caps = apply_filters('map_meta_cap_rs', (array) $cap_name, $cap_name, -1, $object_id)) {
                 $reqd_caps = array_diff($reqd_caps, array($cap_name));
                 $reqd_caps = array_unique(array_merge($reqd_caps, $meta_caps));
             }
         }
         if ('post' == $object_src_name && ($use_term_roles || $use_blog_roles)) {
             if ($post = get_post($object_id)) {
                 $object_date_gmt = $post->post_date_gmt;
             }
         } else {
             $object_date_gmt = '';
         }
     }
     $owner_has_all_caps = true;
     // IMPORTANT: set this false downstream as appropriate
     $rs_where = array();
     // Group the required caps by object type (as defined by $scoper->cap_defs).
     // The 2nd arg causes caps without an otype association to be included with a nullstring src_name key
     // The 3rd arg forces caps with a data source other than $object_src to be also lumped in with sourceless caps
     // $caps_by_otype[src_name][object_type] = array of cap names
     $caps_by_otype = $this->scoper->cap_defs->organize_caps_by_otype($reqd_caps, true, $object_src_name, $object_type);
     foreach ($caps_by_otype as $src_name => $otypes) {
         if ($object_type) {
             $otypes = array_intersect_key($otypes, array($object_type => 1));
         }
         // Cap reqs that pertain to other data sources or have no data source association
         // will only be satisfied by blog roles.
         $args['use_term_roles'] = $use_term_roles && $src_name == $object_src_name;
         $args['skip_object_roles'] = $skip_object_roles || $src_name != $object_src_name;
         $this_src_object_id = $src_name == $object_src_name ? $object_id : 0;
         if ($src_name) {
             if (!($src = $this->scoper->data_sources->get($src_name))) {
                 continue;
             }
             $uses_taxonomies = scoper_get_taxonomy_usage($src_name, array_keys($otypes));
             if ($this_src_object_id && $args['use_term_roles'] && !empty($uses_taxonomies)) {
                 $args['object_terms'] = array();
                 foreach ($uses_taxonomies as $taxonomy) {
                     $args['object_terms'][$taxonomy] = $this->scoper->get_terms($taxonomy, UNFILTERED_RS, COL_ID_RS, $this_src_object_id);
                 }
             }
         }
         foreach ($otypes as $object_type => $this_otype_caps) {
             $qry_roles = array();
             $args['use_term_roles'] = $args['use_term_roles'] && scoper_get_otype_option('use_term_roles', $src_name, $object_type);
             //$caps_by_op = $this->scoper->cap_defs->organize_caps_by_op($this_otype_caps, true); //arg: retain caps which are not scoper-defined
             //foreach ( $caps_by_op as $op => $this_op_caps ) {
             foreach ($this_otype_caps as $cap_name) {
                 // If supporting custom user blogcaps, a separate role clause for each cap
                 // Otherwise (default) all reqd_caps from one role assignment (whatever scope it may be)
                 if ($custom_user_blogcaps) {
                     $reqd_caps_arg = array($cap_name);
                 } else {
                     $reqd_caps_arg = $this_otype_caps;
                     $cap_name = '';
                 }
                 // 'blog' argument forces inclusion of qualifying WP roles even if scoping with RS roles
                 // (will later strip out non-scopable roles for term role / object role clauses)
                 $args['roles'] = $this->scoper->role_defs->qualify_roles($reqd_caps_arg, '', '', array('all_wp_caps' => true));
                 if ($args['roles'] || !$src_name) {
                     if (USER_ROLES_RS && !$ignore_user_roles) {
                         $qry_roles[$cap_name]['general'][ROLE_BASIS_USER] = $this->users_queryroles($reqd_caps_arg, $src_name, $this_src_object_id, $args);
                     }
                     if (GROUP_ROLES_RS && !$ignore_group_roles) {
                         $qry_roles[$cap_name]['general'][ROLE_BASIS_GROUPS] = $this->users_queryroles($reqd_caps_arg, $src_name, $this_src_object_id, $args);
                     }
                 }
                 // potentially, a separate set of role clauses for object owner
                 if ($this_src_object_id && $src->cols->owner) {
                     $owner_needs_caps = $this->scoper->cap_defs->get_base_caps($reqd_caps_arg);
                     //returns array of caps the owner needs, after removing those which are credited to owners automatically
                     if ($owner_needs_caps) {
                         $owner_has_all_caps = false;
                     }
                     if ($owner_needs_caps != $reqd_caps_arg) {
                         if (!isset($stored_owner_id[$src_name][$this_src_object_id])) {
                             // DON'T initialize this at top of function
                             $stored_owner_id[$src_name][$this_src_object_id] = scoper_get_var("SELECT {$src->cols->owner} FROM {$src->table} WHERE {$src->cols->id} = '{$object_id}' LIMIT 1");
                         }
                         if ($stored_owner_id[$src_name][$this_src_object_id]) {
                             $owner_roles = $this->scoper->role_defs->qualify_roles($owner_needs_caps);
                             if ($args['roles'] = array_diff_key($owner_roles, $args['roles'])) {
                                 // if owners (needing fewer caps) qualify under different roles than other users:
                                 if (GROUP_ROLES_RS && !$ignore_group_roles) {
                                     if (!isset($owner_groups)) {
                                         $owner_groups = WP_Scoped_User::get_groups_for_user($stored_owner_id[$src_name][$this_src_object_id]);
                                     }
                                     //$owner_groups = scoper_get_col("SELECT $wpdb->user2group_gid_col FROM $wpdb->user2group_rs WHERE $wpdb->user2group_uid_col = '{$stored_owner_id[$src_name][$this_src_object_id]}'");
                                     if ($owner_groups) {
                                         $qry_roles[$cap_name]['owner'][ROLE_BASIS_GROUPS] = $this->users_queryroles($owner_needs_caps, $src_name, $this_src_object_id, $args);
                                     }
                                 }
                                 if (USER_ROLES_RS && !$ignore_user_roles) {
                                     $qry_roles[$cap_name]['owner'][ROLE_BASIS_USER] = $this->users_queryroles($owner_needs_caps, $src_name, $this_src_object_id, $args);
                                 }
                             }
                             // endif owner needs any caps assigned by role
                         }
                         //endif stored owner_id found
                     }
                     // endif any required caps are automatically granted to owner
                 }
                 // endif request is for a specific object from a data source which stores owner_id
                 // If not supporting custom blogcaps, we actually passed all of this object type's caps together
                 if (!$custom_user_blogcaps) {
                     break;
                 }
             }
             // end foreach this_otype_caps
             //d_echo ('scope data');
             //dump($qry_roles);
             // ------------ Construct this object type's where clause from $qry_roles: -----------------
             // ( note: if custom user blogcaps are not enabled, all roles stored into one cap_name dimension )
             // $qry_roles[cap_name][general/owner][user/groups]['object'][''] = array of role handles
             // $qry_roles[cap_name][general/owner][user/groups]['term'][taxonomy] = array of role handles
             // $qry_roles[cap_name][general/owner][user/groups]['blog'][role_type] = array of role handles
             // now construct the query for this iteration's operation type
             $table_aliases = array(ROLE_BASIS_USER => 'uro', ROLE_BASIS_GROUPS => 'gro');
             foreach ($qry_roles as $cap_name => $user_types) {
                 // note: default is to put qualifying roles from all reqd_caps into a single "cap_name" element
                 $ot_where = array();
                 if (!empty($stored_owner_id) && $owner_has_all_caps && USER_ROLES_RS && !$ignore_user_roles) {
                     $ot_where['owner'][ROLE_BASIS_USER] = "uro.user_id = '{$stored_owner_id[$src_name][$this_src_object_id]}'";
                 }
                 foreach ($user_types as $user_type => $role_bases) {
                     foreach ($role_bases as $role_basis => $scopes) {
                         $alias = $table_aliases[$role_basis];
                         $content_date_comparison = $enforce_content_date_limits && !empty($object_date_gmt) ? "'{$object_date_gmt}'" : '';
                         $duration_clause = scoper_get_duration_clause($content_date_comparison, $alias, $enforce_duration_limits);
                         // arg: skip duration clause
                         foreach ($scopes as $scope => $keys) {
                             foreach ($keys as $key => $role_names) {
                                 if (empty($role_names)) {
                                     continue;
                                 }
                                 $role_in = "'" . implode("','", $role_names) . "'";
                                 switch ($scope) {
                                     case OBJECT_SCOPE_RS:
                                         $id_clause = $object_id ? "AND {$alias}.obj_or_term_id = '{$object_id}'" : '';
                                         $ot_where[$user_type][$role_basis][$scope][$key] = "{$alias}.scope = 'object' AND {$alias}.assign_for IN ('entity', 'both') AND {$alias}.src_or_tx_name = '{$src_name}' AND {$alias}.role_type = 'rs' AND {$alias}.role_name IN ({$role_in}) {$duration_clause} {$id_clause}";
                                         break;
                                     case TERM_SCOPE_RS:
                                         $terms_clause = $object_id && $args['object_terms'][$key] ? "AND {$alias}.obj_or_term_id IN ('" . implode("', '", $args['object_terms'][$key]) . "')" : '';
                                         $ot_where[$user_type][$role_basis][$scope][$key] = "{$alias}.scope = 'term' AND {$alias}.assign_for IN ('entity', 'both') AND {$alias}.src_or_tx_name = '{$key}' {$terms_clause} AND {$alias}.role_type = 'rs' AND {$alias}.role_name IN ({$role_in}) {$duration_clause}";
                                         break;
                                     case BLOG_SCOPE_RS:
                                         $ot_where[$user_type][$role_basis][$scope][$key] = "{$alias}.scope = 'blog' AND {$alias}.role_type = '{$key}' AND {$alias}.role_name IN ({$role_in}) {$duration_clause}";
                                         break;
                                 }
                                 // end scope switch
                             }
                             // end foreach key
                             if (!empty($ot_where[$user_type][$role_basis][$scope])) {
                                 // [key 1 clause] [OR] [key 2 clause] [OR] ...
                                 $ot_where[$user_type][$role_basis][$scope] = agp_implode(' ) OR ( ', $ot_where[$user_type][$role_basis][$scope], ' ( ', ' ) ');
                             }
                         }
                         // end foreach scope
                         if (!empty($ot_where[$user_type][$role_basis])) {
                             // [object scope clauses] [OR] [taxonomy scope clauses] [OR] [blog scope clauses]
                             $ot_where[$user_type][$role_basis] = agp_implode(' ) OR ( ', $ot_where[$user_type][$role_basis], ' ( ', ' ) ');
                             if ('owner' == $user_type) {
                                 switch ($role_basis) {
                                     case ROLE_BASIS_GROUPS:
                                         $ot_where[$user_type][$role_basis] .= "AND gro.group_id IN ('" . implode("', '", $owner_groups) . "')";
                                         break;
                                     case ROLE_BASIS_USER:
                                         $ot_where[$user_type][$role_basis] .= "AND uro.user_id = '{$stored_owner_id[$src_name][$this_src_object_id]}'";
                                 }
                                 // end role basis switch
                             }
                             // endif owner
                         }
                         // endif any role clauses for this user_type/role_basis
                     }
                     // end foreach role basis (user or groups)
                 }
                 // end foreach user type (general or owner)
                 foreach ($ot_where as $user_type => $arr) {
                     foreach ($arr as $role_basis => $val) {
                         if (!empty($ot_where[$user_type])) {
                             // [group role clauses] [OR] [user role clauses]
                             $ot_where[$user_type] = agp_implode(' ) OR ( ', $ot_where[$user_type], ' ( ', ' ) ');
                         }
                     }
                 }
                 if (!empty($ot_where)) {
                     // [general user clauses] [OR] [owner clauses]
                     $rs_where[$src_name][$object_type][$cap_name] = agp_implode(' ) OR ( ', $ot_where, ' ( ', ' ) ');
                 }
             }
             // end foreach cap name (for optional support of custom user blogcaps)
             if (!empty($rs_where[$src_name][$object_type])) {
                 // [cap1 clauses] [AND] [cap2 clauses]
                 $rs_where[$src_name][$object_type] = agp_implode(' ) AND ( ', $rs_where[$src_name][$object_type], ' ( ', ' ) ');
             }
         }
         // end foreach otypes
         if (isset($rs_where[$src_name])) {
             // object_type1 clauses [AND] [object_type2 clauses] [AND] ...
             $rs_where[$src_name] = agp_implode(' ) AND ( ', $rs_where[$src_name], ' ( ', ' ) ');
         }
     }
     // end foreach data source
     // data_source 1 clauses [AND] [data_source 2 clauses] [AND] ...
     $rs_where = agp_implode(' ) AND ( ', $rs_where, ' ( ', ' ) ');
     if ($rs_where) {
         if (false !== strpos($where, $rs_where)) {
             return $where;
         }
         if (!empty($preserve_or_clause)) {
             $rs_where = "( ( {$rs_where} ) OR ( {$preserve_or_clause} ) )";
         }
         if ($where) {
             $where = " AND ( {$rs_where} ) {$where}";
         } else {
             $where = " AND {$rs_where}";
         }
     } else {
         // if no valid role clauses were constructed, required caps are invalid; no users can do it
         $where = ' AND 1=2';
     }
     return $where;
 }
function scoper_any_role_limits()
{
    global $wpdb;
    $any_limits = (object) array('date_limited' => false, 'start_date_gmt' => false, 'end_date_gmt' => false, 'content_date_limited' => false, 'content_min_date_gmt' => false, 'content_max_date_gmt' => false);
    if (scoper_get_var("SELECT assignment_id FROM {$wpdb->user2role2object_rs} WHERE date_limited > 0 LIMIT 1")) {
        $any_limits->date_limited = true;
        if (scoper_get_var("SELECT assignment_id FROM {$wpdb->user2role2object_rs} WHERE start_date_gmt > 0 LIMIT 1")) {
            $any_limits->start_date_gmt = true;
        }
        if (scoper_get_var("SELECT assignment_id FROM {$wpdb->user2role2object_rs} WHERE end_date_gmt != '" . SCOPER_MAX_DATE_STRING . "' LIMIT 1")) {
            $any_limits->end_date_gmt = true;
        }
    }
    if (scoper_get_option('role_content_date_limits') && scoper_get_var("SELECT assignment_id FROM {$wpdb->user2role2object_rs} WHERE content_date_limited > 0 LIMIT 1")) {
        $any_limits->content_date_limited = true;
        if (scoper_get_var("SELECT assignment_id FROM {$wpdb->user2role2object_rs} WHERE content_min_date_gmt > 0 LIMIT 1")) {
            $any_limits->content_min_date_gmt = true;
        }
        if (scoper_get_var("SELECT assignment_id FROM {$wpdb->user2role2object_rs} WHERE content_max_date_gmt != '" . SCOPER_MAX_DATE_STRING . "' LIMIT 1")) {
            $any_limits->content_max_date_gmt = true;
        }
    }
    return $any_limits;
}
 function get_terms($taxonomy, $filtering = true, $cols = COLS_ALL_RS, $object_id = 0, $args = array())
 {
     if (!($tx = $this->taxonomies->get($taxonomy))) {
         return array();
     }
     global $wpdb;
     $defaults = array('order_by' => '', 'use_object_roles' => false, 'operation' => '');
     // IMPORTANT to default operation to nullstring
     $args = array_merge($defaults, (array) $args);
     extract($args);
     if (is_administrator_rs($this->taxonomies->member_property($taxonomy, 'object_source'))) {
         $filtering = false;
     }
     // try to pull it out of wpcache
     $ckey = md5($taxonomy . $cols . $object_id . serialize($args) . $order_by);
     if ($filtering) {
         $src_name = $this->taxonomies->member_property($taxonomy, 'object_source', 'name');
         $args['reqd_caps_by_otype'] = $this->get_terms_reqd_caps($taxonomy, $operation, ADMIN_TERMS_FILTER_RS === $filtering);
         $ckey = md5($ckey . serialize($args['reqd_caps_by_otype']));
         // can vary based on request URI
         global $current_rs_user;
         $cache_flag = 'rs_scoper_get_terms';
         $cache = $current_rs_user->cache_get($cache_flag);
     } else {
         $cache_flag = "all_terms";
         $cache_id = 'all';
         $cache = wpp_cache_get($cache_id, $cache_flag);
     }
     if (isset($cache[$ckey])) {
         return $cache[$ckey];
     }
     // call base class method to build query
     $terms_only = !$filtering || empty($use_object_roles);
     $query_base = $this->taxonomies->get_terms_query($taxonomy, $cols, $object_id, $terms_only);
     if (!$query_base) {
         return array();
     }
     $query = $filtering ? apply_filters('terms_request_rs', $query_base, $taxonomy, $args) : $query_base;
     // avoid sending alarms to SQL purists if this query was not modified by RS filter
     if ($query_base == $query) {
         $query = str_replace('WHERE 1=1 AND', 'WHERE', $query);
     }
     if (COL_ID_RS == $cols) {
         $results = scoper_get_col($query);
     } elseif (COL_COUNT_RS == $cols) {
         $results = intval(scoper_get_var($query));
     } else {
         // TODO: why is this still causing an extra (and costly) scoped query?
         /*
         // for COLS_ALL query, need to call core get_terms call in case another plugin is translating term names
         if ( has_filter( 'get_terms', array('ScoperHardwayTaxonomy', 'flt_get_terms') ) ) {
         	remove_filter( 'get_terms', array('ScoperHardwayTaxonomy', 'flt_get_terms'), 1, 3 );
         	$all_terms = get_terms($taxonomy);
         	add_filter( 'get_terms', array('ScoperHardwayTaxonomy', 'flt_get_terms'), 1, 3 );
         
         	$term_names = scoper_get_property_array( $all_terms, 'term_id', 'name' );
         }
         */
         $results = scoper_get_results($query);
         //scoper_restore_property_array( $results, $term_names, 'term_id', 'name' );
         if (ORDERBY_HIERARCHY_RS == $order_by) {
             require_once dirname(__FILE__) . '/admin/admin_lib_rs.php';
             if ($src = $this->data_sources->get($tx->source)) {
                 if (!empty($src->cols->id) && !empty($src->cols->parent)) {
                     require_once dirname(__FILE__) . '/admin/admin_lib-bulk-parent_rs.php';
                     $results = ScoperAdminBulkParent::order_by_hierarchy($results, $src->cols->id, $src->cols->parent);
                 }
             }
         }
     }
     $cache[$ckey] = $results;
     if ($results || empty($_POST)) {
         // todo: why do we get an empty array for unfiltered request for object terms early in POST processing? (on submission of a new post by a contributor)
         if ($filtering) {
             $current_rs_user->cache_force_set($cache, $cache_flag);
         } else {
             wpp_cache_force_set($cache_id, $cache, $cache_flag);
         }
     }
     return $results;
 }
 function flt_get_comments_number($count)
 {
     global $wpdb;
     global $id;
     // get_comments_number should pass post_id as 2nd arg, but does not as of WP 2.7
     static $last_id;
     static $last_count;
     if (isset($last_count) && $id == $last_id) {
         return $last_count;
     }
     $query = "SELECT COUNT( DISTINCT(comment_ID) ) FROM {$wpdb->comments}" . " INNER JOIN {$wpdb->posts} ON {$wpdb->posts}.ID = {$wpdb->comments}.comment_post_ID" . " WHERE comment_approved = '1' AND comment_post_ID = '{$id}'";
     $count = scoper_get_var($query);
     $last_id = $id;
     $last_count = $count;
     return $count;
 }
 function any_custom_caps_assigned()
 {
     global $wpdb;
     $got_any = scoper_get_var("SELECT assignment_id FROM {$wpdb->user2role2object_rs} WHERE scope = 'blog' AND role_type = 'wp_cap' LIMIT 1");
     return $got_any;
 }
    global $xmlrpc_post_id_rs;
    $xmlrpc_post_id_rs = $post_id;
    $post_type = '';
    if ($pos = strpos($HTTP_RAW_POST_DATA, '<name>post_type</name>')) {
        if ($pos = strpos($HTTP_RAW_POST_DATA, '<string>', $pos)) {
            if ($pos_end = strpos($HTTP_RAW_POST_DATA, '</string>', $pos)) {
                $post_type = substr($HTTP_RAW_POST_DATA, $pos + strlen('<string>'), $pos_end - ($pos + strlen('<string>')));
            }
        }
    }
    if (empty($post_type)) {
        if ($pos_member_end = strpos($HTTP_RAW_POST_DATA, '</member>')) {
            if ($pos_member_end = strpos($HTTP_RAW_POST_DATA, '</member>', $pos_member_end + 1)) {
                $pos_insert = $pos_member_end + strlen('</member>');
                global $wpdb;
                if ($post_type = scoper_get_var("SELECT post_type FROM {$wpdb->posts} WHERE ID = '{$post_id}'")) {
                    if ('post' != $post_type) {
                        global $xmlrpc_post_type_rs;
                        $xmlrpc_post_type_rs = $post_type;
                    }
                    $insert_xml = "          <member>\r\n            <name>post_type</name>\r\n            <value>\r\n              <string>{$post_type}</string>\r\n            </value>\r\n          </member>";
                    $HTTP_RAW_POST_DATA = substr($HTTP_RAW_POST_DATA, 0, $pos_insert + 1) . $insert_xml . substr($HTTP_RAW_POST_DATA, $pos_insert);
                }
                // endif parsed post type
            }
            // endif found existing member markup
        }
        // endif found 2nd existing member markup
    }
    // endif post_type not passed
}
function delete_roles_orphaned_from_item($scope, $src_or_tx_name)
{
    global $scoper, $wpdb;
    if ('term' == $scope) {
        if ('category' == $src_or_tx_name) {
            // this is called early by sync_roles
            $item_table = $wpdb->term_taxonomy;
            $col_item_id = 'term_id';
        } elseif (!empty($scoper)) {
            $qv = $scoper->taxonomies->get_terms_query_vars($src_or_tx_name, true);
            // arg: terms only
            $item_table = $qv->term->table;
            $col_item_id = $qv->term->col_id;
        }
    } else {
        if ('post' == $src_or_tx_name) {
            // this is called early by sync_roles
            $col_item_id = 'ID';
            $item_table = $wpdb->posts;
        } elseif (!empty($scoper)) {
            $col_item_id = $scoper->data_sources->member_property($src_or_tx_name, 'cols', 'id');
            $item_table = $scoper->data_sources->member_property($src_or_tx_name, 'table');
        }
    }
    if ($is_valid_items = scoper_get_var("SELECT {$col_item_id} FROM {$item_table} LIMIT 1")) {
        $where = "AND scope = '{$scope}' AND src_or_tx_name = '{$src_or_tx_name}' AND obj_or_term_id NOT IN ( SELECT {$col_item_id} FROM {$item_table} ) AND obj_or_term_id >= 1 ";
        if ($items_to_delete = scoper_get_var("SELECT assignment_id FROM {$wpdb->user2role2object_rs} WHERE 1=1 {$where} LIMIT 1")) {
            $qry = "DELETE FROM {$wpdb->user2role2object_rs} WHERE 1=1 {$where}";
            scoper_query($qry);
            wpp_cache_flush();
        }
    }
}
function scoper_flt_pre_object_terms($selected_terms, $taxonomy, $args = array())
{
    //rs_errlog( "scoper_flt_pre_object_terms input: " . serialize($selected_terms) );
    // strip out fake term_id -1 (if applied)
    if ($selected_terms && is_array($selected_terms)) {
        $selected_terms = array_diff($selected_terms, array(-1, 0, '0', '-1', ''));
    }
    // not sure who is changing empty $_POST['post_category'] array to an array with nullstring element, but we have to deal with that
    if (defined('DISABLE_QUERYFILTERS_RS')) {
        return $selected_terms;
    }
    if (!is_array($selected_terms)) {
        // don't filter term selection for non-hierarchical taxonomies
        if (isset($GLOBALS['wp_taxonomies'][$taxonomy]) && empty($GLOBALS['wp_taxonomies'][$taxonomy]->hierarchical)) {
            return $selected_terms;
        }
    }
    global $scoper, $current_user, $wpdb;
    if (!($src_name = $scoper->taxonomies->member_property($taxonomy, 'object_source'))) {
        return $selected_terms;
    }
    // don't filter selected terms for content administrator, but still need to apply default term as needed when none were selected
    if (is_content_administrator_rs()) {
        $user_terms = $selected_terms;
    } else {
        if (defined('RVY_VERSION')) {
            global $revisionary;
            if (!empty($revisionary->admin->impose_pending_rev)) {
                return $selected_terms;
            }
        }
        $orig_selected_terms = $selected_terms;
        if (!is_array($selected_terms)) {
            $selected_terms = array();
        }
        require_once dirname(__FILE__) . '/filters-admin-term-selection_rs.php';
        $user_terms = array();
        // will be returned by filter_terms_for_status
        $selected_terms = scoper_filter_terms_for_status($taxonomy, $selected_terms, $user_terms);
        if ('post' == $src_name) {
            // TODO: abstract for other data sources
            if ($object_id = (int) $scoper->data_sources->detect('id', $src_name)) {
                $stored_terms = wp_get_object_terms($object_id, $taxonomy, array('fields' => 'ids'));
                if ($deselected_terms = array_diff($stored_terms, $selected_terms)) {
                    if ($unremovable_terms = array_diff($deselected_terms, $user_terms)) {
                        // --- work around storage of autodraft to default category ---
                        $_post = get_post($object_id);
                        if ('category' == $taxonomy && 'draft' == $_post->post_status) {
                            $default_terms = (array) maybe_unserialize(scoper_get_var("SELECT option_value FROM {$wpdb->options} WHERE option_name = 'default_category'"));
                            $unremovable_terms = array_diff($unremovable_terms, $default_terms);
                        }
                        // --- end workaround ---
                        $selected_terms = array_merge($selected_terms, $unremovable_terms);
                    }
                }
            }
        }
    }
    //rs_errlog( "$taxonomy - user terms: " . serialize($user_terms) );
    //rs_errlog( "selected terms: " . serialize($selected_terms) );
    if (empty($selected_terms)) {
        // For now, always check the DB for default terms.  TODO: only if the default_term_option property is set
        if (!($default_term_option = $scoper->taxonomies->member_property($taxonomy, 'default_term_option'))) {
            $default_term_option = "default_{$taxonomy}";
        }
        // avoid recursive filtering.  Todo: use remove_filter so we can call get_option, supporting filtering by other plugins
        $default_terms = (array) maybe_unserialize(scoper_get_var("SELECT option_value FROM {$wpdb->options} WHERE option_name = '{$default_term_option}'"));
        //$selected_terms = (array) get_option( $tx->default_term_option );
        // but if the default term is not defined or is not in user's subset of usable terms, substitute first available
        if ($user_terms) {
            $_default_terms = array_intersect($default_terms, $user_terms);
            if (!$_default_terms) {
                if ($default_terms || defined('SCOPER_AUTO_DEFAULT_TERM')) {
                    // substitute 1st available only if default term option is set or constant defined
                    //if ( $scoper->taxonomies->member_property( $taxonomy, 'requires_term' )  )
                    $default_terms = (array) $user_terms[0];
                } else {
                    $use_taxonomies = scoper_get_option('use_taxonomies');
                    // If a 'requires_term' taxonomy (i.e. hierarchical) is enabled for RS filtering, a term must be stored
                    if (!empty($use_taxonomies[$taxonomy])) {
                        $default_terms = (array) $user_terms[0];
                    } else {
                        $default_terms = array();
                    }
                }
            }
        }
        //rs_errlog( "default_terms: " . serialize($default_terms) );
        $selected_terms = $default_terms;
    }
    //rs_errlog( "returning selected terms: " . serialize($selected_terms) );
    return $selected_terms;
}
 function _detect_object_id($required_cap)
 {
     if (has_filter('detect_object_id_rs')) {
         // currently not used internally
         if ($object_id = apply_filters('detect_object_id_rs', 0, $required_cap)) {
             return $object_id;
         }
     }
     if ($this->scoper->cap_defs->member_property($required_cap, 'is_taxonomy_cap')) {
         if (!empty($_REQUEST['tag_ID'])) {
             return $_REQUEST['tag_ID'];
         }
     }
     global $pagenow;
     if (in_array($pagenow, array('media-upload.php', 'async-upload.php'))) {
         if (!empty($_POST['post_ID'])) {
             return $_POST['post_ID'];
         } elseif (!empty($_REQUEST['post_id'])) {
             return $_REQUEST['post_id'];
         } elseif (!empty($_REQUEST['attachment_id'])) {
             if ($attachment = get_post($_REQUEST['attachment_id'])) {
                 return $attachment->post_parent;
             }
         }
     }
     if (!($src_name = $this->scoper->cap_defs->member_property($required_cap, 'src_name'))) {
         return;
     }
     if (!empty($_POST)) {
         // special case for comment post ID
         if (!empty($_POST['comment_post_ID'])) {
             $_POST['post_ID'] = $_POST['comment_post_ID'];
         }
         // WP core edit_post function requires edit_published_posts or edit_published_pages cap to save a post to "publish" status, but does not pass a post ID
         // Similar situation with edit_others_posts, publish_posts.
         // So... insert the object ID from POST vars
         if ('post' == $src_name) {
             if (!($id = $this->scoper->data_sources->get_from_http_post('id', 'post'))) {
                 if ('async-upload.php' != $GLOBALS['pagenow']) {
                     if ($attach_id = $this->scoper->data_sources->get_from_http_post('attachment_id', 'post')) {
                         if ($attach_id) {
                             global $wpdb;
                             $id = scoper_get_var("SELECT post_parent FROM {$wpdb->posts} WHERE post_type = 'attachment' AND ID = '{$attach_id}'");
                             if ($id > 0) {
                                 return $id;
                             }
                         }
                     }
                 } elseif (!$id && !empty($_POST['id'])) {
                     // in case normal POST variable differs from ajax variable
                     $id = $_POST['id'];
                 }
             }
         }
         /* on the moderation page, admin-ajax tests for moderate_comments without passing any ID */
         if ('moderate_comments' == $required_cap) {
             if ($comment = get_comment($id)) {
                 return $comment->comment_post_ID;
             }
         }
         if (!empty($id)) {
             return $id;
         }
         // special case for adding categories
         if ('manage_categories' == $required_cap) {
             if (!empty($_POST['newcat_parent'])) {
                 return $_POST['newcat_parent'];
             } elseif (!empty($_POST['category_parent'])) {
                 return $_POST['category_parent'];
             }
         }
     } elseif (defined('XMLRPC_REQUEST')) {
         if (!empty($GLOBALS['xmlrpc_post_id_rs'])) {
             return $GLOBALS['xmlrpc_post_id_rs'];
         }
     } else {
         //rs_errlog("checking uri for source $src_name");
         return $this->scoper->data_sources->get_from_uri('id', $src_name);
     }
 }
 function identify_protected_posts($attachment_id = 0, $attachments = false, $cols = '', $args = array())
 {
     $defaults = array('use_object_restrictions' => true, 'use_term_restrictions' => true, 'use_private_status' => true, 'guid' => '');
     $args = array_merge($defaults, (array) $args);
     extract($args);
     global $wpdb, $scoper;
     if (!isset($scoper) || is_null($scoper)) {
         scoper_get_init_options();
         scoper_init();
     }
     if (empty($scoper->taxonomies)) {
         $scoper->load_config();
     }
     $restricted_roles = array();
     $unrestricted_roles = array();
     // TODO: also protect uploads based on restriction of other taxonomies
     $restricted_terms = array();
     $restricted_objects = array();
     $term_restriction_clause = '';
     $object_restriction_clause = '';
     $limit_clause = '';
     $unattached_clause = '';
     global $scoper;
     $reader_roles = array();
     foreach ($scoper->role_defs->role_caps as $role_handle => $role_caps) {
         $caps_by_op = $scoper->cap_defs->organize_caps_by_op(array_keys($role_caps));
         if (count($caps_by_op) == 1 && 'read' == key($caps_by_op)) {
             $reader_roles[] = $role_handle;
         }
     }
     $role_clause = "AND rs.role_name IN ('" . implode("','", scoper_role_handles_to_names($reader_roles)) . "')";
     //if ( $use_private_status )
     //	$role_clause = ( 'rs' == SCOPER_ROLE_TYPE ) ? "AND rs.role_name IN ('post_reader', 'page_reader')" : '';	// if also checking for private status, don't need to check for restriction of private_reader roles
     //else
     //	$role_clause = ( 'rs' == SCOPER_ROLE_TYPE ) ? "AND rs.role_name IN ('post_reader', 'page_reader', 'private_post_reader', 'private_page_reader')" : '';
     if ($use_term_restrictions) {
         $term_restriction_query = "SELECT rs.obj_or_term_id AS term_id, rs.role_name, rs.max_scope FROM {$wpdb->role_scope_rs} AS rs " . "INNER JOIN {$wpdb->term_taxonomy} AS tt ON tt.taxonomy = rs.src_or_tx_name AND tt.taxonomy = 'category' AND tt.term_taxonomy_id = rs.obj_or_term_id " . "WHERE rs.role_type = 'rs' AND rs.require_for IN ('entity', 'both') AND rs.topic = 'term' {$role_clause}";
         $term_default_restriction_query = "SELECT rs.role_name FROM {$wpdb->role_scope_rs} AS rs " . "WHERE rs.role_type = 'rs' AND rs.require_for IN ('children', 'both') AND rs.topic = 'term' AND rs.max_scope = 'term' AND rs.src_or_tx_name = 'category' AND rs.obj_or_term_id = '0' {$role_clause}";
         $all_terms = array();
         $all_terms['category'] = $scoper->get_terms('category', false, COL_ID_RS);
         if ($results = scoper_get_results($term_restriction_query)) {
             foreach ($results as $row) {
                 if ('blog' == $row->max_scope) {
                     $unrestricted_roles['category'][$row->role_name][] = $row->term_id;
                 } else {
                     $restricted_roles['category'][$row->role_name][] = $row->term_id;
                 }
             }
         }
         // if there a role is default-restricted, mark all terms as restricted (may be unrestricted later)
         if ($results = scoper_get_col($term_default_restriction_query)) {
             foreach ($results as $role_name) {
                 if (isset($unrestricted_roles['category'][$role_name])) {
                     $default_restricted = array_diff($all_terms['category'], $unrestricted_roles['category'][$role_name]);
                 } else {
                     $default_restricted = $all_terms['category'];
                 }
                 if (isset($restricted_roles['category'][$role_name])) {
                     $restricted_roles['category'][$role_name] = array_unique(array_merge($restricted_roles['category'][$role_name], $default_restricted));
                 } else {
                     $restricted_roles['category'][$role_name] = $default_restricted;
                 }
             }
         }
         $restricted_terms['category'] = isset($restricted_roles['category']) ? agp_array_flatten($restricted_roles['category']) : array();
         if ($restricted_terms['category']) {
             $term_restriction_clause = "OR post_parent IN ( SELECT {$wpdb->posts}.ID FROM {$wpdb->posts} " . "INNER JOIN {$wpdb->term_relationships} AS tr ON tr.object_id = {$wpdb->posts}.ID " . "WHERE tr.term_taxonomy_id IN ('" . implode("','", $restricted_terms['category']) . "') )";
         }
     }
     if ($attachment_id) {
         if (is_array($attachment_id)) {
             $id_clause = "AND ID IN ('" . implode("','", $attachment_id) . "')";
         } else {
             $id_clause = "AND ID = '{$attachment_id}'";
             $limit_clause = 'LIMIT 1';
         }
     } elseif ($guid) {
         $id_clause = "AND guid = '{$file_path}'";
     } else {
         $id_clause = '';
     }
     if (defined('SCOPER_NO_THUMBNAIL_FILTER')) {
         if ($thumbnail_ids = scoper_get_col("SELECT DISTINCT meta_value FROM {$wpdb->postmeta} WHERE meta_key = '_thumbnail_id'")) {
             $id_clause .= " AND ID NOT IN ('" . implode("','", $thumbnail_ids) . "')";
         }
     }
     if ($attachments) {
         // to reduce pool of objects, we only care about those that have an attachment
         $attachment_query = "SELECT {$wpdb->posts}.ID FROM {$wpdb->posts} WHERE {$wpdb->posts}.ID IN ( SELECT post_parent FROM {$wpdb->posts} WHERE post_type = 'attachment' {$id_clause} ) ";
     }
     if ($use_object_restrictions) {
         $object_restriction_query = "SELECT rs.obj_or_term_id AS obj_id, rs.role_name, rs.max_scope FROM {$wpdb->role_scope_rs} AS rs " . "WHERE rs.role_type = 'rs' AND rs.require_for IN ('entity', 'both') AND rs.topic = 'object' AND rs.src_or_tx_name = 'post' {$role_clause} AND rs.obj_or_term_id IN ( {$attachment_query} )";
         $object_default_restriction_query = "SELECT rs.role_name FROM {$wpdb->role_scope_rs} AS rs " . "WHERE rs.require_for IN ('children', 'both') AND rs.topic = 'object' AND rs.max_scope = 'object' AND rs.src_or_tx_name = 'post' AND rs.obj_or_term_id = '0' {$role_clause}";
         $all_objects = array();
         $all_objects['post'] = scoper_get_col($attachment_query);
         $restricted_roles = array();
         $unrestricted_roles = array();
         if ($results = scoper_get_results($object_restriction_query)) {
             foreach ($results as $row) {
                 if ('blog' == $row->max_scope) {
                     $unrestricted_roles['post'][$row->role_name][] = $row->obj_id;
                 } else {
                     $restricted_roles['post'][$row->role_name][] = $row->obj_id;
                 }
             }
         }
         // if there a role is default-restricted, mark all terms as restricted (may be unrestricted later)
         if ($results = scoper_get_col($object_default_restriction_query)) {
             foreach ($results as $role_name) {
                 if (isset($unrestricted_roles['category'][$role_name])) {
                     $default_restricted = array_diff($all_terms['post'], $unrestricted_roles['post'][$role_name]);
                 } else {
                     $default_restricted = $all_objects['post'];
                 }
                 if (isset($restricted_roles['post'][$role_name])) {
                     $restricted_roles['post'][$role_name] = array_unique(array_merge($restricted_roles['post'][$role_name], $default_restricted));
                 } else {
                     $restricted_roles['post'][$role_name] = $default_restricted;
                 }
             }
         }
         if (!empty($restricted_roles)) {
             $restricted_objects['post'] = array_unique(agp_array_flatten($restricted_roles['post']));
             if ($restricted_objects['post']) {
                 $object_restriction_clause = "OR post_parent IN ( SELECT ID FROM {$wpdb->posts} WHERE ID IN ('" . implode("','", $restricted_objects['post']) . "') )";
             }
         }
     }
     if ($use_private_status) {
         $status_query = "AND post_parent IN ( SELECT {$wpdb->posts}.ID FROM {$wpdb->posts} WHERE {$wpdb->posts}.post_status = 'private' )";
     }
     if ($attachments) {
         $attachment_type_clause = "post_type = 'attachment' AND";
         $unattached_clause = defined('SCOPER_BLOCK_UNATTACHED_UPLOADS') ? " OR post_parent < 1" : '';
     }
     $single_col = false;
     if (COLS_ALL_RS === $cols) {
         $query_cols = '*';
     } elseif (COL_ID_RS == $cols) {
         $query_cols = 'ID';
         $single_col = true;
     } elseif (COLS_ID_DISPLAYNAME_RS == $cols) {
         if ($attachment) {
             $query_cols = 'ID, post_title, guid';
         } else {
             $query_cols = 'ID, post_title';
         }
     } else {
         if ($attachments) {
             $query_cols = 'ID, guid';
         } else {
             $query_cols = 'ID';
             $single_col = true;
         }
     }
     $query = "SELECT {$query_cols} FROM {$wpdb->posts} WHERE {$attachment_type_clause} ( 1=1 {$status_query} {$term_restriction_clause} {$object_restriction_clause} {$unattached_clause} ) {$id_clause} ORDER BY ID DESC {$limit_clause}";
     if ($attachment_id && !is_array($attachment_id)) {
         if ($single_col) {
             $results = scoper_get_var($query);
         } else {
             $results = scoper_get_row($query);
         }
     } else {
         if ($single_col) {
             $results = scoper_get_col($query);
         } else {
             $results = scoper_get_results($query);
         }
     }
     return $results;
 }
 function check_for_user_roles()
 {
     if (IS_MU_RS) {
         return true;
     }
     // this function is only for performance; not currently dealing with multiple uro tables
     global $wpdb;
     return scoper_get_var("SELECT assignment_id FROM {$wpdb->user2role2object_rs} WHERE role_type = 'rs' AND user_id = '{$this->ID}' LIMIT 1");
 }