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; }
public function flt_getarchives_where($where) { global $current_user, $wpdb, $query_interceptor; // possible @todo: implement in any other PP filters? require_once dirname(__FILE__) . '/lib/sql-tokenizer_pp.php'; $parser = new SqlTokenizer_PP(); $post_type = $parser->ParseArg($where, 'post_type'); $where = str_replace("WHERE ", "WHERE {$wpdb->posts}.post_date > 0 AND ", $where); $stati = array_merge(pp_get_post_stati(array('public' => true, 'post_type' => $post_type)), pp_get_post_stati(array('private' => true, 'post_type' => $post_type))); if (!empty($current_user->ID)) { $where = str_replace("AND post_status = 'publish'", "AND post_status IN ('" . implode("','", $stati) . "')", $where); } $where = str_replace("WHERE ", "AND ", $where); $where = $query_interceptor->flt_posts_where($where, array('skip_teaser' => true, 'post_type' => $post_type)); $where = 'WHERE 1=1 ' . $where; $this->archives_where = $where; return $where; }
public static function add_exception_clauses($where, $required_operation, $post_type, $args = array()) { $defaults = array('source_alias' => '', 'apply_term_restrictions' => true, 'append_post_type_clause' => true, 'additions_only' => false); extract(array_merge($defaults, $args), EXTR_SKIP); global $wpdb, $pp_current_user; $src_table = $source_alias ? $source_alias : $wpdb->posts; $exc_post_type = apply_filters('pp_exception_post_type', $post_type, $required_operation, $args); if (!$additions_only) { if ($where) { // where clause already indicates sitewide caps for one or more statuses (or just want the exceptions clause generated) if ($append_clause = apply_filters('pp_append_query_clause', '', $post_type, $required_operation, $args)) { $where .= $append_clause; } $post_blockage_priority = pp_get_option('post_blockage_priority'); $post_blockage_clause = ''; foreach (array('include' => 'IN', 'exclude' => 'NOT IN') as $mod => $logic) { if ($ids = $pp_current_user->get_exception_posts($required_operation, $mod, $exc_post_type)) { $_args = array_merge($args, compact('mod', 'ids', 'src_table', 'logic')); $clause_var = $post_blockage_priority ? 'post_blockage_clause' : 'where'; ${$clause_var} .= " AND " . apply_filters('pp_exception_clause', "{$src_table}.ID {$logic} ('" . implode("','", $ids) . "')", $required_operation, $post_type, $_args); break; // don't use both include and exclude clauses } } // term restrictions which apply only to this post type if ($apply_term_restrictions) { $where .= self::add_term_restrictions_clause($required_operation, $post_type, $src_table); } } else { $where = '1=2'; } } $additions = array(); $additional_ids = $pp_current_user->get_exception_posts($required_operation, 'additional', $exc_post_type, array('status' => true)); foreach ($additional_ids as $_status => $_ids) { if ($_status) { // db storage is with "post_status:" prefix to allow for implementation of other attributes if (0 === strpos($_status, 'post_status:')) { $_status = str_replace('post_status:', '', $_status); } else { continue; } } if (!isset($additions[$_status])) { $additions[$_status] = array(); } // facilitates user-add on post edit form without dealing with status caps $in_clause = "IN ('" . implode("','", $_ids) . "')"; $additions[$_status][] = apply_filters('pp_additions_clause', "{$src_table}.ID {$in_clause}", $required_operation, $post_type, array('via_item_source' => 'post', 'status' => $_status, 'in_clause' => $in_clause, 'src_table' => $src_table)); } $additional_ttids = array(); foreach (pp_get_enabled_taxonomies(array('object_type' => $post_type)) as $taxonomy) { $tt_ids = $pp_current_user->get_exception_terms($required_operation, 'additional', $post_type, $taxonomy, array('status' => true, 'merge_universals' => true)); // merge this taxonomy exceptions with other taxonomies foreach (array_keys($tt_ids) as $_status) { if (!isset($additional_ttids[$_status])) { $additional_ttids[$_status] = array(); } $additional_ttids[$_status] = array_merge($additional_ttids[$_status], $tt_ids[$_status]); } } if ($additional_ttids) { foreach ($additional_ttids as $_status => $_ttids) { if ($_status) { if (0 === strpos($_status, 'post_status:')) { $_status = str_replace('post_status:', '', $_status); } else { continue; } } if (!isset($additions[$_status])) { $additions[$_status] = array(); } $in_clause = "IN ( SELECT object_id FROM {$wpdb->term_relationships} WHERE term_taxonomy_id IN ('" . implode("','", $_ttids) . "') )"; $additions[$_status][] = apply_filters('pp_additions_clause', "{$src_table}.ID {$in_clause}", $required_operation, $post_type, array('via_item_source' => 'term', 'status' => $_status, 'in_clause' => $in_clause, 'src_table' => $src_table)); } } foreach (array_keys($additions) as $_status) { switch ($_status) { case '': $_status_clause = ''; break; case '{unpublished}': if ('read' != $required_operation) { // sanity check $_stati = array_merge(pp_get_post_stati(array('public' => true, 'post_type' => $post_type)), pp_get_post_stati(array('private' => true, 'post_type' => $post_type))); $_status_clause = "{$src_table}.post_status NOT IN ('" . implode("','", $_stati) . "') AND "; break; } default: $_status_clause = "{$src_table}.post_status = '{$_status}' AND "; break; } $additions[$_status] = $_status_clause . pp_implode(' OR ', $additions[$_status]); } if ($additions = apply_filters('pp_apply_additions', $additions, $where, $required_operation, $post_type, $args)) { $where = "( {$where} ) OR ( " . pp_implode(' OR ', $additions) . " )"; if ($post_blockage_clause) { $post_blockage_clause = "AND ( ( 1=1 {$post_blockage_clause} ) OR ( " . pp_implode(' OR ', $additions) . " ) )"; } /* $additions = pp_implode( ' OR ', $additions ); if ( $append_post_type_clause ) $where = "$src_table.post_type = '$post_type' AND ( ( $where ) OR ( $additions ) )"; else $where = "( $where ) OR ( $additions )"; } elseif ( $append_post_type_clause ) { $where = "$src_table.post_type = '$post_type' AND $where"; */ } if ($post_blockage_priority) { $where = "( {$where} ) {$post_blockage_clause}"; } if ($append_post_type_clause) { $where = "{$src_table}.post_type = '{$post_type}' AND ( {$where} )"; } return $where; }
function get_typecast_caps($role_name) { $arr_name = explode(':', $role_name); if (empty($arr_name[2])) { return array(); } // this role typecast is not db-defined, so generate it $base_role_name = $arr_name[0]; $src_name = $arr_name[1]; $object_type = $arr_name[2]; // typecast role assignment stored, but undefined source name or object_type if (!($type_obj = pp_get_type_object($src_name, $object_type))) { return array(); } // disregard stored Supplemental Roles for Media when Media is no longer enabled for PP filtering (otherwise Post editing caps are granted) if ('attachment' == $object_type) { static $media_filtering_enabled; if (!isset($media_filtering_enabled)) { $media_filtering_enabled = pp_get_enabled_post_types(array('name' => 'attachment')); } if (!$media_filtering_enabled) { return array(); } } if (empty($this->pattern_role_type_caps)) { $this->define_pattern_caps(); } $pattern_role_caps = 'term' == $src_name ? $this->pattern_role_taxonomy_caps : $this->pattern_role_type_caps; if (empty($pattern_role_caps[$base_role_name])) { // if the role definition is not currently configured for Pattern Role usage, disregard the assignment return array(); } if (!defined('PPS_VERSION') && strpos($role_name, 'post_status:private') && isset($pattern_role_caps[$base_role_name]['read'])) { $pattern_role_caps[$base_role_name]['read_private_posts'] = true; } if (!empty($arr_name[3])) { if (empty($arr_name[4])) { // disregard stored roles with invalid status return array(); } elseif ('post_status' == $arr_name[3]) { // ignore supplemental roles for statuses which are no longer active for this post type if (!pp_get_post_stati(array('name' => $arr_name[4], 'post_type' => $object_type))) { return array(); } } } // add all type-specific caps whose base property cap is included in this pattern role // i.e. If 'edit_posts' is in the pattern role, grant $type_obj->cap->edit_posts // if ($caps = array_intersect_key((array) get_object_vars($type_obj->cap), $pattern_role_caps[$base_role_name])) { // At least one type-defined cap is being cast from this pattern role for specified object_type $status_caps = apply_filters('pp_get_typecast_caps', $caps, $arr_name, $type_obj); if (!empty($arr_name[3]) && false === strpos($role_name, 'post_status:private') && $caps == $status_caps) { // if stored status value is invalid, don't credit user for "default statuses" type caps (but allow for subscriber-private if PPS inactive return array(); } else { return apply_filters('pp_apply_arbitrary_caps', $status_caps, $arr_name, $type_obj); } } return $caps; }
function get_posts_where($args) { $defaults = array('post_types' => array(), 'source_alias' => false, 'src_table' => '', 'apply_term_restrictions' => true, 'include_trash' => 0, 'required_operation' => '', 'limit_statuses' => false, 'skip_teaser' => false, 'query_contexts' => array(), 'force_types' => false); $args = array_merge($defaults, (array) $args); extract($args, EXTR_SKIP); //d_echo ("<br /><strong>get_posts_where:</strong> <br />"); global $wpdb; if (!$src_table) { $src_table = $source_alias ? $source_alias : $wpdb->posts; $args['src_table'] = $src_table; } if (!$force_types) { $post_types = array_intersect((array) $post_types, pp_get_enabled_post_types()); } $tease_otypes = array_intersect($post_types, $this->_get_teaser_post_types($post_types, $args)); if (!$required_operation) { $required_operation = pp_is_front() && !is_preview() ? 'read' : 'edit'; $args['required_operation'] = $required_operation; } if ($query_contexts) { $query_contexts = (array) $query_contexts; } $meta_cap = "{$required_operation}_post"; if ('read' == $required_operation) { $use_statuses = array_merge(pp_get_post_stati(array('public' => true, 'post_type' => $post_types), 'object'), pp_get_post_stati(array('private' => true, 'post_type' => $post_types), 'object')); foreach ($use_statuses as $key => $obj) { if (!empty($obj->exclude_from_search)) { // example usage is bbPress hidden status unset($use_statuses[$key]); } } } else { $use_statuses = pp_get_post_stati(array('internal' => false, 'post_type' => $post_types), 'object'); } if (in_array('attachment', $post_types)) { $use_statuses['inherit'] = (object) array(); } if (is_array($limit_statuses)) { $use_statuses = array_intersect_key($use_statuses, $limit_statuses); } if (empty($skip_teaser) && !array_diff($post_types, $tease_otypes)) { // All object types potentially returned by this query will have a teaser filter applied to results, so we don't need to use further query filtering $status_clause = "AND {$src_table}.post_status IN ('" . implode("','", array_keys($use_statuses)) . "')"; return $status_clause; } if (!is_bool($include_trash)) { if (!empty($_REQUEST['post_status']) && 'trash' == $_REQUEST['post_status']) { $include_trash = true; } } $where_arr = array(); global $pp_current_user; global $pp_meta_caps; $flag_meta_caps = !empty($pp_meta_caps); foreach ($post_types as $post_type) { if (in_array($post_type, $tease_otypes) && empty($skip_teaser)) { $where_arr[$post_type] = "{$src_table}.post_type = '{$post_type}' AND 1=1"; } else { $have_site_caps = array(); $type_obj = get_post_type_object($post_type); foreach (array_keys($use_statuses) as $status) { if ('private' == $status) { $cap_property = "{$required_operation}_private_posts"; if (empty($type_obj->cap->{$cap_property})) { continue; } } if ($flag_meta_caps) { $pp_meta_caps->do_status_cap_map = true; } $reqd_caps = pp_map_meta_cap($meta_cap, $pp_current_user->ID, 0, compact('post_type', 'status', 'query_contexts')); if ($flag_meta_caps) { $pp_meta_caps->do_status_cap_map = false; } if ($reqd_caps) { // note: this function is called only for listing query filters (not for user_has_cap filter) if ($missing_caps = apply_filters('pp_query_missing_caps', array_diff($reqd_caps, array_keys($pp_current_user->allcaps)), $reqd_caps, $post_type, $meta_cap)) { $owner_reqd_caps = $this->get_base_caps($reqd_caps, $post_type); // remove "others" and "private" cap requirements for post author if ($owner_reqd_caps != $reqd_caps && $pp_current_user->ID) { // && ! $omit_owner_clause if (!array_diff($owner_reqd_caps, array_keys($pp_current_user->allcaps))) { $have_site_caps['owner'][] = $status; } } } else { $have_site_caps['user'][] = $status; } } } $have_site_caps = apply_filters('pp_have_site_caps', $have_site_caps, $post_type, $args); if ($include_trash) { if ($type_obj = get_post_type_object($post_type)) { if ('edit_post' == $meta_cap && !empty($pp_current_user->allcaps[$type_obj->cap->edit_posts]) || 'delete_post' == $meta_cap && !empty($pp_current_user->allcaps[$type_obj->cap->delete_posts])) { if (!isset($type_obj->cap->delete_others_posts) || !empty($pp_current_user->allcaps[$type_obj->cap->delete_others_posts])) { $have_site_caps['user'][] = 'trash'; } else { $have_site_caps['owner'][] = 'trash'; } } } } $where_arr[$post_type] = array(); if (!empty($have_site_caps['user'])) { $where_arr[$post_type]['user'] = "******" . implode("','", array_unique($have_site_caps['user'])) . "')"; } //dump($have_site_caps); if (!empty($have_site_caps['owner'])) { $parent_clause = ''; // PPCE may be set to "ID IN (...) OR " to enable post revisors to edit their own pending revisions $args['post_type'] = $post_type; $_vars = apply_filters('pp_generate_where_clause_force_vars', null, 'post', $args); if (is_array($_vars)) { extract($_vars); // possible @todo: intersect keys as with pp_has_cap_force_vars } if (!empty($args['skip_stati_usage_clause']) && !$limit_statuses && !array_diff_key($use_statuses, array_flip($have_site_caps['owner']))) { $where_arr[$post_type]['owner'] = "{$parent_clause} ( {$src_table}.post_author = {$pp_current_user->ID} )"; } else { $where_arr[$post_type]['owner'] = "{$parent_clause} ( {$src_table}.post_author = {$pp_current_user->ID} ) AND {$src_table}.post_status IN ('" . implode("','", array_unique($have_site_caps['owner'])) . "')"; } } if (is_array($where_arr[$post_type])) { if ($where_arr[$post_type]) { $where_arr[$post_type] = pp_implode('OR', $where_arr[$post_type]); $where_arr[$post_type] = "1=1 AND ( " . $where_arr[$post_type] . " )"; } else { $where_arr[$post_type] = '1=2'; } } if ($modified = apply_filters('pp_adjust_posts_where_clause', false, $where_arr[$post_type], $post_type, $args)) { $where_arr[$post_type] = $modified; } if ('attachment' == $post_type) { if ('read' == $required_operation || apply_filters('pp_force_attachment_parent_clause', false, $args)) { //if ( ( 'read' == $required_operation ) || ( defined('DOING_AJAX') && DOING_AJAX && ( false != strpos( $_SERVER['REQUEST_URI'], 'async-upload.php' ) ) ) || apply_filters( 'pp_force_attachment_parent_clause', false, $args ) ) { $where_arr[$post_type] = "( " . $this->append_attachment_clause("{$src_table}.post_type = 'attachment'", array(), $args) . " )"; } } if ('delete' == $required_operation) { $const = "PP_EDIT_EXCEPTIONS_ALLOW_" . strtoupper($post_type) . "_DELETION"; if (defined('PP_EDIT_EXCEPTIONS_ALLOW_DELETION') || defined($const)) { $required_operation = 'edit'; } } $where_arr[$post_type] = PP_Exceptions::add_exception_clauses($where_arr[$post_type], $required_operation, $post_type, $args); } } // end foreach post_type if (!($pp_where = pp_implode('OR', $where_arr))) { $pp_where = '1=1'; } // term restrictions which apply to any post type if ($apply_term_restrictions) { if ($term_exc_where = PP_Exceptions::add_term_restrictions_clause($required_operation, '', $src_table, array('merge_universals' => true, 'merge_additions' => true, 'exempt_post_types' => $tease_otypes))) { $pp_where = "( {$pp_where} ) {$term_exc_where}"; } } if ($pp_where) { $pp_where = " AND ( {$pp_where} )"; } return $pp_where; }
public static function flt_get_pages($results, $args = array()) { $results = (array) $results; global $wpdb; // === BEGIN PP ADDITION: global var; various special case exemption checks === // global $pp, $current_user; // buffer titles in case they were filtered previously $titles = pp_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 PP 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, 'required_operation' => '', 'alternate_operation' => ''); // PP arguments added above // === BEGIN PP ADDITION: support front-end optimization $post_type = isset($args['post_type']) ? $args['post_type'] : $defaults['post_type']; $enabled_post_types = pp_get_enabled_post_types(); if (defined('PP_UNFILTERED_FRONT')) { if (defined('PP_UNFILTERED_FRONT_TYPES')) { $unfiltered_types = str_replace(' ', '', PP_UNFILTERED_FRONT_TYPES); $unfiltered_types = explode(',', constant($unfiltered_types)); $enabled_post_types = array_diff($enabled_post_types, $unfiltered_types); } else { return $results; } } if (!in_array($post_type, $enabled_post_types)) { return $results; } if (pp_is_front()) { if ('page' == $post_type && defined('PP_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}.*"; } } else { // required for xmlrpc getpagelist method $defaults['fields'] = "{$wpdb->posts}.*"; } // === END PP MODIFICATION === $r = wp_parse_args($args, $defaults); $args['number'] = (int) $r['number']; $args['offset'] = absint($r['offset']); $args['child_of'] = (int) $r['child_of']; extract(apply_filters('pp_get_pages_args', $r), EXTR_SKIP); // PPE filter modifies append_page, exclude_tree // workaround for CMS Tree Page View (passes post_parent instead of parent) if (-1 == $parent && isset($args['post_parent'])) { $args['parent'] = $args['post_parent']; $parent = $args['post_parent']; } // 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 (is_admin() && 'any' === $post_status) { $post_status = ''; } if ($post_status) { if (!is_array($post_status) && strpos($post_status, ',')) { $post_status = explode(',', $post_status); } if (array_diff((array) $post_status, get_post_stati())) { return $results; } } $intercepted_pages = apply_filters('pp_get_pages_intercept', false, $results, $args); if (is_array($intercepted_pages)) { return $intercepted_pages; } //$pp->last_get_pages_args = $r; // don't copy entire args array unless it proves necessary $pp->last_get_pages_depth = $depth; $pp->last_get_pages_suppress_filters = $suppress_filters; if ($suppress_filters) { return $results; } $orderby_array = array(); $allowed_keys = array('author', 'post_author', 'date', 'post_date', 'title', 'post_title', 'name', 'post_name', 'modified', 'post_modified', 'modified_gmt', 'post_modified_gmt', 'menu_order', 'parent', 'post_parent', 'ID', 'rand', 'comment_count'); foreach (explode(',', $sort_column) as $orderby) { $orderby = trim($orderby); if (!in_array($orderby, $allowed_keys)) { continue; } switch ($orderby) { case 'menu_order': break; case 'ID': $orderby = "{$wpdb->posts}.ID"; break; case 'rand': $orderby = 'RAND()'; break; case 'comment_count': $orderby = "{$wpdb->posts}.comment_count"; break; default: if (0 === strpos($orderby, 'post_')) { $orderby = "{$wpdb->posts}." . $orderby; } else { $orderby = "{$wpdb->posts}.post_" . $orderby; } } $orderby_array[] = $orderby; } $sort_column = !empty($orderby_array) ? implode(',', $orderby_array) : "{$wpdb->posts}.post_title"; // $args can be whatever, only use the args defined in defaults to compute the key $key = md5(serialize(compact(array_keys($defaults)))); $last_changed = wp_cache_get('last_changed', 'posts'); if (!$last_changed) { $last_changed = microtime(); wp_cache_set('last_changed', $last_changed, 'posts'); } $cache_key = "pp_get_pages:{$key}:{$last_changed}"; if ($cache = wp_cache_get($cache_key, 'posts')) { // Convert to WP_Post instances $pages = array_map('get_post', $cache); $pages = apply_filters('pp_get_pages', $pages, $r); return $pages; } $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_user_by('login', $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"; // PP MODIFICATION: was LEFT JOIN in WP 3.0 core // 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 ' . apply_filters('pp_get_pages_parent', 'post_parent = %d ', $args), $parent); } // === BEGIN PP 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 = ''; global $current_user; $is_front = pp_is_front(); if ($is_front && !empty($current_user->ID)) { $frontend_list_private = !defined('PP_SUPPRESS_PRIVATE_PAGES'); } else { $frontend_list_private = false; } $force_publish_status = !$frontend_list_private && 'publish' == $post_status; if ($is_front) { // since we will be applying status clauses based on content-specific roles, only a sanity check safeguard is needed when post_status is unspecified or defaulted to "publish" $safeguard_statuses = array(); foreach (pp_get_post_stati(array('internal' => false, 'post_type' => $post_type), 'object') as $status_name => $status_obj) { if (!$is_front || $status_obj->private || $status_obj->public) { $safeguard_statuses[] = $status_name; } } } // WP core does not include private pages in query. Include private statuses in anticipation of user-specific filtering if (is_array($post_status)) { $where_status = "AND post_status IN ('" . implode("','", $post_status) . "')"; } elseif ($post_status && ('publish' != $post_status || $is_front && !$frontend_list_private)) { $where_status = $wpdb->prepare("AND post_status = %s", $post_status); } elseif ($is_front) { $where_status = "AND post_status IN ('" . implode("','", $safeguard_statuses) . "')"; } else { $where_status = "AND post_status NOT IN ('" . implode("','", get_post_stati(array('internal' => true))) . "')"; } $where_id = ''; global $pagenow; if (is_admin() && in_array($pagenow, array('post.php', 'post-new.php'))) { global $post; if ($post) { $where_id = "AND ID != {$post->ID}"; } } $where = "AND {$where_post_type} AND ( 1=1 {$where_status} {$where} {$author_query} {$where_id} )"; $orderby = "ORDER BY {$sort_column} {$sort_order}"; $limits = !empty($number) ? ' LIMIT ' . $offset . ',' . $number : ''; $query = "SELECT {$fields} FROM {$wpdb->posts} {$join} WHERE 1=1 {$where} {$orderby} {$limits}"; if (pp_is_front() && apply_filters('pp_teaser_enabled', false, 'post', $post_type) && !defined('PP_TEASER_HIDE_PAGE_LISTING')) { // We are in the front end and the teaser is enabled for pages // TODO: move to PPTX $query = str_replace("post_status = 'publish'", " post_status IN ('" . implode("','", $safeguard_statuses) . "')", $query); $pages = $wpdb->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('pp_posts_teaser', $pages, $post_type, array('request' => $query, 'force_teaser' => true)); $tease_all = true; } else { $_args = array('skip_teaser' => true, 'retain_status' => $force_publish_status); $groupby = $distinct = ''; global $pagenow; if (in_array($pagenow, array('post.php', 'post-new.php'))) { $clauses = apply_filters('pp_get_pages_clauses', compact('distinct', 'fields', 'join', 'where', 'groupby', 'orderby', 'limits'), $post_type, $args); } else { // Pass query through the request filter $_args['post_types'] = $post_type; if ($required_operation) { $_args['required_operation'] = $required_operation; } else { $_args['required_operation'] = pp_is_front() && !is_preview() ? 'read' : 'edit'; } if ('edit' == $_args['required_operation'] && isset($args['post_parent']) || 'associate' == $alternate_operation) { // workaround for CMS Page View $_args['alternate_required_ops'] = array('associate'); } $clauses = apply_filters('pp_posts_clauses', compact('distinct', 'fields', 'join', 'where', 'groupby', 'orderby', 'limits'), $_args); } // Execute the filtered query $pages = $wpdb->get_results("SELECT {$distinct} {$clauses['fields']} FROM {$wpdb->posts} {$clauses['join']} WHERE 1=1 {$clauses['where']} {$clauses['orderby']} {$clauses['limits']}"); } if (empty($pages)) { // alternate hook name (WP core already applied get_pages filter) return apply_filters('pp_get_pages', array(), $r); } if ($child_of) { $pages = get_page_children($child_of, $pages); } // restore buffered titles in case they were filtered previously pp_restore_property_array($pages, $titles, 'ID', 'post_title'); // // === END PP MODIFICATION === // ==================================== $num_pages = count($pages); for ($i = 0; $i < $num_pages; $i++) { $pages[$i] = sanitize_post($pages[$i], 'raw'); } // Press Permit note: WP core get_pages has already updated wp_cache and pagecache with unfiltered results. update_post_cache($pages); // === BEGIN PP 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 = PP_Ancestry::get_page_ancestors(); // array of all ancestor IDs for keyed page_id, with direct parent first $orderby = $sort_column; $remap_args = compact('child_of', 'parent', 'exclude', 'depth', 'orderby'); // one or more of these args may have been modified after extraction PP_Ancestry::remap_tree($pages, $ancestors, $remap_args); } // === END PP MODIFICATION === // ==================================== if (!empty($exclude_tree)) { $exclude = array(); $exclude = (int) $exclude_tree; $children = get_page_children($exclude, $pages); // PP note: okay to use unfiltered WP 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 (isset($pages[$i]) && in_array($pages[$i]->ID, $excludes)) { unset($pages[$i]); } } } if (!empty($append_page) && !empty($pages)) { $found = false; foreach (array_keys($pages) as $key) { if ($append_page->ID == $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); $page_structure = array(); foreach ($pages as $page) { $page_structure[] = $page->ID; } wp_cache_set($cache_key, $page_structure, 'posts'); // Convert to WP_Post instances $pages = array_map('get_post', $pages); // alternate hook name (WP core already applied get_pages filter) return apply_filters('pp_get_pages', $pages, $r); }