public static function tally_term_counts(&$terms, $taxonomy, $args = array()) { global $wpdb, $pp_current_user; if (!$terms) { return; } $defaults = array('pad_counts' => true, 'post_type' => '', 'required_operation' => ''); $args = array_merge($defaults, (array) $args); extract($args); $term_items = array(); if ($terms) { if (!is_object(reset($terms))) { return $terms; } foreach ((array) $terms as $key => $term) { $terms_by_id[$term->term_id] =& $terms[$key]; $term_ids[$term->term_taxonomy_id] = $term->term_id; } } // Get the object and term ids and stick them in a lookup table $tax_obj = get_taxonomy($taxonomy); $object_types = $post_type ? (array) $post_type : (array) esc_sql($tax_obj->object_type); if (pp_unfiltered()) { $stati = get_post_stati(array('public' => true, 'private' => true), 'names', 'or'); $type_status_clause = "AND post_type IN ('" . implode("', '", $object_types) . "') AND post_status IN ('" . implode("', '", $stati) . "')"; } else { global $query_interceptor; $type_status_clause = $query_interceptor->get_posts_where(array('post_types' => $object_types, 'required_operation' => $required_operation)); // need to apply term restrictions in case post is restricted by another taxonomy } if (!$required_operation) { $required_operation = pp_is_front() && !is_preview() ? 'read' : 'edit'; } $results = $wpdb->get_results("SELECT object_id, term_taxonomy_id FROM {$wpdb->term_relationships} INNER JOIN {$wpdb->posts} ON object_id = ID WHERE term_taxonomy_id IN ('" . implode("','", array_keys($term_ids)) . "') {$type_status_clause}"); foreach ($results as $row) { $id = $term_ids[$row->term_taxonomy_id]; $term_items[$id][$row->object_id] = isset($term_items[$id][$row->object_id]) ? ++$term_items[$id][$row->object_id] : 1; } // Touch every ancestor's lookup row for each post in each term foreach ($term_ids as $term_id) { $child = $term_id; while (!empty($terms_by_id[$child]) && ($parent = $terms_by_id[$child]->parent)) { if (!empty($term_items[$term_id])) { foreach ($term_items[$term_id] as $item_id => $touches) { $term_items[$parent][$item_id] = isset($term_items[$parent][$item_id]) ? ++$term_items[$parent][$item_id] : 1; } } $child = $parent; } } foreach (array_keys($terms_by_id) as $key) { $terms_by_id[$key]->count = 0; } // Transfer the touched cells foreach ((array) $term_items as $id => $items) { if (isset($terms_by_id[$id])) { $terms_by_id[$id]->count = count($items); } } }
function _pp_flt_administrator_pad_term_counts($terms, $taxonomies, $args) { if (!defined('XMLRPC_REQUEST') && 'all' == $args['fields'] && empty($args['pp_no_filter'])) { global $pagenow; if (!is_admin() || !in_array($pagenow, array('post.php', 'post-new.php'))) { require_once PPC_ABSPATH . '/terms-query-lib_pp.php'; // pp_tally_term_counts() is PP equivalent to WP _pad_term_counts() $args['required_operation'] = pp_is_front() && !is_preview() ? 'read' : 'edit'; PP_TermsQueryLib::tally_term_counts($terms, reset($taxonomies), $args); } } return $terms; }
function flt_terms_clauses($clauses, $taxonomies, $args) { if ($skip = $this->skip_filtering($taxonomies, $args)) { return $clauses; } global $pp_current_user; if ('all' == $args['fields'] || $args['hide_empty'] || $args['pad_counts']) { require_once dirname(__FILE__) . '/terms-interceptor-counts_pp.php'; // adds get_terms filter to adjust post counts based on current user's access and pad_counts setting $clauses = PP_TermCountInterceptor::flt_terms_clauses($clauses, $args); } if (empty($args['required_operation'])) { $args['required_operation'] = apply_filters('pp_get_terms_operation', pp_is_front() ? 'read' : 'assign', $taxonomies, $args); } // must consider all related post types when filtering terms list // NOTE: If hide_empty is true, additional filtering will be applied to the results based on a full posts query. Posts may have direct restrictions which make them inaccessable regardless of term restrictions. $all_excluded_ttids = array(); $enabled_types = pp_get_enabled_post_types(); $required_operation = $args['required_operation']; foreach ($taxonomies as $taxonomy) { $excluded_ttids = $included_ttids = array(); $any_non_inclusions = false; if (!in_array($required_operation, array('manage', 'associate'))) { $universal = array(); $universal['include'] = $pp_current_user->get_exception_terms($required_operation, 'include', '', $taxonomy); $universal['exclude'] = $universal['include'] ? array() : $pp_current_user->get_exception_terms($required_operation, 'exclude', '', $taxonomy); $universal['additional'] = $pp_current_user->get_exception_terms($required_operation, 'additional', '', $taxonomy); $universal = apply_filters('pp_get_terms_universal_exceptions', $universal, $required_operation, $taxonomy, $args); if (!empty($args['object_type'])) { $exception_types = array_intersect((array) $args['object_type'], $enabled_types); } else { $tx = get_taxonomy($taxonomy); $exception_types = array_intersect((array) $tx->object_type, $enabled_types); } } else { $universal = array_fill_keys(array('include', 'exclude', 'additional'), array()); $exception_types = array($taxonomy); } foreach ($exception_types as $post_type) { $additional_tt_ids = apply_filters('pp_get_terms_additional', array_merge($universal['additional'], $pp_current_user->get_exception_terms($required_operation, 'additional', $post_type, $taxonomy)), $required_operation, $post_type, $taxonomy, $args); foreach (array('include', 'exclude') as $mod_type) { $args['additional_tt_ids'] = $additional_tt_ids; $tt_ids = apply_filters('pp_get_terms_exceptions', $pp_current_user->get_exception_terms($required_operation, $mod_type, $post_type, $taxonomy), $required_operation, $mod_type, $post_type, $taxonomy, $args); // remove type-specific inclusions from universal exclusions if ('include' == $mod_type) { $universal['exclude'] = array_diff($universal['exclude'], $tt_ids); } // merge type-specific exceptions with universal if ($tt_ids = array_merge($universal[$mod_type], $tt_ids)) { // add additional terms to includes set, and remove from exclude set (but only if include/exclude set exists to begin with) if ($additional_tt_ids) { $tt_ids = 'include' == $mod_type ? array_merge($tt_ids, $additional_tt_ids) : array_diff($tt_ids, $additional_tt_ids); } } if ($tt_ids) { if ('include' == $mod_type) { $included_ttids = array_merge($included_ttids, $tt_ids); if (count($exception_types) > 1) { continue 2; } // don't support simultaneous include and exclude terms for the same taxonomy (but do support term assign exclusion even if an edit inclusion is set for the same term) } else { $excluded_ttids[] = $tt_ids; $any_non_inclusions = true; } } else { $any_non_inclusions = true; if ('exclude' == $mod_type) { $excluded_ttids[] = array(); } } } } if ($excluded_ttids) { // don't exclude a term unless it is excluded for all post types $exc = $excluded_ttids[0]; for ($i = 1; $i < count($excluded_ttids); $i++) { $exc = array_intersect($exc, $excluded_ttids[$i]); } if ($exc) { // but don't exclude a term which is explicitly included for one or more post types if (count($exception_types) > 1) { $all_excluded_ttids = array_merge($all_excluded_ttids, array_diff($exc, $included_ttids)); } else { $all_excluded_ttids = array_merge($all_excluded_ttids, $exc); } } } if ($included_ttids) { if (empty($wrapped)) { $clauses['where'] = "( {$clauses['where']} )"; $wrapped = true; } // include terms were specified for all post types if (count($taxonomies) == 1) { $clauses['where'] = " ( " . $clauses['where'] . " ) AND tt.term_taxonomy_id IN ('" . implode("','", array_unique($included_ttids)) . "')"; } else { $clauses['where'] .= " AND ( tt.taxonomy != '{$taxonomy}' OR tt.term_taxonomy_id IN ('" . implode("','", array_unique($included_ttids)) . "') )"; } } } if ($all_excluded_ttids) { if (empty($wrapped)) { $clauses['where'] = "( {$clauses['where']} )"; $wrapped = true; } $clauses['where'] .= " AND tt.term_taxonomy_id NOT IN ('" . implode("','", $all_excluded_ttids) . "')"; } return $clauses; }
function add_main_filters() { include_once dirname(__FILE__) . '/hardway/wp-patches_agp.php'; // ===== Filters which support automated role maintenance following content creation/update if (!pp_is_front() || !defined('PP_NO_FRONTEND_ADMIN')) { // advanced users can save some memory if no content/users will be edited via front end global $pp_admin_filters; require_once dirname(__FILE__) . '/admin/filters-maint_pp.php'; $pp_admin_filters = new PP_AdminFilters(); do_action('pp_maint_filters'); } }
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); }