function get_reqd_caps()
 {
     $reqd_caps = array();
     $generic_uri = in_array($GLOBALS['pagenow'], array('index.php', 'comments.php'));
     if (!$generic_uri && ($_post_type = cr_find_post_type('', false))) {
         // arg: don't return 'post' as default if detection fails
         $post_types = array($_post_type => get_post_type_object($_post_type));
     } else {
         $post_types = array_diff_key(get_post_types(array('public' => true), 'object'), array('attachment' => true));
     }
     $use_post_types = scoper_get_option('use_post_types');
     $post_statuses = get_post_stati(array('internal' => null), 'object');
     foreach ($post_types as $_post_type => $type_obj) {
         if (empty($use_post_types[$_post_type])) {
             continue;
         }
         foreach ($post_statuses as $status => $status_obj) {
             $reqd_caps[$_post_type][$status] = array($type_obj->cap->edit_others_posts);
             if (scoper_get_option('require_moderate_comments_cap')) {
                 $reqd_caps[$_post_type][$status][] = 'moderate_comments';
             }
             if ($status_obj->private) {
                 $reqd_caps[$_post_type][$status][] = $type_obj->cap->edit_private_posts;
             }
             if ($status_obj->public || 'future' == $status) {
                 $reqd_caps[$_post_type][$status][] = $type_obj->cap->edit_published_posts;
             }
         }
     }
     return $reqd_caps;
 }
 function flt_dropdown_pages($orig_options_html)
 {
     if ('no_parent_filter' == scoper_get_option('lock_top_pages')) {
         return $orig_options_html;
     }
     if (!strpos($orig_options_html, 'parent_id') || !$orig_options_html || is_content_administrator_rs()) {
         return $orig_options_html;
     }
     $post_type = awp_post_type_from_uri();
     // User can't associate or de-associate a page with Main page unless they have edit_pages blog-wide.
     // Prepend the Main Page option if appropriate (or, to avoid submission errors, if we generated no other options)
     if (!$GLOBALS['scoper_admin_filters']->user_can_associate_main($post_type)) {
         $is_new = $GLOBALS['post']->post_status == 'auto-draft';
         if (!$is_new) {
             global $post;
             $object_id = !empty($post->ID) ? $post->ID : (int) $GLOBALS['scoper']->data_sources->detect('id', 'post', 0, 'post');
             $stored_parent_id = !empty($post->ID) ? $post->post_parent : get_post_field('post_parent', $object_id);
         }
         if ($is_new || $stored_parent_id) {
             $mat = array();
             preg_match('/<option[^v]* value="">[^<]*<\\/option>/', $orig_options_html, $mat);
             if (!empty($mat[0])) {
                 return str_replace($mat[0], '', $orig_options_html);
             }
         }
     }
     return $orig_options_html;
 }
function scoper_requested_file_rule_expire()
{
    if (scoper_get_option('file_filtering')) {
        if ($key = scoper_get_option('file_filtering_regen_key')) {
            if (!empty($_GET['key']) && $key == $_GET['key']) {
                // user must store their own non-null key before this will work
                global $wpdb;
                if (IS_MU_RS) {
                    $blog_ids = scoper_get_col("SELECT blog_id FROM {$wpdb->blogs} ORDER BY blog_id");
                    $orig_blog_id = $GLOBALS['blog_id'];
                    foreach ($blog_ids as $id) {
                        switch_to_blog($id);
                        scoper_query("DELETE FROM {$wpdb->postmeta} WHERE meta_key = '_rs_file_key'");
                    }
                } else {
                    scoper_query("DELETE FROM {$wpdb->postmeta} WHERE meta_key = '_rs_file_key'");
                }
                scoper_expire_file_rules();
                if (IS_MU_RS) {
                    _e("File attachment access keys and rewrite rules will be regenerated for each site at next access.", 'scoper');
                } else {
                    _e("File attachment access keys and rewrite rules were regenerated.", 'scoper');
                }
            } else {
                _e('Invalid argument.', 'scoper');
            }
        } else {
            _e('Please configure File Filtering options!', 'scoper');
        }
    } else {
        _e('The function is disabled.', 'scoper');
    }
    exit(0);
}
function scoper_review_file_htaccess()
{
    $min_date = (int) scoper_get_site_option('file_htaccess_min_date');
    $last_regen = (int) scoper_get_option('file_htaccess_date');
    if (!$last_regen || $min_date > $last_regen) {
        scoper_flush_file_rules();
    }
}
function user_can_admin_role_rs($role_handle, $item_id, $src_name = '', $object_type = '')
{
    if (is_user_administrator_rs()) {
        return true;
    }
    global $scoper;
    static $require_blogwide_editor;
    if (!isset($require_blogwide_editor)) {
        $require_blogwide_editor = scoper_get_option('role_admin_blogwide_editor_only');
    }
    if ('admin' == $require_blogwide_editor) {
        return false;
    }
    // User Admins already returned true
    if ('admin_content' == $require_blogwide_editor && !is_content_administrator_rs()) {
        return false;
    }
    static $role_ops;
    if (!isset($role_ops)) {
        $role_ops = array();
    }
    if (!isset($role_ops[$role_handle])) {
        $role_ops[$role_handle] = $scoper->cap_defs->get_cap_ops(array_keys($scoper->role_defs->role_caps[$role_handle]));
    }
    // user can't view or edit role assignments unless they have all rolecaps
    // however, if this is a new post, allow read role to be assigned even if contributor doesn't have read_private cap blog-wide
    if ($item_id || $role_ops[$role_handle] != array('read' => 1)) {
        static $reqd_caps;
        if (!isset($reqd_caps)) {
            $reqd_caps = array();
        }
        if (!isset($reqd_caps[$role_handle])) {
            $reqd_caps[$role_handle] = $scoper->role_defs->role_caps[$role_handle];
        }
        $type_caps = $scoper->cap_defs->get_matching($src_name, $object_type);
        $reqd_caps[$role_handle] = array_intersect_key($reqd_caps[$role_handle], $type_caps);
        if (is_null($item_id)) {
            $item_id = 0;
        }
        if (!cr_user_can(array_keys($reqd_caps[$role_handle]), $item_id)) {
            return false;
        }
        // are we also applying the additional requirement (based on RS Option setting) that the user is a blog-wide editor?
        if ($require_blogwide_editor) {
            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] = user_can_edit_blogwide_rs($src_name, $object_type, array('require_others_cap' => true));
            }
            if (!$can_edit_blogwide[$src_name][$object_type]) {
                return false;
            }
        }
    }
    return true;
}
Example #6
0
 function otype_option_checkboxes($option_name, $caption, $tab_name, $section_name, $hint_text, $trailing_html, $args = array())
 {
     global $scoper, $scoper_admin;
     $defaults = array('caption_header' => true);
     $args = array_merge($defaults, $args);
     extract($args);
     $return = array('in_scope' => false, 'val' => array());
     if (in_array($option_name, $this->form_options[$tab_name][$section_name])) {
         $this->all_otype_options[] = $option_name;
         if (isset($this->def_otype_options[$option_name])) {
             if (!($return['val'] = scoper_get_option($option_name, $this->sitewide, $this->customize_defaults))) {
                 $return['val'] = array();
             }
             $return['val'] = array_merge($this->def_otype_options[$option_name], $return['val']);
             $label_property = isset($args['label_property']) ? $args['label_property'] : 'name';
             $first_pass = true;
             foreach ($return['val'] as $src_otype => $val) {
                 if ($caption_header && $first_pass) {
                     printf($caption, $scoper_admin->interpret_src_otype($src_otype, $label_property));
                     echo '<br /><div style="margin-left: 2em">';
                     $first_pass = false;
                 }
                 $arr_src_otype = explode(':', $src_otype);
                 if (!scoper_get_otype_option('use_object_roles', $arr_src_otype[0], $arr_src_otype[1])) {
                     continue;
                 }
                 $item_label = $scoper_admin->interpret_src_otype($src_otype, $label_property);
                 //arg: use plural display name
                 $id = str_replace(':', '_', $option_name . '-' . $src_otype);
                 echo "<label for='{$id}'>";
                 echo "<input name='{$id}' type='checkbox' id='{$id}' value='1' ";
                 checked('1', $val);
                 echo " /> ";
                 if ($caption_header) {
                     echo $item_label;
                 } else {
                     printf($caption, $item_label);
                 }
                 echo '</label><br />';
             }
             // end foreach src_otype
             if ($caption_header) {
                 echo '</div>';
             }
             if ($hint_text && $this->display_hints) {
                 echo "<span class='rs-subtext'>" . $hint_text . "</span>";
             }
             if ($trailing_html) {
                 echo $trailing_html;
             }
         }
         // endif default option isset
         $return['in_scope'] = true;
     }
     // endif in this option is controlled in this scope
     return $return;
 }
 function flt_recent_comments($query)
 {
     // Due to missing get_comments hook prior to WP 3.1, this filter operates on every front-end query.
     // If query doesn't pertain to comments, skip out with as little overhead as possible.
     if (strpos($query, 'comment') && strpos($query, "ELECT") && !strpos($query, 'posts as parent') && !strpos($query, "COUNT") && strpos($query, "comment_approved")) {
         if (!is_attachment() && !is_content_administrator_rs()) {
             global $wpdb;
             if (strpos($query, " {$wpdb->posts} ")) {
                 return $query;
             }
             if (awp_is_plugin_active('wp-wall')) {
                 $options = WPWall_GetOptions();
                 if (strpos($query, 'comment_post_ID=' . $options['pageId'])) {
                     return $query;
                 }
             }
             if (strpos($query, $wpdb->comments)) {
                 $query = str_replace(" post_status = 'publish'", " {$wpdb->posts}.post_status = 'publish'", $query);
                 // theoretically, a slight performance enhancement if we can simplify the query to skip filtering of attachment comments
                 if (defined('SCOPER_NO_ATTACHMENT_COMMENTS') || false !== strpos($query, 'comment_post_ID =')) {
                     if (!strpos($query, "JOIN {$wpdb->posts}")) {
                         $query = preg_replace("/FROM\\s*{$wpdb->comments}\\s*WHERE /", "FROM {$wpdb->comments} INNER JOIN {$wpdb->posts} ON {$wpdb->posts}.ID = {$wpdb->comments}.comment_post_ID WHERE ", $query);
                     }
                     $query = apply_filters('objects_request_rs', $query, 'post', '', array('skip_teaser' => true));
                 } else {
                     $query = str_replace("user_id ", "{$wpdb->comments}.user_id ", $query);
                     $query = str_replace("SELECT {$wpdb->comments}.* FROM {$wpdb->comments}", "SELECT DISTINCT {$wpdb->comments}.* FROM {$wpdb->comments}", $query);
                     if (!strpos($query, ' DISTINCT ')) {
                         $query = str_replace("SELECT ", "SELECT DISTINCT ", $query);
                     }
                     $post_types = array_diff(get_post_types(array('public' => true)), array('attachment'));
                     $post_type_in = "'" . implode("','", $post_types) . "'";
                     $join = "LEFT JOIN {$wpdb->posts} as parent ON parent.ID = {$wpdb->posts}.post_parent AND parent.post_type IN ({$post_type_in}) AND {$wpdb->posts}.post_type = 'attachment'";
                     $use_post_types = scoper_get_option('use_post_types');
                     $where = array();
                     foreach ($post_types as $type) {
                         if (!empty($use_post_types[$type])) {
                             $where_post = apply_filters('objects_where_rs', '', 'post', $type, array('skip_teaser' => true));
                         } else {
                             $where_post = "AND 1=1";
                         }
                         $where[] = "{$wpdb->posts}.post_type = '{$type}' {$where_post}";
                         $where[] = "{$wpdb->posts}.post_type = 'attachment' AND parent.post_type = '{$type}' " . str_replace("{$wpdb->posts}.", "parent.", $where_post);
                     }
                     $where = agp_implode(' ) OR ( ', $where, ' ( ', ' ) ');
                     if (!strpos($query, "JOIN {$wpdb->posts}")) {
                         $query = str_replace("WHERE ", "INNER JOIN {$wpdb->posts} ON {$wpdb->posts}.ID = {$wpdb->comments}.comment_post_ID {$join} WHERE ( {$where} ) AND ", $query);
                     } else {
                         $query = str_replace("WHERE ", "{$join} WHERE {$where} AND ", $query);
                     }
                 }
             }
         }
     }
     return $query;
 }
 function flt_comments_clauses($clauses, &$qry_obj)
 {
     global $wpdb;
     if (is_admin() && defined('SCOPER_NO_COMMENT_FILTERING') && empty($GLOBALS['current_user']->allcaps['moderate_comments'])) {
         return $clauses;
     }
     if (empty($clauses['join'])) {
         $clauses['join'] = "JOIN {$wpdb->posts} ON {$wpdb->posts}.ID = {$wpdb->comments}.comment_post_ID";
     }
     // for WP 3.1 and any manual 3rd-party join construction (subsequent filter will expand to additional statuses as appropriate)
     $clauses['where'] = preg_replace("/ post_status\\s*=\\s*[']?publish[']?/", " {$wpdb->posts}.post_status = 'publish'", $clauses['where']);
     // performance enhancement: simplify comments query if there are no attachment comments to filter (TODO: cache this result)
     $qry_any_attachment_comments = "SELECT ID FROM {$wpdb->posts} AS p INNER JOIN {$wpdb->comments} AS c ON p.ID = c.comment_post_ID WHERE p.post_type = 'attachment' LIMIT 1";
     $post_type_arg = isset($qry_obj->query_vars['post_type']) ? $qry_obj->query_vars['post_type'] : '';
     $post_id = !empty($qry_obj->query_vars['post_id']) ? $qry_obj->query_vars['post_id'] : 0;
     $attachment_query = 'attachment' == $post_type_arg || $post_id && 'attachment' == get_post_field('post_type', $post_id);
     $args = array('skip_teaser' => true);
     if (is_admin()) {
         require_once 'admin/comments-interceptor-admin_rs.php';
         $args['force_reqd_caps'] = CommentsInterceptorAdmin_RS::get_reqd_caps();
     }
     // $attachment_query: current query is for attachment post type, or for a specific post which is an attachment
     // $post_id: current query is for a specific post
     // 	 NOTE: even if not $attachment_query, attachment comments are included by default along with comments on other post types (i.e. for Recent Comments sidebar)
     if (defined('SCOPER_NO_ATTACHMENT_COMMENTS') || !$attachment_query && ($post_id || !defined('SCOPER_ATTACHMENT_COMMENTS') && !scoper_get_var($qry_any_attachment_comments))) {
         $clauses['where'] = " AND " . $clauses['where'];
         $clauses['where'] = "1=1" . apply_filters('objects_where_rs', $clauses['where'], 'post', $post_type_arg, $args);
     } else {
         if (false === strpos($clauses['fields'], 'DISTINCT ')) {
             $clauses['fields'] = 'DISTINCT ' . $clauses['fields'];
         }
         if ($post_type_arg) {
             $post_types = (array) $post_type_arg;
         } else {
             $post_types = array_diff(get_post_types(array('public' => true)), array('attachment'));
         }
         $post_type_in = "'" . implode("','", $post_types) . "'";
         $clauses['join'] .= " LEFT JOIN {$wpdb->posts} as parent ON parent.ID = {$wpdb->posts}.post_parent AND parent.post_type IN ({$post_type_in}) AND {$wpdb->posts}.post_type = 'attachment'";
         $use_post_types = scoper_get_option('use_post_types');
         $where = array();
         foreach ($post_types as $type) {
             if (!empty($use_post_types[$type])) {
                 $where_post = apply_filters('objects_where_rs', '', 'post', $type, $args);
             } else {
                 $where_post = "AND 1=1";
             }
             $where[] = "{$wpdb->posts}.post_type = '{$type}' {$where_post}";
             $where[] = "{$wpdb->posts}.post_type = 'attachment' AND parent.post_type = '{$type}' " . str_replace("{$wpdb->posts}.", "parent.", $where_post);
         }
         $clauses['where'] = preg_replace("/\\s*AND\\s*{$wpdb->posts}.post_status\\s*=\\s*[']?publish[']?/", "", $clauses['where']);
         $clauses['where'] .= ' AND ( ' . agp_implode(' ) OR ( ', $where, ' ( ', ' ) ') . ' )';
     }
     return $clauses;
 }
 function act_attachment_access()
 {
     if (is_admin() || defined('DISABLE_QUERYFILTERS_RS') || is_content_administrator_rs() || !scoper_get_option('file_filtering')) {
         return;
     }
     // if ( is_attachment() ) {  as of WP 2.6, is_attachment() returns false for custom permalink attachment URL
     if (is_attachment_rs()) {
         //rs_errlog( 'IS an attachment:' );
         require_once dirname(__FILE__) . '/attachment-template_rs.php';
         AttachmentTemplate_RS::attachment_access();
     }
 }
 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 available_menu_items_parse_query(&$query)
 {
     if (scoper_get_option('admin_nav_menu_filter_items')) {
         $query->query_vars['include'] = '';
         $query->query_vars['post__in'] = '';
         $query->query_vars_hash = '';
         $query->query_vars_changed = true;
         $query->query['include'] = '';
         $query->query['post__in'] = '';
         $query->query_vars['suppress_filters'] = false;
         $query->query_vars['post_status'] = '';
         $query->query['suppress_filters'] = false;
         $query->query['post_status'] = '';
     }
 }
 function organize_assigned_roles($scope, $src_or_tx_name, $obj_or_term_id, $role_handles = '', $role_basis = ROLE_BASIS_USER, $get_defaults = false)
 {
     $assignments = array();
     if ($get_defaults) {
         $obj_or_term_id = intval($obj_or_term_id);
     }
     $args = array('role_handles' => $role_handles);
     $args['id'] = $obj_or_term_id || $get_defaults ? $obj_or_term_id : false;
     $roles = ScoperRoleAssignments::get_assigned_roles($scope, $role_basis, $src_or_tx_name, $args);
     $role_duration_enabled = scoper_get_option('role_duration_limits');
     $content_date_limits_enabled = scoper_get_option('content_date_limits');
     if (!isset($roles[$obj_or_term_id])) {
         return array();
     }
     foreach ($roles[$obj_or_term_id] as $role_handle => $agents) {
         foreach ($agents as $ug_id => $ass) {
             $ass_id = $ass['assignment_id'];
             $assign_for = $ass['assign_for'];
             $assignments[$role_handle]['assigned'][$ug_id]['inherited_from'] = $ass['inherited_from'];
             $assignments[$role_handle]['assigned'][$ug_id]['assign_for'] = $assign_for;
             $assignments[$role_handle]['assigned'][$ug_id]['assignment_id'] = $ass_id;
             if ($role_duration_enabled && $ass['date_limited']) {
                 $assignments[$role_handle]['assigned'][$ug_id]['date_limited'] = $ass['date_limited'];
                 $assignments[$role_handle]['assigned'][$ug_id]['start_date_gmt'] = $ass['start_date_gmt'];
                 $assignments[$role_handle]['assigned'][$ug_id]['end_date_gmt'] = $ass['end_date_gmt'];
             }
             if ($content_date_limits_enabled && $ass['content_date_limited']) {
                 $assignments[$role_handle]['assigned'][$ug_id]['content_date_limited'] = $ass['content_date_limited'];
                 $assignments[$role_handle]['assigned'][$ug_id]['content_min_date_gmt'] = $ass['content_min_date_gmt'];
                 $assignments[$role_handle]['assigned'][$ug_id]['content_max_date_gmt'] = $ass['content_max_date_gmt'];
             }
             // also save the calling function some work by returning each flavor of assignment as an array keyed by user/group id
             if ('children' == $assign_for || 'both' == $assign_for) {
                 $assignments[$role_handle]['children'][$ug_id] = $ass_id;
             }
             if ('entity' == $assign_for || 'both' == $assign_for) {
                 $assignments[$role_handle]['entity'][$ug_id] = $ass_id;
             }
             if ($ass['inherited_from']) {
                 $assignments[$role_handle]['propagated'][$ass['inherited_from']] = $ass_id;
             }
         }
     }
     return $assignments;
 }
 function TemplateInterceptor_RS()
 {
     $this->scoper =& $GLOBALS['scoper'];
     if (scoper_get_option('strip_private_caption')) {
         add_filter('the_title', array(&$this, 'flt_title'), 10, 3);
         if (defined('WPLANG') && WPLANG) {
             add_filter('gettext', array(&$this, 'flt_gettext'), 10, 3);
         }
     }
     if (defined('SCOPER_FILTER_COMMENT_COUNT')) {
         add_filter('get_comments_number', array(&$this, 'flt_get_comments_number'));
     }
     // this filter should pass post_id as 2nd arg, but does not as of WP 2.7
     if (awp_is_plugin_active('events-calendar')) {
         add_filter('query', array(&$this, 'ec_getDaysEvents'));
     }
     if (awp_is_plugin_active('eventcalendar3')) {
         add_filter('query', array(&$this, 'ec3_query'));
     }
 }
