function get_assigned_roles($scope, $role_basis, $src_or_tx_name, $args = array())
 {
     global $wpdb;
     $defaults = array('id' => false, 'ug_id' => 0, 'join' => '', 'role_handles' => '');
     $args = array_merge($defaults, (array) $args);
     extract($args);
     $id = is_string($id) ? (int) $id : $id;
     $ug_id = is_string($ug_id) ? (int) $ug_id : $ug_id;
     if (BLOG_SCOPE_RS == $scope) {
         return ScoperRoleAssignments::get_assigned_blog_roles($role_basis);
     }
     $roles = array();
     switch ($role_basis) {
         case ROLE_BASIS_USER:
             $col_ug_id = 'user_id';
             $ug_clause = $ug_id ? " AND user_id = '{$ug_id}'" : 'AND user_id > 0';
             break;
         case ROLE_BASIS_GROUPS:
             $col_ug_id = 'group_id';
             $ug_clause = $ug_id ? " AND group_id = '{$ug_id}'" : 'AND group_id > 0';
             break;
     }
     $id_clause = false === $id ? '' : "AND obj_or_term_id = '{$id}'";
     if ($role_handles) {
         if (!is_array($role_handles)) {
             $role_handles = (array) $role_handles;
         }
         $role_clause = $role_handles ? "AND role_name IN ('" . implode("', '", scoper_role_handles_to_names($role_handles)) . "')" : '';
     } else {
         $role_clause = '';
     }
     $qry = "SELECT {$col_ug_id}, obj_or_term_id, role_name, assign_for, assignment_id, inherited_from, date_limited, start_date_gmt, end_date_gmt, content_date_limited, content_min_date_gmt, content_max_date_gmt FROM {$wpdb->user2role2object_rs} AS uro " . "{$join} WHERE role_type = 'rs' {$role_clause} AND scope = %s AND src_or_tx_name = %s {$id_clause} {$ug_clause}";
     $results = scoper_get_results($wpdb->prepare($qry, $scope, $src_or_tx_name));
     foreach ($results as $role) {
         $role_handle = 'rs_' . $role->role_name;
         $roles[$role->obj_or_term_id][$role_handle][$role->{$col_ug_id}] = (array) $role;
     }
     return $roles;
 }
 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 restrict_roles($scope, $src_or_tx_name, $item_id, $roles, $args = array())
 {
     $defaults = array('implicit_removal' => false, 'is_auto_insertion' => false, 'force_flush' => false);
     $args = array_merge($defaults, (array) $args);
     extract($args);
     global $wpdb;
     $is_administrator = is_administrator_rs($src_or_tx_name, 'user');
     $delete_reqs = array();
     $role_change = false;
     $default_strict_modes = array(false);
     $strict_role_in = '';
     // for object restriction, handle auto-setting of equivalent object roles ( 'post reader' for 'private post reader', 'post author' for 'post editor' ).  There is no logical distinction between these roles where a single object is concerned.
     if (OBJECT_SCOPE_RS == $scope) {
         foreach (array_keys($roles) as $role_handle) {
             $equiv_role_handles = array();
             if ($objscope_equivalents = $this->scoper->role_defs->member_property($role_handle, 'objscope_equivalents')) {
                 foreach ($objscope_equivalents as $equiv_role_handle) {
                     if (!isset($roles[$equiv_role_handle])) {
                         // if the equiv role was set manually, leave it alone.  This would not be normal RS behavior
                         $roles[$equiv_role_handle] = $roles[$role_handle];
                     }
                 }
             }
         }
     }
     if ($item_id) {
         $default_restrictions = $this->scoper->get_default_restrictions($scope);
         $default_strict_roles = !empty($default_restrictions[$src_or_tx_name]) ? array_keys($default_restrictions[$src_or_tx_name]) : array();
         if ($default_strict_roles) {
             $strict_role_in = "'" . implode("', '", scoper_role_handles_to_names($default_strict_roles)) . "'";
             $default_strict_modes[] = true;
         }
     }
     foreach ($default_strict_modes as $default_strict) {
         $stored_reqs = array();
         $req_ids = array();
         if ($default_strict && $strict_role_in) {
             $role_clause = "AND role_name IN ({$strict_role_in})";
         } elseif ($strict_role_in) {
             $role_clause = "AND role_name NOT IN ({$strict_role_in})";
         } else {
             $role_clause = '';
         }
         // IMPORTANT: max_scope value determines whether we are inserting / updating RESTRICTIONS or UNRESTRICTIONS
         if (TERM_SCOPE_RS == $scope) {
             $query_max_scope = $default_strict ? 'blog' : 'term';
         } else {
             $query_max_scope = $default_strict ? 'blog' : 'object';
         }
         // Storage of 'blog' max_scope as object restriction does not eliminate any term restrictions.  It merely indicates, for data sources that are default strict, that this object does not restrict roles
         $qry = "SELECT requirement_id AS assignment_id, require_for AS assign_for, inherited_from, role_name FROM {$wpdb->role_scope_rs} WHERE topic = %s AND max_scope = %s" . " AND src_or_tx_name = %s AND obj_or_term_id = %d AND role_type = 'rs' {$role_clause}";
         if ($results = scoper_get_results($wpdb->prepare($qry, $scope, $query_max_scope, $src_or_tx_name, $item_id))) {
             foreach ($results as $key => $req) {
                 $role_handle = 'rs_' . $req->role_name;
                 if (OBJECT_SCOPE_RS == $scope && isset($is_objscope_equiv[$role_handle])) {
                     $role_handle = $is_objscope_equiv[$role_handle];
                 }
                 $stored_reqs[$role_handle] = array('assignment_id' => $req->assignment_id, 'assign_for' => $req->assign_for, 'inherited_from' => $req->inherited_from);
                 $req_ids[$role_handle][$req->assignment_id] = array();
             }
         }
         if (!$is_administrator) {
             $user_has_role = $this->_validate_assigner_roles($scope, $src_or_tx_name, $item_id, $roles);
         }
         if ($implicit_removal) {
             // Stored restrictions which are not mirrored in $roles will be deleted (along with their prodigy)
             foreach (array_keys($stored_reqs) as $role_handle) {
                 $max_scope = isset($roles[$role_handle]['max_scope']) ? $roles[$role_handle]['max_scope'] : false;
                 if ($max_scope != $query_max_scope) {
                     $delete_reqs = $delete_reqs + $req_ids[$role_handle];
                 }
             }
         }
         foreach ($roles as $role_handle => $setting) {
             if (!$is_administrator && empty($user_has_role[$role_handle])) {
                 continue;
             }
             if ($default_strict && !in_array($role_handle, $default_strict_roles)) {
                 continue;
             }
             if (!$default_strict && !empty($default_strict_roles) && in_array($role_handle, $default_strict_roles)) {
                 continue;
             }
             $max_scope = $setting['max_scope'];
             if ($max_scope != $query_max_scope) {
                 $require_for = REMOVE_ASSIGNMENT_RS;
             } elseif ($setting['for_item']) {
                 $require_for = $setting['for_children'] ? ASSIGN_FOR_BOTH_RS : ASSIGN_FOR_ENTITY_RS;
             } else {
                 $require_for = $setting['for_children'] ? ASSIGN_FOR_CHILDREN_RS : REMOVE_ASSIGNMENT_RS;
             }
             $update_require_for = array(ASSIGN_FOR_ENTITY_RS => array(), ASSIGN_FOR_CHILDREN_RS => array(), ASSIGN_FOR_BOTH_RS => array());
             $stored_req = isset($stored_reqs[$role_handle]) ? $stored_reqs[$role_handle] : array();
             $unused_byref_arg = '';
             $comparison = $this->_compare_role_settings($require_for, $stored_req, $delete_reqs, $update_require_for, $unused_byref_arg, $unused_byref_arg);
             $insert_restriction = $comparison['unset'] ? false : $require_for;
             // Mark assignment for propagation to child items (But don't do so on storage of default restriction to root item. Default restrictions are only applied at item creation.)
             $propagate_restriction = $item_id && isset($comparison['new_propagation']) ? $comparison['new_propagation'] : '';
             if ($comparison['role_change']) {
                 $role_change = true;
             }
             if (!empty($req_ids[$role_handle])) {
                 $id_in = "'" . implode("', '", array_keys($req_ids[$role_handle])) . "'";
                 // do this for each role prior to insert call because insert function will consider inherited_from value
                 foreach ($update_require_for as $require_for => $this_ass_ids) {
                     if ($this_ass_ids) {
                         $id_in = "'" . implode("', '", $this_ass_ids) . "'";
                         $qry = "UPDATE {$wpdb->role_scope_rs} SET require_for = '{$require_for}', inherited_from = '0' WHERE requirement_id IN ({$id_in})";
                         scoper_query($qry);
                         if ('entity' == $require_for) {
                             // If a parent restriction is changed from "both" or "children" to "entity", delete propagated restrictions
                             $qry = "DELETE FROM {$wpdb->role_scope_rs} WHERE inherited_from IN ({$id_in})";
                             scoper_query($qry);
                         }
                     }
                 }
             }
             if ($insert_restriction || $propagate_restriction) {
                 $this->insert_role_restrictions($scope, $max_scope, $role_handle, $src_or_tx_name, $item_id, $insert_restriction, $propagate_restriction, $args);
             }
         }
         // end foreach roles
     }
     // delete assignments; flush user,group results cache
     if ($role_change || !empty($delete_reqs) || $update_require_for || $force_flush) {
         $this->role_restriction_aftermath($scope, $delete_reqs);
         if (!$item_id) {
             $this->scoper->default_restrictions = array();
         }
     }
     // possible TODO: reinstate this after further testing
     //$this->delete_orphan_restrictions($scope, $src_or_tx_name);
 }
