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; }