function scoper_mu_users_menu()
{
    if (!defined('DEFINE_GROUPS_RS') || !scoper_get_site_option('mu_sitewide_groups')) {
        return;
    }
    $cap_req = is_user_administrator_rs() || current_user_can('recommend_group_membership') ? 'read' : 'manage_groups';
    $groups_caption = defined('GROUPS_CAPTION_RS') ? GROUPS_CAPTION_RS : __('Role Groups', 'scoper');
    global $scoper_admin;
    $menu_name = awp_ver('3.1') ? 'users.php' : 'ms-admin.php';
    add_submenu_page($menu_name, $groups_caption, $groups_caption, $cap_req, 'rs-groups', array(&$scoper_admin, 'menu_handler'));
    if (scoper_get_option('mu_sitewide_groups')) {
        global $plugin_page_cr;
        // satisfy WordPress' demand that all admin links be properly defined in menu
        if ('rs-default_groups' == $plugin_page_cr) {
            add_submenu_page($menu_name, __('User Groups', 'scoper'), __('Default Groups', 'scoper'), $cap_req, 'rs-default_groups', array(&$scoper_admin, 'menu_handler'));
        }
        if ('rs-group_members' == $plugin_page_cr) {
            add_submenu_page($menu_name, __('User Groups', 'scoper'), __('Group Members', 'scoper'), $cap_req, 'rs-group_members', array(&$scoper_admin, 'menu_handler'));
        }
    }
}
 function flt_manage_posts_columns($defaults)
 {
     global $current_user, $scoper, $scoper_role_usage;
     $object_type = cr_find_post_type();
     if ($blogwide_role_requirement = scoper_get_option('role_admin_blogwide_editor_only')) {
         if ('admin' == $blogwide_role_requirement && !is_user_administrator_rs()) {
             return $defaults;
         } elseif ('content_admin' == $blogwide_role_requirement && !is_content_administrator_rs()) {
             return $defaults;
         } elseif ($blogwide_role_requirement) {
             if (!$scoper->user_can_edit_blogwide('post', $object_type, array('require_others_cap' => true))) {
                 return $defaults;
             }
         }
     }
     $use_object_roles = scoper_get_otype_option('use_object_roles', 'post', $object_type);
     $use_term_roles = scoper_get_otype_option('use_term_roles', 'post', $object_type);
     if ($use_term_roles && !empty($scoper_role_usage->any_restricted_terms) || $use_object_roles && !empty($scoper_role_usage->any_restricted_objects)) {
         if (scoper_get_otype_option('restrictions_column', 'post', $object_type)) {
             $defaults['restricted'] = __('Restrict', 'scoper');
         }
     }
     if (!empty($scoper_role_usage->have_termrole_ids['post'])) {
         if (scoper_get_otype_option('term_roles_column', 'post', $object_type)) {
             $defaults['termroles'] = __('Term Roles', 'scoper');
         }
     }
     if ($use_object_roles && !empty($scoper_role_usage->have_objrole_ids['post'])) {
         if (scoper_get_otype_option('object_roles_column', 'post', $object_type)) {
             $otype_display_name = $scoper->data_sources->member_property('post', 'object_types', $object_type, 'display_name');
             //$defaults['objroles'] = sprintf( _ x('%s Roles', 'Post or Page', 'scoper'), $otype_display_name);
             $defaults['objroles'] = sprintf(__('%s Roles', 'scoper'), $otype_display_name);
         }
     }
     return $defaults;
 }
 /**
  * function UsersInterceptor_RS::users_who_can
  * 
  * Get all users with required capabilities, applying scoped roles where pertinent.
  *
  * reqd_caps: array of capability names, or string value containing single capability name
  * cols: enumeration COLS_ALL_RS, COL_ID_RS, COLS_ID_NAME_RS or COLS_ID_DISPLAYNAME_RS. Determines return array dimensions.
  * object_src_name: object data source name as defined in $scoper->data_sources ( 'post' for posts OR pages )
  * object_id: array(reqd_cap => object_id), or string value containing single object_id
  *
  * Any WP-defined or RS-defined cap may be included to filter users on blog-wide capabilities.
  *
  * In addition, object-specific calls filter users for RS-defined caps based on 
  * Taxonomy/Object role assignment and role scoping requirements.
  * Any reqd_caps lacking a Role Scoper definition are still tested for blog-wide users roles.
  *
  * returns query results: 1D array of user_ids for $cols = COL_ID_RS, otherwise 2D array with all user columns
  */
 function users_who_can($reqd_caps, $cols = COLS_ALL_RS, $object_src_name = '', $object_id = 0, $args = array())
 {
     global $wpdb;
     $defaults = array('where' => '', 'orderby' => '', 'disable_memcache' => false, 'group_ids' => '', 'force_refresh' => false, 'force_all_users' => false);
     $args = array_merge($defaults, (array) $args);
     extract($args);
     if (!$orderby) {
         if (COLS_ALL_RS == $cols || COLS_ID_DISPLAYNAME_RS == $cols) {
             $orderby = " ORDER BY display_name";
         } elseif (COLS_ID_NAME_RS == $cols) {
             $orderby = " ORDER BY user_login AS display_name";
         }
         // calling code assumes display_name property for user or group object
     }
     if ('id' == $cols) {
         $cols = COL_ID_RS;
     }
     if (COL_ID_RS == $cols) {
         if ($force_all_users) {
             $qry = "SELECT ID FROM {$wpdb->users}";
         } else {
             $qry = "SELECT DISTINCT uro.user_id AS ID FROM {$wpdb->user2role2object_rs} AS uro";
         }
     } else {
         if (COLS_ID_DISPLAYNAME_RS == $cols) {
             $qcols = "{$wpdb->users}.ID, {$wpdb->users}.display_name";
         } elseif (COLS_ID_NAME_RS == $cols) {
             $qcols = "{$wpdb->users}.ID, {$wpdb->users}.user_login AS display_name";
         } elseif (COLS_ALL_RS == $cols) {
             $qcols = "{$wpdb->users}.*";
         } else {
             $qcols = $cols;
         }
         $qry = "SELECT DISTINCT {$qcols} FROM {$wpdb->users}";
         $where = '';
     }
     if ($reqd_caps || !$force_all_users) {
         if (COL_ID_RS != $cols) {
             $qry .= " INNER JOIN {$wpdb->user2role2object_rs} AS uro ON uro.user_id = {$wpdb->users}.ID";
         }
         if (!is_array($args)) {
             $args = array();
         }
         if (isset($args['ignore_user_roles'])) {
             unset($args['ignore_user_roles']);
         }
         $do_groups = empty($args['ignore_group_roles']);
         $args['ignore_group_roles'] = 1;
         $args['enforce_duration_limits'] = scoper_get_option('role_duration_limits');
         $args['enforce_content_date_limits'] = scoper_get_option('role_content_date_limits');
         //log_mem_usage_rs( 'before flt_users_where' );
         $where = $this->flt_users_where($where, $reqd_caps, $object_src_name, $object_id, $args);
         //log_mem_usage_rs( 'flt_users_where' );
     }
     $id_clause = $force_all_users ? '' : 'AND uro.user_id > 0';
     $qry = "{$qry} WHERE 1=1 {$id_clause} {$where} {$orderby}";
     $qry_key = $qry . serialize($args);
     // if we've already run this query before, return the result
     if (empty($disable_memcache) && isset($this->user_cache[$qry_key])) {
         return $this->user_cache[$qry_key];
     }
     if (COL_ID_RS == $cols) {
         $users = scoper_get_col($qry);
     } else {
         $users = scoper_get_results($qry);
     }
     //log_mem_usage_rs( 'users query' );
     if (!empty($do_groups)) {
         if (!empty($args['preserve_or_clause']) && strpos($args['preserve_or_clause'], 'uro.')) {
             unset($args['preserve_or_clause']);
         }
         if (!empty($args['orderby'])) {
             unset($args['orderby']);
         }
         if (empty($group_ids)) {
             $group_ids = $this->groups_who_can($reqd_caps, COL_ID_RS, $object_src_name, $object_id, $args);
         }
         if (!empty($group_ids)) {
             if (!defined('DISABLE_PERSISTENT_CACHE')) {
                 // if persistent cache is enabled, use cached members list for each group instead of querying for all groups
                 foreach ($group_ids as $group_id) {
                     if ($group_members = ScoperAdminLib::get_group_members($group_id, $cols, true)) {
                         $users = array_merge($users, $group_members);
                     }
                 }
             } else {
                 // avoid separate query for each group if persistent cache is not enabled
                 if ($group_members = ScoperAdminLib::get_group_members($group_ids, $cols, true)) {
                     $users = array_merge($users, $group_members);
                 }
             }
         }
         if (COL_ID_RS == $cols) {
             $users = array_unique($users);
         } else {
             $users = agp_array_unique_md($users);
         }
     }
     $this->user_cache[$qry_key] = $users;
     //log_mem_usage_rs( 'end UsersInt::users_who_can' );
     return $users;
 }
