public static function act_save_item($term_id, $tt_id, $taxonomy) { if (!in_array($taxonomy, pp_get_enabled_taxonomies())) { if (!empty($_REQUEST['pp_enable_taxonomy'])) { $enabled_taxonomies = get_option('pp_enabled_taxonomies'); $enabled_taxonomies[$taxonomy] = '1'; update_option('pp_enabled_taxonomies', $enabled_taxonomies); } return; } static $saved_terms; if (!isset($saved_terms)) { $saved_terms = array(); } // so this filter doesn't get called by hook AND internally if (isset($saved_terms[$taxonomy][$tt_id])) { return; } // parent settings can affect the auto-assignment of propagating exceptions $set_parent = is_taxonomy_hierarchical($taxonomy) && !empty($_REQUEST['parent']) ? (int) $_REQUEST['parent'] : 0; if ($set_parent < 0) { $set_parent = 0; } $saved_terms[$taxonomy][$tt_id] = 1; // Determine whether this object is new (first time this PP filter has run for it, though the object may already be inserted into db) $last_parent = 0; if (!($last_parents = get_option("pp_last_{$taxonomy}_parents"))) { $last_parents = array(); } if (!isset($last_parents[$tt_id])) { $is_new = true; $last_parents = array(); } else { $is_new = false; } if (isset($last_parents[$tt_id])) { $last_parent = $last_parents[$tt_id]; } if ($set_parent != $last_parent && ($set_parent || $last_parent)) { $last_parents[$tt_id] = $set_parent; update_option("pp_last_{$taxonomy}_parents", $last_parents); } $exceptions_customized = false; if (!$is_new) { if ($custom_exc_objects = get_option("pp_custom_{$taxonomy}")) { $exceptions_customized = isset($custom_exc_objects[$tt_id]); } } global $typenow; require_once dirname(__FILE__) . '/item-save_pp.php'; $args = compact('is_new', 'set_parent', 'last_parent', 'disallow_manual_entry'); $args['via_item_type'] = $taxonomy; PP_ItemSave::item_update_process_exceptions('term', 'post', $tt_id, $args); do_action('pp_update_item_exceptions', 'term', $tt_id, $args); }
function skip_filtering($taxonomies, $args) { if (!($taxonomies = array_intersect($taxonomies, pp_get_enabled_taxonomies()))) { return true; } if (!empty($args['pp_no_filter']) || $this->no_filter || apply_filters('pp_terms_skip_filtering', false, $taxonomies, $args)) { return true; } if ('id=>parent' == $args['fields']) { // internal storage of {$taxonomy}_children return true; } }
function add_meta_boxes() { // ========= register WP-rendered metaboxes ============ global $typenow; $taxonomy = isset($_REQUEST['taxonomy']) ? pp_sanitize_key($_REQUEST['taxonomy']) : ''; if (!in_array($taxonomy, pp_get_enabled_taxonomies())) { return; } $tt_id = !empty($_REQUEST['tag_ID']) ? pp_termid_to_ttid((int) $_REQUEST['tag_ID'], $taxonomy) : 0; $post_type = !empty($_REQUEST['pp_universal']) ? '' : $typenow; $hidden_types = apply_filters('pp_hidden_post_types', array()); $hidden_taxonomies = apply_filters('pp_hidden_taxonomies', array()); if (!empty($hidden_taxonomies[$taxonomy]) || $post_type && !empty($hidden_types[$post_type])) { return; } //TODO: selectively enable role assignment by non-administrator if (!current_user_can('pp_assign_roles') || apply_filters('pp_disable_exception_ui', false, 'term', $tt_id, $post_type)) { return; } //if ( ! $this->_roles_editable( $src_name, $object_type ) ) // return; $tx = get_taxonomy($taxonomy); $type_obj = get_post_type_object($post_type); $register_type = $post_type ? $post_type : 'post'; $ops = _pp_can_set_exceptions('read', $post_type, array('via_item_source' => 'term', 'via_item_type' => $taxonomy, 'for_item_source' => 'post')) ? array('read' => true) : array(); $operations = apply_filters('pp_item_edit_exception_ops', $ops, 'post', $taxonomy, $post_type); $boxes = array(); foreach (array_keys($operations) as $op) { if ($op_obj = pp_get_op_object($op, $post_type)) { if ('assign' == $op) { $title = $post_type ? sprintf(__('%1$s %2$s %3$s Exceptions', 'pp'), $type_obj->labels->singular_name, $tx->labels->singular_name, $op_obj->noun_label) : sprintf(__('%1$s %2$s Exceptions (all post types)', 'pp'), $tx->labels->singular_name, $op_obj->noun_label); } elseif (in_array($op, array('read', 'edit'))) { $title = $post_type ? sprintf(__('%1$s %2$s Exceptions (all post statuses)', 'pp'), $type_obj->labels->singular_name, $op_obj->noun_label) : sprintf(__('%1$s Exceptions (all post types, statuses)', 'pp'), $op_obj->noun_label); } else { $title = $post_type ? sprintf(__('%1$s %2$s Exceptions', 'pp'), $type_obj->labels->singular_name, $op_obj->noun_label) : sprintf(__('%1$s Exceptions (all post types)', 'pp'), $op_obj->noun_label); } pp_set_array_elem($boxes, array($op, "pp_{$op}_{$post_type}_exceptions")); $boxes[$op]["pp_{$op}_{$post_type}_exceptions"]['for_item_type'] = $post_type; $boxes[$op]["pp_{$op}_{$post_type}_exceptions"]['title'] = $title; } } $boxes = apply_filters('pp_term_exceptions_metaboxes', $boxes, $taxonomy, $post_type); foreach ($boxes as $op => $boxes) { foreach ($boxes as $box_id => $_box) { // $screen = null, $context = 'advanced', $priority = 'default', $callback_args = null add_meta_box($box_id, $_box['title'], array(&$this, 'draw_exceptions_ui'), $register_type, 'normal', 'default', array('for_item_type' => $_box['for_item_type'], 'op' => $op)); } } }
function skip_filtering($taxonomies, $args) { if (!($taxonomies = array_intersect($taxonomies, pp_get_enabled_taxonomies()))) { return true; } if (!empty($args['pp_no_filter']) || $this->no_filter || apply_filters('pp_terms_skip_filtering', false, $taxonomies, $args)) { return true; } if ('id=>parent' == $args['fields']) { // internal storage of {$taxonomy}_children return true; } // Kriesi Enfold theme conflict on "More Posts" query if (defined('DOING_AJAX') && DOING_AJAX && in_array($_REQUEST['action'], apply_filters('pp_unfiltered_ajax_termcount', array('avia_ajax_masonry_more')))) { return true; } }
public static function display_ui_user_roles($user) { $roles = array(); $post_types = pp_get_enabled_post_types(array(), 'object'); $taxonomies = pp_get_enabled_taxonomies(array(), 'object'); $is_administrator = pp_bulk_roles_enabled() && current_user_can('pp_manage_groups'); $edit_url = $is_administrator ? "admin.php?page=pp-edit-permissions&action=edit&agent_id={$user->ID}&agent_type=user" : ''; $user->retrieve_extra_groups(); foreach (array_keys($user->groups) as $agent_type) { foreach (array_keys($user->groups[$agent_type]) as $agent_id) { $roles = array_merge($roles, ppc_get_roles($agent_type, $agent_id, array('post_types' => $post_types, 'taxonomies' => $taxonomies, 'query_agent_ids' => array_keys($user->groups[$agent_type])))); } } $link = current_user_can('pp_assign_roles') ? "admin.php?page=pp-edit-permissions&action=edit&agent_type=user&agent_id={$user->ID}" : ''; PP_GroupsUI::_current_roles_ui($roles, array('read_only' => true, 'link' => '', 'caption' => sprintf(__('Supplemental Roles %1$s(from primary role or group membership)%2$s', 'pp'), '<small>', '</small>'))); self::abbreviated_exceptions_ui('user', $user->ID, array('edit_url' => '', 'class' => 'pp-group-roles', 'caption' => __('Exceptions (from primary role or group membership)', 'pp'), 'join_groups' => 'groups_only', 'display_limit' => 12)); }
</form> <?php if (current_user_can('pp_assign_roles') && pp_bulk_roles_enabled()) { PP_GroupsUI::_draw_group_permissions($agent_id, $agent_type, $url, $wp_http_referer, compact('agent')); } if ('user' == $agent_type) { ?> <div> <?php if ($agent_id) { $roles = array(); $user = pp_get_user($agent_id); $user->retrieve_extra_groups(); $post_types = pp_get_enabled_post_types(array(), 'object'); $taxonomies = pp_get_enabled_taxonomies(array(), 'object'); foreach (array_keys($user->groups) as $agent_type) { foreach (array_keys($user->groups[$agent_type]) as $_agent_id) { $args = compact($post_types, $taxonomies); $args['query_agent_ids'] = array_keys($user->groups[$agent_type]); $roles = array_merge($roles, ppc_get_roles($agent_type, $_agent_id, $args)); } } require_once dirname(__FILE__) . '/profile_ui_pp.php'; PP_ProfileUI::display_ui_user_groups(false, array('initial_hide' => true, 'selected_only' => true, 'force_display' => true, 'edit_membership_link' => true, 'hide_checkboxes' => true, 'user_id' => $agent_id)); $role_group_caption = sprintf(__('Supplemental Roles %1$s(from primary role or %2$sgroup membership%3$s)%4$s', 'pp'), '<small>', "<a class='pp-show-groups' href='#'>", '</a>', '</small>'); PP_GroupsUI::_current_roles_ui($roles, array('read_only' => true, 'class' => 'pp-group-roles', 'caption' => $role_group_caption)); $exceptions = array(); $args = array('assign_for' => '', 'inherited_from' => 0, 'extra_cols' => array('i.assign_for', 'i.eitem_id'), 'post_types' => array_keys($post_types), 'taxonomies' => array_keys($taxonomies), 'return_raw_results' => true); foreach (array_keys($user->groups) as $agent_type) { $args['agent_type'] = $agent_type;
function _ppc_count_assigned_roles($agent_type, $args = array()) { global $wpdb; $defaults = array('query_agent_ids' => false, 'join_groups' => true); extract(array_merge($defaults, $args), EXTR_SKIP); $count = array(); if ('user' == $agent_type && $join_groups) { $agent_clause = $query_agent_ids ? "AND gm.user_id IN ('" . implode("','", array_map('intval', (array) $query_agent_ids)) . "')" : ''; $results = $wpdb->get_results("SELECT u.ID AS agent_id, r.role_name, COUNT(*) AS rolecount FROM {$wpdb->users} AS u INNER JOIN {$wpdb->pp_group_members} AS gm ON ( gm.user_id = u.ID {$agent_clause} ) INNER JOIN {$wpdb->ppc_roles} AS r ON ( ( r.agent_type = 'user' AND r.agent_id = gm.user_id ) OR ( r.agent_type = 'pp_group' AND r.agent_id = gm.group_id ) ) GROUP BY u.ID, r.role_name"); } else { $agent_clause = $query_agent_ids ? "AND agent_id IN ('" . implode("','", array_map('intval', (array) $query_agent_ids)) . "')" : ''; $results = $wpdb->get_results($wpdb->prepare("SELECT agent_id, role_name, COUNT(*) AS rolecount FROM {$wpdb->ppc_roles} WHERE agent_type = %s {$agent_clause} GROUP BY agent_id, role_name", $agent_type)); } $item_types = array_merge(pp_get_enabled_post_types(), pp_get_enabled_taxonomies()); foreach ($results as $row) { $arr_role = explode(':', $row->role_name); //$base_role_name = $arr_role[0]; //$src_name = $arr_role[1]; //$item_type = $arr_role[2]; $no_ext = !defined('PPCE_VERSION') && !defined('PPS_VERSION'); $no_custom_stati = !defined('PPS_VERSION'); if (isset($arr_role[2]) && in_array($arr_role[2], $item_types)) { // roles for these post statuses will not be applied if corresponding extensions are inactive, so do not indicate in users/groups listing or profile if ($no_ext && strpos($row->role_name, ':post_status:') && !strpos($row->role_name, ':post_status:private')) { continue; } elseif ($no_custom_stati && strpos($row->role_name, ':post_status:') && !strpos($row->role_name, ':post_status:private') && !strpos($row->role_name, ':post_status:draft')) { continue; } if ($role_title = ppc_get_role_title($row->role_name, array('slug_fallback' => false))) { $count[$row->agent_id]['roles'][$role_title] = $row->rolecount; if (!isset($count[$row->agent_id]['role_count'])) { $count[$row->agent_id]['role_count'] = 0; } $count[$row->agent_id]['role_count'] += $row->rolecount; } } } return $count; }
public static function get_exceptions($args = array()) { $defaults = array('operations' => array(), 'inherited_from' => '', 'for_item_source' => false, 'via_item_source' => false, 'assign_for' => 'item', 'for_item_status' => false, 'post_types' => true, 'taxonomies' => true, 'item_id' => false, 'agent_type' => '', 'agent_id' => 0, 'query_agent_ids' => array(), 'ug_clause' => '', 'return_raw_results' => false, 'extra_cols' => array(), 'cols' => array()); $args = array_merge($defaults, $args); extract($args, EXTR_SKIP); global $wpdb; $except = array(); $operations = (array) $operations; if ($operations) { $operations = array_intersect($operations, pp_get_operations()); } else { $operations = pp_get_operations(); } if (!is_array($post_types)) { $post_types = pp_get_enabled_post_types(); } if (!is_array($taxonomies)) { $taxonomies = pp_get_enabled_taxonomies(); } $default_arr = array('include', 'exclude'); if (!defined('PP_NO_ADDITIONAL_ACCESS')) { $default_arr[] = 'additional'; } $valid_src_types = array('post' => array('post' => array('' => array_fill_keys($default_arr, array_fill_keys($post_types, array()))), 'term' => array()), 'term' => array('term' => array()), 'pp_group' => array('pp_group' => array())); if ($add_source_types = apply_filters('pp_add_exception_source_types', array())) { // valid return array is arr[for_item_source] = arr[via_item_src][via_item_type] = array('include', 'exclude' ) $valid_src_types = array_merge($valid_src_types, $add_source_types); } if ($for_item_source) { $for_item_source = array_flip((array) $for_item_source); if (!($for_item_sources = array_intersect_key($for_item_source, $valid_src_types))) { return array(); } } else { $for_item_sources = $valid_src_types; } $for_item_clauses = array(); foreach (array_keys($for_item_sources) as $for_src_name) { if (isset($valid_src_types[$for_src_name])) { foreach ($operations as $op) { $except["{$op}_{$for_src_name}"] = $valid_src_types[$for_src_name]; } $for_types = array(); foreach (array_keys($valid_src_types[$for_src_name]) as $via_src_name) { if ('post' == $via_src_name) { foreach (array_keys($valid_src_types[$for_src_name][$via_src_name]) as $via_type) { foreach (array_keys($valid_src_types[$for_src_name][$via_src_name][$via_type]) as $mod_type) { $for_types = array_merge($for_types, array_keys($valid_src_types[$for_src_name][$via_src_name][$via_type][$mod_type])); } } } elseif ('term' == $via_src_name) { if ('term' == $for_src_name) { $for_types = $taxonomies; } else { $for_types = $post_types; } } else { $for_types = false; } } if (false === $for_types) { $for_item_clauses[] = "e.for_item_source = '{$for_src_name}'"; } else { $for_item_clauses[] = "e.for_item_source = '{$for_src_name}' AND e.for_item_type IN ('', '" . implode("','", array_unique($for_types)) . "')"; } } } if ($type_clause = pp_implode('OR', $for_item_clauses)) { $type_clause = "AND ( {$type_clause} )"; } if ($via_item_source) { $type_clause .= $wpdb->prepare("AND e.via_item_source = '{$via_item_source}'", $via_item_source); } if ($agent_type && !$ug_clause) { $ug_clause = $wpdb->prepare(" AND e.agent_type = %s AND e.agent_id IN ('" . implode("','", array_map('intval', (array) $agent_id)) . "')", $agent_type); } $operation_clause = "AND e.operation IN ('" . implode("','", $operations) . "')"; $mod_clause = defined('PP_NO_ADDITIONAL_ACCESS') ? "AND e.mod_type != 'additional'" : ''; $assign_for_clause = $assign_for ? $wpdb->prepare("AND i.assign_for = %s", $assign_for) : ''; $inherited_from_clause = $inherited_from !== '' ? $wpdb->prepare("AND i.inherited_from = %d", $inherited_from) : ''; $status_clause = false !== $for_item_status ? $wpdb->prepare("AND e.for_item_status = %s", $for_item_status) : ''; if (!$status_clause && !defined('PPS_VERSION')) { $status_clause = "AND e.for_item_status IN ('','post_status:private','post_status:draft')"; } // exceptions for other statuses will not be applied correctly without custom statuses extension if (!$cols) { $cols = "e.operation, e.for_item_source, e.for_item_type, e.mod_type, e.via_item_source, e.via_item_type, e.for_item_status, i.item_id, i.assign_for"; } $extra_cols_clause = $extra_cols ? ', ' . implode(",", $extra_cols) : ''; $id_clause = false !== $item_id ? $wpdb->prepare("AND i.item_id = %d", $item_id) : ''; $results = $wpdb->get_results("SELECT {$cols}{$extra_cols_clause} FROM {$wpdb->ppc_exceptions} AS e INNER JOIN {$wpdb->ppc_exception_items} AS i ON e.exception_id = i.exception_id WHERE ( 1=1 {$operation_clause} {$assign_for_clause} {$inherited_from_clause} {$mod_clause} {$type_clause} {$status_clause} {$id_clause} ) {$ug_clause}"); if ($return_raw_results) { return $results; } foreach ($results as $row) { // note: currently only additional access can be status-specific $except["{$row->operation}_{$row->for_item_source}"][$row->via_item_source][$row->via_item_type][$row->mod_type][$row->for_item_type][$row->for_item_status][] = $row->item_id; } return $except; }
function get_exception_terms($operation, $mod_type, $post_type, $taxonomy, $args = array()) { $status = isset($args['status']) ? $args['status'] : ''; if ($post_type) { $for_item_src = post_type_exists($post_type) ? 'post' : 'term'; if ('post' == $for_item_src && $taxonomy && !in_array($taxonomy, pp_get_enabled_taxonomies(array('object_type' => $post_type)))) { return array(); } } else { $for_item_src = 'post'; } // nullstring post_type means all post types if (!isset($this->except["{$operation}_{$for_item_src}"])) { $this->retrieve_exceptions($operation, $for_item_src); } $args['via_item_source'] = 'term'; $args['via_item_type'] = $taxonomy; $args['status'] = true; // prevent filter from flattening exceptions array, since we will do it below $type_restricts = apply_filters('pp_get_exception_items', false, $operation, $mod_type, $post_type, $args); if (false === $type_restricts) { $type_restricts = isset($this->except["{$operation}_{$for_item_src}"]['term'][$taxonomy][$mod_type][$post_type]) ? $this->except["{$operation}_{$for_item_src}"]['term'][$taxonomy][$mod_type][$post_type] : array(); } if ($post_type && !empty($args['merge_universals'])) { $universal_restricts = apply_filters('pp_get_exception_items', false, $operation, $mod_type, '', $args); if (false === $universal_restricts) { $universal_restricts = isset($this->except["{$operation}_{$for_item_src}"]['term'][$taxonomy][$mod_type]['']) ? $this->except["{$operation}_{$for_item_src}"]['term'][$taxonomy][$mod_type][''] : array(); } foreach (array_keys($universal_restricts) as $_status) { pp_set_array_elem($type_restricts, array($_status)); $type_restricts[$_status] = array_unique(array_merge($type_restricts[$_status], $universal_restricts[$_status])); } } if (!$type_restricts) { return array(); } if (true === $status) { return $type_restricts; } else { $tt_ids = pp_array_flatten(array_intersect_key($type_restricts, array($status => true))); } if (!empty($args['return_term_ids'])) { return pp_ttid_to_termid($tt_ids, $taxonomy); } else { return array_unique($tt_ids); } }
public static function add_term_restrictions_clause($required_operation, $post_type, $src_table, $args = array()) { global $wpdb, $pp_current_user; extract(array_merge(array('merge_additions' => false, 'exempt_post_types' => array()), $args), EXTR_SKIP); $where = ''; $excluded_ttids = array(); $type_exemption_clause = $exempt_post_types ? " OR {$src_table}.post_type IN ('" . implode("','", $exempt_post_types) . "')" : ''; $tx_args = $post_type ? array('object_type' => $post_type) : array(); foreach (pp_get_enabled_taxonomies($tx_args) as $taxonomy) { $tx_additional_ids = $merge_additions ? $pp_current_user->get_exception_terms($required_operation, 'additional', $post_type, $taxonomy, array('status' => '', 'merge_universals' => true)) : array(); // post may be required to be IN a term set for one taxonomy, and NOT IN a term set for another taxonomy foreach (array('include', 'exclude') as $mod) { if ($tt_ids = $pp_current_user->get_exception_terms($required_operation, $mod, $post_type, $taxonomy, $args)) { if ('include' == $mod) { if ($tx_additional_ids) { $tt_ids = array_merge($tt_ids, $tx_additional_ids); } $term_include_clause = apply_filters('pp_term_include_clause', "{$src_table}.ID IN ( SELECT object_id FROM {$wpdb->term_relationships} WHERE term_taxonomy_id IN ('" . implode("','", $tt_ids) . "') )", compact('tt_ids', 'src_table')); $where .= " AND ( {$term_include_clause} {$type_exemption_clause} )"; continue 2; } else { if ($tx_additional_ids) { $tt_ids = array_diff($tt_ids, $tx_additional_ids); } $excluded_ttids = array_merge($excluded_ttids, $tt_ids); } } } } if ($excluded_ttids) { $where .= " AND ( {$src_table}.ID NOT IN ( SELECT object_id FROM {$wpdb->term_relationships} WHERE term_taxonomy_id IN ('" . implode("','", $excluded_ttids) . "') ) {$type_exemption_clause} )"; } return $where; }
if (!is_user_logged_in()) { echo '<option>' . __('(login timed out)', 'pp') . '</option>'; exit; } // TODO: deal with login timeout in JS to avoid multiple messages $types = array(); if ('post' == $for_src_name) { if ('associate' != $operation) { if ('assign' != $operation) { // 'assign' op only pertains to terms if ($type_obj = get_post_type_object($for_type)) { $types = array($for_type => __('selected:', 'pp')); } } $type_arg = $for_type ? array('object_type' => $for_type) : array(); $taxonomies = pp_get_enabled_taxonomies($type_arg, 'object'); if ($taxonomies) { $tax_types = array(); foreach ($taxonomies as $_taxonomy => $tx) { $tax_types[$_taxonomy] = $tx->labels->name; } uasort($tax_types, 'strnatcasecmp'); // sort by values without resetting keys $types = array_merge($types, $tax_types); } } else { // 'associate' exceptions regulate parent assignment. This does not pertain to taxonomies, but may apply to other post types as specified by the filter. $aff_types = (array) apply_filters('pp_parent_types', array($for_type), $for_type); foreach ($aff_types as $_type) { if ($type_obj = get_post_type_object($_type)) { $types[$_type] = $type_obj->labels->name;
function flt_user_has_cap($wp_sitecaps, $orig_reqd_caps, $args) { if ($this->in_process || !isset($args[0])) { return $wp_sitecaps; } global $pp_current_user; if ($args[1] != $pp_current_user->ID) { return $wp_sitecaps; } //$args[0] = (array) $args[0]; $args = (array) $args; $orig_cap = reset($args); if (isset($args[2])) { if (is_object($args[2])) { $args[2] = isset($args[2]->ID) ? $args[2]->ID : 0; } } else { $item_id = 0; } $item_id = isset($args[2]) ? $args[2] : 0; if ('read_document' == $orig_cap) { // todo: api $orig_cap = 'read_post'; } if ('read_post' == $orig_cap && (count($orig_reqd_caps) > 1 || 'read' != reset($orig_reqd_caps))) { global $pp; if (!$pp->direct_file_access) { // deal with map_meta_cap() changing 'read_post' requirement to 'edit_post' $types = get_post_types(array('public' => true), 'object'); foreach (array_keys($types) as $_post_type) { if (array_intersect(array_intersect_key((array) $types[$_post_type]->cap, array_fill_keys(array('edit_posts', 'edit_others_posts', 'edit_published_posts', 'edit_private_posts'), true)), $orig_reqd_caps)) { $orig_cap = 'edit_post'; break; } } } } if (is_array($orig_cap) || !isset($this->meta_caps[$orig_cap])) { // Revisionary may pass array into args[0] // If we would fail a straight post cap check, pass it if appropriate additions stored if (array_diff($orig_reqd_caps, array_keys(array_intersect($wp_sitecaps, array(true, 1, '1'))))) { global $pp_cap_helper; $is_post_cap = false; $item_type = ''; if ($type_caps = array_intersect($orig_reqd_caps, array_keys($pp_cap_helper->all_type_caps))) { if (in_array($orig_cap, array_keys($this->meta_caps)) || in_array($orig_cap, array_keys($pp_cap_helper->all_type_caps))) { $is_post_cap = true; if (!$item_id && apply_filters('pp_do_find_post_id', true, $orig_reqd_caps, $args)) { if ($item_id = pp_get_post_id()) { $item_id = apply_filters('pp_get_post_id', $item_id, $orig_reqd_caps, $args); } } // If a post id can be determined from url or POST, will check for exceptions on that post only // Otherwise, credit basic read / edit_posts / delete_posts cap if corresponding addition is stored for any post/category of this type if ($item_id) { if ($_post = get_post($item_id)) { $item_type = $_post->post_type; $item_status = $_post->post_status; } } else { $item_type = $this->post_type_from_caps($type_caps); $item_status = ''; } if ($item_type && !in_array($item_type, pp_get_enabled_post_types())) { return $wp_sitecaps; } } } if ($params = apply_filters('pp_user_has_cap_params', array(), $orig_reqd_caps, compact('item_id', 'orig_cap', 'item_type'))) { extract(array_diff_key($params, array_fill_keys(array('wp_sitecaps', 'pp_current_user', 'orig_cap', 'orig_reqd_caps'), true))); // prevent some vars from being overwritten my extract //if ( isset( $params['return_caps'] ) ) // return $params['return_caps']; } if ($type_caps) { static $buffer_qualified; if (!isset($buffer_qualified) || $this->flags['memcache_disabled']) { $buffer_qualified = array(); } $bkey = $item_type . $item_id . md5(serialize($type_caps)); if (!empty($buffer_qualified[$bkey])) { return array_merge($wp_sitecaps, array_fill_keys($orig_reqd_caps, true)); } global $query_interceptor; if ($is_post_cap && apply_filters('pp_use_post_exceptions', true, $item_type)) { $pass = false; $base_caps = $query_interceptor->get_base_caps($type_caps, $item_type); /* if ( ! $item_id && array_diff( $type_caps, $base_caps ) ) { return $wp_sitecaps; // don't credit edit_others, edit_private, etc. based on addition stored for another post (this was needed due to previous failure to apply post_id passed into has_cap filter). But it is problematic for edit.php (display of Mine for lack of edit_others_posts) } */ if (count($base_caps) == 1) { $base_cap = reset($base_caps); switch ($base_cap) { case 'read': $op = 'read'; break; default: $op = apply_filters('pp_cap_operation', false, $base_cap, $item_type); } if ($op) { $_args = compact('item_type', 'orig_reqd_caps'); $valid_stati = apply_filters('pp_exception_stati', array_fill_keys(array('', "post_status:{$item_status}"), true), $item_status, $op, $_args); $exc_post_type = apply_filters('pp_exception_post_type', $item_type, $op, $_args); if ($additional_ids = $pp_current_user->get_exception_posts($op, 'additional', $exc_post_type, array('status' => true))) { $additional_ids = pp_array_flatten(array_intersect_key($additional_ids, $valid_stati)); } if ($additional_ids) { $has_post_additions = apply_filters('pp_has_post_additions', null, $additional_ids, $item_type, $item_id, compact('op', 'orig_reqd_caps')); if (is_null($has_post_additions)) { $has_post_additions = !$item_id || in_array($item_id, $additional_ids); } } else { $has_post_additions = false; } if ($has_post_additions) { $pass = true; } else { if ($enabled_taxonomies = pp_get_enabled_taxonomies(array('object_type' => $item_type))) { global $wpdb; if (!$item_id || ($post_ttids = $wpdb->get_col("SELECT tr.term_taxonomy_id FROM {$wpdb->term_relationships} AS tr INNER JOIN {$wpdb->term_taxonomy} AS tt ON tt.term_taxonomy_id = tr.term_taxonomy_id WHERE tt.taxonomy IN ('" . implode("','", $enabled_taxonomies) . "') AND tr.object_id = '{$item_id}'"))) { foreach (pp_get_enabled_taxonomies(array('object_type' => $item_type)) as $taxonomy) { if ($additional_tt_ids = $pp_current_user->get_exception_terms($op, 'additional', $item_type, $taxonomy, array('status' => true))) { $additional_tt_ids = pp_array_flatten(array_intersect_key($additional_tt_ids, $valid_stati)); } // merge in 'include' terms only if user has required caps in site-wide role if (!array_diff($orig_reqd_caps, array_intersect(array_keys($pp_current_user->allcaps), array(1, '1', true)))) { if ($include_tt_ids = $pp_current_user->get_exception_terms($op, 'include', $item_type, $taxonomy, array('status' => true))) { $additional_tt_ids = array_merge($additional_tt_ids, pp_array_flatten(array_intersect_key($include_tt_ids, $valid_stati))); } } if ($additional_tt_ids) { if (!$item_id || array_intersect($additional_tt_ids, $post_ttids)) { $pass = true; break; } } } } } } } } } else { if (!isset($params)) { $params = apply_filters('pp_user_has_cap_params', array(), $orig_reqd_caps, compact('item_id', 'orig_cap', 'item_type')); } $pass = apply_filters('pp_credit_cap_exception', false, array_merge($params, compact('item_id'))); } if ($pass) { $buffer_qualified[$bkey] = true; return array_merge($wp_sitecaps, array_fill_keys($orig_reqd_caps, true)); } } } else { if ($params = apply_filters('pp_user_has_cap_params', array(), $orig_reqd_caps, compact('item_id', 'orig_cap', 'item_type'))) { if (empty($params['item_id'])) { $params['item_id'] = $item_id ? $item_id : pp_get_post_id(); } $wp_sitecaps = apply_filters('pp_user_has_caps', $wp_sitecaps, $orig_reqd_caps, $params); extract(array_diff_key($params, array_fill_keys(array('wp_sitecaps', 'pp_current_user', 'orig_cap', 'orig_reqd_caps'), true))); } } return $wp_sitecaps; } $this->in_process = true; $this->args = $args; $src_name = isset($this->cap_data_sources[$orig_cap]) ? $this->cap_data_sources[$orig_cap] : 'post'; switch ($src_name) { case 'post': if (!isset($required_operation)) { $required_operation = $this->meta_caps[$orig_cap]; } $return = $this->_flt_user_has_post_cap($wp_sitecaps, $orig_reqd_caps, $args, compact('required_operation')); break; default: } // end switch $this->in_process = false; $this->flags = $this->flag_defaults; return $return; }
public static function _current_exceptions_ui($exc_results, $args = array()) { global $pp_admin, $pp_role_defs, $pp_data_sources; $defaults = array('read_only' => false, 'class' => 'pp-group-roles', 'item_links' => false, 'caption' => '', 'link' => '', 'agent_type' => ''); $args = array_merge($defaults, $args); extract($args); if (!$exc_results) { return; } if (!$caption) { $caption = 'user' == $agent_type ? sprintf(__('Exceptions %1$s(for user)%2$s', 'pp'), '<small>', '</small>') : __('Exceptions', 'pp'); } require_once PPC_ABSPATH . '/lib/ancestry_lib_pp.php'; $can_assign = current_user_can('pp_assign_roles') && pp_bulk_roles_enabled(); $exceptions = array_fill_keys(array_merge(array('term', 'post'), pp_get_group_types()), array()); $item_paths = array_fill_keys(array_keys($exceptions), array(__('(none)', 'pp'))); // support imported include exception with no items included $post_types = pp_get_enabled_post_types(array(), 'names'); $taxonomies = pp_get_enabled_taxonomies(array('object_type' => false), 'names'); foreach ($exc_results as $row) { // object_type not strictly necessary here, included for consistency with term role array switch ($row->via_item_source) { case 'term': if ($row->item_id) { $taxonomy = ''; $term_id = (int) pp_ttid_to_termid($row->item_id, $taxonomy); if ($row->item_id) { $item_paths['term'][$row->item_id] = PP_Ancestry::get_term_path($term_id, $taxonomy); } $via_type = $taxonomy; } else { $via_type = $row->via_item_type; } break; case 'post': if ($row->item_id) { $item_paths['post'][$row->item_id] = PP_Ancestry::get_post_path($row->item_id); } // no break // no break default: if (pp_group_type_exists($row->via_item_source)) { static $groups_by_id; if (!isset($groups_by_id)) { $groups_by_id = array(); } if (!isset($groups_by_id[$row->via_item_source])) { $groups_by_id[$row->via_item_source] = array(); foreach (pp_get_groups($row->via_item_source, array('skip_meta_types' => 'wp_role')) as $group) { $groups_by_id[$row->via_item_source][$group->ID] = $group->name; } } if (isset($groups_by_id[$row->via_item_source][$row->item_id])) { $item_paths[$row->via_item_source][$row->item_id] = $groups_by_id[$row->via_item_source][$row->item_id]; } $via_type = $row->via_item_source; } else { $via_type = $row->via_item_type ? $row->via_item_type : $row->for_item_type; } } if (!isset($exceptions[$row->via_item_source][$via_type])) { $exceptions[$row->via_item_source][$via_type] = array(); } if (!isset($exceptions[$row->via_item_source][$via_type][$row->for_item_type])) { $exceptions[$row->via_item_source][$via_type][$row->for_item_type] = array(); } if (!isset($exceptions[$row->via_item_source][$via_type][$row->for_item_type][$row->operation])) { $exceptions[$row->via_item_source][$via_type][$row->for_item_type][$row->operation] = array(); } if (!isset($exceptions[$row->via_item_source][$via_type][$row->for_item_type][$row->operation][$row->mod_type])) { $exceptions[$row->via_item_source][$via_type][$row->for_item_type][$row->operation][$row->mod_type] = array(); } if (!isset($exceptions[$row->via_item_source][$via_type][$row->for_item_type][$row->operation][$row->mod_type][$row->for_item_status])) { $exceptions[$row->via_item_source][$via_type][$row->for_item_type][$row->operation][$row->mod_type][$row->for_item_status] = array(); } if (!isset($exceptions[$row->via_item_source][$via_type][$row->for_item_type][$row->operation][$row->mod_type][$row->for_item_status][$row->item_id])) { $exceptions[$row->via_item_source][$via_type][$row->for_item_type][$row->operation][$row->mod_type][$row->for_item_status][$row->item_id] = array(); } $exceptions[$row->via_item_source][$via_type][$row->for_item_type][$row->operation][$row->mod_type][$row->for_item_status][$row->item_id][$row->assign_for] = $row->eitem_id; if (!empty($row->inherited_from)) { $exceptions[$row->via_item_source][$via_type][$row->for_item_type][$row->operation][$row->mod_type][$row->for_item_status][$row->item_id]['inherited_from'] = $row->inherited_from; } } echo '<div style="clear:both;"></div>' . "<div id='pp_current_exceptions' class='pp-group-box {$class}'>" . '<h3>'; if ($link) { echo "<a href='{$link}'>{$caption}</a>"; } else { echo $caption; } echo '</h3>'; echo '<div>'; echo '<div id="pp_current_exceptions_inner">'; //ksort( $type_roles ); if (empty($_REQUEST['all_types']) && !empty($exceptions['post'])) { $all_types = array_fill_keys(array_merge($post_types, $taxonomies, array('')), true); $all_types = array_diff_key($all_types, array('topic' => true, 'reply' => true)); // hide topic, reply assignments even if they are somehow saved/imported without inherited_from value $exceptions['post'] = array_intersect_key($exceptions['post'], $all_types); foreach (array_keys($exceptions['post']) as $key) { $exceptions['post'][$key] = array_intersect_key($exceptions['post'][$key], $all_types); } } foreach (array_keys($exceptions) as $via_src) { ksort($exceptions[$via_src]); foreach (array_keys($exceptions[$via_src]) as $via_type) { if ($via_type_obj = pp_get_type_object($via_src, $via_type)) { $via_type_caption = $via_type_obj->labels->singular_name; } else { continue; } $any_redundant = false; echo "<div id='pp_current_{$via_src}_{$via_type}_roles' class='pp-current-exceptions'>"; /* if ( 'term' == $via_src ) echo '<h4>' . __( 'Per-Term:', 'pp' ) . '</h4>'; else { if ( $object_type ) echo '<h4>' . sprintf( __( 'Per-%s:', 'pp' ), $type_caption ) . '</h4>'; else echo '<h4>' . sprintf( __( 'Per-object:', 'pp' ), $type_caption ) . '</h4>'; } echo '<h4>' . sprintf( __( '%s Exceptions', 'pp' ), $via_type_caption ) . '</h4>'; */ ksort($exceptions[$via_src][$via_type]); foreach (array_keys($exceptions[$via_src][$via_type]) as $for_type) { if (pp_group_type_exists($for_type)) { $for_src = $for_type; } else { $for_src = taxonomy_exists($for_type) || !$for_type ? 'term' : 'post'; } if (!$for_type) { $for_type_obj = (object) array('labels' => (object) array('singular_name' => __('(all post types)', 'pp'))); } elseif (!($for_type_obj = pp_get_type_object($for_src, $for_type))) { continue; } foreach (array_keys($exceptions[$via_src][$via_type][$for_type]) as $operation) { if (!($operation_obj = pp_get_op_object($operation, $for_type))) { continue; } if ('assign' == $operation) { $op_caption = $for_type ? sprintf(__('%1$s (%2$s: %3$s)', 'pp'), $operation_obj->label, $for_type_obj->labels->singular_name, $via_type_caption) : sprintf(__('%1$s %2$s %3$s', 'pp'), $operation_obj->label, $via_type_caption, $for_type_obj->labels->singular_name); } elseif (in_array($operation, array('manage', 'associate'))) { $op_caption = sprintf(__('%1$s %2$s', 'pp'), $operation_obj->label, $via_type_caption); } else { $op_caption = sprintf(__('%1$s %2$s', 'pp'), $operation_obj->label, $for_type_obj->labels->singular_name); } echo "<div class='type-roles-wrapper'>"; echo '<h4>' . $op_caption . '</h4>'; echo "<div class='pp-current-type-roles'>"; echo '<div class="pp-current-roles-tbl-wrapper"><table>'; // fill table body (item assignments for each role) echo '<tbody>'; foreach (array_keys($exceptions[$via_src][$via_type][$for_type][$operation]) as $mod_type) { if (!($mod_type_obj = pp_get_mod_object($mod_type))) { continue; } foreach (array_keys($exceptions[$via_src][$via_type][$for_type][$operation][$mod_type]) as $status) { if ($status) { $_status = explode(':', $status); if (count($_status) > 1) { $attrib = $_status[0]; $_status = $_status[1]; } else { $attrib = 'post_status'; $_status = $status; } if ('post_status' == $attrib) { if ($status_obj = get_post_status_object($_status)) { $status_label = $status_obj->label; } elseif ('{unpublished}' == $_status) { // @todo: API $status_label = __('unpublished', 'pp'); } else { $status_label = $status; } } else { $status_label = $status; } $mod_caption = sprintf(__('%1$s (%2$s)', 'pp'), $mod_type_obj->label, $status_label); } else { $mod_caption = $mod_type_obj->label; } if ('exclude' == $mod_type && !empty($exceptions[$via_src][$via_type][$for_type][$operation]['include'])) { $tr_class = ' class="pp_faded"'; $mod_caption = sprintf(__('* %s', 'pp'), $mod_caption); $any_faded = true; } else { $tr_class = ''; } echo "<tr{$tr_class}><td class='pp_item_role_caption'>{$mod_caption}</td>"; echo '<td>'; //if ( $item_links ) { // if ( 'term' != $scope ) // $edit_url_base = $pp_data_sources->member_property( $item_source, '_edit_link' ); //} echo "<div class='pp-role-terms-wrapper pp-role-terms-{$via_type}'>"; if ('term' == $via_src && !in_array($operation, array('manage', 'associate'))) { if (taxonomy_exists($via_type)) { // "Categories:" $tx_obj = get_taxonomy($via_type); $tx_caption = $tx_obj->labels->name; } else { $tx_caption = ''; } echo '<div class="pp-taxonomy-caption">' . sprintf(__('%s:', 'pp'), $tx_caption) . '</div>'; //$edit_url_base = ( isset($tx_obj->_edit_link) ) ? $tx_obj->_edit_link : ''; } echo '<div class="pp-role-terms">'; $tx_item_paths = array_intersect_key($item_paths[$via_src], $exceptions[$via_src][$via_type][$for_type][$operation][$mod_type][$status]); uasort($tx_item_paths, 'strnatcasecmp'); // sort by array values, but maintain keys ); foreach ($tx_item_paths as $item_id => $item_path) { //$assignment = $roles[$scope][$role_name][$item_source][$item_type][$item_id]; $assignment = $exceptions[$via_src][$via_type][$for_type][$operation][$mod_type][$status][$item_id]; $classes = array(); if (isset($assignment['children'])) { if (isset($assignment['item'])) { $ass_id = $assignment['item'] . ',' . $assignment['children']; $classes[] = 'role_both'; $any_both = true; } else { $ass_id = '0,' . $assignment['children']; $classes[] = 'role_ch'; $any_child_only = true; } } else { $ass_id = $assignment['item']; } $class = $classes ? "class='" . implode(' ', $classes) . "'" : ''; if ($read_only) { if ($item_links) { //$item_edit_url = sprintf($edit_url_base, $item_id); $item_edit_url = ''; echo "<div><a href='{$item_edit_url}' {$class}>{$item_path}</a></div>"; } else { echo "<div><span {$class}>{$item_path}</span></div>"; } } else { $cb_id = 'pp_edit_exception_' . str_replace(',', '_', $ass_id); if (!empty($assignment['inherited_from'])) { $classes[] = 'inherited'; $classes[] = "from_{$assignment['inherited_from']}"; } if ($tr_class) { // apply fading for redundantly stored exclusions $classes[] = $tr_class; } $lbl_class = $classes ? "class='" . implode(' ', $classes) . "'" : ''; if ('term' == $via_src) { $edit_url = admin_url("edit-tags.php?taxonomy={$via_type}&action=edit&tag_ID=" . pp_ttid_to_termid($item_id, $via_type) . "&post_type={$for_type}"); } else { $edit_url = admin_url("post.php?post={$item_id}&action=edit"); } echo "<div><label for='{$cb_id}' {$lbl_class}><input id='{$cb_id}' type='checkbox' name='pp_edit_exception[]' value='{$ass_id}' {$class}> " . $item_path . '</label><a href="' . $edit_url . '">' . __('edit') . '</a></div>'; } } // end foreach item if (count($tx_item_paths) > 3 && !$read_only) { $cb_id = "pp_check_all_{$via_src}_{$via_type}_{$for_type}_{$operation}_{$status}"; echo "<div><label for='{$cb_id}'><input type='checkbox' id='{$cb_id}' class='pp_check_all'> " . __('(all)', 'pp') . '</label></div>'; } echo '</div></div>'; // pp-role-terms, pp-role-terms-wrapper echo '</td></tr>'; } // end foreach status } // end foreach mod_type echo '</tbody>'; echo '</table></div>'; // pp-current-roles-tbl-wrapper echo '<div class="pp-exception-bulk-edit" style="display:none">'; echo "<select><option value=''>" . __ppw('Bulk Actions', 'pp') . "</option><option value='remove'>" . __ppw('Remove', 'pp') . '</option>'; if ('post' == $via_src && (!$via_type || $via_type_obj->hierarchical)) { echo "<option value='propagate'>" . sprintf(__('Assign for selected and sub-%s', 'pp'), $via_type_obj->labels->name) . '</option>'; echo "<option value='unpropagate'>" . sprintf(__('Assign for selected %s only', 'pp'), $via_type_obj->labels->singular_name) . '</option>'; echo "<option value='children_only'>" . sprintf(__('Assign for sub-%s only', 'pp'), $via_type_obj->labels->name) . '</option>'; } elseif ('term' == $via_src && $via_type_obj->hierarchical) { echo "<option value='propagate'>" . __('Assign for selected and sub-terms', 'pp') . '</option>'; echo "<option value='unpropagate'>" . __('Assign for selected term only', 'pp') . '</option>'; echo "<option value='children_only'>" . __('Assign for sub-terms only', 'pp') . '</option>'; } echo '</select>'; //submit_button( __ppw('Apply'), 'button-secondary submit-edit-item-exception', '', false ); ?> <input type="submit" name="" class="button submit-edit-item-exception" value="<?php _e('Apply', 'pp'); ?> " /> <?php echo '<img class="waiting" style="display:none;" src="' . esc_url(admin_url('images/wpspin_light.gif')) . '" alt="" />'; echo '</div>'; // pp-exception-bulk-edit echo '</div></div>'; // type-roles-wrapper, pp-current-type-roles } // end foreach operation } // end foreach for_type if ($any_redundant) { echo '<div class="pp-current-roles-note">' . __('* = exceptions redundant due to a corresponding "only these" entry', 'pp') . '</div>'; } if (!empty($via_type_obj->hierarchical)) { $_caption = strtolower($via_type_obj->labels->name); if (!empty($any_both) || !empty($any_child_only)) { ?> <div class="pp-current-roles-note"> <?php if (!empty($any_both)) { echo '<span class="role_both" style="padding-right:20px">' . sprintf(__('... = assigned for %1$s and sub-%1$s', 'pp'), $_caption) . '</span>'; } if (!empty($any_child_only)) { echo '<span>' . sprintf(__('* = assigned for sub-%s only', 'pp'), $_caption) . '</span>'; } ?> </div> <?php } $show_all_url = esc_url(add_query_arg('show_propagated', '1', $_SERVER['REQUEST_URI'])); $show_all_link = " <a href='{$show_all_url}'>"; if (empty($_REQUEST['show_propagated'])) { if ('term' == $via_src) { echo '<div class="pp-current-roles-note">' . sprintf(__('note: Exceptions inherited from parent %1$s are not displayed. %2$sshow all%3$s', 'pp'), $_caption, $show_all_link, '</a>') . '</div>'; } else { echo '<div class="pp-current-roles-note">' . sprintf(__('note: Exceptions inherited from parent %1$s or terms are not displayed. %2$sshow all%3$s', 'pp'), $_caption, $show_all_link, '</a>') . '</div>'; } } } echo '</div>'; // pp-current-exceptions } // end foreach via_type } // end foreach via_src echo '</div>'; // pp_current_exceptions_inner echo '</div>'; // no class echo '</div>'; // pp_current_exceptions }