function scoper_limit_subscribe2_autosub($query)
{
    global $wpdb;
    if ("SELECT DISTINCT user_id FROM {$wpdb->usermeta} WHERE {$wpdb->usermeta}.meta_key='s2_autosub' AND {$wpdb->usermeta}.meta_value='yes'" == $query) {
        global $scoper, $subscribe2_category_rs;
        //rs_errlog("subscribe2 cat creation: $subscribe2_category_rs");
        $post_roles = $scoper->role_defs->qualify_roles('read', 'rs', 'post');
        // WP roles containing the 'activate plugins' capability are always honored regardless of object or term restritions
        $admin_roles_wp = array();
        global $wp_roles;
        if (isset($wp_roles->roles)) {
            $admin_cap_name = defined('SCOPER_CONTENT_ADMIN_CAP') ? constant('SCOPER_CONTENT_ADMIN_CAP') : 'activate_plugins';
            foreach (array_keys($wp_roles->roles) as $wp_role_name) {
                if (!empty($wp_roles->roles[$wp_role_name]['capabilities'])) {
                    if (array_intersect_key($wp_roles->roles[$wp_role_name]['capabilities'], array($admin_cap_name => 1))) {
                        $admin_roles_wp = array_merge($admin_roles_wp, array($wp_role_name => 1));
                    }
                }
            }
        }
        if ($admin_roles_wp) {
            $admin_roles_wp = scoper_role_names_to_handles(array_keys($admin_roles_wp), 'wp', true);
        }
        //arg: return as array keys
        $args = array('id' => $subscribe2_category_rs);
        $restrictions = $scoper->get_restrictions(TERM_SCOPE_RS, 'category', $args);
        $restricted_roles = array();
        if (!empty($restrictions['unrestrictions'])) {
            if ($restrictions['unrestrictions'] = array_intersect_key($restrictions['unrestrictions'], $post_roles)) {
                foreach ($restrictions['unrestrictions'] as $role_handle => $entries) {
                    if (!isset($entries[$subscribe2_category_rs]) || 'children' == $entries[$subscribe2_category_rs]) {
                        $restricted_roles[$role_handle] = true;
                    }
                }
            }
        }
        if (!empty($restrictions['restrictions'])) {
            if ($restrictions['restrictions'] = array_intersect_key($restrictions['restrictions'], $post_roles)) {
                foreach ($restrictions['restrictions'] as $role_handle => $entries) {
                    if (isset($entries[$subscribe2_category_rs]) && 'children' != $entries[$subscribe2_category_rs]) {
                        $restricted_roles[$role_handle] = true;
                    }
                }
            }
        }
        $unrestricted_roles = array_diff_key($post_roles, $restricted_roles);
        // for our purposes, a role is only restricted if all its contained qualifying roles are also restricted
        if ($restricted_roles) {
            foreach (array_keys($restricted_roles) as $role_handle) {
                if ($contained_roles = $scoper->role_defs->get_contained_roles($role_handle, false, 'rs')) {
                    if ($contained_roles = array_intersect_key($contained_roles, $unrestricted_roles)) {
                        unset($restricted_roles[$role_handle]);
                    }
                }
            }
            $unrestricted_roles = array_diff_key($post_roles, $restricted_roles);
        }
        // account for WP blog roles
        $unrestricted_roles_wp = array();
        $restricted_roles_wp = array();
        if ($post_roles_wp = $scoper->role_defs->qualify_roles('read', 'wp', 'post')) {
            foreach (array_keys($post_roles_wp) as $wp_role) {
                if ($contains_rs_roles = $scoper->role_defs->get_contained_roles($wp_role, false, 'rs')) {
                    if ($contains_rs_roles = array_intersect_key($contains_rs_roles, $unrestricted_roles)) {
                        $unrestricted_roles_wp = array_merge($unrestricted_roles_wp, array($wp_role => true));
                    }
                }
            }
            $restricted_roles_wp = array_diff_key($post_roles_wp, $unrestricted_roles_wp);
        }
        $unrestricted_roles_wp = array_merge($unrestricted_roles_wp, $admin_roles_wp);
        $role_in_wp = implode("', '", scoper_role_handles_to_names(array_keys($unrestricted_roles_wp)));
        /*
        dump($post_roles);
        dump($restricted_roles);
        dump($restricted_roles_wp);
        dump($unrestricted_roles);
        dump($unrestricted_roles_wp);
        */
        // account for blog roles, where allowed
        if ($unrestricted_roles) {
            $wp_role_clause = !empty($role_in_wp) ? "OR ( role_type = 'wp' AND scope = 'blog' AND role_name IN ('{$role_in_wp}') )" : '';
            $role_in = implode("', '", scoper_role_handles_to_names(array_keys($unrestricted_roles)));
            $qry = "SELECT DISTINCT user_id FROM {$wpdb->user2role2object_rs}" . " WHERE user_id > 0 AND (" . " ( role_type = 'rs' AND scope = 'blog' AND role_name IN ('{$role_in}') ) {$wp_role_clause} )";
            $users = scoper_get_col($qry);
            $qry = "SELECT DISTINCT group_id FROM {$wpdb->user2role2object_rs}" . " WHERE group_id > 0 AND (" . " ( role_type = 'rs' AND scope = 'blog' AND role_name IN ('{$role_in}') ) {$wp_role_clause} )";
            if ($groups = scoper_get_col($qry)) {
                foreach ($groups as $group_id) {
                    if ($group_members = ScoperAdminLib::get_group_members($group_id, $cols, true)) {
                        $users = array_merge($users, $group_members);
                    }
                }
                $users = array_unique($users);
            }
        } else {
            $users = array();
        }
        // account for category roles
        $role_in = implode("', '", scoper_role_handles_to_names(array_keys($post_roles)));
        $qry = "SELECT DISTINCT user_id FROM {$wpdb->user2role2object_rs}" . " WHERE user_id > 0 AND role_type = 'rs' AND scope = 'term' AND role_name IN ('{$role_in}')" . " AND assign_for IN ('entity', 'both')" . " AND src_or_tx_name = 'category' AND obj_or_term_id = '{$subscribe2_category_rs}'";
        $catrole_users = scoper_get_col($qry);
        $users = array_merge($users, $catrole_users);
        $qry = "SELECT DISTINCT group_id FROM {$wpdb->user2role2object_rs}" . " WHERE group_id > 0 AND role_type = 'rs' AND scope = 'term' AND role_name IN ('{$role_in}')" . " AND assign_for IN ('entity', 'both')" . " AND src_or_tx_name = 'category' AND obj_or_term_id = '{$subscribe2_category_rs}'";
        if ($groups = scoper_get_col($qry)) {
            foreach ($groups as $group_id) {
                if ($group_members = ScoperAdminLib::get_group_members($group_id, $cols, true)) {
                    $users = array_merge($users, $group_members);
                }
            }
            $users = array_unique($users);
        }
        if ($users) {
            $query .= " AND user_id IN ('" . implode("', '", $users) . "')";
        } else {
            $query .= ' AND 1=2';
        }
        remove_filter('query', 'scoper_limit_subscribe2_autosub', 99);
    }
    return $query;
}
 function users_queryroles($reqd_caps, $src_name, $object_id = '', $args = array())
 {
     $defaults = array('roles' => '', 'user' => '', 'querying_groups' => 0, 'use_term_roles' => 1, 'use_blog_roles' => 1, 'skip_object_roles' => false, 'ignore_strict_terms' => 0, 'object_terms' => array(), 'object_type' => '', 'objscope_roles' => '', 'any_object' => false);
     $args = array_merge($defaults, (array) $args);
     extract($args);
     $src = $this->scoper->data_sources->get($src_name);
     // ---- The following default argument generation is included to support potential direct usage of this function
     //								(not needed for flt_users_where call -----------------
     // Treat empty reqd_caps array as an error
     if (empty($reqd_caps)) {
         return array();
     }
     $reqd_caps = (array) $reqd_caps;
     // Calling function may save us a little work if it has already made this call
     if (!$roles) {
         if (!($roles = $this->scoper->role_defs->qualify_roles($reqd_caps))) {
             return array();
         }
     } else {
         $roles = (array) $roles;
     }
     // this set of reqd_caps cannot be satisfied by any role
     if (!$reqd_caps && !$roles) {
         return;
     }
     if ($object_id && !$src_name) {
         $object_id = 0;
     }
     // -----------------------------------------------------------------------------------
     // Default to not honoring custom user caps, but support option
     $custom_user_blogcaps = SCOPER_CUSTOM_USER_BLOGCAPS;
     if (!$object_type) {
         if ($object_types = $this->scoper->cap_defs->object_types_from_caps($reqd_caps, $src_name)) {
             if (count($object_types) == 1) {
                 $object_type = reset($object_types);
             }
         }
         if (!$object_type) {
             $object_type = cr_find_object_type($src_name, $object_id);
         }
     }
     // RS roles are object type-specific
     $roles_wp = $this->scoper->role_defs->filter($roles, array('role_type' => 'wp'));
     $roles_rs = $this->scoper->role_defs->filter($roles, array('role_type' => 'rs'));
     $this_otype_roles = $this->scoper->role_defs->get_matching('rs', $src_name, $object_type);
     $roles_rs = array_intersect_key($roles_rs, $this_otype_roles);
     $roles = array_merge($roles_rs, $roles_wp);
     $qualifying_roles = array();
     // --------- ACCOUNT FOR OBJECT ROLES -----------
     // If this set of reqd_caps can be satisfied by a scopable role, check for object role assignements
     if (!$skip_object_roles && ($object_id || $any_object)) {
         // exclude roles which have never been assigned to any object
         if ($object_roles = $this->scoper->qualify_object_roles($reqd_caps, $object_type, -1)) {
             $qualifying_roles[OBJECT_SCOPE_RS][''] = scoper_role_handles_to_names(array_keys($roles));
         }
     }
     // If this inquiry is for a particular object, find out which roles must be object-assigned for it
     if ($object_id) {
         // For term and blog role clauses, exclude roles which require object assignment for that object
         // But don't disqualify a role if any of the roles it "contains" also qualify and are not object-scoped.
         // (i.e. If the required caps are satisfied by admin, editor and contributor, the actual minimum requirement
         // is contributor.  A specification that admin and editor roles "require object assignment" does not apply
         // in this scenario.
         if (!is_array($objscope_roles)) {
             $objscope_roles = $this->get_objscope_roles($src_name, $object_id, '', true);
         }
         if ($objscope_roles) {
             $contained_roles = array();
             $roles_wp = $this->scoper->role_defs->filter($roles, array('role_type' => 'wp'));
             foreach (array_keys($roles_wp) as $role_handle) {
                 // If scoping with RS roles, this will also have the effect of disqualifying a WP blog role if all of the qualifying RS roles it contains are objscoped.
                 $contained_roles[$role_handle] = $this->scoper->role_defs->get_contained_roles($role_handle, false, 'rs');
                 $contained_roles[$role_handle] = array_intersect_key($contained_roles[$role_handle], $roles);
                 if (!array_diff_key($contained_roles[$role_handle], $objscope_roles)) {
                     unset($roles[$role_handle]);
                 }
             }
             foreach (array_keys($roles) as $role_handle) {
                 $contained_roles[$role_handle] = $this->scoper->role_defs->get_contained_roles($role_handle, true, 'rs');
                 //true: include this role in return array
                 $contained_roles[$role_handle] = array_intersect_key($contained_roles[$role_handle], $roles);
                 if (!array_diff_key($contained_roles[$role_handle], $objscope_roles)) {
                     unset($roles[$role_handle]);
                 }
             }
         }
     }
     // --------- ACCOUNT FOR TERM ROLES -----------
     // Consider term scope settings and role assignments
     //
     $uses_taxonomies = scoper_get_taxonomy_usage($src_name, $object_type);
     if ($use_term_roles && $src_name && $roles && !empty($uses_taxonomies)) {
         // If scoping with RS roles, strip out WP role definitions (which were included for blogrole clause)
         $term_roles = $this->scoper->role_defs->filter($roles, array('role_type' => 'rs'));
         if ($term_roles) {
             foreach ($uses_taxonomies as $taxonomy) {
                 // include users with a sufficient term role assignment in any term
                 $qualifying_roles[TERM_SCOPE_RS][$taxonomy] = scoper_role_handles_to_names(array_keys($term_roles));
             }
         }
         // Honor blog-wide assignment of any non-objscope role, but only if at least one term
         // is not "strict" (i.e. merges blogroles into term-specific assignments).
         if (!$ignore_strict_terms) {
             $term_roles = $this->get_unrestricted_term_roles($term_roles, $uses_taxonomies, $object_id, $object_terms);
             // disqualify a WP blog role if all of the qualifying RS roles it contains were excluded by the strict terms filter.
             if ($roles_wp = $this->scoper->role_defs->filter($roles, array('role_type' => 'wp'))) {
                 $contained_roles = array();
                 foreach (array_keys($roles_wp) as $role_handle) {
                     $contained_roles[$role_handle] = $this->scoper->role_defs->get_contained_roles($role_handle, false, 'rs');
                     $contained_roles[$role_handle] = array_intersect_key($contained_roles[$role_handle], $roles);
                     if (!$term_roles || !$contained_roles[$role_handle] || !array_intersect_key($contained_roles[$role_handle], $term_roles)) {
                         unset($roles[$role_handle]);
                     }
                 }
             }
             $roles_current = $this->scoper->role_defs->filter($roles, array('role_type' => 'rs'));
             foreach (array_keys($roles_current) as $role_handle) {
                 if (!isset($term_roles[$role_handle])) {
                     unset($roles[$role_handle]);
                 }
             }
             // Since this term role is restricted for all terms, prevent corresponding blog role from being added to qualifying_roles array by subsequent code
         }
     }
     // --------- ACCOUNT FOR BLOG ROLES -----------
     // For each qualifying role, recognize blog assignment if the reqd_caps set is not associated
     // with a defined data source, if this source/object type does not use term roles,
     // or if some of the the terms are not strict.
     //
     // Note that WP blogrole assignments (if not taxonomy or object-scoped) are honored
     // regardless of Role Scoper role_type setting.
     if ($use_blog_roles) {
         if ($admin_roles = awp_administrator_roles()) {
             $roles = $roles ? array_merge($roles, $admin_roles) : $admin_roles;
         }
         if ($roles) {
             $role_types = array('rs', 'wp');
             foreach ($role_types as $role_type) {
                 //if ( ('rs' == $role_type) && ! RS_BLOG_ROLES )  // rs_blog_roles option has never been active in any RS release; leave commented here in case need arises
                 //		continue;
                 $this_type_roles = $this->scoper->role_defs->filter($roles, array('role_type' => $role_type));
                 $qualifying_roles[BLOG_SCOPE_RS][$role_type] = scoper_role_handles_to_names(array_keys($this_type_roles));
             }
         }
         if ($custom_user_blogcaps && $use_blog_roles) {
             // If custom user blogcaps option is enabled, this function is called separately for each reqd cap.
             // Custom user caps are stored as "hidden" single-cap role of type WP_CAP, sync'd to WP usermeta storage.
             if ($custom_user_blogcaps) {
                 $qualifying_roles[BLOG_SCOPE_RS]['wp_cap'] = $reqd_caps;
             }
             // ...which contains one cap
         }
     }
     return $qualifying_roles;
 }
 function get_restrictions($scope, $src_or_tx_name, $args = array())
 {
     $def_cols = COL_ID_RS;
     // Note: propogating child restrictions are always directly assigned to the child term(s).
     // Use include_child_restrictions to force inclusion of restrictions that are set for child items only,
     // for direct admin of these restrictions and for propagation on term/object creation.
     $defaults = array('id' => 0, 'include_child_restrictions' => false, 'force_refresh' => false, 'cols' => $def_cols, 'return_array' => false);
     $args = array_merge($defaults, (array) $args);
     extract($args);
     $cache_flag = "rs_{$scope}_restrictions_{$src_or_tx_name}";
     $cache_id = md5($src_or_tx_name . $cols . strval($return_array) . strval($include_child_restrictions));
     if (!$force_refresh) {
         $items = wpp_cache_get($cache_id, $cache_flag);
         if (is_array($items)) {
             if ($id) {
                 foreach ($items as $setting_type => $roles) {
                     foreach (array_keys($roles) as $role_handle) {
                         $items[$setting_type][$role_handle] = array_intersect_key($items[$setting_type][$role_handle], array($id => true));
                     }
                 }
             }
             return $items;
         }
     }
     if (!isset($this->default_restrictions[$scope])) {
         $this->default_restrictions[$scope] = $this->get_default_restrictions($scope);
     }
     global $wpdb;
     if (!empty($this->default_restrictions[$scope][$src_or_tx_name])) {
         if ($strict_roles = array_keys($this->default_restrictions[$scope][$src_or_tx_name])) {
             if (OBJECT_SCOPE_RS == $scope) {
                 // apply default_strict handling to objscope equivalents of each strict role
                 foreach ($strict_roles as $role_handle) {
                     if ($objscope_equivalents = $this->role_defs->member_property($role_handle, 'objscope_equivalents')) {
                         $strict_roles = array_merge($strict_roles, $objscope_equivalents);
                     }
                 }
                 $strict_roles = array_unique($strict_roles);
             }
         }
         $strict_role_in = "'" . implode("', '", scoper_role_handles_to_names($strict_roles)) . "'";
     } else {
         $strict_role_in = '';
     }
     $items = array();
     if (!empty($strict_roles)) {
         foreach ($strict_roles as $role_handle) {
             $items['unrestrictions'][$role_handle] = array();
         }
         // calling code will use this as an indication that the role is default strict
     }
     $default_strict_modes = array(false);
     if ($strict_role_in) {
         $default_strict_modes[] = true;
     }
     foreach ($default_strict_modes as $default_strict) {
         $setting_type = $default_strict ? 'unrestrictions' : 'restrictions';
         if (TERM_SCOPE_RS == $scope) {
             $max_scope = $default_strict ? 'blog' : 'term';
         } else {
             $max_scope = $default_strict ? 'blog' : 'object';
         }
         // Storage of 'blog' max_scope as object restriction does not eliminate any term restrictions.  It merely indicates, for data sources that are default strict, that this object does not restrict roles
         if ($default_strict) {
             $role_clause = "AND role_name IN ({$strict_role_in})";
         } elseif ($strict_role_in) {
             $role_clause = "AND role_name NOT IN ({$strict_role_in})";
         } else {
             $role_clause = '';
         }
         $for_clause = $include_child_restrictions ? '' : "AND require_for IN ('entity', 'both')";
         $qry_base = "FROM {$wpdb->role_scope_rs} WHERE role_type = 'rs' AND topic = '{$scope}' AND max_scope = '{$max_scope}' AND src_or_tx_name = '{$src_or_tx_name}' {$for_clause} {$role_clause}";
         if (COL_COUNT_RS == $cols) {
             $qry = "SELECT role_name, count(obj_or_term_id) AS item_count, require_for {$qry_base} GROUP BY role_name";
         } else {
             $qry = "SELECT role_name, obj_or_term_id, require_for AS assign_for, inherited_from {$qry_base}";
         }
         if ($results = scoper_get_results($qry)) {
             foreach ($results as $row) {
                 $role_handle = scoper_get_role_handle($row->role_name, 'rs');
                 if (COL_COUNT_RS == $cols) {
                     $items[$setting_type][$role_handle] = $row->item_count;
                 } elseif ($return_array) {
                     $items[$setting_type][$role_handle][$row->obj_or_term_id] = array('assign_for' => $row->assign_for, 'inherited_from' => $row->inherited_from);
                 } else {
                     $items[$setting_type][$role_handle][$row->obj_or_term_id] = $row->assign_for;
                 }
             }
         }
     }
     // end foreach default_strict_mode
     wpp_cache_force_set($cache_id, $items, $cache_flag);
     if ($id) {
         foreach ($items as $setting_type => $roles) {
             foreach (array_keys($roles) as $role_handle) {
                 $items[$setting_type][$role_handle] = array_intersect_key($items[$setting_type][$role_handle], array($id => true));
             }
         }
     }
     return $items;
 }