function scoper_display_rs_roledefs($args = array())
{
    global $scoper;
    echo "<div id='rs-roledefs' style='clear:both;margin:0;' class='rs-options agp_js_hide {$args['bgcolor_class']}'>";
    if (scoper_get_option('display_hints')) {
        echo '<div class="rs-optionhint">';
        echo '<p style="margin-top:0">';
        _e('These roles are defined by Role Scoper (and possibly other plugins) for your use in designating content-specific access or supplemental site-wide access.  Although the default capabilities are ideal for most installations, you may modify them at your discretion.', 'scoper');
        echo '</p>';
        echo '<p>';
        _e('Since Role Scoper role definitions pertain to a particular object type, available capabilities are defined by the provider of that object type. WordPress core or plugins can add or revise default role definitions based on available capabilities.', 'scoper');
        echo '</p>';
        echo '<p>';
        if (awp_ver('3.0-dev')) {
            _e('WordPress Role assignments function as a default which may be supplemented or overriden by site-wide or content-specific assignment of these RS Roles.', 'scoper');
        } else {
            _e('WordPress Role assignments function as a default which may be supplemented or overriden by blog-wide or content-specific assignment of these RS Roles.', 'scoper');
        }
        echo '</p>';
        echo '</div>';
    }
    echo "<input type='hidden' name='rs_role_defs' value='1' />";
    if (empty($args['customize_defaults'])) {
        $rs_role_defs = $scoper->role_defs;
    } else {
        global $scoper_role_types;
        $rs_role_defs = new CR_Roles();
        //$this->load_role_caps();
        $rs_role_defs->role_caps = apply_filters('define_role_caps_rs', cr_role_caps());
        if ($user_role_caps = scoper_get_option('user_role_caps', -1, true)) {
            $rs_role_defs->add_role_caps($user_role_caps);
        }
        if ($disabled_role_caps = scoper_get_option('disabled_role_caps', -1, true)) {
            $rs_role_defs->remove_role_caps($disabled_role_caps);
        }
        $rs_role_defs->add_member_objects(cr_role_defs());
        $rs_role_defs = apply_filters('define_roles_rs', $rs_role_defs);
        $rs_role_defs->remove_invalid();
        // currently don't allow additional custom-defined post, page or link roles
        // To support merging in of WP role assignments, always note actual WP-defined roles
        // regardless of which role type we are scoping with.
        $scoper->log_wp_roles($rs_role_defs);
        $rs_role_defs->lock();
        // prevent inadvertant improper API usage
    }
    // object_type association of roles needs to be based on default role_caps, otherwise roles with all caps disabled will be excluded from UI
    // This also allows the default bolding to be based on custom default settings when role defs are defined per-blog in wp-mu
    global $scoper_role_types;
    $rs_default_role_defs = new CR_Roles();
    $rs_default_role_defs->role_caps = apply_filters('define_role_caps_rs', cr_role_caps());
    $rs_default_role_defs->add_member_objects(cr_role_defs());
    $rs_default_cap_defs = new CR_Capabilities();
    $rs_default_cap_defs->add_member_objects(cr_cap_defs());
    $rs_default_cap_defs = apply_filters('define_capabilities_rs', $rs_default_cap_defs);
    $scoper->log_cap_usage($rs_default_role_defs, $rs_default_cap_defs);
    if (IS_MU_RS && !$args['customize_defaults'] && !$args['sitewide']) {
        if ($user_role_caps = scoper_get_option('user_role_caps', -1, true)) {
            $rs_default_role_defs->add_role_caps($user_role_caps);
        }
        if ($disabled_role_caps = scoper_get_option('disabled_role_caps', -1, true)) {
            $rs_default_role_defs->remove_role_caps($disabled_role_caps);
        }
    }
    $rs_default_role_defs = apply_filters('define_roles_rs', $rs_default_role_defs);
    $rs_default_role_defs->remove_invalid();
    if (has_filter('define_roles_rs')) {
        require_once SCOPER_ABSPATH . '/extension-helper_rs.php';
        scoper_adjust_legacy_extension_cfg($rs_default_role_defs, $rs_default_cap_defs);
    }
    $reviewed_roles = array();
    foreach ($scoper->data_sources->get_all() as $src_name => $src) {
        $object_types = $src->object_types;
        if ('post' == $src_name) {
            global $wp_taxonomies;
            foreach ($wp_taxonomies as $tx) {
                if ($_tx = $scoper->taxonomies->get($tx->name)) {
                    // use RS taxonomy object so we can pull plural_name property
                    $object_types[$tx->name] = $_tx;
                }
            }
            $use_post_types = scoper_get_option('use_post_types');
            $use_taxonomies = scoper_get_option('use_taxonomies');
        }
        foreach ($object_types as $object_type => $otype) {
            if ('post' == $src_name && empty($use_post_types[$object_type]) && empty($use_taxonomies[$object_type])) {
                continue;
            }
            $otype_roles = array();
            $otype_display_names = array();
            if ($obj_roles = $rs_default_role_defs->get_matching('rs', $src_name, $object_type)) {
                $otype_roles[$object_type] = $obj_roles;
            }
            if (!empty($otype->labels->name)) {
                $otype_display_names[$object_type] = $otype->labels->singular_name;
            } else {
                $otype_display_names[$object_type] = $otype->display_name;
            }
            if (!$otype_roles) {
                continue;
            }
            if ('post' == $src_name) {
                $plural_name = plural_name_from_cap_rs(get_post_type_object($object_type));
            } else {
                $plural_name = '';
            }
            foreach ($otype_roles as $object_type => $roles) {
                //display each role which has capabilities for this object type
                echo '<br />';
                echo '<h3>' . sprintf(__('%s Roles'), $otype_display_names[$object_type]) . '</h3>';
                ?>
<table class='widefat rs-backwhite'>
<thead>
<tr class="thead">
	<th width="15%"><?php 
                echo __awp('Role');
                ?>
</th>
	<th><?php 
                _e('Capabilities (abbreviated, defaults are bolded)', 'scoper');
                ?>
</th>
</tr>
</thead>
<tbody>
<?php 
                $wp_role_sync = array('rs_post_contributor' => 'contributor', 'rs_post_revisor' => 'revisor', 'rs_post_author' => 'author', 'rs_post_editor' => 'editor', 'rs_page_editor' => 'editor');
                if (defined('RVY_VERSION')) {
                    $wp_role_sync['rs_page_revisor'] = 'revisor';
                }
                global $wp_roles;
                $style = '';
                foreach ($roles as $rs_role_handle => $role_def) {
                    $reviewed_roles[] = $rs_role_handle;
                    $style = ' class="alternate"' == $style ? '' : ' class="alternate"';
                    echo "\n\t" . "<tr{$style}><td><strong>" . $rs_role_defs->get_display_name($rs_role_handle) . '</strong>';
                    if (isset($wp_role_sync[$rs_role_handle])) {
                        if (isset($wp_roles->role_objects[$wp_role_sync[$rs_role_handle]])) {
                            $wp_role_handle = "wp_" . $wp_role_sync[$rs_role_handle];
                            $wp_display_name = $wp_roles->role_names[$wp_role_sync[$rs_role_handle]];
                            $contained_roles = $rs_role_defs->get_contained_roles($wp_role_handle);
                            if (!isset($contained_roles[$rs_role_handle])) {
                                echo '<br /><br /><span class="rs-warning">';
                                printf(__('Warning: Since the WP %1$s role def lacks some caps selected here, it will be treated as a lesser role if Restrictions are applied.', 'scoper'), $wp_display_name);
                                echo '</span>';
                                $missing_caps = true;
                            } else {
                                $missing_caps = false;
                            }
                            // only display "sync WP role" checkbox if the WP role has missing caps or extra caps
                            $otype_caps = $scoper->cap_defs->get_matching($src_name, $object_type, '', STATUS_ANY_RS);
                            $wp_defined_caps = array_intersect_key($wp_roles->role_objects[$wp_role_sync[$rs_role_handle]]->capabilities, $otype_caps);
                            $wp_extra_caps = array_diff_key($wp_defined_caps, $rs_role_defs->role_caps[$rs_role_handle]);
                            /*
                            if ( $wp_extra_caps )
                            	$sync_caption = sprintf( _ x( 'sync WP %1$s <br />to these selections (currently includes %2$s)', 'role name', 'scoper' ), $wp_display_name, implode( ", ", array_keys($wp_extra_caps) ) );
                            else
                            	$sync_caption = sprintf( _ x( 'sync WP %s <br />to these selections', 'role name', 'scoper' ), $wp_display_name);
                            */
                            if ($wp_extra_caps) {
                                $sync_caption = sprintf(__('sync WP %1$s <br />to these selections (currently includes %2$s)', 'scoper'), $wp_display_name, implode(", ", array_keys($wp_extra_caps)));
                            } else {
                                $sync_caption = sprintf(__('sync WP %s <br />to these selections', 'scoper'), $wp_display_name);
                            }
                            echo '<br /><br />';
                            $title = __('note: only the capabilities listed here will be affected', 'scoper');
                            echo "<input type='checkbox' name='sync_wp_roles[]' id='sync_wp_role_{$rs_role_handle}' value='{$rs_role_handle}:{$wp_role_handle}' title='{$title}' />" . "<label for='sync_wp_role_{$rs_role_handle}' title='{$title}'>" . $sync_caption . '</label>';
                        }
                    }
                    echo "</td><td><ul class='rs-cap_list'>";
                    $active_cap_names = array_keys($rs_role_defs->role_caps[$rs_role_handle]);
                    if (!empty($role_def->anon_user_blogrole) || !empty($role_def->no_custom_caps)) {
                        $disabled_role = 'disabled="disabled"';
                        $available_cap_names = $active_cap_names;
                    } else {
                        $disabled_role = '';
                        $available_caps = $rs_default_cap_defs->get_matching($src_name, $object_type, '', STATUS_ANY_RS);
                        $available_cap_names = array_keys($available_caps);
                        sort($available_cap_names);
                        $available_cap_names = array_merge($available_cap_names, $active_cap_names);
                    }
                    // abbreviate type caps and reorder display
                    $show_cap_names = array();
                    foreach ($available_cap_names as $cap_name) {
                        if ($plural_name && strpos($cap_name, "_{$plural_name}")) {
                            $display = str_replace("_{$plural_name}", '', $cap_name);
                            $display = sprintf(__('%s...', 'scoper'), $display);
                        } else {
                            $display = $cap_name;
                        }
                        $show_cap_names[$display] = $cap_name;
                    }
                    ksort($show_cap_names);
                    foreach ($show_cap_names as $display => $cap_name) {
                        $checked = in_array($cap_name, $active_cap_names) ? 'checked="checked"' : '';
                        $is_default = !empty($rs_default_role_defs->role_caps[$rs_role_handle][$cap_name]);
                        $disabled_cap = $disabled_role || $is_default && !empty($available_caps[$cap_name]->no_custom_remove) || !$is_default && !empty($available_caps[$cap_name]->no_custom_add);
                        $disabled = $disabled_cap ? 'disabled="disabled"' : '';
                        $style = $is_default ? "style='font-weight: bold'" : '';
                        $cap_safename = str_replace(' ', '_', $cap_name);
                        echo "<li><input type='checkbox' name='{$rs_role_handle}_caps[]' id='{$rs_role_handle}_{$cap_safename}' value='{$cap_name}' {$checked} {$disabled} />" . "<label for='{$rs_role_handle}_{$cap_safename}' title='{$cap_name}' {$style}>" . str_replace(' ', '&nbsp;', ucwords(str_replace('_', ' ', $display))) . '</label></li>';
                    }
                    echo '</ul></td></tr>';
                }
                echo '</tbody></table>';
                echo '<br /><br />';
            }
            // foreach otype_role (distinguish object roles from term roles)
        }
        // end foreach object_type
    }
    // end foreach data source
    $reviewed_roles = implode(',', array_unique($reviewed_roles));
    echo "<input type='hidden' name='reviewed_roles' value='{$reviewed_roles}' />";
    echo '<span class="alignright">';
    echo '<label for="rs_role_resync"><input name="rs_role_resync" type="checkbox" id="rs_role_resync" value="1" />';
    echo '&nbsp;';
    _e('Re-sync with WordPress roles on next Update', 'scoper');
    echo '</label></span>';
    echo '<br />';
    ?>
</div>

<?php 
}
function scoper_object_roles_list($viewing_user, $args = array())
{
    $html = '';
    if (!USER_ROLES_RS && !GROUP_ROLES_RS) {
        wp_die(__awp('Cheatin&#8217; uh?'));
    }
    $defaults = array('enforce_duration_limits' => true, 'is_user_profile' => false, 'echo' => true);
    $args = array_merge($defaults, (array) $args);
    extract($args);
    global $scoper, $wpdb, $current_user;
    if ($viewing_user) {
        if (!is_object($viewing_user)) {
            global $current_rs_user;
            if ($viewing_user == $current_rs_user->ID) {
                $viewing_user = $current_rs_user;
            } else {
                $viewing_user = new WP_Scoped_User($viewing_user);
            }
        }
    }
    $all_roles = array();
    $role_display = array();
    foreach ($scoper->role_defs->get_all_keys() as $role_handle) {
        if ($viewing_user) {
            $role_display[$role_handle] = $scoper->role_defs->get_display_name($role_handle, OBJECT_UI_RS);
        } else {
            $role_display[$role_handle] = $scoper->role_defs->get_abbrev($role_handle, OBJECT_UI_RS);
        }
    }
    if (!$is_user_profile) {
        $require_blogwide_editor = scoper_get_option('role_admin_blogwide_editor_only');
        if ('admin' === $require_blogwide_editor && !is_user_administrator_rs()) {
            return false;
        }
        if ('admin_content' === $require_blogwide_editor && !is_content_administrator_rs()) {
            return false;
        }
    } else {
        $require_blogwide_editor = false;
    }
    foreach ($scoper->data_sources->get_all() as $src_name => $src) {
        $otype_count = 0;
        if (!empty($src->taxonomy_only) || $src_name == 'group' && !$viewing_user) {
            continue;
        }
        $strict_objects = $scoper->get_restrictions(OBJECT_SCOPE_RS, $src_name);
        foreach ($src->object_types as $object_type => $otype) {
            $otype_count++;
            $disable_role_admin = false;
            if ($require_blogwide_editor) {
                if (!$scoper->user_can_edit_blogwide('post', $object_type, array('require_others_cap' => true))) {
                    $disable_role_admin = true;
                }
            }
            if (!empty($src->cols->type) && !empty($otype->name)) {
                $col_type = $src->cols->type;
                $otype_clause = "AND {$src->table}.{$col_type} = '{$otype->name}'";
            } elseif ($otype_count < 2) {
                $otype_clause = '';
            } else {
                continue;
            }
            $col_id = $src->cols->id;
            $col_name = $src->cols->name;
            $ug_clause_for_user_being_viewed = $viewing_user ? $viewing_user->get_user_clause('uro') : '';
            // TODO: replace join with uro subselect
            $qry = "SELECT DISTINCT {$src->table}.{$col_name}, {$src->table}.{$col_id}, uro.role_name, uro.date_limited, uro.start_date_gmt, uro.end_date_gmt" . " FROM {$src->table} ";
            $join = " INNER JOIN {$wpdb->user2role2object_rs} AS uro" . " ON uro.obj_or_term_id = {$src->table}.{$col_id}" . " AND uro.src_or_tx_name = '{$src_name}'" . " AND uro.scope = 'object' AND uro.role_type = 'rs'";
            $duration_clause = $enforce_duration_limits ? scoper_get_duration_clause("{$src->table}.{$src->cols->date}") : '';
            $status_clause = 'post' == $src_name ? "AND post_status != 'auto-draft'" : '';
            // TODO: version update script to delete post roles on auto-drafts (stored via default roles)
            $where = " WHERE 1=1 {$status_clause} {$otype_clause} {$duration_clause} {$ug_clause_for_user_being_viewed}";
            $orderby = " ORDER BY {$src->table}.{$col_name} ASC, uro.role_name ASC";
            $qry .= $join . $where . $orderby;
            $results = scoper_get_results($qry);
            if (!is_user_administrator_rs()) {
                // no need to filter admins - just query the assignments
                // only list role assignments which the logged-in user can administer
                $args['required_operation'] = OP_EDIT_RS;
                // Possible TODO: re-implement OP_ADMIN distinction with admin-specific capabilities
                /*
                if ( cr_get_reqd_caps( $src_name, OP_ADMIN_RS, $object_type ) {
                	$args['required_operation'] = OP_ADMIN_RS;
                } else {
                	$reqd_caps = array();
                	foreach (array_keys($src->statuses) as $status_name) {
                		$admin_caps = $scoper->cap_defs->get_matching($src_name, $object_type, OP_ADMIN_RS, $status_name);
                		$delete_caps = $scoper->cap_defs->get_matching($src_name, $object_type, OP_DELETE_RS, $status_name);
                		$reqd_caps[$object_type][$status_name] = array_merge(array_keys($admin_caps), array_keys($delete_caps));
                	}
                	$args['force_reqd_caps'] = $reqd_caps;
                }
                */
                $qry = "SELECT {$src->table}.{$col_id} FROM {$src->table} WHERE 1=1";
                $args['require_full_object_role'] = true;
                $qry_flt = apply_filters('objects_request_rs', $qry, $src_name, $object_type, $args);
                $cu_admin_results = scoper_get_col($qry_flt);
                if (empty($viewing_user) || $current_user->ID != $viewing_user->ID) {
                    foreach ($results as $key => $row) {
                        if (!in_array($row->{$col_id}, $cu_admin_results)) {
                            unset($results[$key]);
                        }
                    }
                } else {
                    // for current user's view of their own user profile, just de-link unadminable objects
                    $link_roles = array();
                    $link_objects = array();
                    if (!$disable_role_admin) {
                        foreach ($results as $key => $row) {
                            if (in_array($row->{$col_id}, $cu_admin_results)) {
                                $link_roles[$row->{$col_id}] = true;
                            }
                        }
                        $args['required_operation'] = OP_EDIT_RS;
                        $args['require_full_object_role'] = false;
                        if (isset($args['force_reqd_caps'])) {
                            unset($args['force_reqd_caps']);
                        }
                        $qry_flt = apply_filters('objects_request_rs', $qry, $src_name, $object_type, $args);
                        $cu_edit_results = scoper_get_col($qry_flt);
                        foreach ($results as $key => $row) {
                            if (in_array($row->{$col_id}, $cu_edit_results)) {
                                $link_objects[$row->{$col_id}] = true;
                            }
                        }
                    }
                }
            }
            $object_roles = array();
            $objnames = array();
            if ($results) {
                $got_object_roles = true;
                foreach ($results as $row) {
                    if (!isset($objnames[$row->{$col_id}])) {
                        if ('post' == $src->name) {
                            $objnames[$row->{$col_id}] = apply_filters('the_title', $row->{$col_name}, $row->{$col_id});
                        } else {
                            $objnames[$row->{$col_id}] = $row->{$col_name};
                        }
                    }
                    $role_handle = 'rs_' . $row->role_name;
                    if ($row->date_limited) {
                        $duration_key = serialize(array('start_date_gmt' => $row->start_date_gmt, 'end_date_gmt' => $row->end_date_gmt));
                    } else {
                        $duration_key = '';
                    }
                    $object_roles[$duration_key][$row->{$col_id}][$role_handle] = true;
                }
            } else {
                continue;
            }
            ?>

		
		<?php 
            $title_roles = __('edit roles', 'scoper');
            foreach (array_keys($object_roles) as $duration_key) {
                $date_caption = '';
                $limit_class = '';
                $limit_style = '';
                $link_class = '';
                if ($duration_key) {
                    $html .= "<h3 style='margin-bottom:0'>{$date_caption}</h3>";
                    $duration_limits = unserialize($duration_key);
                    $duration_limits['date_limited'] = true;
                    ScoperAdminUI::set_agent_formatting($duration_limits, $date_caption, $limit_class, $link_class, $limit_style);
                    $title = "title='{$date_caption}'";
                    $date_caption = '<span class="rs-gray"> ' . trim($date_caption) . '</span>';
                } else {
                    $title = "title='{$title_roles}'";
                }
                if (!$disable_role_admin && (is_user_administrator_rs() || $cu_admin_results)) {
                    //if ( ( $src_name != $object_type ) && ( 'post' != $object_type ) ) {  // menu links currently assume unique object type names
                    //	$roles_page = "rs-roles-{$object_type}_{$src_name}";
                    //} else {
                    $roles_page = "rs-{$object_type}-roles";
                    //}
                    $url = "admin.php?page={$roles_page}";
                    $html .= "<h4><a name='{$object_type}' href='{$url}'><strong>" . sprintf(__('%1$s Roles%2$s:', 'scoper'), $otype->labels->singular_name, '</strong></a><span style="font-weight:normal">' . $date_caption) . "</span></h4>";
                } else {
                    $html .= "<h4><strong>" . sprintf(__('%1$s Roles%2$s:', 'scoper'), $otype->labels->singular_name, $date_caption) . "</strong></h4>";
                }
                $html .= "<ul class='rs-termlist'><li>" . "<table class='widefat'>" . "<thead>" . "<tr class='thead'>" . "\t<th class='rs-tightcol'>" . __('ID') . "</th>" . "\t<th>" . __awp('Name') . "</th>" . "\t<th>" . __('Role Assignments', 'scoper') . "</th>" . "</tr>" . "</thead>";
                $id_clause = isset($role_codes[$role_handle]) ? "id='roles-{$role_codes[$role_handle]}'" : '';
                $html .= "<tbody {$id_clause}>";
                $style = ' class="rs-backwhite"';
                $title_item = sprintf(__('edit %s', 'scoper'), agp_strtolower($otype->labels->singular_name));
                foreach ($object_roles[$duration_key] as $obj_id => $roles) {
                    $object_name = esc_attr($objnames[$obj_id]);
                    $html .= "\n\t<tr{$style}>";
                    $link_this_object = !isset($link_objects) || isset($link_objects[$obj_id]);
                    // link from object ID to the object type's default editor, if defined
                    if ($link_this_object && !empty($src->edit_url)) {
                        $src_edit_url = sprintf($src->edit_url, $obj_id);
                        $html .= "<td><a href='{$src_edit_url}' class='edit' title='{$title_item}'>{$obj_id}</a></td>";
                    } else {
                        $html .= "<td>{$obj_id}</td>";
                    }
                    $name = !empty($objnames[$obj_id]) ? $objnames[$obj_id] : __('(untitled)', 'scoper');
                    // link from object name to our "Edit Object Role Assignment" interface
                    $link_this_role = !isset($link_roles) || isset($link_roles[$obj_id]);
                    if ($link_this_role) {
                        if ('group' == $object_type) {
                            $rs_edit_url = sprintf($src->edit_url, $obj_id);
                        } else {
                            $rs_edit_url = "admin.php?page=rs-object_role_edit&amp;src_name={$src_name}&amp;object_type={$object_type}&amp;object_id={$obj_id}&amp;object_name={$object_name}";
                        }
                        $html .= "\n\t<td><a {$title}{$limit_style}class='{$link_class}{$limit_class}' href='{$rs_edit_url}'>{$name}</a></td>";
                    } else {
                        $html .= "\n\t<td>{$name}</td>";
                    }
                    $html .= "<td>";
                    $role_list = array();
                    foreach (array_keys($roles) as $role_handle) {
                        // roles which require object assignment are asterisked (bolding would contradict the notation of term roles list, where propogating roles are bolded)
                        if (isset($strict_objects['restrictions'][$role_handle][$obj_id]) || isset($strict_objects['unrestrictions'][$role_handle]) && is_array($strict_objects['unrestrictions'][$role_handle]) && !isset($strict_objects['unrestrictions'][$role_handle][$obj_id])) {
                            $role_list[] = "<span class='rs-backylw'>" . $role_display[$role_handle] . '</span>';
                        } else {
                            $role_list[] = $role_display[$role_handle];
                        }
                    }
                    $html .= implode(', ', $role_list);
                    $html .= '</td></tr>';
                    $style = ' class="alternate"' == $style ? ' class="rs-backwhite"' : ' class="alternate"';
                }
                // end foreach object_roles
                $html .= '</tbody></table>';
                $html .= '</li></ul><br />';
            }
            // end foreach role date range
        }
        // end foreach object_types
    }
    // end foreach data source
    if ($echo) {
        echo $html;
    } else {
        return $html;
    }
}
 function flt_get_pages($results, $args = array())
 {
     $results = (array) $results;
     global $wpdb;
     // === BEGIN Role Scoper ADDITION: global var; various special case exemption checks ===
     //
     global $scoper, $current_rs_user;
     // need to skip cache retrieval if QTranslate is filtering get_pages with a priority of 1 or less
     $no_cache = !defined('SCOPER_QTRANSLATE_COMPAT') && awp_is_plugin_active('qtranslate');
     // buffer titles in case they were filtered previously
     $titles = scoper_get_property_array($results, 'ID', 'post_title');
     // depth is not really a get_pages arg, but remap exclude arg to exclude_tree if wp_list_terms called with depth=1
     if (!empty($args['exclude']) && empty($args['exclude_tree']) && !empty($args['depth']) && 1 == $args['depth']) {
         if (0 !== strpos($args['exclude'], ',')) {
             // work around wp_list_pages() bug of attaching leading comma if a plugin uses wp_list_pages_excludes filter
             $args['exclude_tree'] = $args['exclude'];
         }
     }
     //
     // === END Role Scoper ADDITION ===
     // =================================
     $defaults = array('child_of' => 0, 'sort_order' => 'ASC', 'sort_column' => 'post_title', 'hierarchical' => 1, 'exclude' => array(), 'include' => array(), 'meta_key' => '', 'meta_value' => '', 'authors' => '', 'parent' => -1, 'exclude_tree' => '', 'number' => '', 'offset' => 0, 'post_type' => 'page', 'post_status' => 'publish', 'depth' => 0, 'suppress_filters' => 0, 'remap_parents' => -1, 'enforce_actual_depth' => -1, 'remap_thru_excluded_parent' => -1);
     // Role Scoper arguments added above
     // === BEGIN Role Scoper ADDITION: support front-end optimization
     $post_type = isset($args['post_type']) ? $args['post_type'] : $defaults['post_type'];
     $use_post_types = (array) scoper_get_option('use_post_types');
     if (empty($use_post_types[$post_type])) {
         return $results;
     }
     if ($scoper->is_front()) {
         if ('page' == $post_type && defined('SCOPER_GET_PAGES_LEAN')) {
             // custom types are likely to have custom fields
             $defaults['fields'] = "{$wpdb->posts}.ID, {$wpdb->posts}.post_title, {$wpdb->posts}.post_parent, {$wpdb->posts}.post_date, {$wpdb->posts}.post_date_gmt, {$wpdb->posts}.post_status, {$wpdb->posts}.post_name, {$wpdb->posts}.post_modified, {$wpdb->posts}.post_modified_gmt, {$wpdb->posts}.guid, {$wpdb->posts}.menu_order, {$wpdb->posts}.comment_count";
         } else {
             $defaults['fields'] = "{$wpdb->posts}.*";
             if (!defined('SCOPER_FORCE_PAGES_CACHE')) {
                 $no_cache = true;
             }
             // serialization / unserialization of post_content for all pages is too memory-intensive for sites with a lot of pages
         }
     } else {
         // required for xmlrpc getpagelist method
         $defaults['fields'] = "{$wpdb->posts}.*";
         if (!defined('SCOPER_FORCE_PAGES_CACHE')) {
             $no_cache = true;
         }
     }
     // === END Role Scoper MODIFICATION ===
     $r = wp_parse_args($args, $defaults);
     extract($r, EXTR_SKIP);
     $number = (int) $number;
     $offset = (int) $offset;
     $child_of = (int) $child_of;
     // Role Scoper modification: null value will confuse children array check
     // Make sure the post type is hierarchical
     $hierarchical_post_types = get_post_types(array('public' => true, 'hierarchical' => true));
     if (!in_array($post_type, $hierarchical_post_types)) {
         return $results;
     }
     // Make sure we have a valid post status
     if (!in_array($post_status, get_post_stati())) {
         return $results;
     }
     // for the page parent dropdown, return no available selections for a published main page if the logged user isn't allowed to de-associate it from Main
     if (!empty($name) && 'parent_id' == $name) {
         global $post;
         if (!$post->post_parent && !$GLOBALS['scoper_admin_filters']->user_can_associate_main($post_type)) {
             $status_obj = get_post_status_object($post->post_status);
             if ($status_obj->public || $status_obj->private) {
                 return array();
             }
         }
         if (!empty($post) && $post_type == $post->post_type) {
             if ($post->post_parent) {
                 $append_page = get_post($post->post_parent);
             }
             $exclude_tree = $post->ID;
         }
     }
     //$scoper->last_get_pages_args = $r; // don't copy entire args array unless it proves necessary
     $scoper->last_get_pages_depth = $depth;
     $scoper->last_get_pages_suppress_filters = $suppress_filters;
     if ($suppress_filters) {
         return $results;
     }
     // === BEGIN Role Scoper MODIFICATION: wp-cache key and flag specific to access type and user/groups
     //
     if (!scoper_get_otype_option('use_object_roles', 'post', $post_type)) {
         return $results;
     }
     $key = md5(serialize(compact(array_keys($defaults))));
     $ckey = md5($key . CURRENT_ACCESS_NAME_RS);
     $cache_flag = 'rs_get_pages';
     $cache = $current_rs_user->cache_get($cache_flag);
     if (false !== $cache) {
         if (!is_array($cache)) {
             $cache = array();
         }
         if (!$no_cache && isset($cache[$ckey])) {
             // alternate filter name (WP core already applied get_pages filter)
             return apply_filters('get_pages_rs', $cache[$ckey], $r);
         }
     }
     //
     // === END Role Scoper MODIFICATION ===
     // ====================================
     $inclusions = '';
     if (!empty($include)) {
         $child_of = 0;
         //ignore child_of, parent, exclude, meta_key, and meta_value params if using include
         $parent = -1;
         $exclude = '';
         $meta_key = '';
         $meta_value = '';
         $hierarchical = false;
         $incpages = wp_parse_id_list($include);
         if (!empty($incpages)) {
             foreach ($incpages as $incpage) {
                 if (empty($inclusions)) {
                     $inclusions = ' AND ( ID = ' . intval($incpage) . ' ';
                 } else {
                     $inclusions .= ' OR ID = ' . intval($incpage) . ' ';
                 }
             }
         }
     }
     if (!empty($inclusions)) {
         $inclusions .= ')';
     }
     $exclusions = '';
     if (!empty($exclude)) {
         $expages = wp_parse_id_list($exclude);
         if (!empty($expages)) {
             foreach ($expages as $expage) {
                 if (empty($exclusions)) {
                     $exclusions = ' AND ( ID <> ' . intval($expage) . ' ';
                 } else {
                     $exclusions .= ' AND ID <> ' . intval($expage) . ' ';
                 }
             }
         }
     }
     if (!empty($exclusions)) {
         $exclusions .= ')';
     }
     $author_query = '';
     if (!empty($authors)) {
         $post_authors = wp_parse_id_list($authors);
         if (!empty($post_authors)) {
             foreach ($post_authors as $post_author) {
                 //Do we have an author id or an author login?
                 if (0 == intval($post_author)) {
                     $post_author = get_userdatabylogin($post_author);
                     if (empty($post_author)) {
                         continue;
                     }
                     if (empty($post_author->ID)) {
                         continue;
                     }
                     $post_author = $post_author->ID;
                 }
                 if ('' == $author_query) {
                     $author_query = ' post_author = ' . intval($post_author) . ' ';
                 } else {
                     $author_query .= ' OR post_author = ' . intval($post_author) . ' ';
                 }
             }
             if ('' != $author_query) {
                 $author_query = " AND ({$author_query})";
             }
         }
     }
     $join = '';
     $where = "{$exclusions} {$inclusions} ";
     if (!empty($meta_key) || !empty($meta_value)) {
         $join = " INNER JOIN {$wpdb->postmeta} ON {$wpdb->posts}.ID = {$wpdb->postmeta}.post_id";
         // Role Scoper modification: was LEFT JOIN in WP 3.0 core (TODO: would that botch uro join results?
         // meta_key and meta_value might be slashed
         $meta_key = stripslashes($meta_key);
         $meta_value = stripslashes($meta_value);
         if (!empty($meta_key)) {
             $where .= $wpdb->prepare(" AND {$wpdb->postmeta}.meta_key = %s", $meta_key);
         }
         if (!empty($meta_value)) {
             $where .= $wpdb->prepare(" AND {$wpdb->postmeta}.meta_value = %s", $meta_value);
         }
     }
     if ($parent >= 0) {
         $where .= $wpdb->prepare(' AND post_parent = %d ', $parent);
     }
     // === BEGIN Role Scoper MODIFICATION:
     // allow pages of multiple statuses to be displayed (requires default status=publish to be ignored)
     //
     $where_post_type = $wpdb->prepare("post_type = '%s'", $post_type);
     $where_status = '';
     $is_front = $scoper->is_front();
     $is_teaser_active = $scoper->is_front() && scoper_get_otype_option('do_teaser', 'post') && scoper_get_otype_option('use_teaser', 'post', $post_type);
     $private_teaser = $is_teaser_active && scoper_get_otype_option('use_teaser', 'post', $post_type) && !scoper_get_otype_option('teaser_hide_private', 'post', $post_type);
     if ($is_front && (!empty($current_rs_user->ID) || $private_teaser)) {
         $frontend_list_private = scoper_get_otype_option('private_items_listable', 'post', 'page');
     } else {
         $frontend_list_private = false;
     }
     // WP core does not include private pages in query.  Include private statuses in anticipation of user-specific filtering
     if ($post_status && ('publish' != $post_status || $is_front && !$frontend_list_private)) {
         $where_status = $wpdb->prepare("post_status = '%s'", $post_status);
     } else {
         // since we will be applying status clauses based on content-specific roles and restrictions, only a sanity check safeguard is needed when post_status is unspecified or defaulted to "publish"
         $safeguard_statuses = array();
         foreach (get_post_stati(array('internal' => false), 'object') as $status_name => $status_obj) {
             if (!$is_front || $status_obj->private || $status_obj->public) {
                 $safeguard_statuses[] = $status_name;
             }
         }
         $where_status = "post_status IN ('" . implode("','", $safeguard_statuses) . "')";
     }
     $query = "SELECT {$fields} FROM {$wpdb->posts} {$join} WHERE 1=1 AND {$where_post_type} AND ( {$where_status} {$where} {$author_query} ) ORDER BY {$sort_column} {$sort_order}";
     if (!empty($number)) {
         $query .= ' LIMIT ' . $offset . ',' . $number;
     }
     if ($is_teaser_active && !defined('SCOPER_TEASER_HIDE_PAGE_LISTING')) {
         // We are in the front end and the teaser is enabled for pages
         $query = apply_filters('objects_request_rs', $query, 'post', $post_type, array('force_teaser' => true));
         $pages = scoper_get_results($query);
         // execute unfiltered query
         // Pass results of unfiltered query through the teaser filter.
         // If listing private pages is disabled, they will be omitted completely, but restricted published pages
         // will still be teased.  This is a slight design compromise to satisfy potentially conflicting user goals without yet another option
         $pages = apply_filters('objects_results_rs', $pages, 'post', (array) $post_type, array('request' => $query, 'force_teaser' => true, 'object_type' => $post_type));
         // restore buffered titles in case they were filtered previously
         scoper_restore_property_array($pages, $titles, 'ID', 'post_title');
         $pages = apply_filters('objects_teaser_rs', $pages, 'post', $post_type, array('request' => $query, 'force_teaser' => true));
         if ($frontend_list_private) {
             if (!scoper_get_otype_option('teaser_hide_private', 'post', $post_type)) {
                 $tease_all = true;
             }
         }
     } else {
         $_args = array('skip_teaser' => true);
         if (in_array($GLOBALS['pagenow'], array('post.php', 'post-new.php'))) {
             if ($post_type_obj = get_post_type_object($post_type)) {
                 $plural_name = plural_name_from_cap_rs($post_type_obj);
                 $_args['alternate_reqd_caps'][0] = array("create_child_{$plural_name}");
             }
         }
         // Pass query through the request filter
         $query = apply_filters('objects_request_rs', $query, 'post', $post_type, $_args);
         // Execute the filtered query
         $pages = scoper_get_results($query);
         // restore buffered titles in case they were filtered previously
         scoper_restore_property_array($pages, $titles, 'ID', 'post_title');
     }
     if (empty($pages)) {
         // alternate hook name (WP core already applied get_pages filter)
         return apply_filters('get_pages_rs', array(), $r);
     }
     //
     // === END Role Scoper MODIFICATION ===
     // ====================================
     // Role Scoper note: WP core get_pages has already updated wp_cache and pagecache with unfiltered results.
     update_page_cache($pages);
     // === BEGIN Role Scoper MODIFICATION: Support a disjointed pages tree with some parents hidden ========
     if ($child_of || empty($tease_all)) {
         // if we're including all pages with teaser, no need to continue thru tree remapping
         $ancestors = ScoperAncestry::get_page_ancestors();
         // array of all ancestor IDs for keyed page_id, with direct parent first
         $orderby = $sort_column;
         if ($parent > 0 || !$hierarchical) {
             $remap_parents = false;
         } else {
             // if these settings were passed into this get_pages call, use them
             if (-1 === $remap_parents) {
                 $remap_parents = scoper_get_option('remap_page_parents');
             }
             if ($remap_parents) {
                 if (-1 === $enforce_actual_depth) {
                     $enforce_actual_depth = scoper_get_option('enforce_actual_page_depth');
                 }
                 if (-1 === $remap_thru_excluded_parent) {
                     $remap_thru_excluded_parent = scoper_get_option('remap_thru_excluded_page_parent');
                 }
             }
         }
         $remap_args = compact('child_of', 'parent', 'exclude', 'depth', 'orderby', 'remap_parents', 'enforce_actual_depth', 'remap_thru_excluded_parent');
         // one or more of these args may have been modified after extraction
         ScoperHardway::remap_tree($pages, $ancestors, 'ID', 'post_parent', $remap_args);
     }
     // === END Role Scoper MODIFICATION ===
     // ====================================
     if (!empty($exclude_tree)) {
         $exclude = array();
         $exclude = (int) $exclude_tree;
         $children = get_page_children($exclude, $pages);
         // RS note: okay to use unfiltered function here since it's only used for excluding
         $excludes = array();
         foreach ($children as $child) {
             $excludes[] = $child->ID;
         }
         $excludes[] = $exclude;
         $total = count($pages);
         for ($i = 0; $i < $total; $i++) {
             if (in_array($pages[$i]->ID, $excludes)) {
                 unset($pages[$i]);
             }
         }
     }
     if (!empty($append_page) && !empty($pages)) {
         $found = false;
         foreach (array_keys($pages) as $key) {
             if ($post->post_parent == $pages[$key]->ID) {
                 $found = true;
                 break;
             }
         }
         if (empty($found)) {
             $pages[] = $append_page;
         }
     }
     // re-index the array, just in case anyone cares
     $pages = array_values($pages);
     // === BEGIN Role Scoper MODIFICATION: cache key and flag specific to access type and user/groups
     //
     if (!$no_cache) {
         $cache[$ckey] = $pages;
         $current_rs_user->cache_set($cache, $cache_flag);
     }
     // alternate hook name (WP core already applied get_pages filter)
     $pages = apply_filters('get_pages_rs', $pages, $r);
     //
     // === END Role Scoper MODIFICATION ===
     // ====================================
     return $pages;
 }
            } else {
                _e('Group Administrators', 'scoper');
            }
            ?>
