function dropdown_pages($object_id = '', $stored_parent_id = '') { global $scoper, $wpdb; // buffer titles in case they are filtered on get_pages hook $titles = ScoperAdminBulkParent::get_page_titles(); if (!is_numeric($object_id)) { global $post_ID; if (empty($post_ID)) { $object_id = $scoper->data_sources->detect('id', 'post', 0, 'post'); } else { $object_id = $post_ID; } } if ($object_id && !is_numeric($stored_parent_id)) { $stored_parent_id = $scoper->data_sources->detect('parent', 'post', $object_id); } // make sure the currently stored parent page remains in dropdown regardless of current user roles if ($stored_parent_id) { $preserve_or_clause = " {$wpdb->posts}.ID = '{$stored_parent_id}' "; $args['preserve_or_clause'] = array(); foreach (array_keys($scoper->data_sources->member_property('post', 'statuses')) as $status_name) { $args['preserve_or_clause'][$status_name] = $preserve_or_clause; } } // alternate_caps is a 2D array because objects_request / objects_where filter supports multiple alternate sets of qualifying caps $args['force_reqd_caps']['page'] = array(); foreach (array_keys($scoper->data_sources->member_property('post', 'statuses')) as $status_name) { $args['force_reqd_caps']['page'][$status_name] = array('edit_others_pages'); } $args['alternate_reqd_caps'][0] = array('create_child_pages'); $all_pages_by_id = array(); if ($results = scoper_get_results("SELECT ID, post_parent, post_title FROM {$wpdb->posts} WHERE post_type = 'page'")) { foreach ($results as $row) { $all_pages_by_id[$row->ID] = $row; } } $object_type = awp_post_type_from_uri(); // Editable / associable draft and pending pages will be included in Page Parent dropdown in Edit Forms, but not elsewhere if (is_admin() && 'page' != $object_type) { $status_clause = "AND {$wpdb->posts}.post_status IN ('publish', 'private')"; } else { $status_clause = "AND {$wpdb->posts}.post_status IN ('publish', 'private', 'pending', 'draft')"; } $qry_parents = "SELECT ID, post_parent, post_title FROM {$wpdb->posts} WHERE post_type = 'page' {$status_clause} ORDER BY menu_order"; $qry_parents = apply_filters('objects_request_rs', $qry_parents, 'post', 'page', $args); $filtered_pages_by_id = array(); if ($results = scoper_get_results($qry_parents)) { foreach ($results as $row) { $filtered_pages_by_id[$row->ID] = $row; } } $hidden_pages_by_id = array_diff_key($all_pages_by_id, $filtered_pages_by_id); // temporarily add in the hidden parents so we can order the visible pages by hierarchy $pages = ScoperAdminBulkParent::add_missing_parents($filtered_pages_by_id, $hidden_pages_by_id, 'post_parent'); // convert keys from post ID to title+ID so we can alpha sort them $args['pages'] = array(); foreach (array_keys($pages) as $id) { $args['pages'][$pages[$id]->post_title . chr(11) . $id] = $pages[$id]; } // natural case alpha sort uksort($args['pages'], "strnatcasecmp"); $args['pages'] = ScoperAdminBulkParent::order_by_hierarchy($args['pages'], 'ID', 'post_parent'); // take the hidden parents back out foreach ($args['pages'] as $key => $page) { if (isset($hidden_pages_by_id[$page->ID])) { unset($args['pages'][$key]); } } $output = ''; // restore buffered titles in case they were filtered on get_pages hook scoper_restore_property_array($args['pages'], $titles, 'ID', 'post_title'); if ($object_id) { $args['object_id'] = $object_id; $args['retain_page_ids'] = true; // retain static log to avoid redundant entries by subsequent call with use_parent_clause=false ScoperHardwayParentLegacy::walk_parent_dropdown($output, $args, true, $stored_parent_id); } // next we'll add disjointed branches, but don't allow this page's descendants to be offered as a parent $arr_parent = array(); $arr_children = array(); if ($results = scoper_get_results("SELECT ID, post_parent FROM {$wpdb->posts} WHERE post_type = 'page' {$status_clause}")) { foreach ($results as $row) { $arr_parent[$row->ID] = $row->post_parent; if (!isset($arr_children[$row->post_parent])) { $arr_children[$row->post_parent] = array(); } $arr_children[$row->post_parent][] = $row->ID; } $descendants = array(); if (!empty($arr_children[$object_id])) { foreach ($arr_parent as $page_id => $parent_id) { if (!$parent_id || $page_id == $object_id) { continue; } do { if ($object_id == $parent_id) { $descendants[$page_id] = true; break; } $parent_id = $arr_parent[$parent_id]; } while ($parent_id); } } $args['descendants'] = $descendants; } ScoperHardwayParentLegacy::walk_parent_dropdown($output, $args, false, $stored_parent_id); //log_mem_usage_rs( 'end dropdown_pages()' ); return $output; }
function get_terms($taxonomy, $filtering = true, $cols = COLS_ALL_RS, $object_id = 0, $args = array()) { if (!($tx = $this->taxonomies->get($taxonomy))) { return array(); } global $wpdb; $defaults = array('order_by' => '', 'use_object_roles' => false, 'operation' => ''); // IMPORTANT to default operation to nullstring $args = array_merge($defaults, (array) $args); extract($args); if (is_administrator_rs($this->taxonomies->member_property($taxonomy, 'object_source'))) { $filtering = false; } // try to pull it out of wpcache $ckey = md5($taxonomy . $cols . $object_id . serialize($args) . $order_by); if ($filtering) { $src_name = $this->taxonomies->member_property($taxonomy, 'object_source', 'name'); $args['reqd_caps_by_otype'] = $this->get_terms_reqd_caps($taxonomy, $operation, ADMIN_TERMS_FILTER_RS === $filtering); $ckey = md5($ckey . serialize($args['reqd_caps_by_otype'])); // can vary based on request URI global $current_rs_user; $cache_flag = 'rs_scoper_get_terms'; $cache = $current_rs_user->cache_get($cache_flag); } else { $cache_flag = "all_terms"; $cache_id = 'all'; $cache = wpp_cache_get($cache_id, $cache_flag); } if (isset($cache[$ckey])) { return $cache[$ckey]; } // call base class method to build query $terms_only = !$filtering || empty($use_object_roles); $query_base = $this->taxonomies->get_terms_query($taxonomy, $cols, $object_id, $terms_only); if (!$query_base) { return array(); } $query = $filtering ? apply_filters('terms_request_rs', $query_base, $taxonomy, $args) : $query_base; // avoid sending alarms to SQL purists if this query was not modified by RS filter if ($query_base == $query) { $query = str_replace('WHERE 1=1 AND', 'WHERE', $query); } if (COL_ID_RS == $cols) { $results = scoper_get_col($query); } elseif (COL_COUNT_RS == $cols) { $results = intval(scoper_get_var($query)); } else { // TODO: why is this still causing an extra (and costly) scoped query? /* // for COLS_ALL query, need to call core get_terms call in case another plugin is translating term names if ( has_filter( 'get_terms', array('ScoperHardwayTaxonomy', 'flt_get_terms') ) ) { remove_filter( 'get_terms', array('ScoperHardwayTaxonomy', 'flt_get_terms'), 1, 3 ); $all_terms = get_terms($taxonomy); add_filter( 'get_terms', array('ScoperHardwayTaxonomy', 'flt_get_terms'), 1, 3 ); $term_names = scoper_get_property_array( $all_terms, 'term_id', 'name' ); } */ $results = scoper_get_results($query); //scoper_restore_property_array( $results, $term_names, 'term_id', 'name' ); if (ORDERBY_HIERARCHY_RS == $order_by) { require_once dirname(__FILE__) . '/admin/admin_lib_rs.php'; if ($src = $this->data_sources->get($tx->source)) { if (!empty($src->cols->id) && !empty($src->cols->parent)) { require_once dirname(__FILE__) . '/admin/admin_lib-bulk-parent_rs.php'; $results = ScoperAdminBulkParent::order_by_hierarchy($results, $src->cols->id, $src->cols->parent); } } } } $cache[$ckey] = $results; if ($results || empty($_POST)) { // todo: why do we get an empty array for unfiltered request for object terms early in POST processing? (on submission of a new post by a contributor) if ($filtering) { $current_rs_user->cache_force_set($cache, $cache_flag); } else { wpp_cache_force_set($cache_id, $cache, $cache_flag); } } return $results; }
function get_objects_info($object_ids, &$object_names, &$object_status, &$unlisted_objects, $src, $otype, $ignore_hierarchy) { global $wpdb; // buffer titles in case they are translated if ('page' == $otype->name) { // todo: other hierarchical types? $titles = ScoperAdminBulkParent::get_page_titles(); } $col_id = $src->cols->id; $col_name = $src->cols->name; $cols = "{$col_name}, {$col_id}"; if (isset($src->cols->parent) && !$ignore_hierarchy) { $col_parent = $src->cols->parent; $cols .= ", {$col_parent}"; } else { $col_parent = ''; } $col_status = !empty($src->cols->status) ? $src->cols->status : ''; if ($col_status) { $cols .= ", {$col_status}"; } $unroled_count = 0; $unroled_limit = !empty($otype->admin_max_unroled_objects) ? $otype->admin_max_unroled_objects : 999999; if (!empty($src->cols->type)) { $otype_clause = "AND {$src->cols->type} = '{$otype->name}'"; if ('post' == $src->name) { $otype_clause .= "AND {$src->cols->status} != 'auto-draft'"; } } else { $otype_clause = ''; } $obj = ''; if ($results = scoper_get_results("SELECT {$cols} FROM {$src->table} WHERE 1=1 {$otype_clause} ORDER BY {$col_id} DESC")) { foreach ($results as $row) { if (isset($titles[$row->{$col_id}])) { $object_names[$row->{$col_id}] = $titles[$row->{$col_id}]; } elseif ('post' == $src->name) { $object_names[$row->{$col_id}] = apply_filters('the_title', $row->{$col_name}, $row->{$col_id}); } else { $object_names[$row->{$col_id}] = $row->{$col_name}; } if ($col_status) { $object_status[$row->{$col_id}] = $row->{$col_status}; } unset($obj); if ($col_parent) { // temporarily key by name for alpha sort of additional items prior to hierarchy sort $obj = (object) array($col_id => $row->{$col_id}, $col_name => $row->{$col_name}, $col_parent => $row->{$col_parent}); } else { $obj = (object) array($col_id => $row->{$col_id}, $col_name => $row->{$col_name}); } // List only a limited number of unroled objects if ($unroled_limit >= 0 && !isset($object_ids[$row->{$col_id}])) { if ($unroled_count >= $unroled_limit) { $unlisted_objects[$row->{$col_id}] = $obj; continue; } $unroled_count++; } $listed_objects[$row->{$col_id}] = $obj; } } // restore buffered page titles in case they were filtered previously if ('page' == $otype->name) { scoper_restore_property_array($listed_objects, $titles, 'ID', 'post_title'); scoper_restore_property_array($unlisted_objects, $titles, 'ID', 'post_title'); } return $listed_objects; }
function scoper_admin_object_restrictions($src_name, $object_type) { global $scoper, $scoper_admin; if (!($src = $scoper->data_sources->get($src_name)) || !empty($src->no_object_roles) || !empty($src->taxonomy_only) || $src_name == 'group') { wp_die(__('Invalid data source', 'scoper')); } $is_administrator = is_administrator_rs($src, 'user'); $role_bases = array(); if (USER_ROLES_RS && ($is_administrator || $scoper_admin->user_can_admin_object($src_name, $object_type, 0, true))) { $role_bases[] = ROLE_BASIS_USER; } if (GROUP_ROLES_RS && ($is_administrator || $scoper_admin->user_can_admin_object($src_name, $object_type, 0, true) || current_user_can('manage_groups'))) { $role_bases[] = ROLE_BASIS_GROUPS; } if (empty($role_bases)) { wp_die(__awp('Cheatin’ uh?')); } $otype = $scoper->data_sources->member_property($src_name, 'object_types', $object_type); require_once dirname(__FILE__) . '/admin-bulk_rs.php'; require_once dirname(__FILE__) . '/admin_lib-bulk-parent_rs.php'; $role_assigner = init_role_assigner(); $nonce_id = 'scoper-assign-roles'; $role_codes = ScoperAdminBulk::get_role_codes(); echo '<a name="scoper_top"></a>'; // ==== Process Submission ===== $err = 0; if (isset($_POST['rs_submit'])) { $err = ScoperAdminBulk::role_submission(OBJECT_SCOPE_RS, ROLE_RESTRICTION_RS, '', $src_name, $role_codes, '', $nonce_id); if (scoper_get_option('file_filtering')) { scoper_flush_file_rules(); } } ?> <div class="wrap agp-width97"> <?php $src_otype = isset($src->object_types) ? "{$src_name}:{$object_type}" : $src_name; $item_label_singular = $scoper_admin->interpret_src_otype($src_otype, 'singular_name'); $item_label = $scoper_admin->interpret_src_otype($src_otype); echo '<h2>' . sprintf(__('%s Restrictions', 'scoper'), $item_label_singular) . ' <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">'; $link_open = "<a href='admin.php?page=rs-{$object_type}-roles'>"; $uses_taxonomies = scoper_get_taxonomy_usage($src_name, $object_type); if ($uses_taxonomies && 1 == count($uses_taxonomies)) { $tx_display = $scoper->taxonomies->member_property(reset($uses_taxonomies), 'display_name'); printf(__('Reduce access to a specific %1$s by requiring some role(s) to be %2$s%3$s-assigned%4$s. Corresponding WP-assigned Roles and RS-assigned General and %5$s Role assignments are ignored.', 'scoper'), $item_label_singular, $link_open, $item_label_singular, '</a>', $tx_display); } elseif (count($uses_taxonomies)) { printf(__('Reduce access to a specific %1$s by requiring some role(s) to be %2$s%3$s-assigned%4$s. Corresponding WP-assigned Roles and RS-assigned General and Term Role assignments are ignored.', 'scoper'), $item_label_singular, $link_open, $item_label_singular, '</a>'); } else { printf(__('Reduce access to a specific %1$s by requiring some role(s) to be %2$s%3$s-assigned%4$s. Corresponding WP-assigned Roles and RS-assigned General Role assignments are ignored.', 'scoper'), $item_label_singular, $link_open, $item_label_singular, '</a>'); } echo '</div>'; } $ignore_hierarchy = !empty($otype->ignore_object_hierarchy); ?> <form action="" method="post" name="role_assign" id="role_assign"> <?php wp_nonce_field($nonce_id); // ============ Users / Groups and Assignment Mode Selection Display ================ if (empty($src->cols->parent) || $ignore_hierarchy) { $assignment_modes = array(ASSIGN_FOR_ENTITY_RS => sprintf(__('for selected %s', 'scoper'), $item_label)); } else { $assignment_modes = array(ASSIGN_FOR_ENTITY_RS => sprintf(__('for selected %s', 'scoper'), $item_label), ASSIGN_FOR_CHILDREN_RS => sprintf(__('for sub-%s of selected', 'scoper'), $item_label), ASSIGN_FOR_BOTH_RS => sprintf(__('for selected and sub-%s', 'scoper'), $item_label)); } $max_scopes = array('object' => __('Restrict selected roles', 'scoper'), 'blog' => __('Unrestrict selected roles', 'scoper')); $args = array('max_scopes' => $max_scopes, 'scope' => OBJECT_SCOPE_RS); ScoperAdminBulk::display_inputs(ROLE_RESTRICTION_RS, $assignment_modes, $args); echo '<br />'; $args = array('default_hide_empty' => !empty($otype->admin_default_hide_empty), 'hide_roles' => true, 'scope' => OBJECT_SCOPE_RS, 'src' => $src, 'otype' => $otype); ScoperAdminBulk::item_tree_jslinks(ROLE_RESTRICTION_RS, $args); // buffer prev/next caption for display with each obj type //$prevtext = _ x('prev', 'abbreviated link to previous item', 'scoper'); //$nexttext = _ x('next', 'abbreviated link to next item', 'scoper'); $prevtext = __('prev', 'scoper'); $nexttext = __('next', 'scoper'); $site_url = get_option('siteurl'); $args = array('include_child_restrictions' => true, 'return_array' => true, 'role_type' => 'rs', 'force_refresh' => true); $strict_objects = $scoper->get_restrictions(OBJECT_SCOPE_RS, $src_name, $args); $object_names = array(); $object_status = array(); $listed_objects = array(); $unlisted_objects = array(); $col_id = $src->cols->id; $col_parent = isset($src->cols->parent) && !$ignore_hierarchy ? $src->cols->parent : ''; $object_ids = array(); if (isset($strict_objects['restrictions'])) { foreach (array_keys($strict_objects['restrictions']) as $role_handle) { $object_ids = $object_ids + array_keys($strict_objects['restrictions'][$role_handle]); } } elseif (isset($strict_objects['unrestrictions'])) { foreach (array_keys($strict_objects['unrestrictions']) as $role_handle) { $object_ids = $object_ids + array_keys($strict_objects['unrestrictions'][$role_handle]); } } $object_ids = array_flip(array_unique($object_ids)); // Get the obj name, parent associated with each role (also sets $object_names, $unlisted objects) $listed_objects = ScoperAdminBulkParent::get_objects_info($object_ids, $object_names, $object_status, $unlisted_objects, $src, $otype, $ignore_hierarchy); if ($col_parent) { if ($listed_objects) { if ($unlisted_objects) { // query for any parent objects which don't have their own role assignments $listed_objects = ScoperAdminBulkParent::add_missing_parents($listed_objects, $unlisted_objects, $col_parent); } // convert keys from object ID to title+ID so we can alpha sort them $listed_objects_alpha = array(); foreach (array_keys($listed_objects) as $id) { $listed_objects_alpha[$listed_objects[$id]->{$src->cols->name} . chr(11) . $id] = $listed_objects[$id]; } uksort($listed_objects_alpha, "strnatcasecmp"); $listed_objects = ScoperAdminBulkParent::order_by_hierarchy($listed_objects_alpha, $col_id, $col_parent); } // endif any listed objects } else { // endif doing object hierarchy if ($listed_objects) { // convert keys from object ID to title+ID so we can alpha sort them $listed_objects_alpha = array(); foreach (array_keys($listed_objects) as $id) { $listed_objects_alpha[$listed_objects[$id]->{$src->cols->name} . chr(11) . $id] = $listed_objects[$id]; } uksort($listed_objects_alpha, "strnatcasecmp"); // convert to ordinal integer index $listed_objects = array_combine(array_keys(array_fill(0, count($listed_objects_alpha), true)), $listed_objects_alpha); } } if (!$is_administrator) { $cu_admin_results = ScoperAdminBulk::filter_objects_listing(ROLE_RESTRICTION_RS, $strict_objects, $src, $object_type); } else { $cu_admin_results = ''; } // no need to filter admins // membuffer ids so user_can_admin_role() doesn't trigger a separate has_cap query for each one if ($cu_admin_results) { $scoper->listed_ids[$src_name] = $cu_admin_results; } global $scoper_admin; $role_display = array(); $editable_roles = array(); $role_defs_by_otype = array(); $role_defs_by_otype[$object_type] = $scoper->role_defs->get_matching('rs', $src_name, $object_type); foreach (array_keys($role_defs_by_otype[$object_type]) as $role_handle) { $role_display[$role_handle] = $scoper->role_defs->get_abbrev($role_handle, OBJECT_UI_RS); if ($cu_admin_results && !is_user_administrator_rs()) { foreach (array_keys($cu_admin_results) as $object_id) { if ($scoper_admin->user_can_admin_role($role_handle, $object_id, $src_name, $object_type)) { $editable_roles[$object_id][$role_handle] = true; } } } } $table_captions = ScoperAdminUI::restriction_captions(OBJECT_SCOPE_RS, '', $item_label_singular, $item_label); $args = array('admin_items' => $cu_admin_results, 'editable_roles' => $editable_roles, 'default_hide_empty' => !empty($otype->admin_default_hide_empty), 'ul_class' => 'rs-objlist', 'object_names' => $object_names, 'object_status' => $object_status, 'table_captions' => $table_captions, 'ie_link_style' => '', 'err' => $err); ScoperAdminBulk::item_tree(OBJECT_SCOPE_RS, ROLE_RESTRICTION_RS, $src, $otype, $listed_objects, '', $strict_objects, $role_defs_by_otype, $role_codes, $args); //ScoperAdminBulk::item_tree( OBJECT_SCOPE_RS, ROLE_ASSIGNMENT_RS, $src, $otype, $all_objects, $object_roles, $strict_objects, $role_defs_by_otype, $role_codes, $args); echo '<hr /><div style="background-color: white;"></div>'; echo '<div class="rs-objlistkey">'; $args = array('display_links' => true, 'display_restriction_key' => true); ScoperAdminUI::role_owners_key($otype, $args); echo '</div>'; echo '</form><br /><h4 style="margin-bottom:0.1em"><a name="scoper_notes"></a>' . __("Notes", 'scoper') . ':</h4><ul class="rs-notes">'; echo '<li>'; printf(__('To edit all roles for any %1$s, click on the %1$s name.', 'scoper'), $otype->labels->singular_name); echo '</li>'; echo '<li>'; printf(__("To edit the %s via its default editor, click on the ID link.", 'scoper'), $otype->labels->singular_name); echo '</li>'; if (!$is_administrator) { echo '<li>'; printf(__('To enhance performance, the role editing checkboxes here may not include some roles which you can only edit due to your own %1$s-specific role. In such cases, click on the editing link to edit roles for the individual %1$s.', 'scoper'), $otype->labels->singular_name); echo '</li>'; } echo '</ul>'; echo '<a href="#scoper_top">' . __('top', 'scoper') . '</a>'; ?> </div> <?php }