From 3a4570b0fc8b3d6339bef71d17d7701554e0bbf7 Mon Sep 17 00:00:00 2001 From: donncha Date: Fri, 12 Oct 2007 16:21:15 +0000 Subject: Merge with WP 2.3 - testing use only! Move pluggable functions out of wpmu-functions and into pluggable.php, fixes #439 git-svn-id: http://svn.automattic.com/wordpress-mu/trunk@1069 7be80a69-a1ef-0310-a953-fb0f7c49ff36 --- wp-includes/query.php | 361 +++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 285 insertions(+), 76 deletions(-) (limited to 'wp-includes/query.php') diff --git a/wp-includes/query.php b/wp-includes/query.php index 45b6316..49cff8b 100644 --- a/wp-includes/query.php +++ b/wp-includes/query.php @@ -34,7 +34,7 @@ function wp_reset_query() { function is_admin () { global $wp_query; - return ($wp_query->is_admin || (strpos($_SERVER['REQUEST_URI'], 'wp-admin/') !== false)); + return ($wp_query->is_admin || (stripos($_SERVER['REQUEST_URI'], 'wp-admin/') !== false)); } function is_archive () { @@ -81,16 +81,30 @@ function is_category ($category = '') { $cat_obj = $wp_query->get_queried_object(); - if ( $category == $cat_obj->cat_ID ) + if ( $category == $cat_obj->term_id ) return true; - else if ( $category == $cat_obj->cat_name ) + else if ( $category == $cat_obj->name ) return true; - elseif ( $category == $cat_obj->category_nicename ) + elseif ( $category == $cat_obj->slug ) return true; return false; } +function is_tag( $slug = '' ) { + global $wp_query; + if ( !$wp_query->is_tag ) + return false; + + if ( empty( $slug ) ) + return true; + + $tag_obj = $wp_query->get_queried_object(); + if ( $slug == $tag_obj->slug ) + return true; + return false; +} + function is_comments_popup () { global $wp_query; @@ -261,18 +275,18 @@ function the_post() { } /* - * Comments loop. - */ + * Comments loop. + */ -function have_comments() { - global $wp_query; - return $wp_query->have_comments(); -} +function have_comments() { + global $wp_query; + return $wp_query->have_comments(); +} -function the_comment() { - global $wp_query; - return $wp_query->the_comment(); -} +function the_comment() { + global $wp_query; + return $wp_query->the_comment(); +} /* * WP_Query @@ -310,6 +324,7 @@ class WP_Query { var $is_time = false; var $is_author = false; var $is_category = false; + var $is_tag = false; var $is_search = false; var $is_feed = false; var $is_comment_feed = false; @@ -334,6 +349,7 @@ class WP_Query { $this->is_time = false; $this->is_author = false; $this->is_category = false; + $this->is_tag = false; $this->is_search = false; $this->is_feed = false; $this->is_comment_feed = false; @@ -388,6 +404,8 @@ class WP_Query { , 'year' , 'w' , 'category_name' + , 'tag' + , 'tag_id' , 'author_name' , 'feed' , 'tb' @@ -401,6 +419,13 @@ class WP_Query { $array[$key] = ''; } + $array_keys = array('category__in', 'category__not_in', 'category__and', + 'tag__in', 'tag__not_in', 'tag__and', 'tag_slug__in', 'tag_slug__and'); + + foreach ( $array_keys as $key ) { + if ( !isset($array[$key])) + $array[$key] = array(); + } return $array; } @@ -428,9 +453,9 @@ class WP_Query { $qv['day'] = (int) $qv['day']; $qv['w'] = (int) $qv['w']; $qv['m'] = (int) $qv['m']; - if ( '' != $qv['hour'] ) $qv['hour'] = (int) $qv['hour']; - if ( '' != $qv['minute'] ) $qv['minute'] = (int) $qv['minute']; - if ( '' != $qv['second'] ) $qv['second'] = (int) $qv['second']; + if ( '' !== $qv['hour'] ) $qv['hour'] = (int) $qv['hour']; + if ( '' !== $qv['minute'] ) $qv['minute'] = (int) $qv['minute']; + if ( '' !== $qv['second'] ) $qv['second'] = (int) $qv['second']; // Compat. Map subpost to attachment. if ( '' != $qv['subpost'] ) @@ -439,7 +464,7 @@ class WP_Query { $qv['attachment_id'] = $qv['subpost_id']; $qv['attachment_id'] = (int) $qv['attachment_id']; - + if ( ('' != $qv['attachment']) || !empty($qv['attachment_id']) ) { $this->is_single = true; $this->is_attachment = true; @@ -447,7 +472,7 @@ class WP_Query { $this->is_single = true; } elseif ( $qv['p'] ) { $this->is_single = true; - } elseif ( ('' != $qv['hour']) && ('' != $qv['minute']) &&('' != $qv['second']) && ('' != $qv['year']) && ('' != $qv['monthnum']) && ('' != $qv['day']) ) { + } elseif ( ('' !== $qv['hour']) && ('' !== $qv['minute']) &&('' !== $qv['second']) && ('' != $qv['year']) && ('' != $qv['monthnum']) && ('' != $qv['day']) ) { // If year, month, day, hour, minute, and second are set, a single // post is being queried. $this->is_single = true; @@ -459,17 +484,17 @@ class WP_Query { } else { // Look for archive queries. Dates, categories, authors. - if ( '' != $qv['second'] ) { + if ( '' !== $qv['second'] ) { $this->is_time = true; $this->is_date = true; } - if ( '' != $qv['minute'] ) { + if ( '' !== $qv['minute'] ) { $this->is_time = true; $this->is_date = true; } - if ( '' != $qv['hour'] ) { + if ( '' !== $qv['hour'] ) { $this->is_time = true; $this->is_date = true; } @@ -526,6 +551,67 @@ class WP_Query { $this->is_category = true; } + if ( !is_array($qv['category__in']) || empty($qv['category__in']) ) { + $qv['category__in'] = array(); + } else { + $qv['category__in'] = array_map('intval', $qv['category__in']); + $this->is_category = true; + } + + if ( !is_array($qv['category___not_in']) || empty($qv['category__not_in']) ) { + $qv['category__not_in'] = array(); + } else { + $qv['category__not_in'] = array_map('intval', $qv['category__not_in']); + } + + if ( !is_array($qv['category__and']) || empty($qv['category__and']) ) { + $qv['category__and'] = array(); + } else { + $qv['category__and'] = array_map('intval', $qv['category__and']); + $this->is_category = true; + } + + if ( '' != $qv['tag'] ) + $this->is_tag = true; + + $qv['tag_id'] = (int) $qv['tag_id']; + if ( !empty($qv['tag_id']) ) + $this->is_tag = true; + + if ( !is_array($qv['tag__in']) || empty($qv['tag__in']) ) { + $qv['tag__in'] = array(); + } else { + $qv['tag__in'] = array_map('intval', $qv['tag__in']); + $this->is_tag = true; + } + + if ( !is_array($qv['tag___not_in']) || empty($qv['tag__not_in']) ) { + $qv['tag__not_in'] = array(); + } else { + $qv['tag__not_in'] = array_map('intval', $qv['tag__not_in']); + } + + if ( !is_array($qv['tag__and']) || empty($qv['tag__and']) ) { + $qv['tag__and'] = array(); + } else { + $qv['tag__and'] = array_map('intval', $qv['tag__and']); + $this->is_category = true; + } + + if ( !is_array($qv['tag_slug__in']) || empty($qv['tag_slug__in']) ) { + $qv['tag_slug__in'] = array(); + } else { + $qv['tag_slug__in'] = array_map('sanitize_title', $qv['tag_slug__in']); + $this->is_tag = true; + } + + if ( !is_array($qv['tag_slug__and']) || empty($qv['tag_slug__and']) ) { + $qv['tag_slug__and'] = array(); + } else { + $qv['tag_slug__and'] = array_map('sanitize_title', $qv['tag_slug__and']); + $this->is_tag = true; + } + if ( empty($qv['author']) || ($qv['author'] == '0') ) { $this->is_author = false; } else { @@ -536,7 +622,7 @@ class WP_Query { $this->is_author = true; } - if ( ($this->is_date || $this->is_author || $this->is_category) ) + if ( ($this->is_date || $this->is_author || $this->is_category || $this->is_tag ) ) $this->is_archive = true; } @@ -723,13 +809,13 @@ class WP_Query { $where .= ' AND SECOND(post_date)=' . substr($q['m'], 12, 2); } - if ( '' != $q['hour'] ) + if ( '' !== $q['hour'] ) $where .= " AND HOUR(post_date)='" . $q['hour'] . "'"; - if ( '' != $q['minute'] ) + if ( '' !== $q['minute'] ) $where .= " AND MINUTE(post_date)='" . $q['minute'] . "'"; - if ( '' != $q['second'] ) + if ( '' !== $q['second'] ) $where .= " AND SECOND(post_date)='" . $q['second'] . "'"; if ( $q['year'] ) @@ -809,7 +895,7 @@ class WP_Query { $search .= "{$searchand}((post_title LIKE '{$n}{$term}{$n}') OR (post_content LIKE '{$n}{$term}{$n}'))"; $searchand = ' AND '; } - $term = addslashes_gpc($q['s']); + $term = addslashes_gpc($q['s']); if (!$q['sentence'] && count($q['search_terms']) > 1 && $q['search_terms'][0] != $q['s'] ) $search .= " OR (post_title LIKE '{$n}{$term}{$n}') OR (post_content LIKE '{$n}{$term}{$n}')"; @@ -826,38 +912,51 @@ class WP_Query { } else { $q['cat'] = ''.urldecode($q['cat']).''; $q['cat'] = addslashes_gpc($q['cat']); - $join = " LEFT JOIN $wpdb->post2cat ON ($wpdb->posts.ID = $wpdb->post2cat.post_id) "; $cat_array = preg_split('/[,\s]+/', $q['cat']); - $in_cats = $out_cats = $out_posts = ''; foreach ( $cat_array as $cat ) { $cat = intval($cat); - $in = (strpos($cat, '-') !== false) ? false : true; - $cat = trim($cat, '-'); - if ( $in ) - $in_cats .= "$cat, " . get_category_children($cat, '', ', '); - else - $out_cats .= "$cat, " . get_category_children($cat, '', ', '); - } - $in_cats = substr($in_cats, 0, -2); - $out_cats = substr($out_cats, 0, -2); - if ( strlen($in_cats) > 0 ) - $in_cats = " AND $wpdb->post2cat.category_id IN ($in_cats)"; - if ( strlen($out_cats) > 0 ) { - $ids = $wpdb->get_col("SELECT post_id FROM $wpdb->post2cat WHERE $wpdb->post2cat.category_id IN ($out_cats)"); - if ( is_array($ids) && count($ids > 0) ) { - foreach ( $ids as $id ) - $out_posts .= "$id, "; - $out_posts = substr($out_posts, 0, -2); + $in = ($cat > 0); + $cat = abs($cat); + if ( $in ) { + $q['category__in'][] = $cat; + $q['category__in'] = array_merge($q['category__in'], get_term_children($cat, 'category')); + } else { + $q['category__not_in'][] = $cat; + $q['category__not_in'] = array_merge($q['category__not_in'], get_term_children($cat, 'category')); } - if ( strlen($out_posts) > 0 ) - $out_cats = " AND $wpdb->posts.ID NOT IN ($out_posts)"; - else - $out_cats = ''; } - $whichcat = $in_cats . $out_cats; + } + + if ( !empty($q['category__in']) || !empty($q['category__not_in']) || !empty($q['category__and']) ) { $groupby = "{$wpdb->posts}.ID"; } + if ( !empty($q['category__in']) ) { + $join = " LEFT JOIN $wpdb->term_relationships ON ($wpdb->posts.ID = $wpdb->term_relationships.object_id) LEFT JOIN $wpdb->term_taxonomy ON ($wpdb->term_relationships.term_taxonomy_id = $wpdb->term_taxonomy.term_taxonomy_id) "; + $whichcat .= " AND $wpdb->term_taxonomy.taxonomy = 'category' "; + $include_cats = "'" . implode("', '", $q['category__in']) . "'"; + $whichcat .= " AND $wpdb->term_taxonomy.term_id IN ($include_cats) "; + } + + if ( !empty($q['category__not_in']) ) { + $ids = get_objects_in_term($q['category__not_in'], 'category'); + if ( is_wp_error( $ids ) ) + return $ids; + if ( is_array($ids) && count($ids > 0) ) { + $out_posts = "'" . implode("', '", $ids) . "'"; + $whichcat .= " AND $wpdb->posts.ID NOT IN ($out_posts)"; + } + } + + if ( !empty($q['category__and']) ) { + $count = 0; + foreach ( $q['category__and'] as $category_and ) { + $join .= " LEFT JOIN $wpdb->term_relationships AS tr$count ON ($wpdb->posts.ID = tr$count.object_id) LEFT JOIN $wpdb->term_taxonomy AS tt$count ON (tr$count.term_taxonomy_id = tt$count.term_taxonomy_id) "; + $whichcat .= " AND tt$count.term_id = '$category_and' "; + $count++; + } + } + // Category stuff for nice URLs if ( '' != $q['category_name'] ) { $reqcat = get_category_by_path($q['category_name']); @@ -877,22 +976,104 @@ class WP_Query { $reqcat = get_category_by_path($q['category_name'], false); if ( !empty($reqcat) ) - $reqcat = $reqcat->cat_ID; + $reqcat = $reqcat->term_id; else $reqcat = 0; $q['cat'] = $reqcat; - $tables = ", $wpdb->post2cat, $wpdb->categories"; - $join = " LEFT JOIN $wpdb->post2cat ON ($wpdb->posts.ID = $wpdb->post2cat.post_id) LEFT JOIN $wpdb->categories ON ($wpdb->post2cat.category_id = $wpdb->categories.cat_ID) "; - $whichcat = " AND category_id IN ({$q['cat']}, "; - $whichcat .= get_category_children($q['cat'], '', ', '); - $whichcat = substr($whichcat, 0, -2); - $whichcat .= ")"; + $join = " LEFT JOIN $wpdb->term_relationships ON ($wpdb->posts.ID = $wpdb->term_relationships.object_id) LEFT JOIN $wpdb->term_taxonomy ON ($wpdb->term_relationships.term_taxonomy_id = $wpdb->term_taxonomy.term_taxonomy_id) "; + $whichcat = " AND $wpdb->term_taxonomy.taxonomy = 'category' "; + $in_cats = array($q['cat']); + $in_cats = array_merge($in_cats, get_term_children($q['cat'], 'category')); + $in_cats = "'" . implode("', '", $in_cats) . "'"; + $whichcat .= "AND $wpdb->term_taxonomy.term_id IN ($in_cats)"; $groupby = "{$wpdb->posts}.ID"; } + // Tags + if ( '' != $q['tag'] ) { + if ( strpos($q['tag'], ',') !== false ) { + $tags = preg_split('/[,\s]+/', $q['tag']); + foreach ( (array) $tags as $tag ) { + $tag = sanitize_term_field('slug', $tag, 0, 'post_tag', 'db'); + $q['tag_slug__in'][] = $tag; + } + } else if ( preg_match('/[+\s]+/', $q['tag']) ) { + $tags = preg_split('/[+\s]+/', $q['tag']); + foreach ( (array) $tags as $tag ) { + $tag = sanitize_term_field('slug', $tag, 0, 'post_tag', 'db'); + $q['tag_slug__and'][] = $tag; + } + } else { + $q['tag'] = sanitize_term_field('slug', $q['tag'], 0, 'post_tag', 'db'); + $reqtag = is_term( $q['tag'], 'post_tag' ); + if ( !empty($reqtag) ) + $reqtag = $reqtag['term_id']; + else + $reqtag = 0; + $q['tag_id'] = $reqtag; + $q['tag__in'][] = $reqtag; + } + } + + if ( !empty($q['tag__in']) || !empty($q['tag__not_in']) || !empty($q['tag__and']) || + !empty($q['tag_slug__in']) || !empty($q['tag_slug__and']) ) { + $groupby = "{$wpdb->posts}.ID"; + } + + if ( !empty($q['tag__in']) ) { + $join = " LEFT JOIN $wpdb->term_relationships ON ($wpdb->posts.ID = $wpdb->term_relationships.object_id) LEFT JOIN $wpdb->term_taxonomy ON ($wpdb->term_relationships.term_taxonomy_id = $wpdb->term_taxonomy.term_taxonomy_id) "; + $whichcat .= " AND $wpdb->term_taxonomy.taxonomy = 'post_tag' "; + $include_tags = "'" . implode("', '", $q['tag__in']) . "'"; + $whichcat .= " AND $wpdb->term_taxonomy.term_id IN ($include_tags) "; + $reqtag = is_term( $q['tag__in'][0], 'post_tag' ); + if ( !empty($reqtag) ) + $q['tag_id'] = $reqtag['term_id']; + } + + if ( !empty($q['tag_slug__in']) ) { + $join = " LEFT JOIN $wpdb->term_relationships ON ($wpdb->posts.ID = $wpdb->term_relationships.object_id) LEFT JOIN $wpdb->term_taxonomy ON ($wpdb->term_relationships.term_taxonomy_id = $wpdb->term_taxonomy.term_taxonomy_id) LEFT JOIN $wpdb->terms ON ($wpdb->term_taxonomy.term_id = $wpdb->terms.term_id) "; + $whichcat .= " AND $wpdb->term_taxonomy.taxonomy = 'post_tag' "; + $include_tags = "'" . implode("', '", $q['tag_slug__in']) . "'"; + $whichcat .= " AND $wpdb->terms.slug IN ($include_tags) "; + $reqtag = is_term( $q['tag_slug__in'][0], 'post_tag' ); + if ( !empty($reqtag) ) + $q['tag_id'] = $reqtag['term_id']; + } + + if ( !empty($q['tag__not_in']) ) { + $ids = get_objects_in_term($q['tag__not_in'], 'post_tag'); + if ( is_array($ids) && count($ids > 0) ) { + $out_posts = "'" . implode("', '", $ids) . "'"; + $whichcat .= " AND $wpdb->posts.ID NOT IN ($out_posts)"; + } + } + + if ( !empty($q['tag__and']) ) { + $count = 0; + foreach ( $q['tag__and'] as $tag_and ) { + $join .= " LEFT JOIN $wpdb->term_relationships AS tr$count ON ($wpdb->posts.ID = tr$count.object_id) LEFT JOIN $wpdb->term_taxonomy AS tt$count ON (tr$count.term_taxonomy_id = tt$count.term_taxonomy_id) "; + $whichcat .= " AND tt$count.term_id = '$tag_and' "; + $count++; + } + $reqtag = is_term( $q['tag__and'][0], 'post_tag' ); + if ( !empty($reqtag) ) + $q['tag_id'] = $reqtag['term_id']; + } + + if ( !empty($q['tag_slug__and']) ) { + $count = 0; + foreach ( $q['tag_slug__and'] as $tag_and ) { + $join .= " LEFT JOIN $wpdb->term_relationships AS tr$count ON ($wpdb->posts.ID = tr$count.object_id) LEFT JOIN $wpdb->term_taxonomy AS tt$count ON (tr$count.term_taxonomy_id = tt$count.term_taxonomy_id) LEFT JOIN $wpdb->terms AS term$count ON (tt$count.term_id = term$count.term_id) "; + $whichcat .= " AND term$count.slug = '$tag_and' "; + $count++; + } + $reqtag = is_term( $q['tag_slug__and'][0], 'post_tag' ); + if ( !empty($reqtag) ) + $q['tag_id'] = $reqtag['term_id']; + } // Author/user stuff @@ -964,30 +1145,43 @@ class WP_Query { } if ( $this->is_attachment ) { - $where .= " AND (post_type = 'attachment')"; + $where .= " AND post_type = 'attachment'"; } elseif ($this->is_page) { - $where .= " AND (post_type = 'page')"; + $where .= " AND post_type = 'page'"; } elseif ($this->is_single) { - $where .= " AND (post_type = 'post')"; + $where .= " AND post_type = 'post'"; } else { - $where .= " AND (post_type = '$post_type' AND (post_status = 'publish'"; + $where .= " AND post_type = '$post_type'"; + } + + if ( isset($q['post_status']) && '' != $q['post_status'] ) { + $q_status = explode(',', $q['post_status']); + $r_status = array(); + if ( in_array( 'draft' , $q_status ) ) + $r_status[] = "post_status = 'draft'"; + if ( in_array( 'pending', $q_status ) ) + $r_status[] = "post_status = 'pending'"; + if ( in_array( 'future' , $q_status ) ) + $r_status[] = "post_status = 'future'"; + if ( in_array( 'inherit' , $q_status ) ) + $r_status[] = "post_status = 'inherit'"; + if ( in_array( 'private', $q_status ) ) + $r_status[] = "post_status = 'private'"; + if ( in_array( 'publish', $q_status ) ) + $r_status[] = "post_status = 'publish'"; + if ( !empty($r_status) ) + $where .= " AND (" . join( ' OR ', $r_status ) . ")"; + } elseif ( !$this->is_singular ) { + $where .= " AND (post_status = 'publish'"; if ( is_admin() ) - $where .= " OR post_status = 'future' OR post_status = 'draft'"; + $where .= " OR post_status = 'future' OR post_status = 'draft' OR post_status = 'pending'"; if ( is_user_logged_in() ) { - if ( 'post' == $post_type ) - $cap = 'read_private_posts'; - else - $cap = 'read_private_pages'; - - if ( current_user_can($cap) ) - $where .= " OR post_status = 'private'"; - else - $where .= " OR post_author = $user_ID AND post_status = 'private'"; + $where .= current_user_can( "read_private_{$post_type}s" ) ? " OR post_status = 'private'" : " OR post_author = $user_ID AND post_status = 'private'"; } - $where .= '))'; + $where .= ')'; } // Apply filters on where and join prior to paging so that any @@ -1047,12 +1241,18 @@ class WP_Query { // Apply post-paging filters on where and join. Only plugins that // manipulate paging queries should use these hooks. + + // Announce current selection parameters. For use by caching plugins. + do_action( 'posts_selection', $where . $groupby . $q['orderby'] . $limits . $join ); + $where = apply_filters('posts_where_paged', $where); $groupby = apply_filters('posts_groupby', $groupby); if ( ! empty($groupby) ) $groupby = 'GROUP BY ' . $groupby; $join = apply_filters('posts_join_paged', $join); $orderby = apply_filters('posts_orderby', $q['orderby']); + if ( !empty( $orderby ) ) + $orderby = 'ORDER BY ' . $orderby; $distinct = apply_filters('posts_distinct', $distinct); $fields = apply_filters('posts_fields', "$wpdb->posts.*"); $limits = apply_filters( 'post_limits', $limits ); @@ -1060,10 +1260,12 @@ class WP_Query { if ( !empty($limits) ) $found_rows = 'SQL_CALC_FOUND_ROWS'; - $request = " SELECT $found_rows $distinct $fields FROM $wpdb->posts $join WHERE 1=1 $where $groupby ORDER BY $orderby $limits"; + $request = " SELECT $found_rows $distinct $fields FROM $wpdb->posts $join WHERE 1=1 $where $groupby $orderby $limits"; $this->request = apply_filters('posts_request', $request); $this->posts = $wpdb->get_results($this->request); + // Raw results filter. Prior to status checks. + $this->posts = apply_filters('posts_results', $this->posts); if ( $this->is_comment_feed && $this->is_singular ) { $cjoin = apply_filters('comment_feed_join', ''); @@ -1089,7 +1291,7 @@ class WP_Query { // User must be logged in to view unpublished posts. $this->posts = array(); } else { - if ('draft' == $status) { + if (in_array($status, array('draft', 'pending')) ) { // User must have edit permissions on the draft to preview. if (! current_user_can('edit_post', $this->posts[0]->ID)) { $this->posts = array(); @@ -1212,6 +1414,13 @@ class WP_Query { $category = &get_category($cat); $this->queried_object = &$category; $this->queried_object_id = (int) $cat; + } else if ($this->is_tag) { + $tag_id = $this->get('tag_id'); + $tag = &get_term($tag_id, 'post_tag'); + if ( is_wp_error( $tag ) ) + return $tag; + $this->queried_object = &$tag; + $this->queried_object_id = (int) $tag_id; } else if ($this->is_posts_page) { $this->queried_object = & get_page(get_option('page_for_posts')); $this->queried_object_id = (int) $this->queried_object->ID; @@ -1288,7 +1497,7 @@ function wp_old_slug_redirect () { // Setup global post data. function setup_postdata($post) { - global $id, $postdata, $authordata, $day, $page, $pages, $multipage, $more, $numpages, $wp_query; + global $id, $postdata, $authordata, $day, $currentmonth, $page, $pages, $multipage, $more, $numpages, $wp_query; global $pagenow; $id = (int) $post->ID; -- cgit