WP_User( $id, $name ); } else { parent::__construct( $id, $name ); } // without this, logged users have no read access to blogs they're not registered for if ( IS_MU_RS && $id && ! is_admin() && empty( $this->allcaps ) ) $this->caps['subscriber'] = true; // initialize blog_roles arrays $this->assigned_blog_roles[ANY_CONTENT_DATE_RS] = array(); $this->blog_roles[ANY_CONTENT_DATE_RS] = array(); //log_mem_usage_rs( 'called this->WP_User' ); $defaults = array( 'disable_user_roles' => false, 'disable_group_roles' => false, 'disable_wp_roles' => false ); $args = array_merge( $defaults, (array) $args ); extract($args); if ( $this->ID ) { if ( ! $disable_wp_roles ) { // include both WP roles and custom caps, which are treated as a hidden single-cap role capable of satisfying single-cap current_user_can calls $this->assigned_blog_roles[ANY_CONTENT_DATE_RS] = $this->caps; // prepend role_type prefix to wp rolenames global $wp_roles; foreach ( array_keys($this->assigned_blog_roles[ANY_CONTENT_DATE_RS]) as $name) { if ( isset($wp_roles->role_objects[$name]) ) { $this->assigned_blog_roles[ANY_CONTENT_DATE_RS]['wp_' . $name] = $this->assigned_blog_roles[ANY_CONTENT_DATE_RS][$name]; unset($this->assigned_blog_roles[ANY_CONTENT_DATE_RS][$name]); } } } if ( defined('DEFINE_GROUPS_RS') && ! $disable_group_roles ) { $this->groups = $this->_get_usergroups(); if ( ! empty($args['filter_usergroups']) ) // assist group admin $this->groups = array_intersect_key($this->groups, $args['filter_usergroups']); } // if ( RS_BLOG_ROLES ) { // rs_blog_roles option has never been active in any RS release; leave commented here in case need arises if ( $rs_blogroles = $this->get_blog_roles_daterange( 'rs' ) ) { foreach ( array_keys($rs_blogroles) as $date_key ) { if ( isset($this->assigned_blog_roles[$date_key]) ) $this->assigned_blog_roles[$date_key] = array_merge($this->assigned_blog_roles[$date_key], $rs_blogroles[$date_key]); else $this->assigned_blog_roles[$date_key] = $rs_blogroles[$date_key]; } } //} // note: The allcaps property still governs current_user_can calls when the cap requirements do not pertain to a specific object. // If WP roles fail to provide all required caps, the Role Scoper has_cap filter validates the current_user_can check if any RS blogrole has all the required caps. // // The blog_roles array also comes into play for object permission checks such as page or post listing / edit. // In such cases, roles in the Scoped_User->blog_roles array supplement any pertinent taxonomy or role assignments, // as long as the object or its terms are not configured to require that role to be term-assigned or object-assigned. //log_mem_usage_rs( 'new Scoped User done' ); } } function check_for_user_roles() { if ( IS_MU_RS ) return true; // this function is only for performance; not currently dealing with multiple uro tables global $wpdb; return scoper_get_var("SELECT assignment_id FROM $wpdb->user2role2object_rs WHERE role_type = 'rs' AND user_id = '$this->ID' LIMIT 1"); } function get_user_clause($table_alias) { $table_alias = ( $table_alias ) ? "$table_alias." : ''; $arr = array(); if ( GROUP_ROLES_RS && $this->groups ) $arr []= "{$table_alias}group_id IN ('" . implode("', '", array_keys($this->groups) ) . "')"; if ( USER_ROLES_RS || empty($arr) ) // too risky to allow query with no user or group clause $arr []= "{$table_alias}user_id = '$this->ID'"; $clause = implode( ' OR ', $arr ); if ( count($arr) > 1 ) $clause = "( $clause )"; if ( $clause ) return " AND $clause"; } function cache_get($cache_flag, $append_blog_suffix = true ) { if ( GROUP_ROLES_RS && $this->groups ) { $cache_id = $this->ID; $cache_flag = $cache_flag . '_for_' . ROLE_BASIS_USER_AND_GROUPS; } else { $cache_id = $this->ID; $cache_flag = $cache_flag . '_for_' . ROLE_BASIS_USER; } return wpp_cache_get($cache_id, $cache_flag, $append_blog_suffix); } function cache_set($entry, $cache_flag, $append_blog_suffix = true, $force_update = false ) { if ( GROUP_ROLES_RS && $this->groups ) { $cache_id = $this->ID; $cache_flag = $cache_flag . '_for_' . ROLE_BASIS_USER_AND_GROUPS; } else { $cache_id = $this->ID; $cache_flag = $cache_flag . '_for_' . ROLE_BASIS_USER; } return wpp_cache_set($cache_id, $entry, $cache_flag, 0, $append_blog_suffix, $force_update ); } function cache_force_set( $entry, $cache_flag, $append_blog_suffix = true ) { return $this->cache_set( $entry, $cache_flag, $append_blog_suffix, true ); } // can be called statically by external modules function get_groups_for_user( $user_id, $args = array() ) { if ( empty($args['status']) ) $status = 'active'; elseif ( 'any' == $args['status'] ) { $args['no_cache'] = true; $status = ''; } else { $args['no_cache'] = true; $status = $args['status']; } if ( empty($args['no_cache']) ) { $cache = wpp_cache_get($user_id, 'group_membership_for_user'); if ( is_array($cache) ) return $cache; } global $wpdb; if ( ! $wpdb->user2group_rs ) return array(); $status_clause = ( $status ) ? "AND status = '$status'" : ''; $query = "SELECT $wpdb->user2group_gid_col FROM $wpdb->user2group_rs WHERE $wpdb->user2group_uid_col = '$user_id' $status_clause ORDER BY $wpdb->user2group_gid_col"; if ( ! $user_groups = scoper_get_col($query) ) $user_groups = array(); // include WP metagroup(s) for WP blogrole(s) $metagroup_ids = array(); if ( ! empty($args['metagroup_roles']) ) { foreach ( array_keys($args['metagroup_roles']) as $role_handle ) $metagroup_ids []= 'wp_role_' . str_replace( 'wp_', '', $role_handle ); } if ( $metagroup_ids ) { $meta_id_in = "'" . implode("', '", $metagroup_ids) . "'"; $query = "SELECT $wpdb->groups_id_col FROM $wpdb->groups_rs" . " WHERE {$wpdb->groups_rs}.{$wpdb->groups_meta_id_col} IN ($meta_id_in)" . " ORDER BY $wpdb->groups_id_col"; if ( $meta_groups = scoper_get_col($query) ) $user_groups = array_merge( $user_groups, $meta_groups ); } if ( $user_groups && empty($args['no_cache']) ) { // users should always be in at least a metagroup. Problem with caching empty result on user creation beginning with WP 2.8 $user_groups = array_fill_keys($user_groups, 1); wpp_cache_set($user_id, $user_groups, 'group_membership_for_user'); } return $user_groups; } // return group_id as array keys function _get_usergroups($args = array()) { if ( ! $this->ID ) return array(); $args = (array) $args; if ( ! empty($this->assigned_blog_roles) ) $args['metagroup_roles'] = $this->assigned_blog_roles[ANY_CONTENT_DATE_RS]; $user_groups = WP_Scoped_User::get_groups_for_user( $this->ID, $args ); return $user_groups; } // wrapper for back compat with callin code that does not expect date_key dimension function get_blog_roles( $role_type = 'rs' ) { $blog_roles = $this->get_blog_roles_daterange( $role_type ); if ( isset($blog_roles[ANY_CONTENT_DATE_RS]) && is_array($blog_roles[ANY_CONTENT_DATE_RS]) ) return $blog_roles[ANY_CONTENT_DATE_RS]; else return array(); } function get_blog_roles_daterange( $role_type = 'rs', $args = array() ) { $defaults = array( 'enforce_duration_limits' => true, 'retrieve_content_date_limits' => true, 'include_role_duration_key' => false, 'no_cache' => false ); $args = array_merge( $defaults, (array) $args ); extract($args); if ( $enforce_duration_limits = $enforce_duration_limits && scoper_get_option( 'role_duration_limits' ) ) { $duration_clause = ( $enforce_duration_limits ) ? scoper_get_duration_clause() : ''; $no_cache = $no_cache || strpos( $duration_clause, 'start_date_gmt' ) || strpos( $duration_clause, 'end_date_gmt' ); } else { $duration_clause = ''; } $no_cache = $no_cache || $include_role_duration_key || ! $retrieve_content_date_limits; if ( ! $no_cache ) { $cache_flag = "{$role_type}_blog-roles"; // changed cache key from "blog_roles" to "blog-roles" to prevent retrieval of arrays stored without date_key dimension $cache = $this->cache_get( $cache_flag ); if ( is_array($cache) ) { return $cache; } } global $wpdb; $u_g_clause = $this->get_user_clause('uro'); $extra_cols = ( $include_role_duration_key ) ? ", uro.date_limited, uro.start_date_gmt, uro.end_date_gmt" : ''; $qry = "SELECT uro.role_name, uro.content_date_limited, uro.content_min_date_gmt, uro.content_max_date_gmt $extra_cols FROM $wpdb->user2role2object_rs AS uro WHERE uro.scope = 'blog' AND uro.role_type = '$role_type' $duration_clause $u_g_clause"; $results = scoper_get_results($qry); $role_handles = array( '' => array() ); foreach ( $results as $row ) { $date_key = ( $retrieve_content_date_limits && $row->content_date_limited ) ? serialize( (object) array( 'content_min_date_gmt' => $row->content_min_date_gmt, 'content_max_date_gmt' => $row->content_max_date_gmt ) ) : ''; if ( $include_role_duration_key ) { $role_duration_key = ( $row->date_limited ) ? serialize( (object) array( 'start_date_gmt' => $row->start_date_gmt, 'end_date_gmt' => $row->end_date_gmt ) ) : ''; $role_handles[$role_duration_key][$date_key] [ scoper_get_role_handle( $row->role_name, $role_type ) ] = true; } else $role_handles[$date_key] [ scoper_get_role_handle( $row->role_name, $role_type ) ] = true; } if ( ! $no_cache ) $this->cache_set($role_handles, $cache_flag); return $role_handles; } // wrapper for back compat with calling code that does not expect date_key dimension function get_term_roles( $taxonomy = 'category', $role_type = 'rs' ) { $term_roles = $this->get_term_roles_daterange( $taxonomy, $role_type ); if ( isset($term_roles[ANY_CONTENT_DATE_RS]) && is_array($term_roles[ANY_CONTENT_DATE_RS]) ) return $term_roles[ANY_CONTENT_DATE_RS]; else return array(); } // returns array[role name] = array of term ids for which user has the role assigned (based on current role basis) function get_term_roles_daterange( $taxonomy = 'category', $role_type = 'rs', $args = array() ) { $defaults = array( 'enforce_duration_limits' => true, 'retrieve_content_date_limits' => true, 'include_role_duration_key' => false, 'no_cache' => false ); $args = array_merge( $defaults, (array) $args ); extract($args); global $wpdb; if ( $enforce_duration_limits = $enforce_duration_limits && scoper_get_option( 'role_duration_limits' ) ) { $duration_clause = ( $enforce_duration_limits ) ? scoper_get_duration_clause() : ''; $no_cache = $no_cache || strpos( $duration_clause, 'start_date_gmt' ) || strpos( $duration_clause, 'end_date_gmt' ); } else { $duration_clause = ''; } $no_cache = $no_cache || $include_role_duration_key || ! $retrieve_content_date_limits; if ( ! $no_cache ) { $cache_flag = "{$role_type}_term-roles_{$taxonomy}"; // changed cache key from "term_roles" to "term-roles" to prevent retrieval of arrays stored without date_key dimension $tx_term_roles = $this->cache_get($cache_flag); } else $tx_term_roles = ''; if ( ! is_array($tx_term_roles) ) { // no need to check for this on cache retrieval, since a role_type change results in a rol_defs change, which triggers a full scoper cache flush $tx_term_roles = array( '' => array() ); $u_g_clause = $this->get_user_clause('uro'); $extra_cols = ( $include_role_duration_key ) ? ", uro.date_limited, uro.start_date_gmt, uro.end_date_gmt" : ''; $qry = "SELECT uro.obj_or_term_id, uro.role_name, uro.assignment_id, uro.content_date_limited, uro.content_min_date_gmt, uro.content_max_date_gmt $extra_cols FROM $wpdb->user2role2object_rs AS uro "; $qry .= "WHERE uro.scope = 'term' AND uro.assign_for IN ('entity', 'both') AND uro.role_type = 'rs' AND uro.src_or_tx_name = '$taxonomy' $duration_clause $u_g_clause"; if ( $results = scoper_get_results($qry) ) { foreach($results as $termrole) { $date_key = ( $retrieve_content_date_limits && $termrole->content_date_limited ) ? serialize( (object) array( 'content_min_date_gmt' => $termrole->content_min_date_gmt, 'content_max_date_gmt' => $termrole->content_max_date_gmt ) ) : ''; $role_handle = 'rs_' . $termrole->role_name; if ( $include_role_duration_key ) { $role_duration_key = ( $termrole->date_limited ) ? serialize( (object) array( 'start_date_gmt' => $termrole->start_date_gmt, 'end_date_gmt' => $termrole->end_date_gmt ) ) : ''; $tx_term_roles[$role_duration_key][$date_key][$role_handle][] = $termrole->obj_or_term_id; } else $tx_term_roles[$date_key][$role_handle][] = $termrole->obj_or_term_id; } } if ( ! $no_cache ) $this->cache_set($tx_term_roles, $cache_flag); } if ( $retrieve_content_date_limits && ! $include_role_duration_key ) { // normal usage (only internal call to skip this block is for user profile) $this->assigned_term_roles[$taxonomy] = $tx_term_roles; global $scoper; if ( ! empty($scoper) ) { // this method is only called after Scoper is initialized, but include this sanity check foreach( array_keys($this->assigned_term_roles[$taxonomy]) as $date_key ) { // strip out any assignments for roles which are no longer defined (such as Revisionary roles after Revisionary is deactivated) $this->assigned_term_roles[$taxonomy][$date_key] = array_intersect_key( $this->assigned_term_roles[$taxonomy][$date_key], $scoper->role_defs->role_caps ); $this->term_roles[$taxonomy][$date_key] = $scoper->role_defs->add_contained_term_roles( $this->assigned_term_roles[$taxonomy][$date_key] ); } // support legacy template code using $current_user->term_roles or $current_user->assigned_term_roles if ( $this->ID == $GLOBALS['current_user']->ID ) { $GLOBALS['current_user']->assigned_term_roles[$taxonomy] = $this->assigned_term_roles[$taxonomy]; $GLOBALS['current_user']->term_roles[$taxonomy] = $this->term_roles[$taxonomy]; } } } return $tx_term_roles; } function merge_scoped_blogcaps() { global $scoper; // strip out any assignments for roles which are no longer defined (such as Revisionary roles after Revisionary is deactivated) foreach( array_keys($this->assigned_blog_roles) as $date_key ) $this->assigned_blog_roles[$date_key] = array_intersect_key( $this->assigned_blog_roles[$date_key], $scoper->role_defs->role_caps ); foreach( array_keys($this->assigned_blog_roles[ANY_CONTENT_DATE_RS]) as $role_handle ) { if ( ! is_array($scoper->role_defs->role_caps[$role_handle]) ) continue; $role_spec = scoper_explode_role_handle($role_handle); if ( ! empty($role_spec->role_type) && ( 'rs' == $role_spec->role_type ) && ! empty($scoper->role_defs->role_caps[$role_handle]) ) $this->allcaps = ( is_array($this->allcaps) ) ? array_merge($this->allcaps, $scoper->role_defs->role_caps[$role_handle]) : $scoper->role_defs->role_caps[$role_handle]; } $this->allcaps['is_scoped_user'] = true; // use this to detect when something tampers with scoped allcaps array } } // end class WP_Scoped_User } ?>