ProShell v2.0
Dashboard
Server Info
Server: 158.106.128.192
PHP: 8.2.33
home
planet5
public_html
bansibaba.com
2026-09-17 23:42:36
Editing: role_assigner_rs.php
Cancel
Save Changes
<?php if( basename(__FILE__) == basename($_SERVER['SCRIPT_FILENAME']) ) die(); class ScoperRoleAssigner { var $scoper; var $scoper_admin; function __construct() { $this->scoper =& $GLOBALS['scoper']; $this->scoper_admin =& $GLOBALS['scoper_admin']; } function user_has_role_in_term($role_handle, $taxonomy, $term_id, $user = '', $args = '') { if ( empty( $this->scoper->role_defs->role_caps[$role_handle] ) ) return false; if ( $terms = $this->scoper->qualify_terms( array_keys($this->scoper->role_defs->role_caps[$role_handle]), $taxonomy, '', compact( 'user' ) ) ) // qualify_terms result is memcached return in_array( $term_id, $terms ); } function _validate_assigner_roles($scope, $src_or_tx_name, $item_id, $roles) { if ( ! $item_id && ! is_user_administrator_rs() ) return false; $user_has_role = array(); if ( TERM_SCOPE_RS == $scope ) { foreach ( array_keys($roles) as $role_handle ) { $role_attributes = $this->scoper->role_defs->get_role_attributes($role_handle); $args = array( 'src_name' => $role_attributes->src_name, 'object_type' => $role_attributes->object_type ); $user_has_role[$role_handle] = $this->user_has_role_in_term( $role_handle, $src_or_tx_name, $item_id, $args); } } else { if ( $require_blogwide_editor = scoper_get_option('role_admin_blogwide_editor_only') ) { global $current_user; $is_user_administrator = is_user_administrator_rs(); $is_content_administrator = is_content_administrator_rs(); } foreach ( array_keys($roles) as $role_handle ) { // a user must have a blog-wide edit cap to modify editing role assignments (even if they have Editor role assigned for some current object) if ( $require_blogwide_editor ) { if ( ! $is_user_administrator && ( 'admin' == $require_blogwide_editor ) ) { $user_has_role[$role_handle] = false; continue; } if ( ! $is_content_administrator && ( 'admin_content' == $require_blogwide_editor ) ) { $user_has_role[$role_handle] = false; continue; } $src_name = $this->scoper->role_defs->member_property($role_handle, 'src_name'); $object_type = $this->scoper->role_defs->member_property($role_handle, 'object_type'); static $can_edit_blogwide; if ( ! isset($can_edit_blogwide) ) $can_edit_blogwide = array(); if ( ! isset($can_edit_blogwide[$src_name][$object_type]) ) $can_edit_blogwide[$src_name][$object_type] = $this->scoper->user_can_edit_blogwide($src_name, $object_type, array( 'require_others_cap' => true ) ); if ( ! $can_edit_blogwide[$src_name][$object_type] ) { $user_has_role[$role_handle] = false; continue; } } if ( ! empty( $this->scoper->role_defs->role_caps[$role_handle] ) ) $user_has_role[$role_handle] = cr_user_can( array_keys($this->scoper->role_defs->role_caps[$role_handle]), $item_id ); } } return $user_has_role; } function _compare_role_settings($assign_for, $role_assignment, &$delete_assignments, &$update_assign_for, &$update_role_duration, &$update_content_date_limits, $set_role_duration = '', $set_content_date_limits = '', $skip_assignfor_comparison = false ) { $retval = array( 'role_change' => false, 'unset' => false ); $assignment_id = 0; if ( REMOVE_ASSIGNMENT_RS == $assign_for ) { // since the role is being removed for this user/group, don't insert it $retval['unset'] = true; if ( ! empty($role_assignment['assignment_id']) ) { $assignment_id = $role_assignment['assignment_id']; $delete_assignments [$assignment_id] = true; $retval['role_change'] = true; } } else { if ( ! empty($role_assignment) ) { // no need for any insertion for this entity if a record already exists // (will still consider update and possibly insert roles for children) $retval['unset'] = true; $assignment_id = $role_assignment['assignment_id']; if ( ! $skip_assignfor_comparison ) { // If the currently stored assignment has a different 'assign_for' setting, update the record. // If the currently stored assignment was inherited, convert it to a direct assignment. if ( ($role_assignment['assign_for'] != $assign_for) || ($role_assignment['inherited_from'] != '0') ) { $update_assign_for[$assign_for] []= $role_assignment['assignment_id']; $retval['role_change'] = true; } //endif assign_for changed } if ( $set_role_duration ) { if ( ($role_assignment['date_limited'] != $set_role_duration->date_limited) || ($role_assignment['start_date_gmt'] != $set_role_duration->start_date_gmt) || ($role_assignment['end_date_gmt'] != $set_role_duration->end_date_gmt) ) { $update_role_duration []= $role_assignment['assignment_id']; $retval['role_change'] = true; } //endif role duration changed } if ( $set_content_date_limits ) { if ( ($role_assignment['content_date_limited'] != $set_content_date_limits->content_date_limited) || ($role_assignment['content_min_date_gmt'] != $set_content_date_limits->content_min_date_gmt) || ($role_assignment['content_max_date_gmt'] != $set_content_date_limits->content_max_date_gmt) ) { $update_content_date_limits []= $role_assignment['assignment_id']; $retval['role_change'] = true; } //endif role duration changed } } else //endif any assignment currently stored for this user/group $retval['role_change'] = true; // if assign_for was changed from 'entity' to 'children' or 'both', need to insert roles for children if ( ($assign_for == ASSIGN_FOR_CHILDREN_RS) || ($assign_for == ASSIGN_FOR_BOTH_RS) ) { if ( empty($role_assignment) || ( ASSIGN_FOR_ENTITY_RS == $role_assignment['assign_for'] ) ) { $retval['new_propagation'] = ( $assignment_id ) ? $assignment_id : true; $retval['role_change'] = true; } } } return $retval; } function assign_roles($scope, $src_or_tx_name, $item_id, $roles, $role_basis = ROLE_BASIS_USER, $args = array() ) { $defaults = array( 'implicit_removal' => false, 'is_auto_insertion' => false, 'force_flush' => false, 'set_role_duration' => '', 'set_content_date_limits' => '', 'user_has_role' => array() ); $args = array_merge($defaults, (array) $args); extract($args); global $wpdb; $col_ug_id = ( ROLE_BASIS_GROUPS == $role_basis ) ? 'group_id' : 'user_id'; $is_administrator = is_administrator_rs( $src_or_tx_name, 'user' ); $role_change_agent_ids = array(); $delete_assignments = array(); $propagate_agents = array(); // make sure end date is never accidentally set to zero if ( $set_role_duration && ! $set_role_duration->end_date_gmt ) $set_role_duration->end_date_gmt = SCOPER_MAX_DATE_STRING; if ( $set_content_date_limits && ! $set_content_date_limits->content_max_date_gmt ) $set_content_date_limits->content_max_date_gmt = SCOPER_MAX_DATE_STRING; $ug_clause = ( ROLE_BASIS_USER == $role_basis ) ? "AND user_id > 0" : "AND group_id > 0"; $qry = "SELECT $col_ug_id, assignment_id, assign_for, inherited_from, role_name, date_limited, start_date_gmt, end_date_gmt, content_date_limited, content_min_date_gmt, content_max_date_gmt FROM $wpdb->user2role2object_rs WHERE scope = %s $ug_clause" . " AND role_type = 'rs' AND src_or_tx_name = %s AND obj_or_term_id = %d"; $results = scoper_get_results( $wpdb->prepare( $qry, $scope, $src_or_tx_name, $item_id ) ); $stored_assignments = array(); $assignment_ids = array(); if ( OBJECT_SCOPE_RS == $scope ) { $is_objscope_equiv = array(); foreach ( $this->scoper->role_defs->get_all() as $role_handle => $role_def ) if ( isset($role_def->objscope_equivalents) ) foreach ( $role_def->objscope_equivalents as $equiv_role_handle ) $is_objscope_equiv[$equiv_role_handle] = $role_handle; } foreach ($results as $key => $ass) { $role_handle = scoper_get_role_handle( $ass->role_name, 'rs' ); if ( (OBJECT_SCOPE_RS == $scope) && isset($is_objscope_equiv[$role_handle]) ) $role_handle = $is_objscope_equiv[$role_handle]; $stored_assignments[$role_handle][$ass->$col_ug_id] = (array) $ass; // last-stored assignment for this object and user/group $assignment_ids[$role_handle][$ass->$col_ug_id][$ass->assignment_id] = true; // all assignment ids for this object and user/group } if ( ! $is_administrator && empty($user_has_role[$role_handle]) ) $user_has_role = $this->_validate_assigner_roles($scope, $src_or_tx_name, $item_id, $roles); foreach ( $roles as $role_handle => $agents ) { if ( ! $is_administrator && ! $user_has_role[$role_handle] ) continue; $propagate_agents = array(); $update_assign_for = array( ASSIGN_FOR_ENTITY_RS => array(), ASSIGN_FOR_CHILDREN_RS => array(), ASSIGN_FOR_BOTH_RS => array() ); $update_role_duration = array(); $update_content_date_limits = array(); if ( $implicit_removal && isset($stored_assignments[$role_handle]) ) { // Stored assignments which are not included in $agents will be deleted (along with their prodigy) foreach ( $stored_assignments[$role_handle] as $ug_id => $ass ) { if ( ! isset($agents[$ug_id]) && ! empty($ass['assignment_id']) ) { $assignment_id = $ass['assignment_id']; $delete_assignments [ $assignment_id ] = true; } } } $comparison = array(); foreach ( $agents as $ug_id => $assign_for ) { // don't assign a role which would remove existing assignment of role the current user doesn't have // (i.e. you can't change someone else from category Editor to category Reader if you are only a category Contributor) if ( ! $is_administrator ) { foreach ( $stored_assignments as $stored_role_handle => $this_stored_assignment ) { if ( isset($this_stored_assignment[$ug_id]) ) { if ( ! $user_has_role[$role_handle] ) { unset( $agents[$ug_id] ); continue 2; } } } } if ( REMOVE_ASSIGNMENT_RS == $assign_for ) { // If redundant role entries somehow got stored, make sure we delete them all (_compare_role_settings() does not) if ( ! empty( $assignment_ids[$role_handle][$ug_id] ) ) { $comparison['unset'] = true; foreach ( array_keys($assignment_ids[$role_handle][$ug_id]) as $assignment_id ) { $delete_assignments [$assignment_id] = true; $comparison['role_change'] = true; } } } else { $stored_assignment = ( isset($stored_assignments[$role_handle][$ug_id]) ) ? $stored_assignments[$role_handle][$ug_id] : array(); $comparison = $this->_compare_role_settings($assign_for, $stored_assignment, $delete_assignments, $update_assign_for, $update_role_duration, $update_content_date_limits, $set_role_duration, $set_content_date_limits); // Mark assignment for propagation to child items (But don't do so on storage of default role to root item. Default roles are only applied at item creation.) if ( $item_id && isset($comparison['new_propagation']) ) $propagate_agents[$ug_id] = $comparison['new_propagation']; } if ( ! empty($comparison['unset']) ) unset( $agents[$ug_id] ); if ( ! empty($comparison['role_change']) ) $role_change_agent_ids[$role_basis][$ug_id] = 1; } // end foreach users or groups // do this for each role prior to insert call because insert function will consider inherited_from value foreach ($update_assign_for as $assign_for => $this_ass_ids) { if ( $this_ass_ids ) { $id_in = "'" . implode("', '", $this_ass_ids) . "'"; $qry = "UPDATE $wpdb->user2role2object_rs SET assign_for = '$assign_for', inherited_from = '0' WHERE assignment_id IN ($id_in)"; scoper_query($qry); if ( 'entity' == $assign_for ) { // If a parent role is changed from "both" or "children" to "entity", delete propagated roles $qry = "DELETE FROM $wpdb->user2role2object_rs WHERE inherited_from IN ($id_in)"; scoper_query($qry); } } } if ( $update_role_duration ) { $id_in = "'" . implode("', '", $update_role_duration) . "'"; $qry = "UPDATE $wpdb->user2role2object_rs SET date_limited = '" . (int) $set_role_duration->date_limited . "'"; if ( -1 != $set_role_duration->start_date_gmt ) $qry .= ", start_date_gmt = '$set_role_duration->start_date_gmt'"; if ( -1 != $set_role_duration->end_date_gmt ) $qry .= ", end_date_gmt = '$set_role_duration->end_date_gmt'"; $qry .= " WHERE assignment_id IN ($id_in)"; scoper_query($qry); } if ( $update_content_date_limits ) { $id_in = "'" . implode("', '", $update_content_date_limits) . "'"; $qry = "UPDATE $wpdb->user2role2object_rs SET content_date_limited = '" . (int) $set_content_date_limits->content_date_limited . "'"; if ( -1 != $set_content_date_limits->content_min_date_gmt ) $qry .= ", content_min_date_gmt = '$set_content_date_limits->content_min_date_gmt'"; if ( -1 != $set_content_date_limits->content_max_date_gmt ) $qry .= ", content_max_date_gmt = '$set_content_date_limits->content_max_date_gmt'"; $qry .= " WHERE assignment_id IN ($id_in)"; scoper_query($qry); } if ( $agents || $propagate_agents ) $this->insert_role_assignments($scope, $role_handle, $src_or_tx_name, $item_id, $col_ug_id, $agents, $propagate_agents, $args ); } // end foreach roles // delete assignments; $this->role_assignment_aftermath( $scope, $role_basis, $role_change_agent_ids, $delete_assignments, '', $force_flush || ! empty($update_assign_for) ); // possible todo: reinstate this after further testing //$this->delete_orphan_roles($scope, $src_or_tx_name); } function role_assignment_aftermath($scope, $role_basis, $role_change_agent_ids, $delete_assignments, $object_type = '', $force_flush = false) { global $wpdb; if ( count($delete_assignments) ) { // Propagated roles will be deleted only if the original progenetor goes away. Removal of a "link" in the parent/child propagation chain has no effect. $id_in = "'" . implode("', '", array_keys($delete_assignments) ) . "'"; $qry = "DELETE FROM $wpdb->user2role2object_rs WHERE assignment_id IN ($id_in) OR (inherited_from IN ($id_in) AND inherited_from != '0')"; scoper_query($qry); } } // $agent_ids[agent_id] = role assignment method ('entity', 'children' or 'both') // $propagate_agents[agent_id] = assignment_id for inherited_from function insert_role_assignments ($scope, $role_handle, $src_or_tx_name, $obj_or_term_id, $col_ug_id, $insert_agents, $propagate_agents, $args = array()) { $defaults = array( 'inherited_from' => array(), 'is_auto_insertion' => false, 'set_role_duration' => '', 'set_content_date_limits' => '', 'role_duration_per_agent' => '', 'content_date_limits_per_agent' => '' ); // auto_insertion arg set for role propagation from parent objects $args = array_merge( $defaults, (array) $args ); extract($args); global $current_user, $wpdb; $assigner_id = $current_user->ID; 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 == $scope) || ( (OBJECT_SCOPE_RS == $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(); } // Before inserting a role, delete any overlooked old assignment. // Also delete (for the same user/group) any roles which cannot be simultaneously assigned if ( $role_attrib = $this->scoper->role_defs->get_role_attributes($role_handle) ) { $this_otype_role_defs = $this->scoper->role_defs->get_matching($role_spec->role_type, $role_attrib->src_name, $role_attrib->object_type); $delete_role_if_exists = array_keys($this_otype_role_defs); // need object_type for permission check when modifying propagated object roles $object_type = $role_attrib->object_type; } else { $delete_role_if_exists = array($role_handle); $object_type = ''; // probably won't be able to propagate roles if this error occurs } // prepare hierarchy and object type data for subsequent propagation if ( ! empty($propagate_agents) ) { if ( TERM_SCOPE_RS == $scope ) { if ( ! $tx = $this->scoper->taxonomies->get($src_or_tx_name) ) return; $src = $this->scoper->data_sources->get( $tx->source ); } 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 == $scope ) { 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 ); $retain_roles = $this->scoper->role_defs->add_containing_roles( array($role_handle => true), $role_spec->role_type ); $retain_role_names = scoper_role_handles_to_names(array_keys($retain_roles)); $role_in = "'" . implode("', '", $retain_role_names) . "'"; $role_clause = "AND role_name IN ($role_in)"; } $delete_role_in = "'" . implode("', '", scoper_role_handles_to_names( $delete_role_if_exists ) ) . "'"; $qry_delete_base = "DELETE FROM $wpdb->user2role2object_rs" . " WHERE scope = '$scope' AND src_or_tx_name = '$src_or_tx_name'" . " AND role_type = '$role_spec->role_type' AND role_name IN ($delete_role_in)"; $qry_select_base = "SELECT assignment_id FROM $wpdb->user2role2object_rs" . " WHERE scope = '$scope' AND src_or_tx_name = '$src_or_tx_name'" . " AND role_type = '$role_spec->role_type'"; if ( ! empty($set_role_duration) || ! empty( $role_duration_per_agent ) ) $duration_cols = "date_limited, start_date_gmt, end_date_gmt,"; else $duration_cols = ''; if ( ! empty($set_content_date_limits) || ! empty( $content_date_limits_per_agent ) ) $content_date_cols = "content_date_limited, content_min_date_gmt, content_max_date_gmt,"; else $content_date_cols = ''; if ( ! empty($set_role_duration) ) $universal_duration_vals = "'" . (int) $set_role_duration->date_limited . "', '$set_role_duration->start_date_gmt', '$set_role_duration->end_date_gmt',"; else $universal_duration_vals = ''; if ( ! empty($set_content_date_limits) ) $universal_content_date_vals = "'" . (int) $set_content_date_limits->content_date_limited . "', '$set_content_date_limits->content_min_date_gmt', '$set_content_date_limits->content_max_date_gmt',"; else $universal_content_date_vals = ''; $duration_vals = ''; $content_date_vals = ''; $qry_insert_base = "INSERT INTO $wpdb->user2role2object_rs" . " (src_or_tx_name, role_type, role_name, assigner_id, scope, $duration_cols $content_date_cols obj_or_term_id, assign_for, inherited_from, $col_ug_id)" . " VALUES ('$src_or_tx_name', '$role_spec->role_type', '$role_spec->role_name', '$assigner_id', '$scope', "; // duration values, content date limit values, obj_or_term_id, propagate, inherited_from and group_id/user_id values must be appended $all_agents = $propagate_agents + $insert_agents; foreach ( array_keys($all_agents) as $ug_id ) { $assignment_id = 0; if ( $duration_cols ) { if ( $universal_duration_vals ) $duration_vals = $universal_duration_vals; else { if ( ! empty($role_duration_per_agent[$ug_id]) ) { if ( '' === $role_duration_per_agent[$ug_id]->start_date_gmt ) $role_duration_per_agent[$ug_id]->start_date_gmt = SCOPER_MIN_DATE_STRING; if ( '' === $role_duration_per_agent[$ug_id]->end_date_gmt ) $role_duration_per_agent[$ug_id]->end_date_gmt = SCOPER_MAX_DATE_STRING; $duration_vals = "'" . (int) $role_duration_per_agent[$ug_id]->date_limited . "', '" . $role_duration_per_agent[$ug_id]->start_date_gmt . "', '" . $role_duration_per_agent[$ug_id]->end_date_gmt . "',"; } else $duration_vals = "'0', '" . SCOPER_MIN_DATE_STRING . "', '" . SCOPER_MAX_DATE_STRING . "',"; } } if ( $content_date_cols ) { if ( $universal_content_date_vals ) $content_date_vals = $universal_content_date_vals; else { if ( ! empty($content_date_limits_per_agent[$ug_id]) ) { if ( '' === $content_date_limits_per_agent[$ug_id]->content_min_date_gmt ) $content_date_limits_per_agent[$ug_id]->content_min_date_gmt = SCOPER_MIN_DATE_STRING; if ( '' === $content_date_limits_per_agent[$ug_id]->content_max_date_gmt ) $content_date_limits_per_agent[$ug_id]->content_max_date_gmt = SCOPER_MAX_DATE_STRING; $content_date_vals = "'" . (int) $content_date_limits_per_agent[$ug_id]->content_date_limited . "', '" . $content_date_limits_per_agent[$ug_id]->content_min_date_gmt . "', '" . $content_date_limits_per_agent[$ug_id]->content_max_date_gmt . "',"; } else $content_date_vals = "'0', '" . SCOPER_MIN_DATE_STRING . "', '" . SCOPER_MAX_DATE_STRING . "',"; } } // won't delete any other role assignments which have date limits $date_clause = " AND date_limited = '0' AND start_date_gmt = '" . SCOPER_MIN_DATE_STRING . "' AND end_date_gmt = '" . SCOPER_MAX_DATE_STRING . "' AND content_date_limited = '0' AND content_min_date_gmt = '" . SCOPER_MIN_DATE_STRING . "' AND content_max_date_gmt = '" . SCOPER_MAX_DATE_STRING . "'"; if ( isset($insert_agents[$ug_id]) ) { $assign_for = ( in_array( $insert_agents[$ug_id], array( 'entity', 'children', 'both' ) ) ) ? $insert_agents[$ug_id] : 'entity'; // sanity check to avoid empty assign_for value $this_inherited_from = ( isset($inherited_from[$ug_id]) ) ? $inherited_from[$ug_id] : 0; // don't delete other role assignments if this insertion has date limits if ( ! $duration_vals && ! $content_date_vals ) { // before inserting the role, delete any other matching or conflicting assignments this user/group has for the same object scoper_query( $qry_delete_base . "$date_clause AND $col_ug_id = '$ug_id' AND obj_or_term_id = '$obj_or_term_id';" ); } // insert role for specified object and group(s) scoper_query( $qry_insert_base . " $duration_vals $content_date_vals '$obj_or_term_id', '$assign_for', '$this_inherited_from', '$ug_id')" ); $assignment_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 == $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 ( isset($propagate_agents[$ug_id]) ) { if ( ! $assignment_id ) $assignment_id = $propagate_agents[$ug_id]; // note: Propagated roles will be converted to direct-assigned roles if the parent object/term is deleted. foreach ( $descendant_ids as $id ) { // Don't overwrite an explicitly assigned object role with a propagated assignment // unless the propagated role would be an upgrade if ( $direct_assignment = scoper_get_var( "$qry_select_base AND inherited_from = '0' $role_clause AND $col_ug_id = '$ug_id' AND obj_or_term_id = '$id' LIMIT 1" ) ) continue; // don't delete other role assignments if this insertion has date limits if ( ! $duration_vals && ! $content_date_vals ) { // before inserting the role, delete any other propagated assignments this user/group has for the same object type scoper_query( $qry_delete_base . " $date_clause AND $col_ug_id = '$ug_id' AND obj_or_term_id = '$id'" ); } scoper_query( $qry_insert_base . "$duration_vals $content_date_vals '$id', 'both', '$assignment_id', '$ug_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 ); } 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'; // note: max_scope='object' entries are treated as separate, overriding requirements 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; 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 role_restriction_aftermath($scope, $delete_restrictions = '') { global $wpdb; if ( is_array($delete_restrictions) && count($delete_restrictions) ) { // Propagated roles will be deleted only if the original progenetor goes away. Removal of a "link" in the parent/child propagation chain has no effect. $id_in = "'" . implode("', '", array_keys($delete_restrictions) ) . "'"; $qry = "DELETE FROM $wpdb->role_scope_rs WHERE requirement_id IN ($id_in) OR (inherited_from IN ($id_in) AND inherited_from != '0')"; scoper_query($qry); } } // $insert_restriction = require_for value for insertion ('entity', 'children' or 'both') // $propagate_from_req_id = requirement_id for inherited_from 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 ); } } // end class ScoperRoleAssigner function awp_query_descendant_ids( $table_name, $col_id, $col_parent, $parent_id ) { global $wpdb; $descendant_ids = array(); // todo: abstract this $type_clause = ( $table_name == $wpdb->posts ) ? "AND post_type != 'revision'" : ''; $query = "SELECT $col_id FROM $table_name WHERE $col_parent = '$parent_id' $type_clause"; if ( $results = scoper_get_col($query) ) { foreach ( $results as $id ) { if ( ! in_array( $id, $descendant_ids ) ) { $descendant_ids []= $id; $next_generation = awp_query_descendant_ids($table_name, $col_id, $col_parent, $id, $descendant_ids); $descendant_ids = array_merge($descendant_ids, $next_generation); } } } return $descendant_ids; } ?>
Upload Files
Cancel
Upload
Create New
Cancel
Create
Change Permissions
Cancel
Save
Change Date
Cancel
Save
Rename Item
Cancel
Save
Confirm Delete
Are you sure you want to delete the selected items?
Cancel
Delete