public static function flt_nav_menu_items($items, $menu_name, $args) { global $wpdb; $item_types = array(); //d_echo( '********************** enter flt_nav_menu_items <br /> ' ); foreach ($items as $key => $item) { if (!isset($item_types[$item->type])) { $item_types["{$item->type}"] = array(); } $item_types[$item->type][$item->object][$key] = $item->object_id; } $teaser_enabled = apply_filters('pp_teaser_enabled', false, 'post'); // remove unreadable terms if (isset($item_types['taxonomy'])) { foreach ($item_types['taxonomy'] as $taxonomy => $item_ids) { $hide_empty = defined('PP_NAV_MENU_SHOW_EMPTY_TERMS') ? '0' : '1'; $okay_ids = get_terms($taxonomy, "fields=ids&hide_empty={$hide_empty}"); if ($remove_ids = apply_filters('pp_nav_menu_hide_terms', array_diff($item_ids, $okay_ids), $taxonomy)) { $item_types['taxonomy'][$taxonomy] = array_diff($item_types['taxonomy'][$taxonomy], $remove_ids); foreach (array_keys($items) as $key) { if (!empty($items[$key]->type) && 'taxonomy' == $items[$key]->type && in_array($items[$key]->object_id, $remove_ids)) { unset($items[$key]); } } } } } // remove or tease unreadable posts if (isset($item_types['post_type'])) { $post_types = array_keys($item_types['post_type']); $post_ids = pp_array_flatten($item_types['post_type']); } else { $post_types = $post_ids = array(); } $pub_stati = pp_get_post_stati(array('public' => true, 'post_type' => $post_types)); $pvt_stati = pp_get_post_stati(array('private' => true, 'post_type' => $post_types)); $stati = array_merge($pub_stati, $pvt_stati); $clauses = array_fill_keys(array('distinct', 'join', 'groupby', 'orderby', 'limits'), ''); $clauses['fields'] = 'ID'; $clauses['where'] = "AND post_type IN ( '" . implode("','", $post_types) . "' ) AND ID IN ( '" . implode("','", $post_ids) . "') AND post_status IN ('" . implode("','", $stati) . "')"; $clauses = apply_filters('pp_posts_clauses', $clauses, array('post_types' => $post_types, 'skip_teaser' => true, 'required_operation' => 'read', 'force_types' => true)); $okay_ids = $wpdb->get_col("SELECT {$clauses['distinct']} ID FROM {$wpdb->posts} {$clauses['join']} WHERE 1=1 {$clauses['where']}"); foreach ($post_types as $_post_type) { $remove_ids = array_diff($item_types['post_type'][$_post_type], $okay_ids); if ($remove_ids = apply_filters_ref_array('pp_nav_menu_hide_posts', array($remove_ids, &$items, $_post_type))) { foreach (array_keys($items) as $key) { if (!empty($items[$key]->type) && 'post_type' == $items[$key]->type && in_array($items[$key]->object_id, $remove_ids)) { unset($items[$key]); } } } } //d_echo( '**************** exit flt_nav_menu_items <br /> ' ); return $items; }
function pp_array_flatten($arr_md, $go_deep = false) { //flattens multi-dim arrays (if go_deep, supports > 2D but destroys keys) if (!is_array($arr_md)) { return array(); } $arr_flat = array(); foreach ($arr_md as $element) { if (is_array($element)) { if ($go_deep) { $arr_flat = array_merge($arr_flat, pp_array_flatten($element)); } else { $arr_flat = array_merge($arr_flat, $element); } } else { array_push($arr_flat, $element); } } return $arr_flat; }
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); } }
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; }