</h3>
<?php 
            UserGroups_tp::group_members_checklist($group_id, 'manager', $all_users);
            ?>
</div>
<?php 
        }
        ?>


<?php 
        if (scoper_get_option('group_ajax')) {
            ?>
<div style="clear:both;"></div>
<div class="rs-group_admins">
<h3><?php 
            if ($sitewide_groups) {
                printf(__('Group Moderators %1$s(via login to %2$s)%3$s', 'scoper'), '<span style="font-weight: normal">', rtrim($blog_path, '/'), '</span>');
            } else {
                _e('Group Moderators', 'scoper');
            }
            ?>
</h3>
<?php 
            UserGroups_tp::group_members_checklist($group_id, 'moderator', $all_users);
            ?>
</div>
 function ui_user_roles()
 {
     if (!is_user_administrator_rs() && !scoper_get_option('display_user_profile_roles')) {
         return;
     }
     global $profileuser, $current_rs_user;
     $profile_user_rs = $profileuser->ID == $current_rs_user->ID ? $current_rs_user : new WP_Scoped_User($profileuser->ID);
     include_once dirname(__FILE__) . '/profile_ui_rs.php';
     ScoperProfileUI::display_ui_user_roles($profile_user_rs);
 }
 function force_distinct_taxonomy_caps()
 {
     global $wp_taxonomies;
     $use_taxonomies = scoper_get_option('use_taxonomies');
     // note: we are allowing the 'assign_terms' property to retain its default value of 'edit_posts'.  The RS user_has_cap filter will convert it to the corresponding type-specific cap as needed.
     $tx_specific_caps = array('edit_terms' => 'manage_terms', 'manage_terms' => 'manage_terms', 'delete_terms' => 'manage_terms');
     $used_values = array();
     $customized = array();
     // currently, disallow category and post_tag cap use by custom taxonomies, but don't require category and post_tag to have different caps
     $core_taxonomies = array('category');
     foreach ($core_taxonomies as $taxonomy) {
         foreach (array_keys($tx_specific_caps) as $cap_property) {
             $used_values[] = $wp_taxonomies[$taxonomy]->cap->{$cap_property};
         }
     }
     $used_values = array_unique($used_values);
     $use_taxonomies['nav_menu'] = true;
     foreach (array_keys($wp_taxonomies) as $taxonomy) {
         if ('post_tag' == $taxonomy) {
             // complication due to default use of "manage_categories" cap for both categories and tags
             continue;
         }
         if ('yes' == $wp_taxonomies[$taxonomy]->public) {
             // clean up a GD Taxonomies quirk (otherwise wp_get_taxonomy_object will fail when filtering for public => true)
             $wp_taxonomies[$taxonomy]->public = true;
         } elseif ('' === $wp_taxonomies[$taxonomy]->public && !empty($wp_taxonomies[$taxonomy]->query_var_bool)) {
             // clean up a More Taxonomies quirk (otherwise wp_get_taxonomy_object will fail when filtering for public => true)
             $wp_taxonomies[$taxonomy]->public = true;
         }
         if (empty($use_taxonomies[$taxonomy]) || in_array($taxonomy, $core_taxonomies)) {
             continue;
         }
         $tx_caps = (array) $wp_taxonomies[$taxonomy]->cap;
         $plural_name = $taxonomy . 's';
         // as of WP 3.1, no basis for determinining this unless type-specific caps are set
         // don't allow any capability defined for this taxonomy to match any capability defined for category or post tag (unless this IS category or post tag)
         foreach ($tx_specific_caps as $cap_property => $replacement_cap_format) {
             if (!empty($tx_caps[$cap_property]) && in_array($tx_caps[$cap_property], $used_values)) {
                 $wp_taxonomies[$taxonomy]->cap->{$cap_property} = str_replace('terms', $plural_name, $replacement_cap_format);
                 if ('nav_menu' != $taxonomy) {
                     $customized[$taxonomy] = true;
                 }
                 // WP default is for nav menus editable only by administrator, so no need for notice
             }
             $used_values[] = $tx_caps[$cap_property];
         }
     }
     // One-time message alerting Administrators that custom taxonomies were auto-enabled for RS filtering
     if ($customized) {
         $logged = !empty($_POST['rs_defaults']) ? array() : (array) scoper_get_option('log_customized_taxonomies');
         if ($new_customized = array_diff_key($customized, $logged)) {
             $labels = array();
             foreach (array_keys($new_customized) as $taxonomy) {
                 $tx_obj = get_taxonomy($taxonomy);
                 $labels[$taxonomy] = !empty($tx_obj->labels->name) ? $tx_obj->labels->name : $taxonomy;
                 $label_str = implode(', ', $labels);
             }
             $msg_format = __('The following Custom Taxonomies are enabled for RS filtering: <strong>%1$s</strong>. Non-administrators will be unable to manage them until you either disable filtering (<strong>Roles > Options > Realm > Taxonomy Usage</strong>) or assign taxonomy-specific Roles (<strong>Roles > General</strong>). Disregard this message if you have already done so.', 'scoper');
             $message = sprintf($msg_format, $label_str);
             add_action('admin_notices', create_function('', 'echo \'<div id="message" class="error fade" style="color: black">' . $message . '</div>\';'));
             update_option('scoper_log_customized_taxonomies', array_merge($customized, $new_customized));
         }
     }
 }
Example #23
0
echo '</a> | ';
// Show All
$tr_display = strpos($_SERVER['HTTP_USER_AGENT'], 'MSIE') !== false ? 'block' : 'table-row';
$js_call = "\r\r\nagp_display_marked_elements('li','role-li','block');\r\r\nagp_setcss('.no-role','display','{$tr_display}');\r\r\nagp_setcss('.user-csv','display','inline');\r\r\nagp_setcss('.groups-csv','display','inline');\r\r\n";
echo "<a href='javascript:void(0);' onclick=\"{$js_call}\">";
_e('show all', 'scoper');
echo '</a>';
$all_roles = array();
$otype_source = array();
foreach ($scoper->data_sources->get_all() as $src_name => $src) {
    if (!empty($src->taxonomy_only)) {
        continue;
    }
    $object_types = $src->object_types;
    if ('post' == $src_name) {
        $use_post_types = scoper_get_option('use_post_types');
        $use_post_types['nav_menu_item'] = true;
        // currently no RS Options switch for this
        $object_types['nav_menu_item'] = (object) array('labels' => (object) array('name' => __('Nav Menu Manager', 'scoper')));
    }
    $include_taxonomy_otypes = true;
    foreach ($object_types as $object_type => $otype) {
        if ('post' == $src_name && empty($use_post_types[$object_type])) {
            continue;
        }
        $otype_roles = array();
        $otype_roles[$object_type] = $scoper->role_defs->get_matching('rs', $src_name, $object_type);
        $otype_source[$object_type] = $src_name;
        $uses_taxonomies = scoper_get_taxonomy_usage($src_name, $object_type);
        if ($include_taxonomy_otypes) {
            foreach ($uses_taxonomies as $taxonomy) {
function scoper_get_taxonomy_usage($src_name, $object_types = '')
{
    $taxonomies = array();
    $object_types = (array) $object_types;
    foreach ($object_types as $object_type) {
        if (taxonomy_exists($object_type)) {
            $use_taxonomies = array($object_type => 1);
        } else {
            $use_taxonomies = scoper_get_otype_option('use_term_roles', $src_name, $object_type);
        }
        $taxonomies = array_merge($taxonomies, array_intersect((array) $use_taxonomies, array(1)));
        // array cast prevents PHP warning on first-time execution following update to RS 1.2
    }
    if ($taxonomies) {
        // make sure we indicate non-usage of term roles for taxonomies that are completely disabled for RS
        if ('post' == $src_name) {
            $use_taxonomies = scoper_get_option('use_taxonomies');
            $taxonomies = array_intersect_key($taxonomies, array_intersect($use_taxonomies, array(1)));
        }
        return array_keys($taxonomies);
    } else {
        return array();
    }
}
 function users_who_can($reqd_caps, $cols = COLS_ALL_RS, $object_src_name = '', $object_id = 0, $args = array())
 {
     // if there are not capability requirements, no need to load Users_Interceptor filtering class
     if (!$reqd_caps) {
         if (COL_ID_RS == $cols) {
             $qcols = 'ID';
         } elseif (COLS_ID_NAME_RS == $cols) {
             $qcols = "ID, user_login AS display_name";
         } elseif (COLS_ID_DISPLAYNAME_RS == $cols) {
             $qcols = "ID, display_name";
         } elseif (COLS_ALL_RS == $cols) {
             $qcols = "*";
         } else {
             $qcols = $cols;
         }
         global $wpdb;
         $orderby = $cols == COL_ID_RS ? '' : 'ORDER BY display_name';
         if (IS_MU_RS && !scoper_get_option('mu_sitewide_groups') && !defined('FORCE_ALL_SITE_USERS_RS')) {
             $qry = "SELECT {$qcols} FROM {$wpdb->users} INNER JOIN {$wpdb->usermeta} AS um ON {$wpdb->users}.ID = um.user_id AND um.meta_key = '{$wpdb->prefix}capabilities' {$orderby}";
         } else {
             $qry = "SELECT {$qcols} FROM {$wpdb->users} {$orderby}";
         }
         if (COL_ID_RS == $cols) {
             return scoper_get_col($qry);
         } else {
             return scoper_get_results($qry);
         }
     } else {
         $defaults = array('where' => '', 'orderby' => '', 'disable_memcache' => false, 'group_ids' => '', 'force_refresh' => false, 'force_all_users' => false);
         $args = array_merge($defaults, (array) $args);
         extract($args);
         $cache_flag = "rs_users_who_can";
         $cache_id = md5(serialize($reqd_caps) . $cols . 'src' . $object_src_name . 'id' . $object_id . serialize($args));
         if (!$force_refresh) {
             // if we already have the results cached, no need to load Users_Interceptor filtering class
             $users = wpp_cache_get($cache_id, $cache_flag);
             if (is_array($users)) {
                 return $users;
             }
         }
         $this->init_users_interceptor();
         $users = $GLOBALS['users_interceptor']->users_who_can($reqd_caps, $cols, $object_src_name, $object_id, $args);
         wpp_cache_set($cache_id, $users, $cache_flag);
         return $users;
     }
 }
Example #26
0
 function role_submission($scope, $mode, $role_bases, $src_or_tx_name, $role_codes, $agent_caption_plural, $nonce_id)
 {
     global $scoper;
     $role_assigner = init_role_assigner();
     $err = 0;
     $role_count = 0;
     check_admin_referer($nonce_id);
     $set_roles = array();
     $selected_roles = isset($_POST['roles']) ? $_POST['roles'] : array();
     if (OBJECT_SCOPE_RS == $scope) {
         $src = $scoper->data_sources->get($src_or_tx_name);
         $date_col_defined = !empty($src->cols->date);
     } elseif (TERM_SCOPE_RS == $scope) {
         $tx = $scoper->taxonomies->get($src_or_tx_name);
         $date_col_defined = $scoper->data_sources->member_property($tx->object_source, 'cols', 'date');
     } else {
         $date_col_defined = true;
     }
     switch ($mode) {
         case ROLE_ASSIGNMENT_RS:
             $assign_for = $_POST['assign_for'];
             $selected_agents = array();
             foreach ($role_bases as $role_basis) {
                 if (!empty($_POST[$role_basis])) {
                     $selected_agents[$role_basis] = $_POST[$role_basis];
                 } else {
                     $csv_id = "{$role_basis}_csv";
                     if (!empty($_POST[$csv_id])) {
                         $selected_agents[$role_basis] = ScoperAdminLib::agent_ids_from_csv($csv_id, $role_basis);
                     } else {
                         $role_bases = array_diff($role_bases, array($role_basis));
                     }
                 }
             }
             $agents_msg = array();
             $valid_role_selection = !empty($selected_roles);
             $duration_limits_enabled = $date_col_defined && scoper_get_option('role_duration_limits');
             $content_date_limits_enabled = $date_col_defined && scoper_get_option('role_content_date_limits');
             break;
         case ROLE_RESTRICTION_RS:
             $role_bases = array('n/a');
             $default_restrictions = isset($_POST['default_restrictions']) ? $_POST['default_restrictions'] : array();
             $max_scope = $_POST['max_scope'];
             $require_for = $_POST['require_for'];
             $selected_agents = array('n/a' => array(0));
             $valid_role_selection = !empty($selected_roles) || !empty($default_restrictions);
             $modcount = 0;
             $duration_limits_enabled = $content_date_limits_enabled = false;
             break;
     }
     if (!$selected_agents) {
         $_POST['scoper_error'] = 1;
         echo '<div id="message" class="error"><p><strong>';
         printf(__('Error: no %s were selected!', 'scoper'), $agent_caption_plural);
         echo '</strong></p></div>';
         $err = 1;
     } elseif (!$valid_role_selection) {
         $_POST['scoper_error'] = 1;
         echo '<div id="message" class="error"><p><strong>';
         _e('Error: no roles were selected!', 'scoper');
         echo '</strong></p></div>';
         $err = 2;
     } else {
         if (ROLE_ASSIGNMENT_RS == $mode) {
             if (!empty($_POST['set_role_duration']) || !empty($_POST['set_content_date_limits'])) {
                 $date_entries_gmt = ScoperAdminBulkLib::process_role_date_entries();
             }
         }
         foreach ($role_bases as $role_basis) {
             foreach ($selected_agents[$role_basis] as $agent_id) {
                 // must set default restrictions first
                 if (!empty($default_restrictions)) {
                     $def_roles = array();
                     foreach ($default_restrictions as $role) {
                         $keys = explode('-', $role);
                         //keys[0]=role_code, 1=term_id or obj_id
                         if (count($keys) < 2) {
                             continue;
                         }
                         if (!($role_handle = array_search($keys[0], $role_codes))) {
                             continue;
                         }
                         $def_roles[$keys[1]][$role_handle] = array('max_scope' => $max_scope, 'for_item' => false, 'for_children' => true);
                         $modcount++;
                     }
                     $role_assigner->restrict_roles($scope, $src_or_tx_name, 0, $def_roles[0], array('force_flush' => true));
                 }
                 if (!empty($selected_roles)) {
                     foreach ($selected_roles as $role) {
                         $keys = explode('-', $role);
                         //keys[0]=role_code, 1=term_id or obj_id, 2=group_id or user_id
                         if (count($keys) < 2) {
                             continue;
                         }
                         if (!($role_handle = array_search($keys[0], $role_codes))) {
                             continue;
                         }
                         switch ($mode) {
                             case ROLE_ASSIGNMENT_RS:
                                 $set_roles[$role_basis][$keys[1]][$role_handle][$agent_id] = $keys[1] || !$assign_for ? $assign_for : ASSIGN_FOR_CHILDREN_RS;
                                 // always assign default category assignments as for_children
                                 break;
                             case ROLE_RESTRICTION_RS:
                                 $for_item = ASSIGN_FOR_ENTITY_RS == $require_for || ASSIGN_FOR_BOTH_RS == $require_for;
                                 $for_children = ASSIGN_FOR_CHILDREN_RS == $require_for || ASSIGN_FOR_BOTH_RS == $require_for;
                                 $set_roles[$keys[1]][$role_handle] = array('max_scope' => $max_scope, 'for_item' => $for_item, 'for_children' => $for_children);
                                 $modcount++;
                                 break;
                         }
                     }
                 }
             }
             // end foreach selected agents
             if (ROLE_ASSIGNMENT_RS == $mode) {
                 $args = array('force_flush' => true, 'set_role_duration' => '', 'set_content_date_limits' => '');
                 if ($duration_limits_enabled && !empty($_POST['set_role_duration'])) {
                     $is_limited = $date_entries_gmt->start_date_gmt || $date_entries_gmt->end_date_gmt != SCOPER_MAX_DATE_STRING || !empty($_POST['start_date_gmt_keep-timestamp']) || !empty($_POST['end_date_gmt_keep-timestamp']);
                     $args['set_role_duration'] = (object) array('date_limited' => $is_limited, 'start_date_gmt' => $date_entries_gmt->start_date_gmt, 'end_date_gmt' => $date_entries_gmt->end_date_gmt);
                 }
                 if ($content_date_limits_enabled && !empty($_POST['set_content_date_limits'])) {
                     $is_limited = $date_entries_gmt->content_min_date_gmt || $date_entries_gmt->content_max_date_gmt != SCOPER_MAX_DATE_STRING || !empty($_POST['content_min_date_gmt_keep-timestamp']) || !empty($_POST['content_max_date_gmt_keep-timestamp']);
                     $args['set_content_date_limits'] = (object) array('content_date_limited' => $is_limited, 'content_min_date_gmt' => $date_entries_gmt->content_min_date_gmt, 'content_max_date_gmt' => $date_entries_gmt->content_max_date_gmt);
                 }
                 if (isset($set_roles[$role_basis])) {
                     foreach ($set_roles[$role_basis] as $id => $item_roles) {
                         $role_assigner->assign_roles($scope, $src_or_tx_name, $id, $item_roles, $role_basis, $args);
                     }
                 }
             } else {
                 foreach ($set_roles as $id => $item_roles) {
                     $role_assigner->restrict_roles($scope, $src_or_tx_name, $id, $item_roles, array('force_flush' => true));
                 }
             }
             if (!empty($selected_agents[$role_basis])) {
                 if (ROLE_BASIS_USER == $role_basis) {
                     $agents_msg[] = sprintf(_n("%d user", "%d users", count($selected_agents[$role_basis]), 'scoper'), count($selected_agents[$role_basis]));
                 } else {
                     $agents_msg[] = sprintf(_n("%d group", "%d groups", count($selected_agents[$role_basis]), 'scoper'), count($selected_agents[$role_basis]));
                 }
             }
         }
         // end foreach role basis
         echo '<div id="message" class="updated fade"><p>';
         switch ($mode) {
             case ROLE_ASSIGNMENT_RS:
                 $roles_msg = sprintf(_n("%d role selection", "%d role selections", count($selected_roles), 'scoper'), count($selected_roles));
                 $agents_msg = implode(", ", $agents_msg);
                 //printf( _ x('Role Assignments Updated: %1$s for %2$s', 'n role selections for x users, y groups', 'scoper'), $roles_msg, $agents_msg );
                 printf(__('Role Assignments Updated: %1$s for %2$s', 'scoper'), $roles_msg, $agents_msg);
                 break;
             case ROLE_RESTRICTION_RS:
                 printf(_n("Role Restrictions Updated: %d setting", "Role Restrictions Updated: %d settings", $modcount, 'scoper'), $modcount);
                 break;
         }
         echo '</p></div>';
         // allow the DB server a little time to refresh before querying what we just put in
         global $wpdb;
         $junk = scoper_get_col("SELECT assignment_id FROM {$wpdb->user2role2object_rs} LIMIT 10");
     }
     //endif no input error
     return $err;
 }
 function group_members_checklist($group_id, $user_class = 'member', $all_users = '')
 {
     global $scoper;
     if (!$all_users) {
         $all_users = $scoper->users_who_can('', COLS_ID_NAME_RS);
     }
     if ($group_id) {
         $group = ScoperAdminLib::get_group($group_id);
     }
     if ('member' == $user_class) {
         $current_ids = $group_id ? array_flip(ScoperAdminLib::get_group_members($group_id, COL_ID_RS)) : array();
         if (!empty($group) && in_array($group->meta_id, array('rv_pending_rev_notice_ed_nr_', 'rv_scheduled_rev_notice_ed_nr_'))) {
             $args = array('any_object' => true);
             $eligible_ids = array();
             foreach (get_post_types(array('public' => true), 'object') as $_type => $_type_obj) {
                 $args['object_type'] = $_type;
                 $type_eligible_ids = $scoper->users_who_can(array($_type_obj->cap->edit_published_posts, $_type_obj->cap->edit_others_posts), COL_ID_RS, 'post', 0, $args);
                 $eligible_ids = array_merge($eligible_ids, $type_eligible_ids);
             }
             $eligible_ids = array_unique($eligible_ids);
         } else {
             // force_all_users arg is a temporary measure to ensure that any user can be viewed / added to a sitewide MU group regardless of what blog backend it's edited through
             $_args = IS_MU_RS && scoper_get_option('mu_sitewide_groups', true) ? array('force_all_users' => true) : array();
             $eligible_ids = $scoper->users_who_can('', COL_ID_RS, '', '', $_args);
         }
         $admin_ids = array();
     } else {
         $group_role_defs = 'moderator' == $user_class ? array('rs_group_moderator') : array('rs_group_manager');
         if ($group_id) {
             require_once dirname(__FILE__) . '/role_assignment_lib_rs.php';
             $current_roles = ScoperRoleAssignments::organize_assigned_roles(OBJECT_SCOPE_RS, 'group', $group_id, $group_role_defs, ROLE_BASIS_USER);
             $current_roles = agp_array_flatten($current_roles, false);
             $current_ids = isset($current_roles['assigned']) ? $current_roles['assigned'] : array();
         } else {
             $current_ids = array();
         }
         $cap_name = defined('SCOPER_USER_ADMIN_CAP') ? constant('SCOPER_USER_ADMIN_CAP') : 'edit_users';
         $admin_ids = $scoper->users_who_can($cap_name, COL_ID_RS);
         // optionally, limit available group managers according to role_admin_blogwide_editor_only option
         if ('manager' == $user_class) {
             $require_blogwide_editor = false;
             if (!empty($group)) {
                 if (!strpos($group->meta_id, '_nr_')) {
                     // don't limit manager selection for groups that don't have role assignments
                     $require_blogwide_editor = scoper_get_option('role_admin_blogwide_editor_only');
                 }
             }
             if ('admin' == $require_blogwide_editor) {
                 $eligible_ids = $admin_ids;
             } elseif ('admin_content' == $require_blogwide_editor) {
                 $cap_name = defined('SCOPER_CONTENT_ADMIN_CAP') ? constant('SCOPER_CONTENT_ADMIN_CAP') : 'activate_plugins';
                 $eligible_ids = array_unique(array_merge($admin_ids, $scoper->users_who_can($cap_name, COL_ID_RS)));
             } elseif ($require_blogwide_editor) {
                 $post_editors = $scoper->users_who_can('edit_others_posts', COL_ID_RS);
                 $page_editors = $scoper->users_who_can('edit_others_pages', COL_ID_RS);
                 $eligible_ids = array_unique(array_merge($post_editors, $page_editors, $admin_ids));
             } else {
                 $eligible_ids = '';
             }
         } else {
             $eligible_ids = '';
         }
     }
     // endif user class is not "member"
     $css_id = $user_class;
     $args = array('eligible_ids' => $eligible_ids, 'via_other_scope_ids' => $admin_ids, 'suppress_extra_prefix' => true);
     require_once dirname(__FILE__) . '/agents_checklist_rs.php';
     ScoperAgentsChecklist::agents_checklist(ROLE_BASIS_USER, $all_users, $css_id, $current_ids, $args);
 }
 function add_meta_boxes()
 {
     /*
     // optional hack to prevent role assignment boxes for non-Editors
     //
     //	This is now handled as a Role Scoper Option. 
     //	On the Advanced tab, Hidden Editing Elements section: select "Role administration requires a blog-wide Editor role"
     //
     // end optional hack
     */
     // ========= register WP-rendered metaboxes ============
     $src_name = 'post';
     // TODO: different handling for edit-tags.php
     $object_type = cr_find_post_type();
     $require_blogwide_editor = scoper_get_option('role_admin_blogwide_editor_only');
     if ('admin' == $require_blogwide_editor && !is_user_administrator_rs()) {
         return;
     }
     if ('admin_content' == $require_blogwide_editor && !is_content_administrator_rs()) {
         return;
     }
     if (!scoper_get_otype_option('use_object_roles', $src_name, $object_type)) {
         return;
     }
     if ($require_blogwide_editor) {
         if (!$this->scoper->user_can_edit_blogwide($src_name, $object_type, array('require_others_cap' => true))) {
             return;
         }
     }
     $role_defs = $this->scoper->role_defs->get_matching('rs', $src_name, $object_type);
     foreach ($role_defs as $role_handle => $role_def) {
         if (!isset($role_def->valid_scopes[OBJECT_SCOPE_RS])) {
             continue;
         }
         $box_id = $role_handle;
         add_meta_box($box_id, $this->scoper->role_defs->get_abbrev($role_handle, OBJECT_UI_RS), array(&$this, 'draw_object_roles_content'), $object_type);
         $this->meta_box_ids[$role_handle] = $box_id;
     }
 }
function scoper_admin_section_restrictions($taxonomy)
{
    global $scoper, $scoper_admin;
    $tx = $scoper->taxonomies->get($taxonomy);
    if (empty($tx) || empty($tx->requires_term)) {
        wp_die(__('Invalid taxonomy', 'scoper'));
    }
    $is_administrator = is_administrator_rs($tx, 'user');
    if (!$scoper_admin->user_can_admin_terms($taxonomy)) {
        wp_die(__awp('Cheatin&#8217; uh?'));
    }
    require_once dirname(__FILE__) . '/admin-bulk_rs.php';
    $role_assigner = init_role_assigner();
    $nonce_id = 'scoper-assign-roles';
    $role_codes = ScoperAdminBulk::get_role_codes();
    echo '<a name="scoper_top"></a>';
    // retrieve all terms to track hierarchical relationship, even though some may not be adminable by current user
    $val = ORDERBY_HIERARCHY_RS;
    $args = array('order_by' => $val);
    $all_terms = $scoper->get_terms($taxonomy, UNFILTERED_RS, COLS_ALL_RS, 0, $args);
    // =========================== Submission Handling =========================
    if (isset($_POST['rs_submit'])) {
        $err = ScoperAdminBulk::role_submission(TERM_SCOPE_RS, ROLE_RESTRICTION_RS, '', $taxonomy, $role_codes, '', $nonce_id);
        if (scoper_get_option('file_filtering')) {
            scoper_flush_file_rules();
        }
    } else {
        $err = 0;
    }
    // =========================== Prepare Data ===============================
    $tx_src = $scoper->data_sources->get($tx->source);
    if ($col_id = $tx_src->cols->id) {
        // determine which terms current user can admin
        if ($admin_terms = $scoper->get_terms($taxonomy, ADMIN_TERMS_FILTER_RS, COL_ID_RS)) {
            $admin_terms = array_fill_keys($admin_terms, true);
        }
    } else {
        $admin_terms = array();
    }
    // =========================== Display UI ===============================
    ?>


<div class="wrap agp-width97">
<?php 
    $tx_label = $tx->labels->singular_name;
    $src_label = $scoper->data_sources->member_property($tx->object_source, 'labels', 'singular_name');
    echo '<h2>' . sprintf(__('%s Restrictions', 'scoper'), $tx_label);
    echo '&nbsp;&nbsp;<span style="font-size: 0.6em; font-style: normal">(<a href="#scoper_notes">' . __('see notes', 'scoper') . '</a>)</span></h2>';
    if (scoper_get_option('display_hints')) {
        echo '<div class="rs-hint">';
        if ('category' == $taxonomy && scoper_get_otype_option('use_object_roles', 'post', 'post')) {
            printf(__('Reduce access by requiring some role(s) to be %1$s%2$s-assigned%3$s (or %4$s-assigned). Corresponding General Roles (whether assigned by WordPress or Role Scoper) are ignored.', 'scoper'), "<a href='admin.php?page=rs-{$taxonomy}-roles_t'>", $tx_label, '</a>', $src_label);
        } else {
            printf(__('Reduce access by requiring some role(s) to be %1$s%2$s-assigned%3$s. Corresponding General Role assignments are ignored.', 'scoper'), "<a href='admin.php?page=rs-{$taxonomy}-roles_t'>", $tx_label, '</a>');
        }
        echo '</div>';
    }
    if (!($role_defs_by_otype = $scoper->role_defs->get_for_taxonomy($tx->object_source, $taxonomy))) {
        echo '<br />' . sprintf(__('Role definition error (taxonomy: %s).', 'scoper'), $taxonomy);
        echo '</div>';
        return;
    }
    if (empty($admin_terms)) {
        echo '<br />' . sprintf(__('Either you do not have permission to administer any %s, or none exist.', 'scoper'), $tx->labels->name);
        echo '</div>';
        return;
    }
    ?>

<form action="" method="post" name="role_scope" id="role_assign">
<?php 
    wp_nonce_field($nonce_id);
    echo '<br /><div id="rs-term-scroll-links">';
    echo ScoperAdminBulkLib::taxonomy_scroll_links($tx, $all_terms, $admin_terms);
    echo '</div><hr />';
    // ============ Assignment Mode Selection Display ================
    // TODO: is Link Category label handled without workaround now?
    $tx_label = agp_strtolower($tx->labels->name);
    $tx_label_singular = agp_strtolower($tx->labels->singular_name);
    $parent_col = $tx_src->cols->parent;
    if (!$parent_col || !empty($tx->uses_standard_schema) && empty($tx->hierarchical)) {
        $assignment_modes = array(ASSIGN_FOR_ENTITY_RS => sprintf(__('for selected %s', 'scoper'), $tx_label));
    } else {
        $assignment_modes = array(ASSIGN_FOR_ENTITY_RS => sprintf(__('for selected %s', 'scoper'), $tx_label), ASSIGN_FOR_CHILDREN_RS => sprintf(__('for sub-%s of selected', 'scoper'), $tx_label), ASSIGN_FOR_BOTH_RS => sprintf(__('for selected and sub-%s', 'scoper'), $tx_label));
    }
    $max_scopes = array('term' => __('Restrict selected roles', 'scoper'), 'blog' => __('Unrestrict selected roles', 'scoper'));
    $args = array('max_scopes' => $max_scopes, 'scope' => TERM_SCOPE_RS);
    ScoperAdminBulk::display_inputs(ROLE_RESTRICTION_RS, $assignment_modes, $args);
    ScoperAdminBulk::item_tree_jslinks(ROLE_RESTRICTION_RS);
    // IE (6 at least) won't obey link color directive in a.classname CSS
    $ie_link_style = strpos($_SERVER['HTTP_USER_AGENT'], 'MSIE') !== false ? ' style="color:white;"' : '';
    $args = array('include_child_restrictions' => true, 'return_array' => true, 'role_type' => 'rs', 'force_refresh' => true);
    $strict_terms = $scoper->get_restrictions(TERM_SCOPE_RS, $taxonomy, $args);
    //strict_terms[taxonomy][role name][term_id] = array: terms which require Role Scoper assignment for specified role (user blog roles ignored, required caps may be supplied by scoper term role or object-specific assignment)
    // (for other terms, Role Scoper role assignment is optional (term role assignments will supplement blog caps)
    $editable_roles = array();
    foreach ($all_terms as $term) {
        $id = $term->{$col_id};
        foreach ($role_defs_by_otype as $object_type => $role_defs) {
            foreach (array_keys($role_defs) as $role_handle) {
                if ($role_assigner->user_has_role_in_term($role_handle, $taxonomy, $id, '', array('src_name' => $tx->object_source, 'object_type' => $object_type))) {
                    $editable_roles[$id][$role_handle] = true;
                }
            }
        }
    }
    $default_restrictions = $scoper->get_default_restrictions(TERM_SCOPE_RS);
    $default_strict_roles = !empty($default_restrictions[$taxonomy]) ? array_flip(array_keys($default_restrictions[$taxonomy])) : array();
    $table_captions = ScoperAdminUI::restriction_captions(TERM_SCOPE_RS, $tx, $tx_label_singular, $tx_label);
    $args = array('admin_items' => $admin_terms, 'editable_roles' => $editable_roles, 'default_strict_roles' => $default_strict_roles, 'ul_class' => 'rs-termlist', 'ie_link_style' => $ie_link_style, 'err' => $err, 'table_captions' => $table_captions);
    ScoperAdminBulk::item_tree(TERM_SCOPE_RS, ROLE_RESTRICTION_RS, $tx_src, $tx, $all_terms, '', $strict_terms, $role_defs_by_otype, $role_codes, $args);
    echo '<a href="#scoper_top">' . __('top', 'scoper') . '</a>';
    echo '<hr />';
    echo '<h4 style="margin-bottom:0.1em"><a name="scoper_notes"></a>' . __("Notes", 'scoper') . ':</h4><ul class="rs-notes">';
    $osrc = $scoper->data_sources->get($tx->object_source);
    if (empty($osrc->no_object_roles)) {
        echo '<li>';
        printf(__('Any %1$s Restriction causes the specified role to be granted only via %1$s Role assignment, regardless of these %2$s settings.', 'scoper'), $osrc->labels->singular_name, $tx->labels->singular_name);
        echo '</li></ul>';
    }
    ?>

</form>
</div>
<?php 
}
 function _flt_last_resort_query($query)
 {
     global $wpdb, $pagenow, $scoper;
     $posts = $wpdb->posts;
     $comments = $wpdb->comments;
     $links = $wpdb->links;
     $term_taxonomy = $wpdb->term_taxonomy;
     // WP 3.0:  SELECT * FROM wp_comments c LEFT JOIN wp_posts p ON c.comment_post_ID = p.ID WHERE p.post_status != 'trash' AND ( c.comment_approved = '0' OR c.comment_approved = '1' ) ORDER BY c.comment_date_gmt
     //
     if (strpos($query, "ELECT ") && preg_match("/FROM\\s*{$GLOBALS['wpdb']->comments}/", $query) && (!strpos($query, "ELECT COUNT") || empty($_POST)) && !strpos($_SERVER['SCRIPT_FILENAME'], 'p-admin/upload.php')) {
         //define( 'SCOPER_NO_COMMENT_FILTERING', true );
         if (defined('SCOPER_NO_COMMENT_FILTERING') && empty($GLOBALS['current_user']->allcaps['moderate_comments'])) {
             return $query;
         }
         // cache the filtered results for pending comment count query, which (as of WP 3.0.1) is executed once per-post in the edit listing
         $post_id = 0;
         if ($doing_pending_comment_count = strpos($query, 'COUNT(comment_ID)') && strpos($query, 'comment_post_ID') && strpos($query, "comment_approved = '0'")) {
             if ('index.php' != $pagenow) {
                 // there's too much happening on the dashboard (and too much low-level query filtering) to buffer listed IDs reliably.
                 if (preg_match("/comment_post_ID IN \\( '([0-9]+)' \\)/", $query, $matches)) {
                     if ($matches[1]) {
                         $post_id = $matches[1];
                     }
                 }
             }
             if ($post_id) {
                 static $cache_pending_comment_count;
                 if (!isset($cache_pending_comment_count)) {
                     $cache_pending_comment_count = array();
                 } elseif (isset($cache_pending_comment_count[$post_id])) {
                     return "SELECT {$post_id} AS comment_post_ID, {$cache_pending_comment_count[$post_id]} AS num_comments";
                 }
             }
         }
         $comment_alias = strpos($query, "{$comments} c") || strpos($query, "{$comments} AS c") ? 'c' : $comments;
         // apply DISTINCT clause so JOINs don't cause redundant comment count
         $query = str_replace("SELECT *", "SELECT DISTINCT {$comment_alias}.*", $query);
         $query = str_replace("SELECT SQL_CALC_FOUND_ROWS *", "SELECT SQL_CALC_FOUND_ROWS DISTINCT {$comment_alias}.*", $query);
         if (!strpos($query, ' DISTINCT ')) {
             $query = str_replace("SELECT ", "SELECT DISTINCT ", $query);
         }
         //$query = str_replace( "COUNT(*)", " COUNT(DISTINCT $comments.comment_ID)", $query);				// TODO: confirm preg_replace works and str_replace is not needed
         //$query = str_replace( "COUNT(comment_ID)", " COUNT(DISTINCT $comments.comment_ID)", $query);
         $query = preg_replace("/COUNT(\\s*\\*\\s*)/", " COUNT(DISTINCT {$comments}.comment_ID)", $query);
         $query = preg_replace("/COUNT(\\s*comment_ID\\s*)/", " COUNT(DISTINCT {$comments}.comment_ID)", $query);
         $query = str_replace(" user_id ", " {$comment_alias}.user_id ", $query);
         if (!strpos($query, "JOIN {$posts}")) {
             if (strpos($query, "{$comments} c")) {
                 $query = preg_replace("/FROM\\s*{$comments} c\\s*WHERE /", "FROM {$comments} c INNER JOIN {$posts} ON {$posts}.ID = {$comment_alias}.comment_post_ID WHERE ", $query);
             } else {
                 $query = preg_replace("/FROM\\s*{$comments}\\s*WHERE /", "FROM {$comments} INNER JOIN {$posts} ON {$posts}.ID = {$comment_alias}.comment_post_ID WHERE ", $query);
             }
             if (strpos($query, "GROUP BY")) {
                 $query = preg_replace("/FROM\\s*{$comments}\\s*GROUP BY /", "FROM {$comments} INNER JOIN {$posts} ON {$posts}.ID = {$comment_alias}.comment_post_ID GROUP BY ", $query);
             }
         }
         $generic_uri = in_array($pagenow, array('index.php', 'comments.php'));
         if (!$generic_uri && ($_post_type = cr_find_post_type('', false))) {
             // arg: don't return 'post' as default if detection fails
             $post_types = array($_post_type => get_post_type_object($_post_type));
         } else {
             $post_types = array_diff_key(get_post_types(array('public' => true), 'object'), array('attachment' => true));
         }
         $post_statuses = get_post_stati(array('internal' => null), 'object');
         $reqd_caps = array();
         $use_post_types = scoper_get_option('use_post_types');
         foreach ($post_types as $_post_type => $type_obj) {
             if (empty($use_post_types[$_post_type])) {
                 continue;
             }
             foreach ($post_statuses as $status => $status_obj) {
                 $reqd_caps[$_post_type][$status] = array($type_obj->cap->edit_others_posts, 'moderate_comments');
                 if ($status_obj->private) {
                     $reqd_caps[$_post_type][$status][] = $type_obj->cap->edit_private_posts;
                 }
                 $status_name = 'publish' == $status || 'future' == $status ? 'published' : $status;
                 $property = "edit_{$status_name}_posts";
                 if (!empty($type_obj->cap->{$property}) && !in_array($type_obj->cap->{$property}, $reqd_caps[$_post_type][$status])) {
                     $reqd_caps[$_post_type][$status][] = $type_obj->cap->{$property};
                 }
             }
         }
         $args = array('force_reqd_caps' => $reqd_caps);
         if (strpos($query, "{$posts} p") || strpos($query, "{$posts} AS p")) {
             $args['source_alias'] = 'p';
         }
         $object_type = 'edit.php' == $pagenow ? cr_find_post_type() : '';
         $query = apply_filters('objects_request_rs', $query, 'post', $object_type, $args);
         // pre-execute the comments listing query and buffer the listed IDs for more efficient user_has_cap calls
         if (strpos($query, "* FROM {$comments}") && empty($scoper->listed_ids['post'])) {
             if ($results = scoper_get_results($query)) {
                 $scoper->listed_ids['post'] = array();
                 foreach ($results as $row) {
                     if (!empty($row->comment_post_ID)) {
                         $scoper->listed_ids['post'][$row->comment_post_ID] = true;
                     }
                 }
             }
         } elseif ($doing_pending_comment_count && $post_id) {
             if (isset($scoper->listed_ids['post'])) {
                 $listed_ids = array_keys($scoper->listed_ids['post']);
             } elseif (!empty($GLOBALS['wp_object_cache']->cache['posts']) && is_array($GLOBALS['wp_object_cache']->cache['posts'])) {
                 $listed_ids = array_keys($GLOBALS['wp_object_cache']->cache['posts']);
             } else {
                 $listed_ids = array();
             }
             // make sure our current post_id is in the list
             $listed_ids[] = $post_id;
             if (count($listed_ids) > 1) {
                 // cache the pending comment count for all listed posts
                 $query = str_replace("comment_post_ID IN ( '{$post_id}' )", "comment_post_ID IN ( '" . implode("','", $listed_ids) . "' )", $query);
                 $results = scoper_get_results($query);
                 $cache_pending_comment_count = array_fill_keys($listed_ids, 0);
                 foreach ($results as $row) {
                     $cache_pending_comment_count[$row->comment_post_ID] = $row->comment_count;
                 }
             }
         }
         //d_echo( "<br />replaced: $query<br />" );
         //rs_errlog ("<br /><br />replaced with $query<br /><br />");
     }
     // endif matched query substring
     // num cats: "SELECT COUNT(*) FROM wp_term_taxonomy"
     // SELECT DISTINCT COUNT(tt.term_id) FROM wp_term_taxonomy AS tt WHERE 1=1 AND tt.taxonomy = 'category'
     // SELECT DISTINCT tt.term_id FROM wp_term_taxonomy AS tt WHERE
     if (!in_array($pagenow, array('post.php', 'post-new.php')) && !defined('XMLRPC_REQUEST')) {
         if (strpos($query, " FROM {$term_taxonomy}") || strpos($query, " FROM {$wpdb->terms}")) {
             //rs_errlog ("<br />caught $query <br />");
             // don't mess with parent category selection/availability for single term edit
             $is_term_admin = in_array($pagenow, array('edit-tags.php', 'edit-link-categories.php'));
             if ($is_term_admin) {
                 if (!empty($_REQUEST['tag_ID'])) {
                     return $query;
                 }
             }
             $matches = array();
             if ($return = preg_match("/taxonomy IN \\('(.*)'/", $query, $matches)) {
                 $taxonomy = explode("','", str_replace(' ', '', $matches[1]));
             } elseif ($return = preg_match("/taxonomy\\s*=\\s*'(.*)'/", $query, $matches)) {
                 $taxonomy = $matches[1];
             }
             if (!empty($taxonomy)) {
                 if ('profile.php' == $pagenow) {
                     return $query;
                 } else {
                     $query = apply_filters('terms_request_rs', $query, $taxonomy, array('is_term_admin' => $is_term_admin));
                 }
             }
             //rs_errlog ("<br /><br /> returning $query <br />");
             return $query;
         }
     }
     // get_users_drafts() and get_others_unpublished_posts()
     //
     // Recent posts: SELECT ID, post_title FROM wp_posts WHERE post_type = 'post' AND (post_status = 'publish' OR post_status = 'private') AND post_date_gmt < '2008-04-30 05:04:04' ORDER BY post_date DESC LIMIT 5
     // Scheduled entries: SELECT ID, post_title, post_date_gmt FROM wp_posts WHERE post_type = 'post' AND post_status = 'future' ORDER BY post_date ASC"
     if (strpos($query, "post_date_gmt <") && strpos($query, "ELECT ID, post_title") && strpos($query, " FROM {$posts} WHERE ") || strpos($query, "ELECT ID, post_title, post_date_gmt") && strpos($query, " FROM {$posts} WHERE ")) {
         if ($_post_type = cr_find_post_type()) {
             $query = apply_filters('objects_request_rs', $query, 'post', $_post_type, '');
         }
     }
     // links
     //SELECT * , IF (DATE_ADD(link_updated, INTERVAL 120 MINUTE) >= NOW(), 1,0) as recently_updated FROM wp_links WHERE 1=1 ORDER BY link_name ASC
     if ((strpos($query, "FROM {$links} WHERE") || strpos($query, "FROM {$links}  WHERE")) && strpos($query, "ELECT ")) {
         $query = apply_filters('objects_request_rs', $query, 'link', 'link');
         return $query;
     }
     return $query;
 }