function scoper_get_parent_roles($obj_or_term_id, $scope, $src_or_tx_name, $parent_id, $object_type = '')
{
    global $wpdb, $scoper;
    $role_clause = '';
    if (!$parent_id && OBJECT_SCOPE_RS == $scope) {
        // for default roles, need to distinguish between otype-specific roles
        // (note: this only works w/ RS role type. Default object roles are disabled for WP role type because we'd be stuck assigning all default roles to both post & page.)
        $src = $scoper->data_sources->get($src_or_tx_name);
        if (!empty($src->cols->type)) {
            if (!$object_type) {
                $object_type = cr_find_object_type($src_name, $object_id);
            }
            if ($object_type) {
                $role_defs = $scoper->role_defs->get_matching('rs', $src_or_tx_name, $object_type);
                if ($role_names = scoper_role_handles_to_names(array_keys($role_defs))) {
                    $role_clause = "AND role_type = 'rs' AND role_name IN ('" . implode("', '", $role_names) . "')";
                }
            }
        }
    }
    // Since this is a new object, propagate roles from parent (if any are marked for propagation)
    $qry = "SELECT * FROM {$wpdb->user2role2object_rs} WHERE scope = %s AND assign_for IN ('children', 'both') {$role_clause} AND src_or_tx_name = %s AND obj_or_term_id = %d ORDER BY role_type, role_name";
    $results = scoper_get_results($wpdb->prepare($qry, $scope, $src_or_tx_name, $parent_id));
    return $results;
}