2019-11-02 10:38:58 +01:00
< ? php
/**
* Query API : WP_Query class
*
* @ package WordPress
* @ subpackage Query
* @ since 4.7 . 0
*/
/**
* The WordPress Query class .
*
2019-11-15 22:59:44 +01:00
* @ link https :// developer . wordpress . org / reference / classes / wp_query /
2019-11-02 10:38:58 +01:00
*
* @ since 1.5 . 0
* @ since 4.5 . 0 Removed the `$comments_popup` property .
*/
2022-12-15 17:47:31 +01:00
#[AllowDynamicProperties]
2019-11-02 10:38:58 +01:00
class WP_Query {
/**
2022-04-02 10:26:41 +02:00
* Query vars set by the user .
2019-11-02 10:38:58 +01:00
*
* @ since 1.5 . 0
* @ var array
*/
public $query ;
/**
2022-04-02 10:26:41 +02:00
* Query vars , after parsing .
2019-11-02 10:38:58 +01:00
*
* @ since 1.5 . 0
* @ var array
*/
public $query_vars = array ();
/**
2022-04-02 10:26:41 +02:00
* Taxonomy query , as passed to get_tax_sql () .
2019-11-02 10:38:58 +01:00
*
* @ since 3.1 . 0
2024-04-17 11:32:24 +02:00
* @ var WP_Tax_Query | null A taxonomy query instance .
2019-11-02 10:38:58 +01:00
*/
public $tax_query ;
/**
2022-04-02 10:26:41 +02:00
* Metadata query container .
2019-11-02 10:38:58 +01:00
*
* @ since 3.2 . 0
2020-09-15 14:29:22 +02:00
* @ var WP_Meta_Query A meta query instance .
2019-11-02 10:38:58 +01:00
*/
public $meta_query = false ;
/**
2022-04-02 10:26:41 +02:00
* Date query container .
2019-11-02 10:38:58 +01:00
*
* @ since 3.7 . 0
2020-09-15 14:29:22 +02:00
* @ var WP_Date_Query A date query instance .
2019-11-02 10:38:58 +01:00
*/
public $date_query = false ;
/**
* Holds the data for a single object that is queried .
*
* Holds the contents of a post , page , category , attachment .
*
* @ since 1.5 . 0
2020-12-10 14:06:04 +01:00
* @ var WP_Term | WP_Post_Type | WP_Post | WP_User | null
2019-11-02 10:38:58 +01:00
*/
public $queried_object ;
/**
* The ID of the queried object .
*
* @ since 1.5 . 0
* @ var int
*/
public $queried_object_id ;
/**
2021-04-27 08:32:47 +02:00
* SQL for the database query .
2019-11-02 10:38:58 +01:00
*
* @ since 2.0 . 1
* @ var string
*/
public $request ;
/**
2021-04-27 08:32:47 +02:00
* Array of post objects or post IDs .
2019-11-02 10:38:58 +01:00
*
* @ since 1.5 . 0
2021-04-27 08:32:47 +02:00
* @ var WP_Post [] | int []
2019-11-02 10:38:58 +01:00
*/
public $posts ;
/**
2022-04-02 10:26:41 +02:00
* The number of posts for the current query .
2019-11-02 10:38:58 +01:00
*
* @ since 1.5 . 0
* @ var int
*/
public $post_count = 0 ;
/**
* Index of the current item in the loop .
*
* @ since 1.5 . 0
* @ var int
*/
public $current_post = - 1 ;
2023-09-26 10:33:34 +02:00
/**
* Whether the caller is before the loop .
*
* @ since 6.3 . 0
* @ var bool
*/
public $before_loop = true ;
2019-11-02 10:38:58 +01:00
/**
* Whether the loop has started and the caller is in the loop .
*
* @ since 2.0 . 0
* @ var bool
*/
public $in_the_loop = false ;
/**
* The current post .
*
2021-04-27 08:32:47 +02:00
* This property does not get populated when the `fields` argument is set to
* `ids` or `id=>parent` .
*
2019-11-02 10:38:58 +01:00
* @ since 1.5 . 0
2021-04-27 08:32:47 +02:00
* @ var WP_Post | null
2019-11-02 10:38:58 +01:00
*/
public $post ;
/**
* The list of comments for current post .
*
* @ since 2.2 . 0
2021-04-27 08:32:47 +02:00
* @ var WP_Comment []
2019-11-02 10:38:58 +01:00
*/
public $comments ;
/**
2022-04-02 10:26:41 +02:00
* The number of comments for the posts .
2019-11-02 10:38:58 +01:00
*
* @ since 2.2 . 0
* @ var int
*/
public $comment_count = 0 ;
/**
* The index of the comment in the comment loop .
*
* @ since 2.2 . 0
* @ var int
*/
public $current_comment = - 1 ;
/**
2021-04-27 08:32:47 +02:00
* Current comment object .
2019-11-02 10:38:58 +01:00
*
* @ since 2.2 . 0
2021-04-27 08:32:47 +02:00
* @ var WP_Comment
2019-11-02 10:38:58 +01:00
*/
public $comment ;
/**
2022-04-02 10:26:41 +02:00
* The number of found posts for the current query .
2019-11-02 10:38:58 +01:00
*
* If limit clause was not used , equals $post_count .
*
* @ since 2.1 . 0
* @ var int
*/
public $found_posts = 0 ;
/**
2022-04-02 10:26:41 +02:00
* The number of pages .
2019-11-02 10:38:58 +01:00
*
* @ since 2.1 . 0
* @ var int
*/
public $max_num_pages = 0 ;
/**
2022-04-02 10:26:41 +02:00
* The number of comment pages .
2019-11-02 10:38:58 +01:00
*
* @ since 2.7 . 0
* @ var int
*/
public $max_num_comment_pages = 0 ;
/**
* Signifies whether the current query is for a single post .
*
* @ since 1.5 . 0
* @ var bool
*/
public $is_single = false ;
/**
* Signifies whether the current query is for a preview .
*
* @ since 2.0 . 0
* @ var bool
*/
public $is_preview = false ;
/**
* Signifies whether the current query is for a page .
*
* @ since 1.5 . 0
* @ var bool
*/
public $is_page = false ;
/**
* Signifies whether the current query is for an archive .
*
* @ since 1.5 . 0
* @ var bool
*/
public $is_archive = false ;
/**
* Signifies whether the current query is for a date archive .
*
* @ since 1.5 . 0
* @ var bool
*/
public $is_date = false ;
/**
* Signifies whether the current query is for a year archive .
*
* @ since 1.5 . 0
* @ var bool
*/
public $is_year = false ;
/**
* Signifies whether the current query is for a month archive .
*
* @ since 1.5 . 0
* @ var bool
*/
public $is_month = false ;
/**
* Signifies whether the current query is for a day archive .
*
* @ since 1.5 . 0
* @ var bool
*/
public $is_day = false ;
/**
* Signifies whether the current query is for a specific time .
*
* @ since 1.5 . 0
* @ var bool
*/
public $is_time = false ;
/**
* Signifies whether the current query is for an author archive .
*
* @ since 1.5 . 0
* @ var bool
*/
public $is_author = false ;
/**
* Signifies whether the current query is for a category archive .
*
* @ since 1.5 . 0
* @ var bool
*/
public $is_category = false ;
/**
* Signifies whether the current query is for a tag archive .
*
* @ since 2.3 . 0
* @ var bool
*/
public $is_tag = false ;
/**
* Signifies whether the current query is for a taxonomy archive .
*
* @ since 2.5 . 0
* @ var bool
*/
public $is_tax = false ;
/**
* Signifies whether the current query is for a search .
*
* @ since 1.5 . 0
* @ var bool
*/
public $is_search = false ;
/**
* Signifies whether the current query is for a feed .
*
* @ since 1.5 . 0
* @ var bool
*/
public $is_feed = false ;
/**
* Signifies whether the current query is for a comment feed .
*
* @ since 2.2 . 0
* @ var bool
*/
public $is_comment_feed = false ;
/**
* Signifies whether the current query is for trackback endpoint call .
*
* @ since 1.5 . 0
* @ var bool
*/
public $is_trackback = false ;
/**
* Signifies whether the current query is for the site homepage .
*
* @ since 1.5 . 0
* @ var bool
*/
public $is_home = false ;
/**
* Signifies whether the current query is for the Privacy Policy page .
*
* @ since 5.2 . 0
* @ var bool
*/
public $is_privacy_policy = false ;
/**
* Signifies whether the current query couldn ' t find anything .
*
* @ since 1.5 . 0
* @ var bool
*/
public $is_404 = false ;
/**
* Signifies whether the current query is for an embed .
*
* @ since 4.4 . 0
* @ var bool
*/
public $is_embed = false ;
/**
* Signifies whether the current query is for a paged result and not for the first page .
*
* @ since 1.5 . 0
* @ var bool
*/
public $is_paged = false ;
/**
* Signifies whether the current query is for an administrative interface page .
*
* @ since 1.5 . 0
* @ var bool
*/
public $is_admin = false ;
/**
* Signifies whether the current query is for an attachment page .
*
* @ since 2.0 . 0
* @ var bool
*/
public $is_attachment = false ;
/**
* Signifies whether the current query is for an existing single post of any post type
* ( post , attachment , page , custom post types ) .
*
* @ since 2.1 . 0
* @ var bool
*/
public $is_singular = false ;
/**
* Signifies whether the current query is for the robots . txt file .
*
* @ since 2.1 . 0
* @ var bool
*/
public $is_robots = false ;
2020-05-06 17:23:38 +02:00
/**
* Signifies whether the current query is for the favicon . ico file .
*
* @ since 5.4 . 0
* @ var bool
*/
public $is_favicon = false ;
2019-11-02 10:38:58 +01:00
/**
* Signifies whether the current query is for the page_for_posts page .
*
* Basically , the homepage if the option isn ' t set for the static homepage .
*
* @ since 2.1 . 0
* @ var bool
*/
public $is_posts_page = false ;
/**
* Signifies whether the current query is for a post type archive .
*
* @ since 3.1 . 0
* @ var bool
*/
public $is_post_type_archive = false ;
/**
* Stores the -> query_vars state like md5 ( serialize ( $this -> query_vars ) ) so we know
* whether we have to re - parse because something has changed
*
* @ since 3.1 . 0
* @ var bool | string
*/
private $query_vars_hash = false ;
/**
* Whether query vars have changed since the initial parse_query () call . Used to catch modifications to query vars made
* via pre_get_posts hooks .
*
* @ since 3.1 . 1
2025-04-25 12:30:07 +02:00
* @ var bool
2019-11-02 10:38:58 +01:00
*/
private $query_vars_changed = true ;
/**
* Set if post thumbnails are cached
*
* @ since 3.2 . 0
* @ var bool
*/
public $thumbnails_cached = false ;
2022-12-15 17:47:31 +01:00
/**
* Controls whether an attachment query should include filenames or not .
*
* @ since 6.0 . 3
* @ var bool
*/
protected $allow_query_attachment_by_filename = false ;
2019-11-02 10:38:58 +01:00
/**
* Cached list of search stopwords .
*
* @ since 3.7 . 0
* @ var array
*/
private $stopwords ;
private $compat_fields = array ( 'query_vars_hash' , 'query_vars_changed' );
private $compat_methods = array ( 'init_query_flags' , 'parse_tax_query' );
2025-04-25 12:30:07 +02:00
/**
* The cache key generated by the query .
*
* The cache key is generated by the method :: generate_cache_key () after the
* query has been normalized .
*
* @ since 6.8 . 0
* @ var string
*/
private $query_cache_key = '' ;
2019-11-02 10:38:58 +01:00
/**
* Resets query flags to false .
*
* The query flags are what page info WordPress was able to figure out .
*
* @ since 2.0 . 0
*/
private function init_query_flags () {
$this -> is_single = false ;
$this -> is_preview = false ;
$this -> is_page = false ;
$this -> is_archive = false ;
$this -> is_date = false ;
$this -> is_year = false ;
$this -> is_month = false ;
$this -> is_day = false ;
$this -> is_time = false ;
$this -> is_author = false ;
$this -> is_category = false ;
$this -> is_tag = false ;
$this -> is_tax = false ;
$this -> is_search = false ;
$this -> is_feed = false ;
$this -> is_comment_feed = false ;
$this -> is_trackback = false ;
$this -> is_home = false ;
$this -> is_privacy_policy = false ;
$this -> is_404 = false ;
$this -> is_paged = false ;
$this -> is_admin = false ;
$this -> is_attachment = false ;
$this -> is_singular = false ;
$this -> is_robots = false ;
2020-05-06 17:23:38 +02:00
$this -> is_favicon = false ;
2019-11-02 10:38:58 +01:00
$this -> is_posts_page = false ;
$this -> is_post_type_archive = false ;
}
/**
* Initiates object properties and sets default values .
*
* @ since 1.5 . 0
*/
public function init () {
unset ( $this -> posts );
unset ( $this -> query );
$this -> query_vars = array ();
unset ( $this -> queried_object );
unset ( $this -> queried_object_id );
$this -> post_count = 0 ;
$this -> current_post = - 1 ;
$this -> in_the_loop = false ;
2023-09-26 10:33:34 +02:00
$this -> before_loop = true ;
2019-11-02 10:38:58 +01:00
unset ( $this -> request );
unset ( $this -> post );
unset ( $this -> comments );
unset ( $this -> comment );
$this -> comment_count = 0 ;
$this -> current_comment = - 1 ;
$this -> found_posts = 0 ;
$this -> max_num_pages = 0 ;
$this -> max_num_comment_pages = 0 ;
$this -> init_query_flags ();
}
/**
2023-09-26 10:33:34 +02:00
* Reparses the query vars .
2019-11-02 10:38:58 +01:00
*
* @ since 1.5 . 0
*/
public function parse_query_vars () {
$this -> parse_query ();
}
/**
* Fills in the query variables , which do not exist within the parameter .
*
* @ since 2.1 . 0
2019-11-15 22:59:44 +01:00
* @ since 4.5 . 0 Removed the `comments_popup` public query variable .
2019-11-02 10:38:58 +01:00
*
2022-06-16 14:03:35 +02:00
* @ param array $query_vars Defined query variables .
2019-11-02 10:38:58 +01:00
* @ return array Complete query variables with undefined ones filled in empty .
*/
2022-06-16 14:03:35 +02:00
public function fill_query_vars ( $query_vars ) {
2019-11-02 10:38:58 +01:00
$keys = array (
'error' ,
'm' ,
'p' ,
'post_parent' ,
'subpost' ,
'subpost_id' ,
'attachment' ,
'attachment_id' ,
'name' ,
'pagename' ,
'page_id' ,
'second' ,
'minute' ,
'hour' ,
'day' ,
'monthnum' ,
'year' ,
'w' ,
'category_name' ,
'tag' ,
'cat' ,
'tag_id' ,
'author' ,
'author_name' ,
'feed' ,
'tb' ,
'paged' ,
'meta_key' ,
'meta_value' ,
'preview' ,
's' ,
'sentence' ,
'title' ,
'fields' ,
'menu_order' ,
'embed' ,
);
foreach ( $keys as $key ) {
2022-06-16 14:03:35 +02:00
if ( ! isset ( $query_vars [ $key ] ) ) {
$query_vars [ $key ] = '' ;
2019-11-02 10:38:58 +01:00
}
}
$array_keys = array (
'category__in' ,
'category__not_in' ,
'category__and' ,
'post__in' ,
'post__not_in' ,
'post_name__in' ,
'tag__in' ,
'tag__not_in' ,
'tag__and' ,
'tag_slug__in' ,
'tag_slug__and' ,
'post_parent__in' ,
'post_parent__not_in' ,
'author__in' ,
'author__not_in' ,
2023-04-26 17:39:43 +02:00
'search_columns' ,
2019-11-02 10:38:58 +01:00
);
foreach ( $array_keys as $key ) {
2022-06-16 14:03:35 +02:00
if ( ! isset ( $query_vars [ $key ] ) ) {
$query_vars [ $key ] = array ();
2019-11-02 10:38:58 +01:00
}
}
2022-06-16 14:03:35 +02:00
return $query_vars ;
2019-11-02 10:38:58 +01:00
}
/**
2023-09-26 10:33:34 +02:00
* Parses a query string and sets query type booleans .
2019-11-02 10:38:58 +01:00
*
* @ since 1.5 . 0
* @ since 4.2 . 0 Introduced the ability to order by specific clauses of a `$meta_query` , by passing the clause ' s
* array key to `$orderby` .
* @ since 4.4 . 0 Introduced `$post_name__in` and `$title` parameters . `$s` was updated to support excluded
* search terms , by prepending a hyphen .
* @ since 4.5 . 0 Removed the `$comments_popup` parameter .
* Introduced the `$comment_status` and `$ping_status` parameters .
* Introduced `RAND(x)` syntax for `$orderby` , which allows an integer seed value to random sorts .
* @ since 4.6 . 0 Added 'post_name__in' support for `$orderby` . Introduced the `$lazy_load_term_meta` argument .
* @ since 4.9 . 0 Introduced the `$comment_count` parameter .
* @ since 5.1 . 0 Introduced the `$meta_compare_key` parameter .
2019-11-15 22:59:44 +01:00
* @ since 5.3 . 0 Introduced the `$meta_type_key` parameter .
2022-12-15 17:47:31 +01:00
* @ since 6.1 . 0 Introduced the `$update_menu_item_cache` parameter .
2023-04-26 17:39:43 +02:00
* @ since 6.2 . 0 Introduced the `$search_columns` parameter .
2019-11-02 10:38:58 +01:00
*
* @ param string | array $query {
* Optional . Array or string of Query parameters .
*
2023-09-26 10:33:34 +02:00
* @ type int $attachment_id Attachment post ID . Used for 'attachment' post_type .
* @ type int | string $author Author ID , or comma - separated list of IDs .
* @ type string $author_name User 'user_nicename' .
* @ type int [] $author__in An array of author IDs to query from .
* @ type int [] $author__not_in An array of author IDs not to query from .
* @ type bool $cache_results Whether to cache post information . Default true .
* @ type int | string $cat Category ID or comma - separated list of IDs ( this or any children ) .
* @ type int [] $category__and An array of category IDs ( AND in ) .
* @ type int [] $category__in An array of category IDs ( OR in , no children ) .
* @ type int [] $category__not_in An array of category IDs ( NOT in ) .
* @ type string $category_name Use category slug ( not name , this or any children ) .
* @ type array | int $comment_count Filter results by comment count . Provide an integer to match
* comment count exactly . Provide an array with integer 'value'
* and 'compare' operator ( '=' , '!=' , '>' , '>=' , '<' , '<=' ) to
* compare against comment_count in a specific way .
* @ type string $comment_status Comment status .
* @ type int $comments_per_page The number of comments to return per page .
* Default 'comments_per_page' option .
* @ type array $date_query An associative array of WP_Date_Query arguments .
* See WP_Date_Query :: __construct () .
* @ type int $day Day of the month . Default empty . Accepts numbers 1 - 31.
* @ type bool $exact Whether to search by exact keyword . Default false .
* @ type string $fields Post fields to query for . Accepts :
* - '' Returns an array of complete post objects ( `WP_Post[]` ) .
* - 'ids' Returns an array of post IDs ( `int[]` ) .
* - 'id=>parent' Returns an associative array of parent post IDs ,
* keyed by post ID ( `int[]` ) .
* Default '' .
* @ type int $hour Hour of the day . Default empty . Accepts numbers 0 - 23.
* @ type int | bool $ignore_sticky_posts Whether to ignore sticky posts or not . Setting this to false
* excludes stickies from 'post__in' . Accepts 1 | true , 0 | false .
* Default false .
* @ type int $m Combination YearMonth . Accepts any four - digit year and month
* numbers 01 - 12. Default empty .
* @ type string | string [] $meta_key Meta key or keys to filter by .
* @ type string | string [] $meta_value Meta value or values to filter by .
* @ type string $meta_compare MySQL operator used for comparing the meta value .
* See WP_Meta_Query :: __construct () for accepted values and default value .
* @ type string $meta_compare_key MySQL operator used for comparing the meta key .
* See WP_Meta_Query :: __construct () for accepted values and default value .
* @ type string $meta_type MySQL data type that the meta_value column will be CAST to for comparisons .
* See WP_Meta_Query :: __construct () for accepted values and default value .
* @ type string $meta_type_key MySQL data type that the meta_key column will be CAST to for comparisons .
* See WP_Meta_Query :: __construct () for accepted values and default value .
* @ type array $meta_query An associative array of WP_Meta_Query arguments .
* See WP_Meta_Query :: __construct () for accepted values .
* @ type int $menu_order The menu order of the posts .
* @ type int $minute Minute of the hour . Default empty . Accepts numbers 0 - 59.
* @ type int $monthnum The two - digit month . Default empty . Accepts numbers 1 - 12.
* @ type string $name Post slug .
* @ type bool $nopaging Show all posts ( true ) or paginate ( false ) . Default false .
* @ type bool $no_found_rows Whether to skip counting the total rows found . Enabling can improve
* performance . Default false .
* @ type int $offset The number of posts to offset before retrieval .
* @ type string $order Designates ascending or descending order of posts . Default 'DESC' .
* Accepts 'ASC' , 'DESC' .
* @ type string | array $orderby Sort retrieved posts by parameter . One or more options may be passed .
* To use 'meta_value' , or 'meta_value_num' , 'meta_key=keyname' must be
* also be defined . To sort by a specific `$meta_query` clause , use that
* clause ' s array key . Accepts :
* - 'none'
* - 'name'
* - 'author'
* - 'date'
* - 'title'
* - 'modified'
* - 'menu_order'
* - 'parent'
* - 'ID'
* - 'rand'
* - 'relevance'
* - 'RAND(x)' ( where 'x' is an integer seed value )
* - 'comment_count'
* - 'meta_value'
* - 'meta_value_num'
* - 'post__in'
* - 'post_name__in'
* - 'post_parent__in'
* - The array keys of `$meta_query` .
* Default is 'date' , except when a search is being performed , when
* the default is 'relevance' .
* @ type int $p Post ID .
* @ type int $page Show the number of posts that would show up on page X of a
* static front page .
* @ type int $paged The number of the current page .
* @ type int $page_id Page ID .
* @ type string $pagename Page slug .
* @ type string $perm Show posts if user has the appropriate capability .
* @ type string $ping_status Ping status .
* @ type int [] $post__in An array of post IDs to retrieve , sticky posts will be included .
* @ type int [] $post__not_in An array of post IDs not to retrieve . Note : a string of comma -
* separated IDs will NOT work .
* @ type string $post_mime_type The mime type of the post . Used for 'attachment' post_type .
* @ type string [] $post_name__in An array of post slugs that results must match .
* @ type int $post_parent Page ID to retrieve child pages for . Use 0 to only retrieve
* top - level pages .
* @ type int [] $post_parent__in An array containing parent page IDs to query child pages from .
* @ type int [] $post_parent__not_in An array containing parent page IDs not to query child pages from .
* @ type string | string [] $post_type A post type slug ( string ) or array of post type slugs .
* Default 'any' if using 'tax_query' .
* @ type string | string [] $post_status A post status ( string ) or array of post statuses .
* @ type int $posts_per_page The number of posts to query for . Use - 1 to request all posts .
* @ type int $posts_per_archive_page The number of posts to query for by archive page . Overrides
* 'posts_per_page' when is_archive (), or is_search () are true .
* @ type string $s Search keyword ( s ) . Prepending a term with a hyphen will
* exclude posts matching that term . Eg , 'pillow -sofa' will
* return posts containing 'pillow' but not 'sofa' . The
* character used for exclusion can be modified using the
* the 'wp_query_search_exclusion_prefix' filter .
* @ type string [] $search_columns Array of column names to be searched . Accepts 'post_title' ,
* 'post_excerpt' and 'post_content' . Default empty array .
* @ type int $second Second of the minute . Default empty . Accepts numbers 0 - 59.
* @ type bool $sentence Whether to search by phrase . Default false .
* @ type bool $suppress_filters Whether to suppress filters . Default false .
* @ type string $tag Tag slug . Comma - separated ( either ), Plus - separated ( all ) .
* @ type int [] $tag__and An array of tag IDs ( AND in ) .
* @ type int [] $tag__in An array of tag IDs ( OR in ) .
* @ type int [] $tag__not_in An array of tag IDs ( NOT in ) .
* @ type int $tag_id Tag id or comma - separated list of IDs .
* @ type string [] $tag_slug__and An array of tag slugs ( AND in ) .
* @ type string [] $tag_slug__in An array of tag slugs ( OR in ) . unless 'ignore_sticky_posts' is
* true . Note : a string of comma - separated IDs will NOT work .
* @ type array $tax_query An associative array of WP_Tax_Query arguments .
* See WP_Tax_Query :: __construct () .
* @ type string $title Post title .
* @ type bool $update_post_meta_cache Whether to update the post meta cache . Default true .
* @ type bool $update_post_term_cache Whether to update the post term cache . Default true .
* @ type bool $update_menu_item_cache Whether to update the menu item cache . Default false .
* @ type bool $lazy_load_term_meta Whether to lazy - load term meta . Setting to false will
* disable cache priming for term meta , so that each
* get_term_meta () call will hit the database .
* Defaults to the value of `$update_post_term_cache` .
* @ type int $w The week number of the year . Default empty . Accepts numbers 0 - 53.
* @ type int $year The four - digit year . Default empty . Accepts any four - digit year .
2019-11-02 10:38:58 +01:00
* }
*/
public function parse_query ( $query = '' ) {
if ( ! empty ( $query ) ) {
$this -> init ();
2019-11-15 22:59:44 +01:00
$this -> query = wp_parse_args ( $query );
$this -> query_vars = $this -> query ;
2019-11-02 10:38:58 +01:00
} elseif ( ! isset ( $this -> query ) ) {
$this -> query = $this -> query_vars ;
}
$this -> query_vars = $this -> fill_query_vars ( $this -> query_vars );
2025-12-12 13:15:55 +01:00
$query_vars = & $this -> query_vars ;
2019-11-02 10:38:58 +01:00
$this -> query_vars_changed = true ;
2025-12-12 13:15:55 +01:00
if ( ! empty ( $query_vars [ 'robots' ] ) ) {
2019-11-02 10:38:58 +01:00
$this -> is_robots = true ;
2025-12-12 13:15:55 +01:00
} elseif ( ! empty ( $query_vars [ 'favicon' ] ) ) {
2020-05-06 17:23:38 +02:00
$this -> is_favicon = true ;
2019-11-02 10:38:58 +01:00
}
2025-12-12 13:15:55 +01:00
if ( ! is_scalar ( $query_vars [ 'p' ] ) || ( int ) $query_vars [ 'p' ] < 0 ) {
$query_vars [ 'p' ] = 0 ;
$query_vars [ 'error' ] = '404' ;
2019-11-02 10:38:58 +01:00
} else {
2025-12-12 13:15:55 +01:00
$query_vars [ 'p' ] = ( int ) $query_vars [ 'p' ];
}
$query_vars [ 'page_id' ] = is_scalar ( $query_vars [ 'page_id' ] ) ? absint ( $query_vars [ 'page_id' ] ) : 0 ;
$query_vars [ 'year' ] = is_scalar ( $query_vars [ 'year' ] ) ? absint ( $query_vars [ 'year' ] ) : 0 ;
$query_vars [ 'monthnum' ] = is_scalar ( $query_vars [ 'monthnum' ] ) ? absint ( $query_vars [ 'monthnum' ] ) : 0 ;
$query_vars [ 'day' ] = is_scalar ( $query_vars [ 'day' ] ) ? absint ( $query_vars [ 'day' ] ) : 0 ;
$query_vars [ 'w' ] = is_scalar ( $query_vars [ 'w' ] ) ? absint ( $query_vars [ 'w' ] ) : 0 ;
$query_vars [ 'm' ] = is_scalar ( $query_vars [ 'm' ] ) ? preg_replace ( '|[^0-9]|' , '' , $query_vars [ 'm' ] ) : '' ;
$query_vars [ 'paged' ] = is_scalar ( $query_vars [ 'paged' ] ) ? absint ( $query_vars [ 'paged' ] ) : 0 ;
$query_vars [ 'cat' ] = preg_replace ( '|[^0-9,-]|' , '' , $query_vars [ 'cat' ] ); // Array or comma-separated list of positive or negative integers.
$query_vars [ 'author' ] = is_scalar ( $query_vars [ 'author' ] ) ? preg_replace ( '|[^0-9,-]|' , '' , $query_vars [ 'author' ] ) : '' ; // Comma-separated list of positive or negative integers.
$query_vars [ 'pagename' ] = is_scalar ( $query_vars [ 'pagename' ] ) ? trim ( $query_vars [ 'pagename' ] ) : '' ;
$query_vars [ 'name' ] = is_scalar ( $query_vars [ 'name' ] ) ? trim ( $query_vars [ 'name' ] ) : '' ;
$query_vars [ 'title' ] = is_scalar ( $query_vars [ 'title' ] ) ? trim ( $query_vars [ 'title' ] ) : '' ;
if ( is_scalar ( $query_vars [ 'hour' ] ) && '' !== $query_vars [ 'hour' ] ) {
$query_vars [ 'hour' ] = absint ( $query_vars [ 'hour' ] );
2022-12-15 17:47:31 +01:00
} else {
2025-12-12 13:15:55 +01:00
$query_vars [ 'hour' ] = '' ;
2019-11-02 10:38:58 +01:00
}
2022-12-15 17:47:31 +01:00
2025-12-12 13:15:55 +01:00
if ( is_scalar ( $query_vars [ 'minute' ] ) && '' !== $query_vars [ 'minute' ] ) {
$query_vars [ 'minute' ] = absint ( $query_vars [ 'minute' ] );
2022-12-15 17:47:31 +01:00
} else {
2025-12-12 13:15:55 +01:00
$query_vars [ 'minute' ] = '' ;
2019-11-02 10:38:58 +01:00
}
2022-12-15 17:47:31 +01:00
2025-12-12 13:15:55 +01:00
if ( is_scalar ( $query_vars [ 'second' ] ) && '' !== $query_vars [ 'second' ] ) {
$query_vars [ 'second' ] = absint ( $query_vars [ 'second' ] );
2022-12-15 17:47:31 +01:00
} else {
2025-12-12 13:15:55 +01:00
$query_vars [ 'second' ] = '' ;
2019-11-02 10:38:58 +01:00
}
2022-12-15 17:47:31 +01:00
2025-12-12 13:15:55 +01:00
if ( is_scalar ( $query_vars [ 'menu_order' ] ) && '' !== $query_vars [ 'menu_order' ] ) {
$query_vars [ 'menu_order' ] = absint ( $query_vars [ 'menu_order' ] );
2022-12-15 17:47:31 +01:00
} else {
2025-12-12 13:15:55 +01:00
$query_vars [ 'menu_order' ] = '' ;
2019-11-02 10:38:58 +01:00
}
2020-12-10 14:06:04 +01:00
// Fairly large, potentially too large, upper bound for search string lengths.
2025-12-12 13:15:55 +01:00
if ( ! is_scalar ( $query_vars [ 's' ] ) || ( ! empty ( $query_vars [ 's' ] ) && strlen ( $query_vars [ 's' ] ) > 1600 ) ) {
$query_vars [ 's' ] = '' ;
2019-11-02 10:38:58 +01:00
}
// Compat. Map subpost to attachment.
2025-12-12 13:15:55 +01:00
if ( is_scalar ( $query_vars [ 'subpost' ] ) && '' != $query_vars [ 'subpost' ] ) {
$query_vars [ 'attachment' ] = $query_vars [ 'subpost' ];
2019-11-02 10:38:58 +01:00
}
2025-12-12 13:15:55 +01:00
if ( is_scalar ( $query_vars [ 'subpost_id' ] ) && '' != $query_vars [ 'subpost_id' ] ) {
$query_vars [ 'attachment_id' ] = $query_vars [ 'subpost_id' ];
2019-11-02 10:38:58 +01:00
}
2025-12-12 13:15:55 +01:00
$query_vars [ 'attachment_id' ] = is_scalar ( $query_vars [ 'attachment_id' ] ) ? absint ( $query_vars [ 'attachment_id' ] ) : 0 ;
2019-11-02 10:38:58 +01:00
2025-12-12 13:15:55 +01:00
if ( ( '' !== $query_vars [ 'attachment' ] ) || ! empty ( $query_vars [ 'attachment_id' ] ) ) {
2019-11-02 10:38:58 +01:00
$this -> is_single = true ;
$this -> is_attachment = true ;
2025-12-12 13:15:55 +01:00
} elseif ( '' !== $query_vars [ 'name' ] ) {
2019-11-02 10:38:58 +01:00
$this -> is_single = true ;
2025-12-12 13:15:55 +01:00
} elseif ( $query_vars [ 'p' ] ) {
2019-11-02 10:38:58 +01:00
$this -> is_single = true ;
2025-12-12 13:15:55 +01:00
} elseif ( '' !== $query_vars [ 'pagename' ] || ! empty ( $query_vars [ 'page_id' ] ) ) {
2019-11-02 10:38:58 +01:00
$this -> is_page = true ;
$this -> is_single = false ;
} else {
// Look for archive queries. Dates, categories, authors, search, post type archives.
if ( isset ( $this -> query [ 's' ] ) ) {
$this -> is_search = true ;
}
2025-12-12 13:15:55 +01:00
if ( '' !== $query_vars [ 'second' ] ) {
2019-11-02 10:38:58 +01:00
$this -> is_time = true ;
$this -> is_date = true ;
}
2025-12-12 13:15:55 +01:00
if ( '' !== $query_vars [ 'minute' ] ) {
2019-11-02 10:38:58 +01:00
$this -> is_time = true ;
$this -> is_date = true ;
}
2025-12-12 13:15:55 +01:00
if ( '' !== $query_vars [ 'hour' ] ) {
2019-11-02 10:38:58 +01:00
$this -> is_time = true ;
$this -> is_date = true ;
}
2025-12-12 13:15:55 +01:00
if ( $query_vars [ 'day' ] ) {
2019-11-02 10:38:58 +01:00
if ( ! $this -> is_date ) {
2025-12-12 13:15:55 +01:00
$date = sprintf ( '%04d-%02d-%02d' , $query_vars [ 'year' ], $query_vars [ 'monthnum' ], $query_vars [ 'day' ] );
if ( $query_vars [ 'monthnum' ] && $query_vars [ 'year' ] && ! wp_checkdate ( $query_vars [ 'monthnum' ], $query_vars [ 'day' ], $query_vars [ 'year' ], $date ) ) {
$query_vars [ 'error' ] = '404' ;
2019-11-02 10:38:58 +01:00
} else {
$this -> is_day = true ;
$this -> is_date = true ;
}
}
}
2025-12-12 13:15:55 +01:00
if ( $query_vars [ 'monthnum' ] ) {
2019-11-02 10:38:58 +01:00
if ( ! $this -> is_date ) {
2025-12-12 13:15:55 +01:00
if ( 12 < $query_vars [ 'monthnum' ] ) {
$query_vars [ 'error' ] = '404' ;
2019-11-02 10:38:58 +01:00
} else {
$this -> is_month = true ;
$this -> is_date = true ;
}
}
}
2025-12-12 13:15:55 +01:00
if ( $query_vars [ 'year' ] ) {
2019-11-02 10:38:58 +01:00
if ( ! $this -> is_date ) {
$this -> is_year = true ;
$this -> is_date = true ;
}
}
2025-12-12 13:15:55 +01:00
if ( $query_vars [ 'm' ] ) {
2019-11-02 10:38:58 +01:00
$this -> is_date = true ;
2025-12-12 13:15:55 +01:00
if ( strlen ( $query_vars [ 'm' ] ) > 9 ) {
2019-11-02 10:38:58 +01:00
$this -> is_time = true ;
2025-12-12 13:15:55 +01:00
} elseif ( strlen ( $query_vars [ 'm' ] ) > 7 ) {
2019-11-02 10:38:58 +01:00
$this -> is_day = true ;
2025-12-12 13:15:55 +01:00
} elseif ( strlen ( $query_vars [ 'm' ] ) > 5 ) {
2019-11-02 10:38:58 +01:00
$this -> is_month = true ;
} else {
$this -> is_year = true ;
}
}
2025-12-12 13:15:55 +01:00
if ( $query_vars [ 'w' ] ) {
2019-11-02 10:38:58 +01:00
$this -> is_date = true ;
}
$this -> query_vars_hash = false ;
2025-12-12 13:15:55 +01:00
$this -> parse_tax_query ( $query_vars );
2019-11-02 10:38:58 +01:00
foreach ( $this -> tax_query -> queries as $tax_query ) {
if ( ! is_array ( $tax_query ) ) {
continue ;
}
2020-09-15 14:29:22 +02:00
if ( isset ( $tax_query [ 'operator' ] ) && 'NOT IN' !== $tax_query [ 'operator' ] ) {
2019-11-02 10:38:58 +01:00
switch ( $tax_query [ 'taxonomy' ] ) {
case 'category' :
$this -> is_category = true ;
break ;
case 'post_tag' :
$this -> is_tag = true ;
break ;
default :
$this -> is_tax = true ;
}
}
}
unset ( $tax_query );
2025-12-12 13:15:55 +01:00
if ( empty ( $query_vars [ 'author' ] ) || ( '0' == $query_vars [ 'author' ] ) ) {
2019-11-02 10:38:58 +01:00
$this -> is_author = false ;
} else {
$this -> is_author = true ;
}
2025-12-12 13:15:55 +01:00
if ( '' !== $query_vars [ 'author_name' ] ) {
2019-11-02 10:38:58 +01:00
$this -> is_author = true ;
}
2025-12-12 13:15:55 +01:00
if ( ! empty ( $query_vars [ 'post_type' ] ) && ! is_array ( $query_vars [ 'post_type' ] ) ) {
$post_type_obj = get_post_type_object ( $query_vars [ 'post_type' ] );
2019-11-02 10:38:58 +01:00
if ( ! empty ( $post_type_obj -> has_archive ) ) {
$this -> is_post_type_archive = true ;
}
}
if ( $this -> is_post_type_archive || $this -> is_date || $this -> is_author || $this -> is_category || $this -> is_tag || $this -> is_tax ) {
$this -> is_archive = true ;
}
}
2025-12-12 13:15:55 +01:00
if ( '' != $query_vars [ 'feed' ] ) {
2019-11-02 10:38:58 +01:00
$this -> is_feed = true ;
}
2025-12-12 13:15:55 +01:00
if ( '' != $query_vars [ 'embed' ] ) {
2019-11-02 10:38:58 +01:00
$this -> is_embed = true ;
}
2025-12-12 13:15:55 +01:00
if ( '' != $query_vars [ 'tb' ] ) {
2019-11-02 10:38:58 +01:00
$this -> is_trackback = true ;
}
2025-12-12 13:15:55 +01:00
if ( '' != $query_vars [ 'paged' ] && ( ( int ) $query_vars [ 'paged' ] > 1 ) ) {
2019-11-02 10:38:58 +01:00
$this -> is_paged = true ;
}
2020-05-06 17:23:38 +02:00
// If we're previewing inside the write screen.
2025-12-12 13:15:55 +01:00
if ( '' != $query_vars [ 'preview' ] ) {
2019-11-02 10:38:58 +01:00
$this -> is_preview = true ;
}
if ( is_admin () ) {
$this -> is_admin = true ;
}
2025-12-12 13:15:55 +01:00
if ( str_contains ( $query_vars [ 'feed' ], 'comments-' ) ) {
$query_vars [ 'feed' ] = str_replace ( 'comments-' , '' , $query_vars [ 'feed' ] );
$query_vars [ 'withcomments' ] = 1 ;
2019-11-02 10:38:58 +01:00
}
$this -> is_singular = $this -> is_single || $this -> is_page || $this -> is_attachment ;
2025-12-12 13:15:55 +01:00
if ( $this -> is_feed && ( ! empty ( $query_vars [ 'withcomments' ] ) || ( empty ( $query_vars [ 'withoutcomments' ] ) && $this -> is_singular ) ) ) {
2019-11-02 10:38:58 +01:00
$this -> is_comment_feed = true ;
}
2020-05-06 17:23:38 +02:00
if ( ! ( $this -> is_singular || $this -> is_archive || $this -> is_search || $this -> is_feed
2024-04-17 11:32:24 +02:00
|| ( wp_is_serving_rest_request () && $this -> is_main_query () )
2020-05-06 17:23:38 +02:00
|| $this -> is_trackback || $this -> is_404 || $this -> is_admin || $this -> is_robots || $this -> is_favicon ) ) {
2019-11-02 10:38:58 +01:00
$this -> is_home = true ;
}
2020-05-06 17:23:38 +02:00
// Correct `is_*` for 'page_on_front' and 'page_for_posts'.
2020-09-15 14:29:22 +02:00
if ( $this -> is_home && 'page' === get_option ( 'show_on_front' ) && get_option ( 'page_on_front' ) ) {
2019-11-02 10:38:58 +01:00
$_query = wp_parse_args ( $this -> query );
2020-05-06 17:23:38 +02:00
// 'pagename' can be set and empty depending on matched rewrite rules. Ignore an empty 'pagename'.
2020-09-15 14:29:22 +02:00
if ( isset ( $_query [ 'pagename' ] ) && '' === $_query [ 'pagename' ] ) {
2019-11-02 10:38:58 +01:00
unset ( $_query [ 'pagename' ] );
}
unset ( $_query [ 'embed' ] );
if ( empty ( $_query ) || ! array_diff ( array_keys ( $_query ), array ( 'preview' , 'page' , 'paged' , 'cpage' ) ) ) {
2025-12-12 13:15:55 +01:00
$this -> is_page = true ;
$this -> is_home = false ;
$query_vars [ 'page_id' ] = get_option ( 'page_on_front' );
2020-05-06 17:23:38 +02:00
// Correct <!--nextpage--> for 'page_on_front'.
2025-12-12 13:15:55 +01:00
if ( ! empty ( $query_vars [ 'paged' ] ) ) {
$query_vars [ 'page' ] = $query_vars [ 'paged' ];
unset ( $query_vars [ 'paged' ] );
2019-11-02 10:38:58 +01:00
}
}
}
2025-12-12 13:15:55 +01:00
if ( '' !== $query_vars [ 'pagename' ] ) {
$this -> queried_object = get_page_by_path ( $query_vars [ 'pagename' ] );
2019-11-02 10:38:58 +01:00
2020-09-15 14:29:22 +02:00
if ( $this -> queried_object && 'attachment' === $this -> queried_object -> post_type ) {
2019-11-02 10:38:58 +01:00
if ( preg_match ( '/^[^%]*%(?:postname)%/' , get_option ( 'permalink_structure' ) ) ) {
2020-05-06 17:23:38 +02:00
// See if we also have a post with the same slug.
2025-12-12 13:15:55 +01:00
$post = get_page_by_path ( $query_vars [ 'pagename' ], OBJECT , 'post' );
2019-11-02 10:38:58 +01:00
if ( $post ) {
$this -> queried_object = $post ;
$this -> is_page = false ;
$this -> is_single = true ;
}
}
}
if ( ! empty ( $this -> queried_object ) ) {
$this -> queried_object_id = ( int ) $this -> queried_object -> ID ;
} else {
unset ( $this -> queried_object );
}
2020-05-06 17:23:38 +02:00
if ( 'page' === get_option ( 'show_on_front' ) && isset ( $this -> queried_object_id ) && get_option ( 'page_for_posts' ) == $this -> queried_object_id ) {
2019-11-02 10:38:58 +01:00
$this -> is_page = false ;
$this -> is_home = true ;
$this -> is_posts_page = true ;
}
2020-05-06 17:23:38 +02:00
if ( isset ( $this -> queried_object_id ) && get_option ( 'wp_page_for_privacy_policy' ) == $this -> queried_object_id ) {
2019-11-02 10:38:58 +01:00
$this -> is_privacy_policy = true ;
}
}
2025-12-12 13:15:55 +01:00
if ( $query_vars [ 'page_id' ] ) {
if ( 'page' === get_option ( 'show_on_front' ) && get_option ( 'page_for_posts' ) == $query_vars [ 'page_id' ] ) {
2019-11-02 10:38:58 +01:00
$this -> is_page = false ;
$this -> is_home = true ;
$this -> is_posts_page = true ;
}
2025-12-12 13:15:55 +01:00
if ( get_option ( 'wp_page_for_privacy_policy' ) == $query_vars [ 'page_id' ] ) {
2019-11-02 10:38:58 +01:00
$this -> is_privacy_policy = true ;
}
}
2025-12-12 13:15:55 +01:00
if ( ! empty ( $query_vars [ 'post_type' ] ) ) {
if ( is_array ( $query_vars [ 'post_type' ] ) ) {
$query_vars [ 'post_type' ] = array_map ( 'sanitize_key' , array_unique ( $query_vars [ 'post_type' ] ) );
sort ( $query_vars [ 'post_type' ] );
2019-11-02 10:38:58 +01:00
} else {
2025-12-12 13:15:55 +01:00
$query_vars [ 'post_type' ] = sanitize_key ( $query_vars [ 'post_type' ] );
2019-11-02 10:38:58 +01:00
}
}
2025-12-12 13:15:55 +01:00
if ( ! empty ( $query_vars [ 'post_status' ] ) ) {
if ( is_array ( $query_vars [ 'post_status' ] ) ) {
$query_vars [ 'post_status' ] = array_map ( 'sanitize_key' , array_unique ( $query_vars [ 'post_status' ] ) );
sort ( $query_vars [ 'post_status' ] );
2019-11-02 10:38:58 +01:00
} else {
2025-12-12 13:15:55 +01:00
$query_vars [ 'post_status' ] = preg_replace ( '|[^a-z0-9_,-]|' , '' , $query_vars [ 'post_status' ] );
2019-11-02 10:38:58 +01:00
}
}
2025-12-12 13:15:55 +01:00
if ( $this -> is_posts_page && ( ! isset ( $query_vars [ 'withcomments' ] ) || ! $query_vars [ 'withcomments' ] ) ) {
2019-11-02 10:38:58 +01:00
$this -> is_comment_feed = false ;
}
$this -> is_singular = $this -> is_single || $this -> is_page || $this -> is_attachment ;
2020-05-06 17:23:38 +02:00
// Done correcting `is_*` for 'page_on_front' and 'page_for_posts'.
2019-11-02 10:38:58 +01:00
2025-12-12 13:15:55 +01:00
if ( '404' == $query_vars [ 'error' ] ) {
2019-11-02 10:38:58 +01:00
$this -> set_404 ();
}
$this -> is_embed = $this -> is_embed && ( $this -> is_singular || $this -> is_404 );
$this -> query_vars_hash = md5 ( serialize ( $this -> query_vars ) );
$this -> query_vars_changed = false ;
/**
* Fires after the main query vars have been parsed .
*
* @ since 1.5 . 0
*
2021-04-27 08:32:47 +02:00
* @ param WP_Query $query The WP_Query instance ( passed by reference ) .
2019-11-02 10:38:58 +01:00
*/
do_action_ref_array ( 'parse_query' , array ( & $this ) );
}
/**
* Parses various taxonomy related query vars .
*
* For BC , this method is not marked as protected . See [ 28987 ] .
*
* @ since 3.1 . 0
*
2025-12-12 13:15:55 +01:00
* @ param array $query_vars The query variables . Passed by reference .
2019-11-02 10:38:58 +01:00
*/
2025-12-12 13:15:55 +01:00
public function parse_tax_query ( & $query_vars ) {
if ( ! empty ( $query_vars [ 'tax_query' ] ) && is_array ( $query_vars [ 'tax_query' ] ) ) {
$tax_query = $query_vars [ 'tax_query' ];
2019-11-02 10:38:58 +01:00
} else {
$tax_query = array ();
}
2025-12-12 13:15:55 +01:00
if ( ! empty ( $query_vars [ 'taxonomy' ] ) && ! empty ( $query_vars [ 'term' ] ) ) {
2019-11-02 10:38:58 +01:00
$tax_query [] = array (
2025-12-12 13:15:55 +01:00
'taxonomy' => $query_vars [ 'taxonomy' ],
'terms' => array ( $query_vars [ 'term' ] ),
2019-11-02 10:38:58 +01:00
'field' => 'slug' ,
);
}
foreach ( get_taxonomies ( array (), 'objects' ) as $taxonomy => $t ) {
2020-09-15 14:29:22 +02:00
if ( 'post_tag' === $taxonomy ) {
2025-12-12 13:15:55 +01:00
continue ; // Handled further down in the $query_vars['tag'] block.
2019-11-02 10:38:58 +01:00
}
2025-12-12 13:15:55 +01:00
if ( $t -> query_var && ! empty ( $query_vars [ $t -> query_var ] ) ) {
2019-11-02 10:38:58 +01:00
$tax_query_defaults = array (
'taxonomy' => $taxonomy ,
'field' => 'slug' ,
);
2021-07-23 11:58:50 +02:00
if ( ! empty ( $t -> rewrite [ 'hierarchical' ] ) ) {
2025-12-12 13:15:55 +01:00
$query_vars [ $t -> query_var ] = wp_basename ( $query_vars [ $t -> query_var ] );
2019-11-02 10:38:58 +01:00
}
2025-12-12 13:15:55 +01:00
$term = $query_vars [ $t -> query_var ];
2019-11-02 10:38:58 +01:00
2025-04-25 12:30:07 +02:00
if ( ! is_array ( $term ) ) {
$term = explode ( ',' , $term );
$term = array_map ( 'trim' , $term );
2019-11-02 10:38:58 +01:00
}
2025-04-25 12:30:07 +02:00
sort ( $term );
$term = implode ( ',' , $term );
2019-11-02 10:38:58 +01:00
2023-09-26 10:33:34 +02:00
if ( str_contains ( $term , '+' ) ) {
2019-11-02 10:38:58 +01:00
$terms = preg_split ( '/[+]+/' , $term );
foreach ( $terms as $term ) {
$tax_query [] = array_merge (
$tax_query_defaults ,
array (
'terms' => array ( $term ),
)
);
}
} else {
$tax_query [] = array_merge (
$tax_query_defaults ,
array (
'terms' => preg_split ( '/[,]+/' , $term ),
)
);
}
}
}
2020-05-06 17:23:38 +02:00
// If query string 'cat' is an array, implode it.
2025-12-12 13:15:55 +01:00
if ( is_array ( $query_vars [ 'cat' ] ) ) {
$query_vars [ 'cat' ] = implode ( ',' , $query_vars [ 'cat' ] );
2019-11-02 10:38:58 +01:00
}
2020-05-06 17:23:38 +02:00
// Category stuff.
2025-12-12 13:15:55 +01:00
if ( ! empty ( $query_vars [ 'cat' ] ) && ! $this -> is_singular ) {
2019-11-15 22:59:44 +01:00
$cat_in = array ();
$cat_not_in = array ();
2019-11-02 10:38:58 +01:00
2025-12-12 13:15:55 +01:00
$cat_array = preg_split ( '/[,\s]+/' , urldecode ( $query_vars [ 'cat' ] ) );
2019-11-02 10:38:58 +01:00
$cat_array = array_map ( 'intval' , $cat_array );
2025-04-25 12:30:07 +02:00
sort ( $cat_array );
2025-12-12 13:15:55 +01:00
$query_vars [ 'cat' ] = implode ( ',' , $cat_array );
2019-11-02 10:38:58 +01:00
foreach ( $cat_array as $cat ) {
if ( $cat > 0 ) {
$cat_in [] = $cat ;
} elseif ( $cat < 0 ) {
$cat_not_in [] = abs ( $cat );
}
}
if ( ! empty ( $cat_in ) ) {
$tax_query [] = array (
'taxonomy' => 'category' ,
'terms' => $cat_in ,
'field' => 'term_id' ,
'include_children' => true ,
);
}
if ( ! empty ( $cat_not_in ) ) {
$tax_query [] = array (
'taxonomy' => 'category' ,
'terms' => $cat_not_in ,
'field' => 'term_id' ,
'operator' => 'NOT IN' ,
'include_children' => true ,
);
}
unset ( $cat_array , $cat_in , $cat_not_in );
}
2025-12-12 13:15:55 +01:00
if ( ! empty ( $query_vars [ 'category__and' ] ) && 1 === count ( ( array ) $query_vars [ 'category__and' ] ) ) {
$query_vars [ 'category__and' ] = ( array ) $query_vars [ 'category__and' ];
if ( ! isset ( $query_vars [ 'category__in' ] ) ) {
$query_vars [ 'category__in' ] = array ();
2019-11-02 10:38:58 +01:00
}
2025-12-12 13:15:55 +01:00
$query_vars [ 'category__in' ][] = absint ( reset ( $query_vars [ 'category__and' ] ) );
unset ( $query_vars [ 'category__and' ] );
2019-11-02 10:38:58 +01:00
}
2025-12-12 13:15:55 +01:00
if ( ! empty ( $query_vars [ 'category__in' ] ) ) {
$query_vars [ 'category__in' ] = array_map ( 'absint' , array_unique ( ( array ) $query_vars [ 'category__in' ] ) );
sort ( $query_vars [ 'category__in' ] );
2025-04-25 12:30:07 +02:00
$tax_query [] = array (
2019-11-02 10:38:58 +01:00
'taxonomy' => 'category' ,
2025-12-12 13:15:55 +01:00
'terms' => $query_vars [ 'category__in' ],
2019-11-02 10:38:58 +01:00
'field' => 'term_id' ,
'include_children' => false ,
);
}
2025-12-12 13:15:55 +01:00
if ( ! empty ( $query_vars [ 'category__not_in' ] ) ) {
$query_vars [ 'category__not_in' ] = array_map ( 'absint' , array_unique ( ( array ) $query_vars [ 'category__not_in' ] ) );
sort ( $query_vars [ 'category__not_in' ] );
2025-04-25 12:30:07 +02:00
$tax_query [] = array (
2019-11-02 10:38:58 +01:00
'taxonomy' => 'category' ,
2025-12-12 13:15:55 +01:00
'terms' => $query_vars [ 'category__not_in' ],
2019-11-02 10:38:58 +01:00
'operator' => 'NOT IN' ,
'include_children' => false ,
);
}
2025-12-12 13:15:55 +01:00
if ( ! empty ( $query_vars [ 'category__and' ] ) ) {
$query_vars [ 'category__and' ] = array_map ( 'absint' , array_unique ( ( array ) $query_vars [ 'category__and' ] ) );
sort ( $query_vars [ 'category__and' ] );
2025-04-25 12:30:07 +02:00
$tax_query [] = array (
2019-11-02 10:38:58 +01:00
'taxonomy' => 'category' ,
2025-12-12 13:15:55 +01:00
'terms' => $query_vars [ 'category__and' ],
2019-11-02 10:38:58 +01:00
'field' => 'term_id' ,
'operator' => 'AND' ,
'include_children' => false ,
);
}
2020-05-06 17:23:38 +02:00
// If query string 'tag' is array, implode it.
2025-12-12 13:15:55 +01:00
if ( is_array ( $query_vars [ 'tag' ] ) ) {
$query_vars [ 'tag' ] = implode ( ',' , $query_vars [ 'tag' ] );
2019-11-02 10:38:58 +01:00
}
2020-05-06 17:23:38 +02:00
// Tag stuff.
2025-12-12 13:15:55 +01:00
if ( '' !== $query_vars [ 'tag' ] && ! $this -> is_singular && $this -> query_vars_changed ) {
if ( str_contains ( $query_vars [ 'tag' ], ',' ) ) {
2025-04-25 12:30:07 +02:00
// @todo Handle normalizing `tag` query string.
2025-12-12 13:15:55 +01:00
$tags = preg_split ( '/[,\r\n\t ]+/' , $query_vars [ 'tag' ] );
2019-11-02 10:38:58 +01:00
foreach ( ( array ) $tags as $tag ) {
2025-12-12 13:15:55 +01:00
$tag = sanitize_term_field ( 'slug' , $tag , 0 , 'post_tag' , 'db' );
$query_vars [ 'tag_slug__in' ][] = $tag ;
sort ( $query_vars [ 'tag_slug__in' ] );
2019-11-02 10:38:58 +01:00
}
2025-12-12 13:15:55 +01:00
} elseif ( preg_match ( '/[+\r\n\t ]+/' , $query_vars [ 'tag' ] ) || ! empty ( $query_vars [ 'cat' ] ) ) {
$tags = preg_split ( '/[+\r\n\t ]+/' , $query_vars [ 'tag' ] );
2019-11-02 10:38:58 +01:00
foreach ( ( array ) $tags as $tag ) {
2025-12-12 13:15:55 +01:00
$tag = sanitize_term_field ( 'slug' , $tag , 0 , 'post_tag' , 'db' );
$query_vars [ 'tag_slug__and' ][] = $tag ;
2019-11-02 10:38:58 +01:00
}
} else {
2025-12-12 13:15:55 +01:00
$query_vars [ 'tag' ] = sanitize_term_field ( 'slug' , $query_vars [ 'tag' ], 0 , 'post_tag' , 'db' );
$query_vars [ 'tag_slug__in' ][] = $query_vars [ 'tag' ];
sort ( $query_vars [ 'tag_slug__in' ] );
2019-11-02 10:38:58 +01:00
}
}
2025-12-12 13:15:55 +01:00
if ( ! empty ( $query_vars [ 'tag_id' ] ) ) {
$query_vars [ 'tag_id' ] = absint ( $query_vars [ 'tag_id' ] );
$tax_query [] = array (
2019-11-02 10:38:58 +01:00
'taxonomy' => 'post_tag' ,
2025-12-12 13:15:55 +01:00
'terms' => $query_vars [ 'tag_id' ],
2019-11-02 10:38:58 +01:00
);
}
2025-12-12 13:15:55 +01:00
if ( ! empty ( $query_vars [ 'tag__in' ] ) ) {
$query_vars [ 'tag__in' ] = array_map ( 'absint' , array_unique ( ( array ) $query_vars [ 'tag__in' ] ) );
sort ( $query_vars [ 'tag__in' ] );
2025-04-25 12:30:07 +02:00
$tax_query [] = array (
2019-11-02 10:38:58 +01:00
'taxonomy' => 'post_tag' ,
2025-12-12 13:15:55 +01:00
'terms' => $query_vars [ 'tag__in' ],
2019-11-02 10:38:58 +01:00
);
}
2025-12-12 13:15:55 +01:00
if ( ! empty ( $query_vars [ 'tag__not_in' ] ) ) {
$query_vars [ 'tag__not_in' ] = array_map ( 'absint' , array_unique ( ( array ) $query_vars [ 'tag__not_in' ] ) );
sort ( $query_vars [ 'tag__not_in' ] );
2025-04-25 12:30:07 +02:00
$tax_query [] = array (
2019-11-02 10:38:58 +01:00
'taxonomy' => 'post_tag' ,
2025-12-12 13:15:55 +01:00
'terms' => $query_vars [ 'tag__not_in' ],
2019-11-02 10:38:58 +01:00
'operator' => 'NOT IN' ,
);
}
2025-12-12 13:15:55 +01:00
if ( ! empty ( $query_vars [ 'tag__and' ] ) ) {
$query_vars [ 'tag__and' ] = array_map ( 'absint' , array_unique ( ( array ) $query_vars [ 'tag__and' ] ) );
sort ( $query_vars [ 'tag__and' ] );
2025-04-25 12:30:07 +02:00
$tax_query [] = array (
2019-11-02 10:38:58 +01:00
'taxonomy' => 'post_tag' ,
2025-12-12 13:15:55 +01:00
'terms' => $query_vars [ 'tag__and' ],
2019-11-02 10:38:58 +01:00
'operator' => 'AND' ,
);
}
2025-12-12 13:15:55 +01:00
if ( ! empty ( $query_vars [ 'tag_slug__in' ] ) ) {
$query_vars [ 'tag_slug__in' ] = array_map ( 'sanitize_title_for_query' , array_unique ( ( array ) $query_vars [ 'tag_slug__in' ] ) );
sort ( $query_vars [ 'tag_slug__in' ] );
2025-04-25 12:30:07 +02:00
$tax_query [] = array (
2019-11-02 10:38:58 +01:00
'taxonomy' => 'post_tag' ,
2025-12-12 13:15:55 +01:00
'terms' => $query_vars [ 'tag_slug__in' ],
2019-11-02 10:38:58 +01:00
'field' => 'slug' ,
);
}
2025-12-12 13:15:55 +01:00
if ( ! empty ( $query_vars [ 'tag_slug__and' ] ) ) {
$query_vars [ 'tag_slug__and' ] = array_map ( 'sanitize_title_for_query' , array_unique ( ( array ) $query_vars [ 'tag_slug__and' ] ) );
sort ( $query_vars [ 'tag_slug__and' ] );
2025-04-25 12:30:07 +02:00
$tax_query [] = array (
2019-11-02 10:38:58 +01:00
'taxonomy' => 'post_tag' ,
2025-12-12 13:15:55 +01:00
'terms' => $query_vars [ 'tag_slug__and' ],
2019-11-02 10:38:58 +01:00
'field' => 'slug' ,
'operator' => 'AND' ,
);
}
$this -> tax_query = new WP_Tax_Query ( $tax_query );
/**
* Fires after taxonomy - related query vars have been parsed .
*
* @ since 3.7 . 0
*
2021-04-27 08:32:47 +02:00
* @ param WP_Query $query The WP_Query instance .
2019-11-02 10:38:58 +01:00
*/
do_action ( 'parse_tax_query' , $this );
}
/**
* Generates SQL for the WHERE clause based on passed search terms .
*
* @ since 3.7 . 0
*
* @ global wpdb $wpdb WordPress database abstraction object .
*
2025-12-12 13:15:55 +01:00
* @ param array $query_vars Query variables .
2019-11-02 10:38:58 +01:00
* @ return string WHERE clause .
*/
2025-12-12 13:15:55 +01:00
protected function parse_search ( & $query_vars ) {
2019-11-02 10:38:58 +01:00
global $wpdb ;
$search = '' ;
2020-05-06 17:23:38 +02:00
// Added slashes screw with quote grouping when done early, so done later.
2025-12-12 13:15:55 +01:00
$query_vars [ 's' ] = stripslashes ( $query_vars [ 's' ] );
2019-11-02 10:38:58 +01:00
if ( empty ( $_GET [ 's' ] ) && $this -> is_main_query () ) {
2025-12-12 13:15:55 +01:00
$query_vars [ 's' ] = urldecode ( $query_vars [ 's' ] );
2019-11-02 10:38:58 +01:00
}
2020-05-06 17:23:38 +02:00
// There are no line breaks in <input /> fields.
2025-12-12 13:15:55 +01:00
$query_vars [ 's' ] = str_replace ( array ( " \r " , " \n " ), '' , $query_vars [ 's' ] );
$query_vars [ 'search_terms_count' ] = 1 ;
if ( ! empty ( $query_vars [ 'sentence' ] ) ) {
$query_vars [ 'search_terms' ] = array ( $query_vars [ 's' ] );
2019-11-02 10:38:58 +01:00
} else {
2025-12-12 13:15:55 +01:00
if ( preg_match_all ( '/".*?("|$)|((?<=[\t ",+])|^)[^\t ",+]+/' , $query_vars [ 's' ], $matches ) ) {
$query_vars [ 'search_terms_count' ] = count ( $matches [ 0 ] );
$query_vars [ 'search_terms' ] = $this -> parse_search_terms ( $matches [ 0 ] );
2020-05-06 17:23:38 +02:00
// If the search string has only short terms or stopwords, or is 10+ terms long, match it as sentence.
2025-12-12 13:15:55 +01:00
if ( empty ( $query_vars [ 'search_terms' ] ) || count ( $query_vars [ 'search_terms' ] ) > 9 ) {
$query_vars [ 'search_terms' ] = array ( $query_vars [ 's' ] );
2019-11-02 10:38:58 +01:00
}
} else {
2025-12-12 13:15:55 +01:00
$query_vars [ 'search_terms' ] = array ( $query_vars [ 's' ] );
2019-11-02 10:38:58 +01:00
}
}
2025-12-12 13:15:55 +01:00
$n = ! empty ( $query_vars [ 'exact' ] ) ? '' : '%' ;
$searchand = '' ;
$query_vars [ 'search_orderby_title' ] = array ();
2019-11-02 10:38:58 +01:00
2023-04-26 17:39:43 +02:00
$default_search_columns = array ( 'post_title' , 'post_excerpt' , 'post_content' );
2025-12-12 13:15:55 +01:00
$search_columns = ! empty ( $query_vars [ 'search_columns' ] ) ? $query_vars [ 'search_columns' ] : $default_search_columns ;
2023-04-26 17:39:43 +02:00
if ( ! is_array ( $search_columns ) ) {
$search_columns = array ( $search_columns );
}
/**
* Filters the columns to search in a WP_Query search .
*
* The supported columns are `post_title` , `post_excerpt` and `post_content` .
* They are all included by default .
*
* @ since 6.2 . 0
*
* @ param string [] $search_columns Array of column names to be searched .
* @ param string $search Text being searched .
* @ param WP_Query $query The current WP_Query instance .
*/
2025-12-12 13:15:55 +01:00
$search_columns = ( array ) apply_filters ( 'post_search_columns' , $search_columns , $query_vars [ 's' ], $this );
2023-04-26 17:39:43 +02:00
// Use only supported search columns.
$search_columns = array_intersect ( $search_columns , $default_search_columns );
if ( empty ( $search_columns ) ) {
$search_columns = $default_search_columns ;
}
2019-11-02 10:38:58 +01:00
/**
* Filters the prefix that indicates that a search term should be excluded from results .
*
* @ since 4.7 . 0
*
* @ param string $exclusion_prefix The prefix . Default '-' . Returning
* an empty value disables exclusions .
*/
$exclusion_prefix = apply_filters ( 'wp_query_search_exclusion_prefix' , '-' );
2025-12-12 13:15:55 +01:00
foreach ( $query_vars [ 'search_terms' ] as $term ) {
2019-11-02 10:38:58 +01:00
// If there is an $exclusion_prefix, terms prefixed with it should be excluded.
2023-09-26 10:33:34 +02:00
$exclude = $exclusion_prefix && str_starts_with ( $term , $exclusion_prefix );
2019-11-02 10:38:58 +01:00
if ( $exclude ) {
$like_op = 'NOT LIKE' ;
$andor_op = 'AND' ;
$term = substr ( $term , 1 );
} else {
$like_op = 'LIKE' ;
$andor_op = 'OR' ;
}
if ( $n && ! $exclude ) {
2025-12-12 13:15:55 +01:00
$like = '%' . $wpdb -> esc_like ( $term ) . '%' ;
$query_vars [ 'search_orderby_title' ][] = $wpdb -> prepare ( " { $wpdb -> posts } .post_title LIKE %s " , $like );
2019-11-02 10:38:58 +01:00
}
2022-12-15 17:47:31 +01:00
$like = $n . $wpdb -> esc_like ( $term ) . $n ;
2023-04-26 17:39:43 +02:00
$search_columns_parts = array ();
foreach ( $search_columns as $search_column ) {
$search_columns_parts [ $search_column ] = $wpdb -> prepare ( " ( { $wpdb -> posts } . $search_column $like_op %s) " , $like );
}
2022-12-15 17:47:31 +01:00
if ( ! empty ( $this -> allow_query_attachment_by_filename ) ) {
2023-04-26 17:39:43 +02:00
$search_columns_parts [ 'attachment' ] = $wpdb -> prepare ( " (sq1.meta_value $like_op %s) " , $like );
2022-12-15 17:47:31 +01:00
}
2023-04-26 17:39:43 +02:00
$search .= " $searchand ( " . implode ( " $andor_op " , $search_columns_parts ) . ')' ;
2019-11-02 10:38:58 +01:00
$searchand = ' AND ' ;
}
if ( ! empty ( $search ) ) {
$search = " AND ( { $search } ) " ;
if ( ! is_user_logged_in () ) {
$search .= " AND ( { $wpdb -> posts } .post_password = '') " ;
}
}
return $search ;
}
/**
2023-09-26 10:33:34 +02:00
* Checks if the terms are suitable for searching .
2019-11-02 10:38:58 +01:00
*
* Uses an array of stopwords ( terms ) that are excluded from the separate
* term matching when searching for posts . The list of English stopwords is
* the approximate search engines list , and is translatable .
*
* @ since 3.7 . 0
*
* @ param string [] $terms Array of terms to check .
2020-05-06 17:23:38 +02:00
* @ return string [] Terms that are not stopwords .
2019-11-02 10:38:58 +01:00
*/
protected function parse_search_terms ( $terms ) {
$strtolower = function_exists ( 'mb_strtolower' ) ? 'mb_strtolower' : 'strtolower' ;
$checked = array ();
$stopwords = $this -> get_search_stopwords ();
foreach ( $terms as $term ) {
2020-05-06 17:23:38 +02:00
// Keep before/after spaces when term is for exact match.
2019-11-02 10:38:58 +01:00
if ( preg_match ( '/^".+"$/' , $term ) ) {
$term = trim ( $term , " \" ' " );
} else {
$term = trim ( $term , " \" ' " );
}
// Avoid single A-Z and single dashes.
if ( ! $term || ( 1 === strlen ( $term ) && preg_match ( '/^[a-z\-]$/i' , $term ) ) ) {
continue ;
}
if ( in_array ( call_user_func ( $strtolower , $term ), $stopwords , true ) ) {
continue ;
}
$checked [] = $term ;
}
return $checked ;
}
/**
2023-09-26 10:33:34 +02:00
* Retrieves stopwords used when parsing search terms .
2019-11-02 10:38:58 +01:00
*
* @ since 3.7 . 0
*
2020-05-06 17:23:38 +02:00
* @ return string [] Stopwords .
2019-11-02 10:38:58 +01:00
*/
protected function get_search_stopwords () {
if ( isset ( $this -> stopwords ) ) {
return $this -> stopwords ;
}
2019-11-15 22:59:44 +01:00
/*
* translators : This is a comma - separated list of very common words that should be excluded from a search ,
2019-11-02 10:38:58 +01:00
* like a , an , and the . These are usually called " stopwords " . You should not simply translate these individual
* words into your language . Instead , look for and provide commonly accepted stopwords in your language .
*/
$words = explode (
',' ,
_x (
'about,an,are,as,at,be,by,com,for,from,how,in,is,it,of,on,or,that,the,this,to,was,what,when,where,who,will,with,www' ,
'Comma-separated list of search stopwords in your language'
)
);
$stopwords = array ();
foreach ( $words as $word ) {
$word = trim ( $word , " \r \n \t " );
if ( $word ) {
$stopwords [] = $word ;
}
}
/**
* Filters stopwords used when parsing search terms .
*
* @ since 3.7 . 0
*
* @ param string [] $stopwords Array of stopwords .
*/
$this -> stopwords = apply_filters ( 'wp_search_stopwords' , $stopwords );
return $this -> stopwords ;
}
/**
* Generates SQL for the ORDER BY condition based on passed search terms .
*
* @ since 3.7 . 0
*
* @ global wpdb $wpdb WordPress database abstraction object .
*
2025-12-12 13:15:55 +01:00
* @ param array $query_vars Query variables .
2019-11-02 10:38:58 +01:00
* @ return string ORDER BY clause .
*/
2025-12-12 13:15:55 +01:00
protected function parse_search_order ( & $query_vars ) {
2019-11-02 10:38:58 +01:00
global $wpdb ;
2025-12-12 13:15:55 +01:00
if ( $query_vars [ 'search_terms_count' ] > 1 ) {
$num_terms = count ( $query_vars [ 'search_orderby_title' ] );
2019-11-02 10:38:58 +01:00
// If the search terms contain negative queries, don't bother ordering by sentence matches.
$like = '' ;
2025-12-12 13:15:55 +01:00
if ( ! preg_match ( '/(?:\s|^)\-/' , $query_vars [ 's' ] ) ) {
$like = '%' . $wpdb -> esc_like ( $query_vars [ 's' ] ) . '%' ;
2019-11-02 10:38:58 +01:00
}
$search_orderby = '' ;
2020-05-06 17:23:38 +02:00
// Sentence match in 'post_title'.
2019-11-02 10:38:58 +01:00
if ( $like ) {
$search_orderby .= $wpdb -> prepare ( " WHEN { $wpdb -> posts } .post_title LIKE %s THEN 1 " , $like );
}
2023-09-26 10:33:34 +02:00
/*
* Sanity limit , sort as sentence when more than 6 terms
* ( few searches are longer than 6 terms and most titles are not ) .
*/
2019-11-02 10:38:58 +01:00
if ( $num_terms < 7 ) {
2020-05-06 17:23:38 +02:00
// All words in title.
2025-12-12 13:15:55 +01:00
$search_orderby .= 'WHEN ' . implode ( ' AND ' , $query_vars [ 'search_orderby_title' ] ) . ' THEN 2 ' ;
2020-05-06 17:23:38 +02:00
// Any word in title, not needed when $num_terms == 1.
2019-11-02 10:38:58 +01:00
if ( $num_terms > 1 ) {
2025-12-12 13:15:55 +01:00
$search_orderby .= 'WHEN ' . implode ( ' OR ' , $query_vars [ 'search_orderby_title' ] ) . ' THEN 3 ' ;
2019-11-02 10:38:58 +01:00
}
}
// Sentence match in 'post_content' and 'post_excerpt'.
if ( $like ) {
$search_orderby .= $wpdb -> prepare ( " WHEN { $wpdb -> posts } .post_excerpt LIKE %s THEN 4 " , $like );
$search_orderby .= $wpdb -> prepare ( " WHEN { $wpdb -> posts } .post_content LIKE %s THEN 5 " , $like );
}
if ( $search_orderby ) {
$search_orderby = '(CASE ' . $search_orderby . 'ELSE 6 END)' ;
}
} else {
2020-05-06 17:23:38 +02:00
// Single word or sentence search.
2025-12-12 13:15:55 +01:00
$search_orderby = reset ( $query_vars [ 'search_orderby_title' ] ) . ' DESC' ;
2019-11-02 10:38:58 +01:00
}
return $search_orderby ;
}
/**
* Converts the given orderby alias ( if allowed ) to a properly - prefixed value .
*
* @ since 4.0 . 0
*
* @ global wpdb $wpdb WordPress database abstraction object .
*
* @ param string $orderby Alias for the field to order by .
* @ return string | false Table - prefixed value to used in the ORDER clause . False otherwise .
*/
protected function parse_orderby ( $orderby ) {
global $wpdb ;
// Used to filter values.
$allowed_keys = array (
'post_name' ,
'post_author' ,
'post_date' ,
'post_title' ,
'post_modified' ,
'post_parent' ,
'post_type' ,
'name' ,
'author' ,
'date' ,
'title' ,
'modified' ,
'parent' ,
'type' ,
'ID' ,
'menu_order' ,
'comment_count' ,
'rand' ,
'post__in' ,
'post_parent__in' ,
'post_name__in' ,
);
$primary_meta_key = '' ;
$primary_meta_query = false ;
$meta_clauses = $this -> meta_query -> get_clauses ();
if ( ! empty ( $meta_clauses ) ) {
$primary_meta_query = reset ( $meta_clauses );
if ( ! empty ( $primary_meta_query [ 'key' ] ) ) {
$primary_meta_key = $primary_meta_query [ 'key' ];
$allowed_keys [] = $primary_meta_key ;
}
$allowed_keys [] = 'meta_value' ;
$allowed_keys [] = 'meta_value_num' ;
$allowed_keys = array_merge ( $allowed_keys , array_keys ( $meta_clauses ) );
}
// If RAND() contains a seed value, sanitize and add to allowed keys.
$rand_with_seed = false ;
if ( preg_match ( '/RAND\(([0-9]+)\)/i' , $orderby , $matches ) ) {
2020-12-10 14:06:04 +01:00
$orderby = sprintf ( 'RAND(%s)' , ( int ) $matches [ 1 ] );
2019-11-02 10:38:58 +01:00
$allowed_keys [] = $orderby ;
$rand_with_seed = true ;
}
if ( ! in_array ( $orderby , $allowed_keys , true ) ) {
return false ;
}
$orderby_clause = '' ;
switch ( $orderby ) {
case 'post_name' :
case 'post_author' :
case 'post_date' :
case 'post_title' :
case 'post_modified' :
case 'post_parent' :
case 'post_type' :
case 'ID' :
case 'menu_order' :
case 'comment_count' :
$orderby_clause = " { $wpdb -> posts } . { $orderby } " ;
break ;
case 'rand' :
$orderby_clause = 'RAND()' ;
break ;
case $primary_meta_key :
case 'meta_value' :
if ( ! empty ( $primary_meta_query [ 'type' ] ) ) {
$orderby_clause = " CAST( { $primary_meta_query [ 'alias' ] } .meta_value AS { $primary_meta_query [ 'cast' ] } ) " ;
} else {
$orderby_clause = " { $primary_meta_query [ 'alias' ] } .meta_value " ;
}
break ;
case 'meta_value_num' :
$orderby_clause = " { $primary_meta_query [ 'alias' ] } .meta_value+0 " ;
break ;
case 'post__in' :
if ( ! empty ( $this -> query_vars [ 'post__in' ] ) ) {
$orderby_clause = " FIELD( { $wpdb -> posts } .ID, " . implode ( ',' , array_map ( 'absint' , $this -> query_vars [ 'post__in' ] ) ) . ')' ;
}
break ;
case 'post_parent__in' :
if ( ! empty ( $this -> query_vars [ 'post_parent__in' ] ) ) {
$orderby_clause = " FIELD( { $wpdb -> posts } .post_parent, " . implode ( ', ' , array_map ( 'absint' , $this -> query_vars [ 'post_parent__in' ] ) ) . ' )' ;
}
break ;
case 'post_name__in' :
if ( ! empty ( $this -> query_vars [ 'post_name__in' ] ) ) {
$post_name__in = array_map ( 'sanitize_title_for_query' , $this -> query_vars [ 'post_name__in' ] );
$post_name__in_string = " ' " . implode ( " ',' " , $post_name__in ) . " ' " ;
$orderby_clause = " FIELD( { $wpdb -> posts } .post_name, " . $post_name__in_string . ' )' ;
}
break ;
default :
if ( array_key_exists ( $orderby , $meta_clauses ) ) {
// $orderby corresponds to a meta_query clause.
$meta_clause = $meta_clauses [ $orderby ];
$orderby_clause = " CAST( { $meta_clause [ 'alias' ] } .meta_value AS { $meta_clause [ 'cast' ] } ) " ;
} elseif ( $rand_with_seed ) {
$orderby_clause = $orderby ;
} else {
// Default: order by post field.
$orderby_clause = " { $wpdb -> posts } .post_ " . sanitize_key ( $orderby );
}
break ;
}
return $orderby_clause ;
}
/**
* Parse an 'order' query variable and cast it to ASC or DESC as necessary .
*
* @ since 4.0 . 0
*
* @ param string $order The 'order' query variable .
* @ return string The sanitized 'order' query variable .
*/
protected function parse_order ( $order ) {
if ( ! is_string ( $order ) || empty ( $order ) ) {
return 'DESC' ;
}
if ( 'ASC' === strtoupper ( $order ) ) {
return 'ASC' ;
} else {
return 'DESC' ;
}
}
/**
* Sets the 404 property and saves whether query is feed .
*
* @ since 2.0 . 0
*/
public function set_404 () {
$is_feed = $this -> is_feed ;
$this -> init_query_flags ();
$this -> is_404 = true ;
$this -> is_feed = $is_feed ;
2020-09-15 14:29:22 +02:00
/**
* Fires after a 404 is triggered .
*
* @ since 5.5 . 0
*
2021-04-27 08:32:47 +02:00
* @ param WP_Query $query The WP_Query instance ( passed by reference ) .
2020-09-15 14:29:22 +02:00
*/
do_action_ref_array ( 'set_404' , array ( $this ) );
2019-11-02 10:38:58 +01:00
}
/**
2020-12-10 14:06:04 +01:00
* Retrieves the value of a query variable .
2019-11-02 10:38:58 +01:00
*
* @ since 1.5 . 0
2022-06-16 14:03:35 +02:00
* @ since 3.9 . 0 The `$default_value` argument was introduced .
2019-11-02 10:38:58 +01:00
*
2022-06-16 14:03:35 +02:00
* @ param string $query_var Query variable key .
2023-04-26 17:39:43 +02:00
* @ param mixed $default_value Optional . Value to return if the query variable is not set .
* Default empty string .
2019-11-02 10:38:58 +01:00
* @ return mixed Contents of the query variable .
*/
2022-06-16 14:03:35 +02:00
public function get ( $query_var , $default_value = '' ) {
2019-11-02 10:38:58 +01:00
if ( isset ( $this -> query_vars [ $query_var ] ) ) {
return $this -> query_vars [ $query_var ];
}
2022-06-16 14:03:35 +02:00
return $default_value ;
2019-11-02 10:38:58 +01:00
}
/**
2020-12-10 14:06:04 +01:00
* Sets the value of a query variable .
2019-11-02 10:38:58 +01:00
*
* @ since 1.5 . 0
*
* @ param string $query_var Query variable key .
* @ param mixed $value Query variable value .
*/
public function set ( $query_var , $value ) {
$this -> query_vars [ $query_var ] = $value ;
}
/**
* Retrieves an array of posts based on query variables .
*
* There are a few filters and actions that can be used to modify the post
* database query .
*
* @ since 1.5 . 0
*
2021-04-27 08:32:47 +02:00
* @ global wpdb $wpdb WordPress database abstraction object .
*
2019-11-02 10:38:58 +01:00
* @ return WP_Post [] | int [] Array of post objects or post IDs .
*/
public function get_posts () {
global $wpdb ;
$this -> parse_query ();
/**
* Fires after the query variable object is created , but before the actual query is run .
*
* Note : If using conditional tags , use the method versions within the passed instance
* ( e . g . $this -> is_main_query () instead of is_main_query ()) . This is because the functions
* like is_main_query () test against the global $wp_query instance , not the passed one .
*
* @ since 2.0 . 0
*
2021-04-27 08:32:47 +02:00
* @ param WP_Query $query The WP_Query instance ( passed by reference ) .
2019-11-02 10:38:58 +01:00
*/
do_action_ref_array ( 'pre_get_posts' , array ( & $this ) );
2025-12-12 13:15:55 +01:00
// Locally scoped reference for easy of use.
$query_vars = & $this -> query_vars ;
2019-11-02 10:38:58 +01:00
2020-05-06 17:23:38 +02:00
// Fill again in case 'pre_get_posts' unset some vars.
2025-12-12 13:15:55 +01:00
$query_vars = $this -> fill_query_vars ( $query_vars );
2019-11-02 10:38:58 +01:00
2022-12-15 17:47:31 +01:00
/**
* Filters whether an attachment query should include filenames or not .
*
* @ since 6.0 . 3
*
* @ param bool $allow_query_attachment_by_filename Whether or not to include filenames .
*/
$this -> allow_query_attachment_by_filename = apply_filters ( 'wp_allow_query_attachment_by_filename' , false );
remove_all_filters ( 'wp_allow_query_attachment_by_filename' );
2020-05-06 17:23:38 +02:00
// Parse meta query.
2019-11-02 10:38:58 +01:00
$this -> meta_query = new WP_Meta_Query ();
2025-12-12 13:15:55 +01:00
$this -> meta_query -> parse_query_vars ( $query_vars );
2019-11-02 10:38:58 +01:00
2020-05-06 17:23:38 +02:00
// Set a flag if a 'pre_get_posts' hook changed the query vars.
2019-11-02 10:38:58 +01:00
$hash = md5 ( serialize ( $this -> query_vars ) );
2025-04-25 12:30:07 +02:00
if ( $hash !== $this -> query_vars_hash ) {
2019-11-02 10:38:58 +01:00
$this -> query_vars_changed = true ;
$this -> query_vars_hash = $hash ;
}
unset ( $hash );
2020-05-06 17:23:38 +02:00
// First let's clear some variables.
2019-11-02 10:38:58 +01:00
$distinct = '' ;
$whichauthor = '' ;
$whichmimetype = '' ;
$where = '' ;
$limits = '' ;
$join = '' ;
$search = '' ;
$groupby = '' ;
$post_status_join = false ;
$page = 1 ;
2025-12-12 13:15:55 +01:00
if ( isset ( $query_vars [ 'caller_get_posts' ] ) ) {
2019-11-02 10:38:58 +01:00
_deprecated_argument (
'WP_Query' ,
'3.1.0' ,
sprintf (
2019-11-15 22:59:44 +01:00
/* translators: 1: caller_get_posts, 2: ignore_sticky_posts */
2019-11-02 10:38:58 +01:00
__ ( '%1$s is deprecated. Use %2$s instead.' ),
'<code>caller_get_posts</code>' ,
'<code>ignore_sticky_posts</code>'
)
);
2025-12-12 13:15:55 +01:00
if ( ! isset ( $query_vars [ 'ignore_sticky_posts' ] ) ) {
$query_vars [ 'ignore_sticky_posts' ] = $query_vars [ 'caller_get_posts' ];
2019-11-02 10:38:58 +01:00
}
}
2025-12-12 13:15:55 +01:00
if ( ! isset ( $query_vars [ 'ignore_sticky_posts' ] ) ) {
$query_vars [ 'ignore_sticky_posts' ] = false ;
2019-11-02 10:38:58 +01:00
}
2025-12-12 13:15:55 +01:00
if ( ! isset ( $query_vars [ 'suppress_filters' ] ) ) {
$query_vars [ 'suppress_filters' ] = false ;
2019-11-02 10:38:58 +01:00
}
2025-12-12 13:15:55 +01:00
if ( ! isset ( $query_vars [ 'cache_results' ] ) ) {
$query_vars [ 'cache_results' ] = true ;
2019-11-02 10:38:58 +01:00
}
2025-12-12 13:15:55 +01:00
if ( ! isset ( $query_vars [ 'update_post_term_cache' ] ) ) {
$query_vars [ 'update_post_term_cache' ] = true ;
2019-11-02 10:38:58 +01:00
}
2025-12-12 13:15:55 +01:00
if ( ! isset ( $query_vars [ 'update_menu_item_cache' ] ) ) {
$query_vars [ 'update_menu_item_cache' ] = false ;
2022-12-15 17:47:31 +01:00
}
2025-12-12 13:15:55 +01:00
if ( ! isset ( $query_vars [ 'lazy_load_term_meta' ] ) ) {
$query_vars [ 'lazy_load_term_meta' ] = $query_vars [ 'update_post_term_cache' ];
} elseif ( $query_vars [ 'lazy_load_term_meta' ] ) { // Lazy loading term meta only works if term caches are primed.
$query_vars [ 'update_post_term_cache' ] = true ;
2019-11-02 10:38:58 +01:00
}
2025-12-12 13:15:55 +01:00
if ( ! isset ( $query_vars [ 'update_post_meta_cache' ] ) ) {
$query_vars [ 'update_post_meta_cache' ] = true ;
2019-11-02 10:38:58 +01:00
}
2025-12-12 13:15:55 +01:00
if ( ! isset ( $query_vars [ 'post_type' ] ) ) {
2019-11-02 10:38:58 +01:00
if ( $this -> is_search ) {
2025-12-12 13:15:55 +01:00
$query_vars [ 'post_type' ] = 'any' ;
2019-11-02 10:38:58 +01:00
} else {
2025-12-12 13:15:55 +01:00
$query_vars [ 'post_type' ] = '' ;
2019-11-02 10:38:58 +01:00
}
}
2025-12-12 13:15:55 +01:00
$post_type = $query_vars [ 'post_type' ];
if ( empty ( $query_vars [ 'posts_per_page' ] ) ) {
$query_vars [ 'posts_per_page' ] = get_option ( 'posts_per_page' );
2019-11-02 10:38:58 +01:00
}
2025-12-12 13:15:55 +01:00
if ( isset ( $query_vars [ 'showposts' ] ) && $query_vars [ 'showposts' ] ) {
$query_vars [ 'showposts' ] = ( int ) $query_vars [ 'showposts' ];
$query_vars [ 'posts_per_page' ] = $query_vars [ 'showposts' ];
2019-11-02 10:38:58 +01:00
}
2025-12-12 13:15:55 +01:00
if ( ( isset ( $query_vars [ 'posts_per_archive_page' ] ) && 0 != $query_vars [ 'posts_per_archive_page' ] ) && ( $this -> is_archive || $this -> is_search ) ) {
$query_vars [ 'posts_per_page' ] = $query_vars [ 'posts_per_archive_page' ];
2019-11-02 10:38:58 +01:00
}
2025-12-12 13:15:55 +01:00
if ( ! isset ( $query_vars [ 'nopaging' ] ) ) {
if ( - 1 == $query_vars [ 'posts_per_page' ] ) {
$query_vars [ 'nopaging' ] = true ;
2019-11-02 10:38:58 +01:00
} else {
2025-12-12 13:15:55 +01:00
$query_vars [ 'nopaging' ] = false ;
2019-11-02 10:38:58 +01:00
}
}
if ( $this -> is_feed ) {
2020-05-06 17:23:38 +02:00
// This overrides 'posts_per_page'.
2025-12-12 13:15:55 +01:00
if ( ! empty ( $query_vars [ 'posts_per_rss' ] ) ) {
$query_vars [ 'posts_per_page' ] = $query_vars [ 'posts_per_rss' ];
2019-11-02 10:38:58 +01:00
} else {
2025-12-12 13:15:55 +01:00
$query_vars [ 'posts_per_page' ] = get_option ( 'posts_per_rss' );
2019-11-02 10:38:58 +01:00
}
2025-12-12 13:15:55 +01:00
$query_vars [ 'nopaging' ] = false ;
2019-11-02 10:38:58 +01:00
}
2025-04-25 12:30:07 +02:00
2025-12-12 13:15:55 +01:00
$query_vars [ 'posts_per_page' ] = ( int ) $query_vars [ 'posts_per_page' ];
if ( $query_vars [ 'posts_per_page' ] < - 1 ) {
$query_vars [ 'posts_per_page' ] = abs ( $query_vars [ 'posts_per_page' ] );
} elseif ( 0 === $query_vars [ 'posts_per_page' ] ) {
$query_vars [ 'posts_per_page' ] = 1 ;
2019-11-02 10:38:58 +01:00
}
2025-12-12 13:15:55 +01:00
if ( ! isset ( $query_vars [ 'comments_per_page' ] ) || 0 == $query_vars [ 'comments_per_page' ] ) {
$query_vars [ 'comments_per_page' ] = get_option ( 'comments_per_page' );
2019-11-02 10:38:58 +01:00
}
2025-12-12 13:15:55 +01:00
if ( $this -> is_home && ( empty ( $this -> query ) || 'true' === $query_vars [ 'preview' ] ) && ( 'page' === get_option ( 'show_on_front' ) ) && get_option ( 'page_on_front' ) ) {
$this -> is_page = true ;
$this -> is_home = false ;
$query_vars [ 'page_id' ] = get_option ( 'page_on_front' );
2019-11-02 10:38:58 +01:00
}
2025-12-12 13:15:55 +01:00
if ( isset ( $query_vars [ 'page' ] ) ) {
$query_vars [ 'page' ] = is_scalar ( $query_vars [ 'page' ] ) ? absint ( trim ( $query_vars [ 'page' ], '/' ) ) : 0 ;
2019-11-02 10:38:58 +01:00
}
// If true, forcibly turns off SQL_CALC_FOUND_ROWS even when limits are present.
2025-12-12 13:15:55 +01:00
if ( isset ( $query_vars [ 'no_found_rows' ] ) ) {
$query_vars [ 'no_found_rows' ] = ( bool ) $query_vars [ 'no_found_rows' ];
2019-11-02 10:38:58 +01:00
} else {
2025-12-12 13:15:55 +01:00
$query_vars [ 'no_found_rows' ] = false ;
2019-11-02 10:38:58 +01:00
}
2025-12-12 13:15:55 +01:00
switch ( $query_vars [ 'fields' ] ) {
2019-11-02 10:38:58 +01:00
case 'ids' :
$fields = " { $wpdb -> posts } .ID " ;
break ;
case 'id=>parent' :
$fields = " { $wpdb -> posts } .ID, { $wpdb -> posts } .post_parent " ;
break ;
2025-04-25 12:30:07 +02:00
case '' :
/*
* Set the default to 'all' .
*
* This is used in `WP_Query::the_post` to determine if the
* entire post object has been queried .
*/
2025-12-12 13:15:55 +01:00
$query_vars [ 'fields' ] = 'all' ;
2025-04-25 12:30:07 +02:00
// Falls through.
2019-11-02 10:38:58 +01:00
default :
$fields = " { $wpdb -> posts } .* " ;
}
2025-12-12 13:15:55 +01:00
if ( '' !== $query_vars [ 'menu_order' ] ) {
$where .= " AND { $wpdb -> posts } .menu_order = " . $query_vars [ 'menu_order' ];
2019-11-02 10:38:58 +01:00
}
2020-05-06 17:23:38 +02:00
// The "m" parameter is meant for months but accepts datetimes of varying specificity.
2025-12-12 13:15:55 +01:00
if ( $query_vars [ 'm' ] ) {
$where .= " AND YEAR( { $wpdb -> posts } .post_date)= " . substr ( $query_vars [ 'm' ], 0 , 4 );
if ( strlen ( $query_vars [ 'm' ] ) > 5 ) {
$where .= " AND MONTH( { $wpdb -> posts } .post_date)= " . substr ( $query_vars [ 'm' ], 4 , 2 );
2019-11-02 10:38:58 +01:00
}
2025-12-12 13:15:55 +01:00
if ( strlen ( $query_vars [ 'm' ] ) > 7 ) {
$where .= " AND DAYOFMONTH( { $wpdb -> posts } .post_date)= " . substr ( $query_vars [ 'm' ], 6 , 2 );
2019-11-02 10:38:58 +01:00
}
2025-12-12 13:15:55 +01:00
if ( strlen ( $query_vars [ 'm' ] ) > 9 ) {
$where .= " AND HOUR( { $wpdb -> posts } .post_date)= " . substr ( $query_vars [ 'm' ], 8 , 2 );
2019-11-02 10:38:58 +01:00
}
2025-12-12 13:15:55 +01:00
if ( strlen ( $query_vars [ 'm' ] ) > 11 ) {
$where .= " AND MINUTE( { $wpdb -> posts } .post_date)= " . substr ( $query_vars [ 'm' ], 10 , 2 );
2019-11-02 10:38:58 +01:00
}
2025-12-12 13:15:55 +01:00
if ( strlen ( $query_vars [ 'm' ] ) > 13 ) {
$where .= " AND SECOND( { $wpdb -> posts } .post_date)= " . substr ( $query_vars [ 'm' ], 12 , 2 );
2019-11-02 10:38:58 +01:00
}
}
2020-05-06 17:23:38 +02:00
// Handle the other individual date parameters.
2019-11-02 10:38:58 +01:00
$date_parameters = array ();
2025-12-12 13:15:55 +01:00
if ( '' !== $query_vars [ 'hour' ] ) {
$date_parameters [ 'hour' ] = $query_vars [ 'hour' ];
2019-11-02 10:38:58 +01:00
}
2025-12-12 13:15:55 +01:00
if ( '' !== $query_vars [ 'minute' ] ) {
$date_parameters [ 'minute' ] = $query_vars [ 'minute' ];
2019-11-02 10:38:58 +01:00
}
2025-12-12 13:15:55 +01:00
if ( '' !== $query_vars [ 'second' ] ) {
$date_parameters [ 'second' ] = $query_vars [ 'second' ];
2019-11-02 10:38:58 +01:00
}
2025-12-12 13:15:55 +01:00
if ( $query_vars [ 'year' ] ) {
$date_parameters [ 'year' ] = $query_vars [ 'year' ];
2019-11-02 10:38:58 +01:00
}
2025-12-12 13:15:55 +01:00
if ( $query_vars [ 'monthnum' ] ) {
$date_parameters [ 'monthnum' ] = $query_vars [ 'monthnum' ];
2019-11-02 10:38:58 +01:00
}
2025-12-12 13:15:55 +01:00
if ( $query_vars [ 'w' ] ) {
$date_parameters [ 'week' ] = $query_vars [ 'w' ];
2019-11-02 10:38:58 +01:00
}
2025-12-12 13:15:55 +01:00
if ( $query_vars [ 'day' ] ) {
$date_parameters [ 'day' ] = $query_vars [ 'day' ];
2019-11-02 10:38:58 +01:00
}
if ( $date_parameters ) {
$date_query = new WP_Date_Query ( array ( $date_parameters ) );
$where .= $date_query -> get_sql ();
}
unset ( $date_parameters , $date_query );
2020-05-06 17:23:38 +02:00
// Handle complex date queries.
2025-12-12 13:15:55 +01:00
if ( ! empty ( $query_vars [ 'date_query' ] ) ) {
$this -> date_query = new WP_Date_Query ( $query_vars [ 'date_query' ] );
2019-11-02 10:38:58 +01:00
$where .= $this -> date_query -> get_sql ();
}
// If we've got a post_type AND it's not "any" post_type.
2025-12-12 13:15:55 +01:00
if ( ! empty ( $query_vars [ 'post_type' ] ) && 'any' !== $query_vars [ 'post_type' ] ) {
foreach ( ( array ) $query_vars [ 'post_type' ] as $_post_type ) {
2019-11-02 10:38:58 +01:00
$ptype_obj = get_post_type_object ( $_post_type );
2025-12-12 13:15:55 +01:00
if ( ! $ptype_obj || ! $ptype_obj -> query_var || empty ( $query_vars [ $ptype_obj -> query_var ] ) ) {
2019-11-02 10:38:58 +01:00
continue ;
}
if ( ! $ptype_obj -> hierarchical ) {
// Non-hierarchical post types can directly use 'name'.
2025-12-12 13:15:55 +01:00
$query_vars [ 'name' ] = $query_vars [ $ptype_obj -> query_var ];
2019-11-02 10:38:58 +01:00
} else {
// Hierarchical post types will operate through 'pagename'.
2025-12-12 13:15:55 +01:00
$query_vars [ 'pagename' ] = $query_vars [ $ptype_obj -> query_var ];
$query_vars [ 'name' ] = '' ;
2019-11-02 10:38:58 +01:00
}
// Only one request for a slug is possible, this is why name & pagename are overwritten above.
break ;
2020-05-06 17:23:38 +02:00
} // End foreach.
2019-11-02 10:38:58 +01:00
unset ( $ptype_obj );
}
2025-12-12 13:15:55 +01:00
if ( '' !== $query_vars [ 'title' ] ) {
$where .= $wpdb -> prepare ( " AND { $wpdb -> posts } .post_title = %s " , stripslashes ( $query_vars [ 'title' ] ) );
2019-11-02 10:38:58 +01:00
}
// Parameters related to 'post_name'.
2025-12-12 13:15:55 +01:00
if ( '' !== $query_vars [ 'name' ] ) {
$query_vars [ 'name' ] = sanitize_title_for_query ( $query_vars [ 'name' ] );
$where .= " AND { $wpdb -> posts } .post_name = ' " . $query_vars [ 'name' ] . " ' " ;
} elseif ( '' !== $query_vars [ 'pagename' ] ) {
2019-11-02 10:38:58 +01:00
if ( isset ( $this -> queried_object_id ) ) {
$reqpage = $this -> queried_object_id ;
} else {
2025-12-12 13:15:55 +01:00
if ( 'page' !== $query_vars [ 'post_type' ] ) {
foreach ( ( array ) $query_vars [ 'post_type' ] as $_post_type ) {
2019-11-02 10:38:58 +01:00
$ptype_obj = get_post_type_object ( $_post_type );
if ( ! $ptype_obj || ! $ptype_obj -> hierarchical ) {
continue ;
}
2025-12-12 13:15:55 +01:00
$reqpage = get_page_by_path ( $query_vars [ 'pagename' ], OBJECT , $_post_type );
2019-11-02 10:38:58 +01:00
if ( $reqpage ) {
break ;
}
}
unset ( $ptype_obj );
} else {
2025-12-12 13:15:55 +01:00
$reqpage = get_page_by_path ( $query_vars [ 'pagename' ] );
2019-11-02 10:38:58 +01:00
}
if ( ! empty ( $reqpage ) ) {
$reqpage = $reqpage -> ID ;
} else {
$reqpage = 0 ;
}
}
$page_for_posts = get_option ( 'page_for_posts' );
2020-09-15 14:29:22 +02:00
if ( ( 'page' !== get_option ( 'show_on_front' ) ) || empty ( $page_for_posts ) || ( $reqpage != $page_for_posts ) ) {
2025-12-12 13:15:55 +01:00
$query_vars [ 'pagename' ] = sanitize_title_for_query ( wp_basename ( $query_vars [ 'pagename' ] ) );
$query_vars [ 'name' ] = $query_vars [ 'pagename' ];
$where .= " AND ( { $wpdb -> posts } .ID = ' $reqpage ') " ;
$reqpage_obj = get_post ( $reqpage );
2020-09-15 14:29:22 +02:00
if ( is_object ( $reqpage_obj ) && 'attachment' === $reqpage_obj -> post_type ) {
2025-12-12 13:15:55 +01:00
$this -> is_attachment = true ;
$post_type = 'attachment' ;
$query_vars [ 'post_type' ] = 'attachment' ;
$this -> is_page = true ;
$query_vars [ 'attachment_id' ] = $reqpage ;
2019-11-02 10:38:58 +01:00
}
}
2025-12-12 13:15:55 +01:00
} elseif ( '' !== $query_vars [ 'attachment' ] ) {
$query_vars [ 'attachment' ] = sanitize_title_for_query ( wp_basename ( $query_vars [ 'attachment' ] ) );
$query_vars [ 'name' ] = $query_vars [ 'attachment' ];
$where .= " AND { $wpdb -> posts } .post_name = ' " . $query_vars [ 'attachment' ] . " ' " ;
} elseif ( is_array ( $query_vars [ 'post_name__in' ] ) && ! empty ( $query_vars [ 'post_name__in' ] ) ) {
$query_vars [ 'post_name__in' ] = array_map ( 'sanitize_title_for_query' , $query_vars [ 'post_name__in' ] );
2025-04-25 12:30:07 +02:00
// Duplicate array before sorting to allow for the orderby clause.
2025-12-12 13:15:55 +01:00
$post_name__in_for_where = array_unique ( $query_vars [ 'post_name__in' ] );
2025-04-25 12:30:07 +02:00
sort ( $post_name__in_for_where );
$post_name__in = " ' " . implode ( " ',' " , $post_name__in_for_where ) . " ' " ;
$where .= " AND { $wpdb -> posts } .post_name IN ( $post_name__in ) " ;
2019-11-02 10:38:58 +01:00
}
// If an attachment is requested by number, let it supersede any post number.
2025-12-12 13:15:55 +01:00
if ( $query_vars [ 'attachment_id' ] ) {
$query_vars [ 'p' ] = absint ( $query_vars [ 'attachment_id' ] );
2019-11-02 10:38:58 +01:00
}
2020-05-06 17:23:38 +02:00
// If a post number is specified, load that post.
2025-12-12 13:15:55 +01:00
if ( $query_vars [ 'p' ] ) {
$where .= " AND { $wpdb -> posts } .ID = " . $query_vars [ 'p' ];
} elseif ( $query_vars [ 'post__in' ] ) {
2025-04-25 12:30:07 +02:00
// Duplicate array before sorting to allow for the orderby clause.
2025-12-12 13:15:55 +01:00
$post__in_for_where = $query_vars [ 'post__in' ];
2025-04-25 12:30:07 +02:00
$post__in_for_where = array_unique ( array_map ( 'absint' , $post__in_for_where ) );
sort ( $post__in_for_where );
$post__in = implode ( ',' , array_map ( 'absint' , $post__in_for_where ) );
2019-11-02 10:38:58 +01:00
$where .= " AND { $wpdb -> posts } .ID IN ( $post__in ) " ;
2025-12-12 13:15:55 +01:00
} elseif ( $query_vars [ 'post__not_in' ] ) {
sort ( $query_vars [ 'post__not_in' ] );
$post__not_in = implode ( ',' , array_map ( 'absint' , $query_vars [ 'post__not_in' ] ) );
2019-11-02 10:38:58 +01:00
$where .= " AND { $wpdb -> posts } .ID NOT IN ( $post__not_in ) " ;
}
2025-12-12 13:15:55 +01:00
if ( is_numeric ( $query_vars [ 'post_parent' ] ) ) {
$where .= $wpdb -> prepare ( " AND { $wpdb -> posts } .post_parent = %d " , $query_vars [ 'post_parent' ] );
} elseif ( $query_vars [ 'post_parent__in' ] ) {
2025-04-25 12:30:07 +02:00
// Duplicate array before sorting to allow for the orderby clause.
2025-12-12 13:15:55 +01:00
$post_parent__in_for_where = $query_vars [ 'post_parent__in' ];
2025-04-25 12:30:07 +02:00
$post_parent__in_for_where = array_unique ( array_map ( 'absint' , $post_parent__in_for_where ) );
sort ( $post_parent__in_for_where );
$post_parent__in = implode ( ',' , array_map ( 'absint' , $post_parent__in_for_where ) );
2019-11-02 10:38:58 +01:00
$where .= " AND { $wpdb -> posts } .post_parent IN ( $post_parent__in ) " ;
2025-12-12 13:15:55 +01:00
} elseif ( $query_vars [ 'post_parent__not_in' ] ) {
sort ( $query_vars [ 'post_parent__not_in' ] );
$post_parent__not_in = implode ( ',' , array_map ( 'absint' , $query_vars [ 'post_parent__not_in' ] ) );
2019-11-02 10:38:58 +01:00
$where .= " AND { $wpdb -> posts } .post_parent NOT IN ( $post_parent__not_in ) " ;
}
2025-12-12 13:15:55 +01:00
if ( $query_vars [ 'page_id' ] ) {
if ( ( 'page' !== get_option ( 'show_on_front' ) ) || ( get_option ( 'page_for_posts' ) != $query_vars [ 'page_id' ] ) ) {
$query_vars [ 'p' ] = $query_vars [ 'page_id' ];
$where = " AND { $wpdb -> posts } .ID = " . $query_vars [ 'page_id' ];
2019-11-02 10:38:58 +01:00
}
}
// If a search pattern is specified, load the posts that match.
2025-12-12 13:15:55 +01:00
if ( strlen ( $query_vars [ 's' ] ) ) {
$search = $this -> parse_search ( $query_vars );
2019-11-02 10:38:58 +01:00
}
2025-12-12 13:15:55 +01:00
if ( ! $query_vars [ 'suppress_filters' ] ) {
2019-11-02 10:38:58 +01:00
/**
* Filters the search SQL that is used in the WHERE clause of WP_Query .
*
* @ since 3.0 . 0
*
* @ param string $search Search SQL for WHERE clause .
2021-04-27 08:32:47 +02:00
* @ param WP_Query $query The current WP_Query object .
2019-11-02 10:38:58 +01:00
*/
$search = apply_filters_ref_array ( 'posts_search' , array ( $search , & $this ) );
}
2020-05-06 17:23:38 +02:00
// Taxonomies.
2019-11-02 10:38:58 +01:00
if ( ! $this -> is_singular ) {
2025-12-12 13:15:55 +01:00
$this -> parse_tax_query ( $query_vars );
2019-11-02 10:38:58 +01:00
$clauses = $this -> tax_query -> get_sql ( $wpdb -> posts , 'ID' );
$join .= $clauses [ 'join' ];
$where .= $clauses [ 'where' ];
}
if ( $this -> is_tax ) {
if ( empty ( $post_type ) ) {
2020-05-06 17:23:38 +02:00
// Do a fully inclusive search for currently registered post types of queried taxonomies.
2019-11-02 10:38:58 +01:00
$post_type = array ();
$taxonomies = array_keys ( $this -> tax_query -> queried_terms );
foreach ( get_post_types ( array ( 'exclude_from_search' => false ) ) as $pt ) {
2020-05-06 17:23:38 +02:00
$object_taxonomies = 'attachment' === $pt ? get_taxonomies_for_attachments () : get_object_taxonomies ( $pt );
2019-11-02 10:38:58 +01:00
if ( array_intersect ( $taxonomies , $object_taxonomies ) ) {
$post_type [] = $pt ;
}
}
if ( ! $post_type ) {
$post_type = 'any' ;
2023-09-26 10:33:34 +02:00
} elseif ( count ( $post_type ) === 1 ) {
2019-11-02 10:38:58 +01:00
$post_type = $post_type [ 0 ];
2025-02-28 08:42:11 +01:00
} else {
// Sort post types to ensure same cache key generation.
sort ( $post_type );
2019-11-02 10:38:58 +01:00
}
$post_status_join = true ;
2020-09-15 14:29:22 +02:00
} elseif ( in_array ( 'attachment' , ( array ) $post_type , true ) ) {
2019-11-02 10:38:58 +01:00
$post_status_join = true ;
}
}
/*
* Ensure that 'taxonomy' , 'term' , 'term_id' , 'cat' , and
* 'category_name' vars are set for backward compatibility .
*/
if ( ! empty ( $this -> tax_query -> queried_terms ) ) {
/*
* Set 'taxonomy' , 'term' , and 'term_id' to the
* first taxonomy other than 'post_tag' or 'category' .
*/
2025-12-12 13:15:55 +01:00
if ( ! isset ( $query_vars [ 'taxonomy' ] ) ) {
2019-11-02 10:38:58 +01:00
foreach ( $this -> tax_query -> queried_terms as $queried_taxonomy => $queried_items ) {
if ( empty ( $queried_items [ 'terms' ][ 0 ] ) ) {
continue ;
}
2020-09-15 14:29:22 +02:00
if ( ! in_array ( $queried_taxonomy , array ( 'category' , 'post_tag' ), true ) ) {
2025-12-12 13:15:55 +01:00
$query_vars [ 'taxonomy' ] = $queried_taxonomy ;
2019-11-02 10:38:58 +01:00
if ( 'slug' === $queried_items [ 'field' ] ) {
2025-12-12 13:15:55 +01:00
$query_vars [ 'term' ] = $queried_items [ 'terms' ][ 0 ];
2019-11-02 10:38:58 +01:00
} else {
2025-12-12 13:15:55 +01:00
$query_vars [ 'term_id' ] = $queried_items [ 'terms' ][ 0 ];
2019-11-02 10:38:58 +01:00
}
// Take the first one we find.
break ;
}
}
}
2020-05-06 17:23:38 +02:00
// 'cat', 'category_name', 'tag_id'.
2019-11-02 10:38:58 +01:00
foreach ( $this -> tax_query -> queried_terms as $queried_taxonomy => $queried_items ) {
if ( empty ( $queried_items [ 'terms' ][ 0 ] ) ) {
continue ;
}
if ( 'category' === $queried_taxonomy ) {
$the_cat = get_term_by ( $queried_items [ 'field' ], $queried_items [ 'terms' ][ 0 ], 'category' );
if ( $the_cat ) {
$this -> set ( 'cat' , $the_cat -> term_id );
$this -> set ( 'category_name' , $the_cat -> slug );
}
unset ( $the_cat );
}
if ( 'post_tag' === $queried_taxonomy ) {
$the_tag = get_term_by ( $queried_items [ 'field' ], $queried_items [ 'terms' ][ 0 ], 'post_tag' );
if ( $the_tag ) {
$this -> set ( 'tag_id' , $the_tag -> term_id );
}
unset ( $the_tag );
}
}
}
2022-12-15 17:47:31 +01:00
if ( ! empty ( $this -> tax_query -> queries ) || ! empty ( $this -> meta_query -> queries ) || ! empty ( $this -> allow_query_attachment_by_filename ) ) {
2019-11-02 10:38:58 +01:00
$groupby = " { $wpdb -> posts } .ID " ;
}
2020-05-06 17:23:38 +02:00
// Author/user stuff.
2019-11-02 10:38:58 +01:00
2025-12-12 13:15:55 +01:00
if ( ! empty ( $query_vars [ 'author' ] ) && '0' != $query_vars [ 'author' ] ) {
$query_vars [ 'author' ] = addslashes_gpc ( '' . urldecode ( $query_vars [ 'author' ] ) );
$authors = array_unique ( array_map ( 'intval' , preg_split ( '/[,\s]+/' , $query_vars [ 'author' ] ) ) );
2025-04-25 12:30:07 +02:00
sort ( $authors );
2019-11-02 10:38:58 +01:00
foreach ( $authors as $author ) {
2025-12-12 13:15:55 +01:00
$key = $author > 0 ? 'author__in' : 'author__not_in' ;
$query_vars [ $key ][] = abs ( $author );
2019-11-02 10:38:58 +01:00
}
2025-12-12 13:15:55 +01:00
$query_vars [ 'author' ] = implode ( ',' , $authors );
2019-11-02 10:38:58 +01:00
}
2025-12-12 13:15:55 +01:00
if ( ! empty ( $query_vars [ 'author__not_in' ] ) ) {
if ( is_array ( $query_vars [ 'author__not_in' ] ) ) {
$query_vars [ 'author__not_in' ] = array_unique ( array_map ( 'absint' , $query_vars [ 'author__not_in' ] ) );
sort ( $query_vars [ 'author__not_in' ] );
2025-04-25 12:30:07 +02:00
}
2025-12-12 13:15:55 +01:00
$author__not_in = implode ( ',' , ( array ) $query_vars [ 'author__not_in' ] );
2019-11-02 10:38:58 +01:00
$where .= " AND { $wpdb -> posts } .post_author NOT IN ( $author__not_in ) " ;
2025-12-12 13:15:55 +01:00
} elseif ( ! empty ( $query_vars [ 'author__in' ] ) ) {
if ( is_array ( $query_vars [ 'author__in' ] ) ) {
$query_vars [ 'author__in' ] = array_unique ( array_map ( 'absint' , $query_vars [ 'author__in' ] ) );
sort ( $query_vars [ 'author__in' ] );
2025-04-25 12:30:07 +02:00
}
2025-12-12 13:15:55 +01:00
$author__in = implode ( ',' , array_map ( 'absint' , array_unique ( ( array ) $query_vars [ 'author__in' ] ) ) );
2019-11-02 10:38:58 +01:00
$where .= " AND { $wpdb -> posts } .post_author IN ( $author__in ) " ;
}
2020-05-06 17:23:38 +02:00
// Author stuff for nice URLs.
2019-11-02 10:38:58 +01:00
2025-12-12 13:15:55 +01:00
if ( '' !== $query_vars [ 'author_name' ] ) {
if ( str_contains ( $query_vars [ 'author_name' ], '/' ) ) {
$query_vars [ 'author_name' ] = explode ( '/' , $query_vars [ 'author_name' ] );
if ( $query_vars [ 'author_name' ][ count ( $query_vars [ 'author_name' ] ) - 1 ] ) {
$query_vars [ 'author_name' ] = $query_vars [ 'author_name' ][ count ( $query_vars [ 'author_name' ] ) - 1 ]; // No trailing slash.
2019-11-02 10:38:58 +01:00
} else {
2025-12-12 13:15:55 +01:00
$query_vars [ 'author_name' ] = $query_vars [ 'author_name' ][ count ( $query_vars [ 'author_name' ] ) - 2 ]; // There was a trailing slash.
2019-11-02 10:38:58 +01:00
}
}
2025-12-12 13:15:55 +01:00
$query_vars [ 'author_name' ] = sanitize_title_for_query ( $query_vars [ 'author_name' ] );
$query_vars [ 'author' ] = get_user_by ( 'slug' , $query_vars [ 'author_name' ] );
if ( $query_vars [ 'author' ] ) {
$query_vars [ 'author' ] = $query_vars [ 'author' ] -> ID ;
2019-11-02 10:38:58 +01:00
}
2025-12-12 13:15:55 +01:00
$whichauthor .= " AND ( { $wpdb -> posts } .post_author = " . absint ( $query_vars [ 'author' ] ) . ')' ;
2019-11-02 10:38:58 +01:00
}
// Matching by comment count.
2025-12-12 13:15:55 +01:00
if ( isset ( $query_vars [ 'comment_count' ] ) ) {
2019-11-02 10:38:58 +01:00
// Numeric comment count is converted to array format.
2025-12-12 13:15:55 +01:00
if ( is_numeric ( $query_vars [ 'comment_count' ] ) ) {
$query_vars [ 'comment_count' ] = array (
'value' => ( int ) $query_vars [ 'comment_count' ],
2019-11-02 10:38:58 +01:00
);
}
2025-12-12 13:15:55 +01:00
if ( isset ( $query_vars [ 'comment_count' ][ 'value' ] ) ) {
$query_vars [ 'comment_count' ] = array_merge (
2019-11-02 10:38:58 +01:00
array (
'compare' => '=' ,
),
2025-12-12 13:15:55 +01:00
$query_vars [ 'comment_count' ]
2019-11-02 10:38:58 +01:00
);
// Fallback for invalid compare operators is '='.
$compare_operators = array ( '=' , '!=' , '>' , '>=' , '<' , '<=' );
2025-12-12 13:15:55 +01:00
if ( ! in_array ( $query_vars [ 'comment_count' ][ 'compare' ], $compare_operators , true ) ) {
$query_vars [ 'comment_count' ][ 'compare' ] = '=' ;
2019-11-02 10:38:58 +01:00
}
2025-12-12 13:15:55 +01:00
$where .= $wpdb -> prepare ( " AND { $wpdb -> posts } .comment_count { $query_vars [ 'comment_count' ][ 'compare' ] } %d " , $query_vars [ 'comment_count' ][ 'value' ] );
2019-11-02 10:38:58 +01:00
}
}
2020-05-06 17:23:38 +02:00
// MIME-Type stuff for attachment browsing.
2019-11-02 10:38:58 +01:00
2025-12-12 13:15:55 +01:00
if ( isset ( $query_vars [ 'post_mime_type' ] ) && '' !== $query_vars [ 'post_mime_type' ] ) {
$whichmimetype = wp_post_mime_type_where ( $query_vars [ 'post_mime_type' ], $wpdb -> posts );
2019-11-02 10:38:58 +01:00
}
$where .= $search . $whichauthor . $whichmimetype ;
2022-12-15 17:47:31 +01:00
if ( ! empty ( $this -> allow_query_attachment_by_filename ) ) {
$join .= " LEFT JOIN { $wpdb -> postmeta } AS sq1 ON ( { $wpdb -> posts } .ID = sq1.post_id AND sq1.meta_key = '_wp_attached_file' ) " ;
}
2019-11-02 10:38:58 +01:00
if ( ! empty ( $this -> meta_query -> queries ) ) {
$clauses = $this -> meta_query -> get_sql ( 'post' , $wpdb -> posts , 'ID' , $this );
$join .= $clauses [ 'join' ];
$where .= $clauses [ 'where' ];
}
2025-12-12 13:15:55 +01:00
$rand = ( isset ( $query_vars [ 'orderby' ] ) && 'rand' === $query_vars [ 'orderby' ] );
if ( ! isset ( $query_vars [ 'order' ] ) ) {
$query_vars [ 'order' ] = $rand ? '' : 'DESC' ;
2019-11-02 10:38:58 +01:00
} else {
2025-12-12 13:15:55 +01:00
$query_vars [ 'order' ] = $rand ? '' : $this -> parse_order ( $query_vars [ 'order' ] );
2019-11-02 10:38:58 +01:00
}
// These values of orderby should ignore the 'order' parameter.
$force_asc = array ( 'post__in' , 'post_name__in' , 'post_parent__in' );
2025-12-12 13:15:55 +01:00
if ( isset ( $query_vars [ 'orderby' ] ) && in_array ( $query_vars [ 'orderby' ], $force_asc , true ) ) {
$query_vars [ 'order' ] = '' ;
2019-11-02 10:38:58 +01:00
}
// Order by.
2025-12-12 13:15:55 +01:00
if ( empty ( $query_vars [ 'orderby' ] ) ) {
2019-11-02 10:38:58 +01:00
/*
* Boolean false or empty array blanks out ORDER BY ,
* while leaving the value unset or otherwise empty sets the default .
*/
2025-12-12 13:15:55 +01:00
if ( isset ( $query_vars [ 'orderby' ] ) && ( is_array ( $query_vars [ 'orderby' ] ) || false === $query_vars [ 'orderby' ] ) ) {
2019-11-02 10:38:58 +01:00
$orderby = '' ;
} else {
2025-12-12 13:15:55 +01:00
$orderby = " { $wpdb -> posts } .post_date " . $query_vars [ 'order' ];
2019-11-02 10:38:58 +01:00
}
2025-12-12 13:15:55 +01:00
} elseif ( 'none' === $query_vars [ 'orderby' ] ) {
2019-11-02 10:38:58 +01:00
$orderby = '' ;
} else {
$orderby_array = array ();
2025-12-12 13:15:55 +01:00
if ( is_array ( $query_vars [ 'orderby' ] ) ) {
foreach ( $query_vars [ 'orderby' ] as $_orderby => $order ) {
2019-11-02 10:38:58 +01:00
$orderby = addslashes_gpc ( urldecode ( $_orderby ) );
$parsed = $this -> parse_orderby ( $orderby );
if ( ! $parsed ) {
continue ;
}
$orderby_array [] = $parsed . ' ' . $this -> parse_order ( $order );
}
$orderby = implode ( ', ' , $orderby_array );
} else {
2025-12-12 13:15:55 +01:00
$query_vars [ 'orderby' ] = urldecode ( $query_vars [ 'orderby' ] );
$query_vars [ 'orderby' ] = addslashes_gpc ( $query_vars [ 'orderby' ] );
2019-11-02 10:38:58 +01:00
2025-12-12 13:15:55 +01:00
foreach ( explode ( ' ' , $query_vars [ 'orderby' ] ) as $i => $orderby ) {
2019-11-02 10:38:58 +01:00
$parsed = $this -> parse_orderby ( $orderby );
// Only allow certain values for safety.
if ( ! $parsed ) {
continue ;
}
$orderby_array [] = $parsed ;
}
2025-12-12 13:15:55 +01:00
$orderby = implode ( ' ' . $query_vars [ 'order' ] . ', ' , $orderby_array );
2019-11-02 10:38:58 +01:00
if ( empty ( $orderby ) ) {
2025-12-12 13:15:55 +01:00
$orderby = " { $wpdb -> posts } .post_date " . $query_vars [ 'order' ];
} elseif ( ! empty ( $query_vars [ 'order' ] ) ) {
$orderby .= " { $query_vars [ 'order' ] } " ;
2019-11-02 10:38:58 +01:00
}
}
}
// Order search results by relevance only when another "orderby" is not specified in the query.
2025-12-12 13:15:55 +01:00
if ( ! empty ( $query_vars [ 's' ] ) ) {
2019-11-02 10:38:58 +01:00
$search_orderby = '' ;
2025-12-12 13:15:55 +01:00
if ( ! empty ( $query_vars [ 'search_orderby_title' ] ) && ( empty ( $query_vars [ 'orderby' ] ) && ! $this -> is_feed ) || ( isset ( $query_vars [ 'orderby' ] ) && 'relevance' === $query_vars [ 'orderby' ] ) ) {
$search_orderby = $this -> parse_search_order ( $query_vars );
2019-11-02 10:38:58 +01:00
}
2025-12-12 13:15:55 +01:00
if ( ! $query_vars [ 'suppress_filters' ] ) {
2019-11-02 10:38:58 +01:00
/**
* Filters the ORDER BY used when ordering search results .
*
* @ since 3.7 . 0
*
* @ param string $search_orderby The ORDER BY clause .
2021-04-27 08:32:47 +02:00
* @ param WP_Query $query The current WP_Query instance .
2019-11-02 10:38:58 +01:00
*/
$search_orderby = apply_filters ( 'posts_search_orderby' , $search_orderby , $this );
}
if ( $search_orderby ) {
$orderby = $orderby ? $search_orderby . ', ' . $orderby : $search_orderby ;
}
}
if ( is_array ( $post_type ) && count ( $post_type ) > 1 ) {
$post_type_cap = 'multiple_post_type' ;
} else {
if ( is_array ( $post_type ) ) {
$post_type = reset ( $post_type );
}
$post_type_object = get_post_type_object ( $post_type );
if ( empty ( $post_type_object ) ) {
$post_type_cap = $post_type ;
}
}
2025-12-12 13:15:55 +01:00
if ( isset ( $query_vars [ 'post_password' ] ) ) {
$where .= $wpdb -> prepare ( " AND { $wpdb -> posts } .post_password = %s " , $query_vars [ 'post_password' ] );
if ( empty ( $query_vars [ 'perm' ] ) ) {
$query_vars [ 'perm' ] = 'readable' ;
2019-11-02 10:38:58 +01:00
}
2025-12-12 13:15:55 +01:00
} elseif ( isset ( $query_vars [ 'has_password' ] ) ) {
$where .= sprintf ( " AND { $wpdb -> posts } .post_password %s '' " , $query_vars [ 'has_password' ] ? '!=' : '=' );
2019-11-02 10:38:58 +01:00
}
2025-12-12 13:15:55 +01:00
if ( ! empty ( $query_vars [ 'comment_status' ] ) ) {
$where .= $wpdb -> prepare ( " AND { $wpdb -> posts } .comment_status = %s " , $query_vars [ 'comment_status' ] );
2019-11-02 10:38:58 +01:00
}
2025-12-12 13:15:55 +01:00
if ( ! empty ( $query_vars [ 'ping_status' ] ) ) {
$where .= $wpdb -> prepare ( " AND { $wpdb -> posts } .ping_status = %s " , $query_vars [ 'ping_status' ] );
2019-11-02 10:38:58 +01:00
}
2022-04-02 10:26:41 +02:00
$skip_post_status = false ;
2020-09-15 14:29:22 +02:00
if ( 'any' === $post_type ) {
2019-11-02 10:38:58 +01:00
$in_search_post_types = get_post_types ( array ( 'exclude_from_search' => false ) );
if ( empty ( $in_search_post_types ) ) {
2022-04-02 10:26:41 +02:00
$post_type_where = ' AND 1=0 ' ;
$skip_post_status = true ;
2019-11-02 10:38:58 +01:00
} else {
2022-04-02 10:26:41 +02:00
$post_type_where = " AND { $wpdb -> posts } .post_type IN (' " . implode ( " ', ' " , array_map ( 'esc_sql' , $in_search_post_types ) ) . " ') " ;
2019-11-02 10:38:58 +01:00
}
} elseif ( ! empty ( $post_type ) && is_array ( $post_type ) ) {
2025-02-28 08:42:11 +01:00
// Sort post types to ensure same cache key generation.
sort ( $post_type );
2022-04-02 10:26:41 +02:00
$post_type_where = " AND { $wpdb -> posts } .post_type IN (' " . implode ( " ', ' " , esc_sql ( $post_type ) ) . " ') " ;
2019-11-02 10:38:58 +01:00
} elseif ( ! empty ( $post_type ) ) {
2022-04-02 10:26:41 +02:00
$post_type_where = $wpdb -> prepare ( " AND { $wpdb -> posts } .post_type = %s " , $post_type );
2019-11-02 10:38:58 +01:00
$post_type_object = get_post_type_object ( $post_type );
} elseif ( $this -> is_attachment ) {
2022-04-02 10:26:41 +02:00
$post_type_where = " AND { $wpdb -> posts } .post_type = 'attachment' " ;
2019-11-02 10:38:58 +01:00
$post_type_object = get_post_type_object ( 'attachment' );
} elseif ( $this -> is_page ) {
2022-04-02 10:26:41 +02:00
$post_type_where = " AND { $wpdb -> posts } .post_type = 'page' " ;
2019-11-02 10:38:58 +01:00
$post_type_object = get_post_type_object ( 'page' );
} else {
2022-04-02 10:26:41 +02:00
$post_type_where = " AND { $wpdb -> posts } .post_type = 'post' " ;
2019-11-02 10:38:58 +01:00
$post_type_object = get_post_type_object ( 'post' );
}
$edit_cap = 'edit_post' ;
$read_cap = 'read_post' ;
if ( ! empty ( $post_type_object ) ) {
$edit_others_cap = $post_type_object -> cap -> edit_others_posts ;
$read_private_cap = $post_type_object -> cap -> read_private_posts ;
} else {
$edit_others_cap = 'edit_others_' . $post_type_cap . 's' ;
$read_private_cap = 'read_private_' . $post_type_cap . 's' ;
}
$user_id = get_current_user_id ();
$q_status = array ();
2022-04-02 10:26:41 +02:00
if ( $skip_post_status ) {
$where .= $post_type_where ;
2025-12-12 13:15:55 +01:00
} elseif ( ! empty ( $query_vars [ 'post_status' ] ) ) {
2022-04-02 10:26:41 +02:00
$where .= $post_type_where ;
2019-11-02 10:38:58 +01:00
$statuswheres = array ();
2025-12-12 13:15:55 +01:00
$q_status = $query_vars [ 'post_status' ];
2019-11-02 10:38:58 +01:00
if ( ! is_array ( $q_status ) ) {
$q_status = explode ( ',' , $q_status );
}
2025-04-25 12:30:07 +02:00
sort ( $q_status );
2019-11-02 10:38:58 +01:00
$r_status = array ();
$p_status = array ();
$e_status = array ();
2020-09-15 14:29:22 +02:00
if ( in_array ( 'any' , $q_status , true ) ) {
2019-11-02 10:38:58 +01:00
foreach ( get_post_stati ( array ( 'exclude_from_search' => true ) ) as $status ) {
2020-09-15 14:29:22 +02:00
if ( ! in_array ( $status , $q_status , true ) ) {
2019-11-02 10:38:58 +01:00
$e_status [] = " { $wpdb -> posts } .post_status <> ' $status ' " ;
}
}
} else {
foreach ( get_post_stati () as $status ) {
2020-09-15 14:29:22 +02:00
if ( in_array ( $status , $q_status , true ) ) {
if ( 'private' === $status ) {
2019-11-02 10:38:58 +01:00
$p_status [] = " { $wpdb -> posts } .post_status = ' $status ' " ;
} else {
$r_status [] = " { $wpdb -> posts } .post_status = ' $status ' " ;
}
}
}
}
2025-12-12 13:15:55 +01:00
if ( empty ( $query_vars [ 'perm' ] ) || 'readable' !== $query_vars [ 'perm' ] ) {
2019-11-02 10:38:58 +01:00
$r_status = array_merge ( $r_status , $p_status );
unset ( $p_status );
}
if ( ! empty ( $e_status ) ) {
2020-12-10 14:06:04 +01:00
$statuswheres [] = '(' . implode ( ' AND ' , $e_status ) . ')' ;
2019-11-02 10:38:58 +01:00
}
if ( ! empty ( $r_status ) ) {
2025-12-12 13:15:55 +01:00
if ( ! empty ( $query_vars [ 'perm' ] ) && 'editable' === $query_vars [ 'perm' ] && ! current_user_can ( $edit_others_cap ) ) {
2020-12-10 14:06:04 +01:00
$statuswheres [] = " ( { $wpdb -> posts } .post_author = $user_id " . 'AND (' . implode ( ' OR ' , $r_status ) . '))' ;
2019-11-02 10:38:58 +01:00
} else {
2020-12-10 14:06:04 +01:00
$statuswheres [] = '(' . implode ( ' OR ' , $r_status ) . ')' ;
2019-11-02 10:38:58 +01:00
}
}
if ( ! empty ( $p_status ) ) {
2025-12-12 13:15:55 +01:00
if ( ! empty ( $query_vars [ 'perm' ] ) && 'readable' === $query_vars [ 'perm' ] && ! current_user_can ( $read_private_cap ) ) {
2020-12-10 14:06:04 +01:00
$statuswheres [] = " ( { $wpdb -> posts } .post_author = $user_id " . 'AND (' . implode ( ' OR ' , $p_status ) . '))' ;
2019-11-02 10:38:58 +01:00
} else {
2020-12-10 14:06:04 +01:00
$statuswheres [] = '(' . implode ( ' OR ' , $p_status ) . ')' ;
2019-11-02 10:38:58 +01:00
}
}
if ( $post_status_join ) {
$join .= " LEFT JOIN { $wpdb -> posts } AS p2 ON ( { $wpdb -> posts } .post_parent = p2.ID) " ;
foreach ( $statuswheres as $index => $statuswhere ) {
$statuswheres [ $index ] = " ( $statuswhere OR ( { $wpdb -> posts } .post_status = 'inherit' AND " . str_replace ( $wpdb -> posts , 'p2' , $statuswhere ) . '))' ;
}
}
$where_status = implode ( ' OR ' , $statuswheres );
if ( ! empty ( $where_status ) ) {
$where .= " AND ( $where_status ) " ;
}
} elseif ( ! $this -> is_singular ) {
2022-04-02 10:26:41 +02:00
if ( 'any' === $post_type ) {
$queried_post_types = get_post_types ( array ( 'exclude_from_search' => false ) );
} elseif ( is_array ( $post_type ) ) {
$queried_post_types = $post_type ;
} elseif ( ! empty ( $post_type ) ) {
$queried_post_types = array ( $post_type );
} else {
$queried_post_types = array ( 'post' );
2019-11-02 10:38:58 +01:00
}
2022-04-02 10:26:41 +02:00
if ( ! empty ( $queried_post_types ) ) {
2025-02-28 08:42:11 +01:00
sort ( $queried_post_types );
2022-04-02 10:26:41 +02:00
$status_type_clauses = array ();
foreach ( $queried_post_types as $queried_post_type ) {
$queried_post_type_object = get_post_type_object ( $queried_post_type );
$type_where = '(' . $wpdb -> prepare ( " { $wpdb -> posts } .post_type = %s AND ( " , $queried_post_type );
// Public statuses.
$public_statuses = get_post_stati ( array ( 'public' => true ) );
$status_clauses = array ();
foreach ( $public_statuses as $public_status ) {
$status_clauses [] = " { $wpdb -> posts } .post_status = ' $public_status ' " ;
}
$type_where .= implode ( ' OR ' , $status_clauses );
// Add protected states that should show in the admin all list.
if ( $this -> is_admin ) {
$admin_all_statuses = get_post_stati (
array (
'protected' => true ,
'show_in_admin_all_list' => true ,
)
);
foreach ( $admin_all_statuses as $admin_all_status ) {
$type_where .= " OR { $wpdb -> posts } .post_status = ' $admin_all_status ' " ;
}
}
// Add private states that are visible to current user.
if ( is_user_logged_in () && $queried_post_type_object instanceof WP_Post_Type ) {
$read_private_cap = $queried_post_type_object -> cap -> read_private_posts ;
$private_statuses = get_post_stati ( array ( 'private' => true ) );
foreach ( $private_statuses as $private_status ) {
$type_where .= current_user_can ( $read_private_cap ) ? " \n OR { $wpdb -> posts } .post_status = ' $private_status ' " : " \n OR ( { $wpdb -> posts } .post_author = $user_id AND { $wpdb -> posts } .post_status = ' $private_status ') " ;
}
}
$type_where .= '))' ;
$status_type_clauses [] = $type_where ;
2019-11-02 10:38:58 +01:00
}
2022-04-02 10:26:41 +02:00
if ( ! empty ( $status_type_clauses ) ) {
$where .= ' AND (' . implode ( ' OR ' , $status_type_clauses ) . ')' ;
2019-11-02 10:38:58 +01:00
}
2022-04-02 10:26:41 +02:00
} else {
$where .= ' AND 1=0 ' ;
2019-11-02 10:38:58 +01:00
}
2022-04-02 10:26:41 +02:00
} else {
$where .= $post_type_where ;
2019-11-02 10:38:58 +01:00
}
/*
* Apply filters on where and join prior to paging so that any
* manipulations to them are reflected in the paging by day queries .
*/
2025-12-12 13:15:55 +01:00
if ( ! $query_vars [ 'suppress_filters' ] ) {
2019-11-02 10:38:58 +01:00
/**
* Filters the WHERE clause of the query .
*
* @ since 1.5 . 0
*
* @ param string $where The WHERE clause of the query .
2021-04-27 08:32:47 +02:00
* @ param WP_Query $query The WP_Query instance ( passed by reference ) .
2019-11-02 10:38:58 +01:00
*/
$where = apply_filters_ref_array ( 'posts_where' , array ( $where , & $this ) );
/**
* Filters the JOIN clause of the query .
*
* @ since 1.5 . 0
*
2021-04-27 08:32:47 +02:00
* @ param string $join The JOIN clause of the query .
* @ param WP_Query $query The WP_Query instance ( passed by reference ) .
2019-11-02 10:38:58 +01:00
*/
$join = apply_filters_ref_array ( 'posts_join' , array ( $join , & $this ) );
}
2020-05-06 17:23:38 +02:00
// Paging.
2025-12-12 13:15:55 +01:00
if ( empty ( $query_vars [ 'nopaging' ] ) && ! $this -> is_singular ) {
$page = absint ( $query_vars [ 'paged' ] );
2019-11-02 10:38:58 +01:00
if ( ! $page ) {
$page = 1 ;
}
// If 'offset' is provided, it takes precedence over 'paged'.
2025-12-12 13:15:55 +01:00
if ( isset ( $query_vars [ 'offset' ] ) && is_numeric ( $query_vars [ 'offset' ] ) ) {
$query_vars [ 'offset' ] = absint ( $query_vars [ 'offset' ] );
$pgstrt = $query_vars [ 'offset' ] . ', ' ;
2019-11-02 10:38:58 +01:00
} else {
2025-12-12 13:15:55 +01:00
$pgstrt = absint ( ( $page - 1 ) * $query_vars [ 'posts_per_page' ] ) . ', ' ;
2019-11-02 10:38:58 +01:00
}
2025-12-12 13:15:55 +01:00
$limits = 'LIMIT ' . $pgstrt . $query_vars [ 'posts_per_page' ];
2019-11-02 10:38:58 +01:00
}
2020-05-06 17:23:38 +02:00
// Comments feeds.
2019-11-02 10:38:58 +01:00
if ( $this -> is_comment_feed && ! $this -> is_singular ) {
if ( $this -> is_archive || $this -> is_search ) {
2021-07-23 11:58:50 +02:00
$cjoin = " JOIN { $wpdb -> posts } ON ( { $wpdb -> comments } .comment_post_ID = { $wpdb -> posts } .ID ) $join " ;
2019-11-02 10:38:58 +01:00
$cwhere = " WHERE comment_approved = '1' $where " ;
$cgroupby = " { $wpdb -> comments } .comment_id " ;
2020-05-06 17:23:38 +02:00
} else { // Other non-singular, e.g. front.
2019-11-02 10:38:58 +01:00
$cjoin = " JOIN { $wpdb -> posts } ON ( { $wpdb -> comments } .comment_post_ID = { $wpdb -> posts } .ID ) " ;
$cwhere = " WHERE ( post_status = 'publish' OR ( post_status = 'inherit' AND post_type = 'attachment' ) ) AND comment_approved = '1' " ;
$cgroupby = '' ;
}
2025-12-12 13:15:55 +01:00
if ( ! $query_vars [ 'suppress_filters' ] ) {
2019-11-02 10:38:58 +01:00
/**
* Filters the JOIN clause of the comments feed query before sending .
*
* @ since 2.2 . 0
*
* @ param string $cjoin The JOIN clause of the query .
2021-04-27 08:32:47 +02:00
* @ param WP_Query $query The WP_Query instance ( passed by reference ) .
2019-11-02 10:38:58 +01:00
*/
$cjoin = apply_filters_ref_array ( 'comment_feed_join' , array ( $cjoin , & $this ) );
/**
* Filters the WHERE clause of the comments feed query before sending .
*
* @ since 2.2 . 0
*
* @ param string $cwhere The WHERE clause of the query .
2021-04-27 08:32:47 +02:00
* @ param WP_Query $query The WP_Query instance ( passed by reference ) .
2019-11-02 10:38:58 +01:00
*/
$cwhere = apply_filters_ref_array ( 'comment_feed_where' , array ( $cwhere , & $this ) );
/**
* Filters the GROUP BY clause of the comments feed query before sending .
*
* @ since 2.2 . 0
*
* @ param string $cgroupby The GROUP BY clause of the query .
2021-04-27 08:32:47 +02:00
* @ param WP_Query $query The WP_Query instance ( passed by reference ) .
2019-11-02 10:38:58 +01:00
*/
$cgroupby = apply_filters_ref_array ( 'comment_feed_groupby' , array ( $cgroupby , & $this ) );
/**
* Filters the ORDER BY clause of the comments feed query before sending .
*
* @ since 2.8 . 0
*
* @ param string $corderby The ORDER BY clause of the query .
2021-04-27 08:32:47 +02:00
* @ param WP_Query $query The WP_Query instance ( passed by reference ) .
2019-11-02 10:38:58 +01:00
*/
$corderby = apply_filters_ref_array ( 'comment_feed_orderby' , array ( 'comment_date_gmt DESC' , & $this ) );
/**
* Filters the LIMIT clause of the comments feed query before sending .
*
* @ since 2.8 . 0
*
* @ param string $climits The JOIN clause of the query .
2021-04-27 08:32:47 +02:00
* @ param WP_Query $query The WP_Query instance ( passed by reference ) .
2019-11-02 10:38:58 +01:00
*/
$climits = apply_filters_ref_array ( 'comment_feed_limits' , array ( 'LIMIT ' . get_option ( 'posts_per_rss' ), & $this ) );
}
2019-11-15 22:59:44 +01:00
2019-11-02 10:38:58 +01:00
$cgroupby = ( ! empty ( $cgroupby ) ) ? 'GROUP BY ' . $cgroupby : '' ;
$corderby = ( ! empty ( $corderby ) ) ? 'ORDER BY ' . $corderby : '' ;
2019-11-15 22:59:44 +01:00
$climits = ( ! empty ( $climits ) ) ? $climits : '' ;
2019-11-02 10:38:58 +01:00
2022-06-16 14:03:35 +02:00
$comments_request = " SELECT $distinct { $wpdb -> comments } .comment_ID FROM { $wpdb -> comments } $cjoin $cwhere $cgroupby $corderby $climits " ;
$key = md5 ( $comments_request );
2025-12-12 13:15:55 +01:00
$last_changed = array (
wp_cache_get_last_changed ( 'comment' ),
wp_cache_get_last_changed ( 'posts' ),
);
2022-06-16 14:03:35 +02:00
2025-12-12 13:15:55 +01:00
$cache_key = " comment_feed: $key " ;
$comment_ids = wp_cache_get_salted ( $cache_key , 'comment-queries' , $last_changed );
2022-06-16 14:03:35 +02:00
if ( false === $comment_ids ) {
$comment_ids = $wpdb -> get_col ( $comments_request );
2025-12-12 13:15:55 +01:00
wp_cache_set_salted ( $cache_key , $comment_ids , 'comment-queries' , $last_changed );
2022-06-16 14:03:35 +02:00
}
2023-09-26 10:33:34 +02:00
_prime_comment_caches ( $comment_ids );
2022-06-16 14:03:35 +02:00
2020-05-06 17:23:38 +02:00
// Convert to WP_Comment.
2021-04-27 08:32:47 +02:00
/** @var WP_Comment[] */
2022-06-16 14:03:35 +02:00
$this -> comments = array_map ( 'get_comment' , $comment_ids );
2019-11-02 10:38:58 +01:00
$this -> comment_count = count ( $this -> comments );
$post_ids = array ();
foreach ( $this -> comments as $comment ) {
$post_ids [] = ( int ) $comment -> comment_post_ID ;
}
2020-12-10 14:06:04 +01:00
$post_ids = implode ( ',' , $post_ids );
2019-11-02 10:38:58 +01:00
$join = '' ;
if ( $post_ids ) {
$where = " AND { $wpdb -> posts } .ID IN ( $post_ids ) " ;
} else {
$where = 'AND 0' ;
}
}
$pieces = array ( 'where' , 'groupby' , 'join' , 'orderby' , 'distinct' , 'fields' , 'limits' );
/*
* Apply post - paging filters on where and join . Only plugins that
* manipulate paging queries should use these hooks .
*/
2025-12-12 13:15:55 +01:00
if ( ! $query_vars [ 'suppress_filters' ] ) {
2019-11-02 10:38:58 +01:00
/**
* Filters the WHERE clause of the query .
*
* Specifically for manipulating paging queries .
*
* @ since 1.5 . 0
*
* @ param string $where The WHERE clause of the query .
2021-04-27 08:32:47 +02:00
* @ param WP_Query $query The WP_Query instance ( passed by reference ) .
2019-11-02 10:38:58 +01:00
*/
$where = apply_filters_ref_array ( 'posts_where_paged' , array ( $where , & $this ) );
/**
* Filters the GROUP BY clause of the query .
*
* @ since 2.0 . 0
*
* @ param string $groupby The GROUP BY clause of the query .
2021-04-27 08:32:47 +02:00
* @ param WP_Query $query The WP_Query instance ( passed by reference ) .
2019-11-02 10:38:58 +01:00
*/
$groupby = apply_filters_ref_array ( 'posts_groupby' , array ( $groupby , & $this ) );
/**
* Filters the JOIN clause of the query .
*
* Specifically for manipulating paging queries .
*
* @ since 1.5 . 0
*
2021-04-27 08:32:47 +02:00
* @ param string $join The JOIN clause of the query .
* @ param WP_Query $query The WP_Query instance ( passed by reference ) .
2019-11-02 10:38:58 +01:00
*/
$join = apply_filters_ref_array ( 'posts_join_paged' , array ( $join , & $this ) );
/**
* Filters the ORDER BY clause of the query .
*
* @ since 1.5 . 1
*
* @ param string $orderby The ORDER BY clause of the query .
2021-04-27 08:32:47 +02:00
* @ param WP_Query $query The WP_Query instance ( passed by reference ) .
2019-11-02 10:38:58 +01:00
*/
$orderby = apply_filters_ref_array ( 'posts_orderby' , array ( $orderby , & $this ) );
/**
* Filters the DISTINCT clause of the query .
*
* @ since 2.1 . 0
*
* @ param string $distinct The DISTINCT clause of the query .
2021-04-27 08:32:47 +02:00
* @ param WP_Query $query The WP_Query instance ( passed by reference ) .
2019-11-02 10:38:58 +01:00
*/
$distinct = apply_filters_ref_array ( 'posts_distinct' , array ( $distinct , & $this ) );
/**
* Filters the LIMIT clause of the query .
*
* @ since 2.1 . 0
*
* @ param string $limits The LIMIT clause of the query .
2021-04-27 08:32:47 +02:00
* @ param WP_Query $query The WP_Query instance ( passed by reference ) .
2019-11-02 10:38:58 +01:00
*/
$limits = apply_filters_ref_array ( 'post_limits' , array ( $limits , & $this ) );
/**
* Filters the SELECT clause of the query .
*
* @ since 2.1 . 0
*
* @ param string $fields The SELECT clause of the query .
2021-04-27 08:32:47 +02:00
* @ param WP_Query $query The WP_Query instance ( passed by reference ) .
2019-11-02 10:38:58 +01:00
*/
$fields = apply_filters_ref_array ( 'posts_fields' , array ( $fields , & $this ) );
/**
* Filters all query clauses at once , for convenience .
*
* Covers the WHERE , GROUP BY , JOIN , ORDER BY , DISTINCT ,
2022-04-02 10:26:41 +02:00
* fields ( SELECT ), and LIMIT clauses .
2019-11-02 10:38:58 +01:00
*
* @ since 3.1 . 0
*
2022-04-02 10:26:41 +02:00
* @ param string [] $clauses {
* Associative array of the clauses for the query .
*
* @ type string $where The WHERE clause of the query .
* @ type string $groupby The GROUP BY clause of the query .
* @ type string $join The JOIN clause of the query .
* @ type string $orderby The ORDER BY clause of the query .
* @ type string $distinct The DISTINCT clause of the query .
* @ type string $fields The SELECT clause of the query .
* @ type string $limits The LIMIT clause of the query .
* }
2021-04-27 08:32:47 +02:00
* @ param WP_Query $query The WP_Query instance ( passed by reference ) .
2019-11-02 10:38:58 +01:00
*/
$clauses = ( array ) apply_filters_ref_array ( 'posts_clauses' , array ( compact ( $pieces ), & $this ) );
$where = isset ( $clauses [ 'where' ] ) ? $clauses [ 'where' ] : '' ;
$groupby = isset ( $clauses [ 'groupby' ] ) ? $clauses [ 'groupby' ] : '' ;
$join = isset ( $clauses [ 'join' ] ) ? $clauses [ 'join' ] : '' ;
$orderby = isset ( $clauses [ 'orderby' ] ) ? $clauses [ 'orderby' ] : '' ;
$distinct = isset ( $clauses [ 'distinct' ] ) ? $clauses [ 'distinct' ] : '' ;
$fields = isset ( $clauses [ 'fields' ] ) ? $clauses [ 'fields' ] : '' ;
$limits = isset ( $clauses [ 'limits' ] ) ? $clauses [ 'limits' ] : '' ;
}
/**
* Fires to announce the query ' s current selection parameters .
*
* For use by caching plugins .
*
* @ since 2.3 . 0
*
* @ param string $selection The assembled selection query .
*/
do_action ( 'posts_selection' , $where . $groupby . $orderby . $limits . $join );
/*
* Filters again for the benefit of caching plugins .
* Regular plugins should use the hooks above .
*/
2025-12-12 13:15:55 +01:00
if ( ! $query_vars [ 'suppress_filters' ] ) {
2019-11-02 10:38:58 +01:00
/**
* Filters the WHERE clause of the query .
*
* For use by caching plugins .
*
* @ since 2.5 . 0
*
* @ param string $where The WHERE clause of the query .
2021-04-27 08:32:47 +02:00
* @ param WP_Query $query The WP_Query instance ( passed by reference ) .
2019-11-02 10:38:58 +01:00
*/
$where = apply_filters_ref_array ( 'posts_where_request' , array ( $where , & $this ) );
/**
* Filters the GROUP BY clause of the query .
*
* For use by caching plugins .
*
* @ since 2.5 . 0
*
* @ param string $groupby The GROUP BY clause of the query .
2021-04-27 08:32:47 +02:00
* @ param WP_Query $query The WP_Query instance ( passed by reference ) .
2019-11-02 10:38:58 +01:00
*/
$groupby = apply_filters_ref_array ( 'posts_groupby_request' , array ( $groupby , & $this ) );
/**
* Filters the JOIN clause of the query .
*
* For use by caching plugins .
*
* @ since 2.5 . 0
*
2021-04-27 08:32:47 +02:00
* @ param string $join The JOIN clause of the query .
* @ param WP_Query $query The WP_Query instance ( passed by reference ) .
2019-11-02 10:38:58 +01:00
*/
$join = apply_filters_ref_array ( 'posts_join_request' , array ( $join , & $this ) );
/**
* Filters the ORDER BY clause of the query .
*
* For use by caching plugins .
*
* @ since 2.5 . 0
*
* @ param string $orderby The ORDER BY clause of the query .
2021-04-27 08:32:47 +02:00
* @ param WP_Query $query The WP_Query instance ( passed by reference ) .
2019-11-02 10:38:58 +01:00
*/
$orderby = apply_filters_ref_array ( 'posts_orderby_request' , array ( $orderby , & $this ) );
/**
* Filters the DISTINCT clause of the query .
*
* For use by caching plugins .
*
* @ since 2.5 . 0
*
* @ param string $distinct The DISTINCT clause of the query .
2021-04-27 08:32:47 +02:00
* @ param WP_Query $query The WP_Query instance ( passed by reference ) .
2019-11-02 10:38:58 +01:00
*/
$distinct = apply_filters_ref_array ( 'posts_distinct_request' , array ( $distinct , & $this ) );
/**
* Filters the SELECT clause of the query .
*
* For use by caching plugins .
*
* @ since 2.5 . 0
*
* @ param string $fields The SELECT clause of the query .
2021-04-27 08:32:47 +02:00
* @ param WP_Query $query The WP_Query instance ( passed by reference ) .
2019-11-02 10:38:58 +01:00
*/
$fields = apply_filters_ref_array ( 'posts_fields_request' , array ( $fields , & $this ) );
/**
* Filters the LIMIT clause of the query .
*
* For use by caching plugins .
*
* @ since 2.5 . 0
*
* @ param string $limits The LIMIT clause of the query .
2021-04-27 08:32:47 +02:00
* @ param WP_Query $query The WP_Query instance ( passed by reference ) .
2019-11-02 10:38:58 +01:00
*/
$limits = apply_filters_ref_array ( 'post_limits_request' , array ( $limits , & $this ) );
/**
* Filters all query clauses at once , for convenience .
*
* For use by caching plugins .
*
* Covers the WHERE , GROUP BY , JOIN , ORDER BY , DISTINCT ,
2022-04-02 10:26:41 +02:00
* fields ( SELECT ), and LIMIT clauses .
2019-11-02 10:38:58 +01:00
*
* @ since 3.1 . 0
*
2022-06-16 14:03:35 +02:00
* @ param string [] $clauses {
2022-04-02 10:26:41 +02:00
* Associative array of the clauses for the query .
*
* @ type string $where The WHERE clause of the query .
* @ type string $groupby The GROUP BY clause of the query .
* @ type string $join The JOIN clause of the query .
* @ type string $orderby The ORDER BY clause of the query .
* @ type string $distinct The DISTINCT clause of the query .
* @ type string $fields The SELECT clause of the query .
* @ type string $limits The LIMIT clause of the query .
* }
2021-04-27 08:32:47 +02:00
* @ param WP_Query $query The WP_Query instance ( passed by reference ) .
2019-11-02 10:38:58 +01:00
*/
$clauses = ( array ) apply_filters_ref_array ( 'posts_clauses_request' , array ( compact ( $pieces ), & $this ) );
$where = isset ( $clauses [ 'where' ] ) ? $clauses [ 'where' ] : '' ;
$groupby = isset ( $clauses [ 'groupby' ] ) ? $clauses [ 'groupby' ] : '' ;
$join = isset ( $clauses [ 'join' ] ) ? $clauses [ 'join' ] : '' ;
$orderby = isset ( $clauses [ 'orderby' ] ) ? $clauses [ 'orderby' ] : '' ;
$distinct = isset ( $clauses [ 'distinct' ] ) ? $clauses [ 'distinct' ] : '' ;
$fields = isset ( $clauses [ 'fields' ] ) ? $clauses [ 'fields' ] : '' ;
$limits = isset ( $clauses [ 'limits' ] ) ? $clauses [ 'limits' ] : '' ;
}
if ( ! empty ( $groupby ) ) {
$groupby = 'GROUP BY ' . $groupby ;
}
if ( ! empty ( $orderby ) ) {
$orderby = 'ORDER BY ' . $orderby ;
}
$found_rows = '' ;
2025-12-12 13:15:55 +01:00
if ( ! $query_vars [ 'no_found_rows' ] && ! empty ( $limits ) ) {
2019-11-02 10:38:58 +01:00
$found_rows = 'SQL_CALC_FOUND_ROWS' ;
}
2025-02-28 08:42:11 +01:00
/*
* Beginning of the string is on a new line to prevent leading whitespace .
*
* The additional indentation of subsequent lines is to ensure the SQL
* queries are identical to those generated when splitting queries . This
* improves caching of the query by ensuring the same cache key is
* generated for the same database queries functionally .
*
* See https :// core . trac . wordpress . org / ticket / 56841.
* See https :// github . com / WordPress / wordpress - develop / pull / 6393 #issuecomment-2088217429
*/
2024-04-17 11:32:24 +02:00
$old_request =
" SELECT $found_rows $distinct $fields
2025-02-28 08:42:11 +01:00
FROM { $wpdb -> posts } $join
WHERE 1 = 1 $where
$groupby
$orderby
$limits " ;
2022-06-16 14:03:35 +02:00
2019-11-15 22:59:44 +01:00
$this -> request = $old_request ;
2019-11-02 10:38:58 +01:00
2025-12-12 13:15:55 +01:00
if ( ! $query_vars [ 'suppress_filters' ] ) {
2019-11-02 10:38:58 +01:00
/**
* Filters the completed SQL query before sending .
*
* @ since 2.0 . 0
*
* @ param string $request The complete SQL query .
2021-04-27 08:32:47 +02:00
* @ param WP_Query $query The WP_Query instance ( passed by reference ) .
2019-11-02 10:38:58 +01:00
*/
$this -> request = apply_filters_ref_array ( 'posts_request' , array ( $this -> request , & $this ) );
}
/**
* Filters the posts array before the query takes place .
*
2020-12-10 14:06:04 +01:00
* Return a non - null value to bypass WordPress ' default post queries .
2019-11-02 10:38:58 +01:00
*
* Filtering functions that require pagination information are encouraged to set
* the `found_posts` and `max_num_pages` properties of the WP_Query object ,
* passed to the filter by reference . If WP_Query does not perform a database
* query , it will not have enough information to generate these values itself .
*
* @ since 4.6 . 0
*
2021-04-27 08:32:47 +02:00
* @ param WP_Post [] | int [] | null $posts Return an array of post data to short - circuit WP ' s query ,
* or null to allow WP to run its normal queries .
* @ param WP_Query $query The WP_Query instance ( passed by reference ) .
2019-11-02 10:38:58 +01:00
*/
$this -> posts = apply_filters_ref_array ( 'posts_pre_query' , array ( null , & $this ) );
2022-12-15 17:47:31 +01:00
/*
* Ensure the ID database query is able to be cached .
*
* Random queries are expected to have unpredictable results and
* cannot be cached . Note the space before `RAND` in the string
* search , that to ensure against a collision with another
* function .
*
* If `$fields` has been modified by the `posts_fields` ,
* `posts_fields_request` , `post_clauses` or `posts_clauses_request`
* filters , then caching is disabled to prevent caching collisions .
*/
$id_query_is_cacheable = ! str_contains ( strtoupper ( $orderby ), ' RAND(' );
$cacheable_field_values = array (
" { $wpdb -> posts } .* " ,
" { $wpdb -> posts } .ID, { $wpdb -> posts } .post_parent " ,
" { $wpdb -> posts } .ID " ,
);
if ( ! in_array ( $fields , $cacheable_field_values , true ) ) {
$id_query_is_cacheable = false ;
}
2025-12-12 13:15:55 +01:00
$last_changed = ( array ) wp_cache_get_last_changed ( 'posts' );
if ( ! empty ( $this -> tax_query -> queries ) ) {
$last_changed [] = wp_cache_get_last_changed ( 'terms' );
}
if ( $query_vars [ 'cache_results' ] && $id_query_is_cacheable ) {
2022-12-15 17:47:31 +01:00
$new_request = str_replace ( $fields , " { $wpdb -> posts } .* " , $this -> request );
2025-12-12 13:15:55 +01:00
$cache_key = $this -> generate_cache_key ( $query_vars , $new_request );
2022-12-15 17:47:31 +01:00
$cache_found = false ;
if ( null === $this -> posts ) {
2025-12-12 13:15:55 +01:00
$cached_results = wp_cache_get_salted ( $cache_key , 'post-queries' , $last_changed );
2022-12-15 17:47:31 +01:00
if ( $cached_results ) {
2025-12-12 13:15:55 +01:00
$cache_found = true ;
2023-12-07 09:44:11 +01:00
/** @var int[] */
$post_ids = array_map ( 'intval' , $cached_results [ 'posts' ] );
2022-12-15 17:47:31 +01:00
2023-12-07 09:44:11 +01:00
$this -> post_count = count ( $post_ids );
2022-12-15 17:47:31 +01:00
$this -> found_posts = $cached_results [ 'found_posts' ];
$this -> max_num_pages = $cached_results [ 'max_num_pages' ];
2025-12-12 13:15:55 +01:00
if ( 'ids' === $query_vars [ 'fields' ] ) {
2023-12-07 09:44:11 +01:00
$this -> posts = $post_ids ;
2022-12-15 17:47:31 +01:00
return $this -> posts ;
2025-12-12 13:15:55 +01:00
} elseif ( 'id=>parent' === $query_vars [ 'fields' ] ) {
2023-12-07 09:44:11 +01:00
_prime_post_parent_id_caches ( $post_ids );
$post_parent_cache_keys = array ();
foreach ( $post_ids as $post_id ) {
$post_parent_cache_keys [] = 'post_parent:' . ( string ) $post_id ;
}
2022-12-15 17:47:31 +01:00
/** @var int[] */
2023-12-07 09:44:11 +01:00
$post_parents = wp_cache_get_multiple ( $post_parent_cache_keys , 'posts' );
2022-12-15 17:47:31 +01:00
2023-12-07 09:44:11 +01:00
foreach ( $post_parents as $cache_key => $post_parent ) {
2022-12-15 17:47:31 +01:00
$obj = new stdClass ();
2023-12-07 09:44:11 +01:00
$obj -> ID = ( int ) str_replace ( 'post_parent:' , '' , $cache_key );
$obj -> post_parent = ( int ) $post_parent ;
2022-12-15 17:47:31 +01:00
2023-12-07 09:44:11 +01:00
$this -> posts [] = $obj ;
2022-12-15 17:47:31 +01:00
}
return $post_parents ;
2023-12-07 09:44:11 +01:00
} else {
2025-12-12 13:15:55 +01:00
_prime_post_caches ( $post_ids , $query_vars [ 'update_post_term_cache' ], $query_vars [ 'update_post_meta_cache' ] );
2023-12-07 09:44:11 +01:00
/** @var WP_Post[] */
$this -> posts = array_map ( 'get_post' , $post_ids );
2022-12-15 17:47:31 +01:00
}
}
}
}
2025-12-12 13:15:55 +01:00
if ( 'ids' === $query_vars [ 'fields' ] ) {
2019-11-02 10:38:58 +01:00
if ( null === $this -> posts ) {
$this -> posts = $wpdb -> get_col ( $this -> request );
}
2021-04-27 08:32:47 +02:00
/** @var int[] */
2019-11-02 10:38:58 +01:00
$this -> posts = array_map ( 'intval' , $this -> posts );
$this -> post_count = count ( $this -> posts );
2025-12-12 13:15:55 +01:00
$this -> set_found_posts ( $query_vars , $limits );
2019-11-02 10:38:58 +01:00
2025-12-12 13:15:55 +01:00
if ( $query_vars [ 'cache_results' ] && $id_query_is_cacheable ) {
2022-12-15 17:47:31 +01:00
$cache_value = array (
'posts' => $this -> posts ,
'found_posts' => $this -> found_posts ,
'max_num_pages' => $this -> max_num_pages ,
);
2025-12-12 13:15:55 +01:00
wp_cache_set_salted ( $cache_key , $cache_value , 'post-queries' , $last_changed );
2022-12-15 17:47:31 +01:00
}
2019-11-02 10:38:58 +01:00
return $this -> posts ;
}
2025-12-12 13:15:55 +01:00
if ( 'id=>parent' === $query_vars [ 'fields' ] ) {
2019-11-02 10:38:58 +01:00
if ( null === $this -> posts ) {
$this -> posts = $wpdb -> get_results ( $this -> request );
}
$this -> post_count = count ( $this -> posts );
2025-12-12 13:15:55 +01:00
$this -> set_found_posts ( $query_vars , $limits );
2019-11-02 10:38:58 +01:00
2021-04-27 08:32:47 +02:00
/** @var int[] */
2023-12-07 09:44:11 +01:00
$post_parents = array ();
$post_ids = array ();
$post_parents_cache = array ();
2022-12-15 17:47:31 +01:00
2019-11-02 10:38:58 +01:00
foreach ( $this -> posts as $key => $post ) {
$this -> posts [ $key ] -> ID = ( int ) $post -> ID ;
$this -> posts [ $key ] -> post_parent = ( int ) $post -> post_parent ;
2022-12-15 17:47:31 +01:00
$post_parents [ ( int ) $post -> ID ] = ( int ) $post -> post_parent ;
$post_ids [] = ( int ) $post -> ID ;
2023-12-07 09:44:11 +01:00
$post_parents_cache [ 'post_parent:' . ( string ) $post -> ID ] = ( int ) $post -> post_parent ;
2022-12-15 17:47:31 +01:00
}
2023-12-07 09:44:11 +01:00
// Prime post parent caches, so that on second run, there is not another database query.
wp_cache_add_multiple ( $post_parents_cache , 'posts' );
2022-12-15 17:47:31 +01:00
2025-12-12 13:15:55 +01:00
if ( $query_vars [ 'cache_results' ] && $id_query_is_cacheable ) {
2022-12-15 17:47:31 +01:00
$cache_value = array (
'posts' => $post_ids ,
'found_posts' => $this -> found_posts ,
'max_num_pages' => $this -> max_num_pages ,
);
2025-12-12 13:15:55 +01:00
wp_cache_set_salted ( $cache_key , $cache_value , 'post-queries' , $last_changed );
2019-11-02 10:38:58 +01:00
}
2022-12-15 17:47:31 +01:00
return $post_parents ;
2019-11-02 10:38:58 +01:00
}
2025-04-25 12:30:07 +02:00
$is_unfiltered_query = $old_request === $this -> request && " { $wpdb -> posts } .* " === $fields ;
2023-12-07 09:44:11 +01:00
2019-11-02 10:38:58 +01:00
if ( null === $this -> posts ) {
2023-12-07 09:44:11 +01:00
$split_the_query = (
$is_unfiltered_query
&& (
wp_using_ext_object_cache ()
2025-12-12 13:15:55 +01:00
|| ( ! empty ( $limits ) && $query_vars [ 'posts_per_page' ] < 500 )
2023-12-07 09:44:11 +01:00
)
);
2019-11-02 10:38:58 +01:00
/**
* Filters whether to split the query .
*
* Splitting the query will cause it to fetch just the IDs of the found posts
* ( and then individually fetch each post by ID ), rather than fetching every
* complete row at once . One massive result vs . many small results .
*
* @ since 3.4 . 0
2025-02-28 08:42:11 +01:00
* @ since 6.6 . 0 Added the `$old_request` and `$clauses` parameters .
2019-11-02 10:38:58 +01:00
*
* @ param bool $split_the_query Whether or not to split the query .
2021-04-27 08:32:47 +02:00
* @ param WP_Query $query The WP_Query instance .
2025-02-28 08:42:11 +01:00
* @ param string $old_request The complete SQL query before filtering .
* @ param string [] $clauses {
* Associative array of the clauses for the query .
*
* @ type string $where The WHERE clause of the query .
* @ type string $groupby The GROUP BY clause of the query .
* @ type string $join The JOIN clause of the query .
* @ type string $orderby The ORDER BY clause of the query .
* @ type string $distinct The DISTINCT clause of the query .
* @ type string $fields The SELECT clause of the query .
* @ type string $limits The LIMIT clause of the query .
* }
2019-11-02 10:38:58 +01:00
*/
2025-02-28 08:42:11 +01:00
$split_the_query = apply_filters ( 'split_the_query' , $split_the_query , $this , $old_request , compact ( $pieces ) );
2019-11-02 10:38:58 +01:00
if ( $split_the_query ) {
2020-05-06 17:23:38 +02:00
// First get the IDs and then fill in the objects.
2019-11-02 10:38:58 +01:00
2024-04-17 11:32:24 +02:00
// Beginning of the string is on a new line to prevent leading whitespace. See https://core.trac.wordpress.org/ticket/56841.
$this -> request =
" SELECT $found_rows $distinct { $wpdb -> posts } .ID
FROM { $wpdb -> posts } $join
WHERE 1 = 1 $where
$groupby
$orderby
$limits " ;
2019-11-02 10:38:58 +01:00
/**
* Filters the Post IDs SQL request before sending .
*
* @ since 3.4 . 0
*
* @ param string $request The post ID request .
2021-04-27 08:32:47 +02:00
* @ param WP_Query $query The WP_Query instance .
2019-11-02 10:38:58 +01:00
*/
$this -> request = apply_filters ( 'posts_request_ids' , $this -> request , $this );
2022-12-15 17:47:31 +01:00
$post_ids = $wpdb -> get_col ( $this -> request );
2019-11-02 10:38:58 +01:00
2022-12-15 17:47:31 +01:00
if ( $post_ids ) {
$this -> posts = $post_ids ;
2025-12-12 13:15:55 +01:00
$this -> set_found_posts ( $query_vars , $limits );
_prime_post_caches ( $post_ids , $query_vars [ 'update_post_term_cache' ], $query_vars [ 'update_post_meta_cache' ] );
2019-11-02 10:38:58 +01:00
} else {
$this -> posts = array ();
}
} else {
$this -> posts = $wpdb -> get_results ( $this -> request );
2025-12-12 13:15:55 +01:00
$this -> set_found_posts ( $query_vars , $limits );
2019-11-02 10:38:58 +01:00
}
}
// Convert to WP_Post objects.
if ( $this -> posts ) {
2021-04-27 08:32:47 +02:00
/** @var WP_Post[] */
2019-11-02 10:38:58 +01:00
$this -> posts = array_map ( 'get_post' , $this -> posts );
}
2023-12-07 09:44:11 +01:00
$unfiltered_posts = $this -> posts ;
2025-12-12 13:15:55 +01:00
if ( $query_vars [ 'cache_results' ] && $id_query_is_cacheable && ! $cache_found ) {
2022-12-15 17:47:31 +01:00
$post_ids = wp_list_pluck ( $this -> posts , 'ID' );
$cache_value = array (
'posts' => $post_ids ,
'found_posts' => $this -> found_posts ,
'max_num_pages' => $this -> max_num_pages ,
);
2025-12-12 13:15:55 +01:00
wp_cache_set_salted ( $cache_key , $cache_value , 'post-queries' , $last_changed );
2022-12-15 17:47:31 +01:00
}
2025-12-12 13:15:55 +01:00
if ( ! $query_vars [ 'suppress_filters' ] ) {
2019-11-02 10:38:58 +01:00
/**
* Filters the raw post results array , prior to status checks .
*
* @ since 2.3 . 0
*
* @ param WP_Post [] $posts Array of post objects .
2021-04-27 08:32:47 +02:00
* @ param WP_Query $query The WP_Query instance ( passed by reference ) .
2019-11-02 10:38:58 +01:00
*/
$this -> posts = apply_filters_ref_array ( 'posts_results' , array ( $this -> posts , & $this ) );
}
if ( ! empty ( $this -> posts ) && $this -> is_comment_feed && $this -> is_singular ) {
/** This filter is documented in wp-includes/query.php */
$cjoin = apply_filters_ref_array ( 'comment_feed_join' , array ( '' , & $this ) );
/** This filter is documented in wp-includes/query.php */
$cwhere = apply_filters_ref_array ( 'comment_feed_where' , array ( " WHERE comment_post_ID = ' { $this -> posts [ 0 ] -> ID } ' AND comment_approved = '1' " , & $this ) );
/** This filter is documented in wp-includes/query.php */
$cgroupby = apply_filters_ref_array ( 'comment_feed_groupby' , array ( '' , & $this ) );
$cgroupby = ( ! empty ( $cgroupby ) ) ? 'GROUP BY ' . $cgroupby : '' ;
/** This filter is documented in wp-includes/query.php */
$corderby = apply_filters_ref_array ( 'comment_feed_orderby' , array ( 'comment_date_gmt DESC' , & $this ) );
$corderby = ( ! empty ( $corderby ) ) ? 'ORDER BY ' . $corderby : '' ;
/** This filter is documented in wp-includes/query.php */
$climits = apply_filters_ref_array ( 'comment_feed_limits' , array ( 'LIMIT ' . get_option ( 'posts_per_rss' ), & $this ) );
2022-06-16 14:03:35 +02:00
$comments_request = " SELECT { $wpdb -> comments } .comment_ID FROM { $wpdb -> comments } $cjoin $cwhere $cgroupby $corderby $climits " ;
2022-12-15 17:47:31 +01:00
$comment_key = md5 ( $comments_request );
$comment_last_changed = wp_cache_get_last_changed ( 'comment' );
2022-06-16 14:03:35 +02:00
2025-12-12 13:15:55 +01:00
$comment_cache_key = " comment_feed: $comment_key " ;
$comment_ids = wp_cache_get_salted ( $comment_cache_key , 'comment-queries' , $comment_last_changed );
2022-06-16 14:03:35 +02:00
if ( false === $comment_ids ) {
$comment_ids = $wpdb -> get_col ( $comments_request );
2025-12-12 13:15:55 +01:00
wp_cache_set_salted ( $comment_cache_key , $comment_ids , 'comment-queries' , $comment_last_changed );
2022-06-16 14:03:35 +02:00
}
2023-09-26 10:33:34 +02:00
_prime_comment_caches ( $comment_ids );
2022-06-16 14:03:35 +02:00
2020-05-06 17:23:38 +02:00
// Convert to WP_Comment.
2021-04-27 08:32:47 +02:00
/** @var WP_Comment[] */
2022-06-16 14:03:35 +02:00
$this -> comments = array_map ( 'get_comment' , $comment_ids );
2019-11-02 10:38:58 +01:00
$this -> comment_count = count ( $this -> comments );
}
// Check post status to determine if post should be displayed.
if ( ! empty ( $this -> posts ) && ( $this -> is_single || $this -> is_page ) ) {
$status = get_post_status ( $this -> posts [ 0 ] );
2020-05-06 17:23:38 +02:00
2019-11-02 10:38:58 +01:00
if ( 'attachment' === $this -> posts [ 0 ] -> post_type && 0 === ( int ) $this -> posts [ 0 ] -> post_parent ) {
$this -> is_page = false ;
$this -> is_single = true ;
$this -> is_attachment = true ;
}
// If the post_status was specifically requested, let it pass through.
2020-09-15 14:29:22 +02:00
if ( ! in_array ( $status , $q_status , true ) ) {
2020-05-06 17:23:38 +02:00
$post_status_obj = get_post_status_object ( $status );
2019-11-02 10:38:58 +01:00
2020-05-06 17:23:38 +02:00
if ( $post_status_obj && ! $post_status_obj -> public ) {
if ( ! is_user_logged_in () ) {
// User must be logged in to view unpublished posts.
$this -> posts = array ();
} else {
if ( $post_status_obj -> protected ) {
// User must have edit permissions on the draft to preview.
if ( ! current_user_can ( $edit_cap , $this -> posts [ 0 ] -> ID ) ) {
$this -> posts = array ();
} else {
$this -> is_preview = true ;
2020-09-15 14:29:22 +02:00
if ( 'future' !== $status ) {
2020-05-06 17:23:38 +02:00
$this -> posts [ 0 ] -> post_date = current_time ( 'mysql' );
}
2019-11-02 10:38:58 +01:00
}
2020-05-06 17:23:38 +02:00
} elseif ( $post_status_obj -> private ) {
if ( ! current_user_can ( $read_cap , $this -> posts [ 0 ] -> ID ) ) {
$this -> posts = array ();
}
} else {
2019-11-02 10:38:58 +01:00
$this -> posts = array ();
}
2020-05-06 17:23:38 +02:00
}
} elseif ( ! $post_status_obj ) {
// Post status is not registered, assume it's not public.
if ( ! current_user_can ( $edit_cap , $this -> posts [ 0 ] -> ID ) ) {
2019-11-02 10:38:58 +01:00
$this -> posts = array ();
}
}
}
if ( $this -> is_preview && $this -> posts && current_user_can ( $edit_cap , $this -> posts [ 0 ] -> ID ) ) {
/**
* Filters the single post for preview mode .
*
* @ since 2.7 . 0
*
* @ param WP_Post $post_preview The Post object .
2021-04-27 08:32:47 +02:00
* @ param WP_Query $query The WP_Query instance ( passed by reference ) .
2019-11-02 10:38:58 +01:00
*/
$this -> posts [ 0 ] = get_post ( apply_filters_ref_array ( 'the_preview' , array ( $this -> posts [ 0 ], & $this ) ) );
}
}
2020-05-06 17:23:38 +02:00
// Put sticky posts at the top of the posts array.
2019-11-02 10:38:58 +01:00
$sticky_posts = get_option ( 'sticky_posts' );
2025-12-12 13:15:55 +01:00
if ( $this -> is_home && $page <= 1 && is_array ( $sticky_posts ) && ! empty ( $sticky_posts ) && ! $query_vars [ 'ignore_sticky_posts' ] ) {
2019-11-02 10:38:58 +01:00
$num_posts = count ( $this -> posts );
$sticky_offset = 0 ;
// Loop over posts and relocate stickies to the front.
for ( $i = 0 ; $i < $num_posts ; $i ++ ) {
2020-09-15 14:29:22 +02:00
if ( in_array ( $this -> posts [ $i ] -> ID , $sticky_posts , true ) ) {
2019-11-02 10:38:58 +01:00
$sticky_post = $this -> posts [ $i ];
2020-05-06 17:23:38 +02:00
// Remove sticky from current position.
2019-11-02 10:38:58 +01:00
array_splice ( $this -> posts , $i , 1 );
2020-05-06 17:23:38 +02:00
// Move to front, after other stickies.
2019-11-02 10:38:58 +01:00
array_splice ( $this -> posts , $sticky_offset , 0 , array ( $sticky_post ) );
// Increment the sticky offset. The next sticky will be placed at this offset.
2023-12-07 09:44:11 +01:00
++ $sticky_offset ;
2020-05-06 17:23:38 +02:00
// Remove post from sticky posts array.
2020-09-15 14:29:22 +02:00
$offset = array_search ( $sticky_post -> ID , $sticky_posts , true );
2019-11-02 10:38:58 +01:00
unset ( $sticky_posts [ $offset ] );
}
}
// If any posts have been excluded specifically, Ignore those that are sticky.
2025-12-12 13:15:55 +01:00
if ( ! empty ( $sticky_posts ) && ! empty ( $query_vars [ 'post__not_in' ] ) ) {
$sticky_posts = array_diff ( $sticky_posts , $query_vars [ 'post__not_in' ] );
2019-11-02 10:38:58 +01:00
}
2020-05-06 17:23:38 +02:00
// Fetch sticky posts that weren't in the query results.
2019-11-02 10:38:58 +01:00
if ( ! empty ( $sticky_posts ) ) {
$stickies = get_posts (
array (
2022-06-16 14:03:35 +02:00
'post__in' => $sticky_posts ,
'post_type' => $post_type ,
'post_status' => 'publish' ,
'posts_per_page' => count ( $sticky_posts ),
2025-12-12 13:15:55 +01:00
'suppress_filters' => $query_vars [ 'suppress_filters' ],
'cache_results' => $query_vars [ 'cache_results' ],
'update_post_meta_cache' => $query_vars [ 'update_post_meta_cache' ],
'update_post_term_cache' => $query_vars [ 'update_post_term_cache' ],
'lazy_load_term_meta' => $query_vars [ 'lazy_load_term_meta' ],
2019-11-02 10:38:58 +01:00
)
);
foreach ( $stickies as $sticky_post ) {
array_splice ( $this -> posts , $sticky_offset , 0 , array ( $sticky_post ) );
2023-12-07 09:44:11 +01:00
++ $sticky_offset ;
2019-11-02 10:38:58 +01:00
}
}
}
2025-12-12 13:15:55 +01:00
if ( ! $query_vars [ 'suppress_filters' ] ) {
2019-11-02 10:38:58 +01:00
/**
* Filters the array of retrieved posts after they ' ve been fetched and
* internally processed .
*
* @ since 1.5 . 0
*
* @ param WP_Post [] $posts Array of post objects .
2021-04-27 08:32:47 +02:00
* @ param WP_Query $query The WP_Query instance ( passed by reference ) .
2019-11-02 10:38:58 +01:00
*/
$this -> posts = apply_filters_ref_array ( 'the_posts' , array ( $this -> posts , & $this ) );
}
2023-09-26 10:33:34 +02:00
/*
* Ensure that any posts added / modified via one of the filters above are
* of the type WP_Post and are filtered .
*/
2019-11-02 10:38:58 +01:00
if ( $this -> posts ) {
$this -> post_count = count ( $this -> posts );
2021-04-27 08:32:47 +02:00
/** @var WP_Post[] */
2019-11-02 10:38:58 +01:00
$this -> posts = array_map ( 'get_post' , $this -> posts );
2025-12-12 13:15:55 +01:00
if ( $query_vars [ 'cache_results' ] ) {
2023-12-07 09:44:11 +01:00
if ( $is_unfiltered_query && $unfiltered_posts === $this -> posts ) {
2025-12-12 13:15:55 +01:00
update_post_caches ( $this -> posts , $post_type , $query_vars [ 'update_post_term_cache' ], $query_vars [ 'update_post_meta_cache' ] );
2023-12-07 09:44:11 +01:00
} else {
$post_ids = wp_list_pluck ( $this -> posts , 'ID' );
2025-12-12 13:15:55 +01:00
_prime_post_caches ( $post_ids , $query_vars [ 'update_post_term_cache' ], $query_vars [ 'update_post_meta_cache' ] );
2023-12-07 09:44:11 +01:00
}
2019-11-02 10:38:58 +01:00
}
2021-04-27 08:32:47 +02:00
/** @var WP_Post */
2019-11-02 10:38:58 +01:00
$this -> post = reset ( $this -> posts );
} else {
$this -> post_count = 0 ;
$this -> posts = array ();
}
2025-12-12 13:15:55 +01:00
if ( ! empty ( $this -> posts ) && $query_vars [ 'update_menu_item_cache' ] ) {
2022-12-15 17:47:31 +01:00
update_menu_item_cache ( $this -> posts );
}
2025-12-12 13:15:55 +01:00
if ( $query_vars [ 'lazy_load_term_meta' ] ) {
2019-11-02 10:38:58 +01:00
wp_queue_posts_for_term_meta_lazyload ( $this -> posts );
}
return $this -> posts ;
}
/**
2023-09-26 10:33:34 +02:00
* Sets up the amount of found posts and the number of pages ( if limit clause was used )
2019-11-02 10:38:58 +01:00
* for the current query .
*
* @ since 3.5 . 0
*
2021-04-27 08:32:47 +02:00
* @ global wpdb $wpdb WordPress database abstraction object .
*
2025-12-12 13:15:55 +01:00
* @ param array $query_vars Query variables .
* @ param string $limits LIMIT clauses of the query .
2019-11-02 10:38:58 +01:00
*/
2025-12-12 13:15:55 +01:00
private function set_found_posts ( $query_vars , $limits ) {
2019-11-02 10:38:58 +01:00
global $wpdb ;
2021-04-27 08:32:47 +02:00
2023-09-26 10:33:34 +02:00
/*
* Bail if posts is an empty array . Continue if posts is an empty string ,
* null , or false to accommodate caching plugins that fill posts later .
*/
2025-12-12 13:15:55 +01:00
if ( $query_vars [ 'no_found_rows' ] || ( is_array ( $this -> posts ) && ! $this -> posts ) ) {
2019-11-02 10:38:58 +01:00
return ;
}
if ( ! empty ( $limits ) ) {
/**
* Filters the query to run for retrieving the found posts .
*
* @ since 2.1 . 0
*
2020-09-15 14:29:22 +02:00
* @ param string $found_posts_query The query to run to find the found posts .
2021-04-27 08:32:47 +02:00
* @ param WP_Query $query The WP_Query instance ( passed by reference ) .
2019-11-02 10:38:58 +01:00
*/
2020-09-15 14:29:22 +02:00
$found_posts_query = apply_filters_ref_array ( 'found_posts_query' , array ( 'SELECT FOUND_ROWS()' , & $this ) );
$this -> found_posts = ( int ) $wpdb -> get_var ( $found_posts_query );
2019-11-02 10:38:58 +01:00
} else {
if ( is_array ( $this -> posts ) ) {
$this -> found_posts = count ( $this -> posts );
} else {
if ( null === $this -> posts ) {
$this -> found_posts = 0 ;
} else {
$this -> found_posts = 1 ;
}
}
}
/**
* Filters the number of found posts for the query .
*
* @ since 2.1 . 0
*
* @ param int $found_posts The number of posts found .
2021-04-27 08:32:47 +02:00
* @ param WP_Query $query The WP_Query instance ( passed by reference ) .
2019-11-02 10:38:58 +01:00
*/
2020-09-15 14:29:22 +02:00
$this -> found_posts = ( int ) apply_filters_ref_array ( 'found_posts' , array ( $this -> found_posts , & $this ) );
2019-11-02 10:38:58 +01:00
if ( ! empty ( $limits ) ) {
2025-12-12 13:15:55 +01:00
$this -> max_num_pages = ( int ) ceil ( $this -> found_posts / $query_vars [ 'posts_per_page' ] );
2019-11-02 10:38:58 +01:00
}
}
/**
2023-09-26 10:33:34 +02:00
* Sets up the next post and iterate current post index .
2019-11-02 10:38:58 +01:00
*
* @ since 1.5 . 0
*
* @ return WP_Post Next post .
*/
public function next_post () {
2023-12-07 09:44:11 +01:00
++ $this -> current_post ;
2019-11-02 10:38:58 +01:00
2021-04-27 08:32:47 +02:00
/** @var WP_Post */
2019-11-02 10:38:58 +01:00
$this -> post = $this -> posts [ $this -> current_post ];
return $this -> post ;
}
/**
* Sets up the current post .
*
* Retrieves the next post , sets up the post , sets the 'in the loop'
* property to true .
*
* @ since 1.5 . 0
*
2019-11-15 22:59:44 +01:00
* @ global WP_Post $post Global post object .
2019-11-02 10:38:58 +01:00
*/
public function the_post () {
global $post ;
2022-12-15 17:47:31 +01:00
if ( ! $this -> in_the_loop ) {
2025-04-25 12:30:07 +02:00
if ( 'all' === $this -> query_vars [ 'fields' ] ) {
// Full post objects queried.
$post_objects = $this -> posts ;
} else {
if ( 'ids' === $this -> query_vars [ 'fields' ] ) {
// Post IDs queried.
$post_ids = $this -> posts ;
} else {
// Only partial objects queried, need to prime the cache for the loop.
$post_ids = array_reduce (
$this -> posts ,
function ( $carry , $post ) {
if ( isset ( $post -> ID ) ) {
$carry [] = $post -> ID ;
}
return $carry ;
},
array ()
);
}
2022-12-15 17:47:31 +01:00
_prime_post_caches ( $post_ids , $this -> query_vars [ 'update_post_term_cache' ], $this -> query_vars [ 'update_post_meta_cache' ] );
2025-04-25 12:30:07 +02:00
$post_objects = array_map ( 'get_post' , $post_ids );
2022-12-15 17:47:31 +01:00
}
update_post_author_caches ( $post_objects );
}
2019-11-02 10:38:58 +01:00
$this -> in_the_loop = true ;
2023-09-26 10:33:34 +02:00
$this -> before_loop = false ;
2019-11-02 10:38:58 +01:00
2025-04-25 12:30:07 +02:00
if ( - 1 === $this -> current_post ) { // Loop has just started.
2019-11-02 10:38:58 +01:00
/**
* Fires once the loop is started .
*
* @ since 2.0 . 0
*
2021-04-27 08:32:47 +02:00
* @ param WP_Query $query The WP_Query instance ( passed by reference ) .
2019-11-02 10:38:58 +01:00
*/
do_action_ref_array ( 'loop_start' , array ( & $this ) );
}
$post = $this -> next_post ();
2025-04-25 12:30:07 +02:00
// Ensure a full post object is available.
if ( 'all' !== $this -> query_vars [ 'fields' ] ) {
if ( 'ids' === $this -> query_vars [ 'fields' ] ) {
// Post IDs queried.
$post = get_post ( $post );
} elseif ( isset ( $post -> ID ) ) {
/*
* Partial objecct queried .
*
* The post object was queried with a partial set of
* fields , populate the entire object for the loop .
*/
$post = get_post ( $post -> ID );
}
}
// Set up the global post object for the loop.
2019-11-02 10:38:58 +01:00
$this -> setup_postdata ( $post );
}
/**
* Determines whether there are more posts available in the loop .
*
* Calls the { @ see 'loop_end' } action when the loop is complete .
*
* @ since 1.5 . 0
*
2020-09-15 14:29:22 +02:00
* @ return bool True if posts are available , false if end of the loop .
2019-11-02 10:38:58 +01:00
*/
public function have_posts () {
if ( $this -> current_post + 1 < $this -> post_count ) {
return true ;
2025-04-25 12:30:07 +02:00
} elseif ( $this -> current_post + 1 === $this -> post_count && $this -> post_count > 0 ) {
2019-11-02 10:38:58 +01:00
/**
* Fires once the loop has ended .
*
* @ since 2.0 . 0
*
2021-04-27 08:32:47 +02:00
* @ param WP_Query $query The WP_Query instance ( passed by reference ) .
2019-11-02 10:38:58 +01:00
*/
do_action_ref_array ( 'loop_end' , array ( & $this ) );
2025-04-25 12:30:07 +02:00
2020-05-06 17:23:38 +02:00
// Do some cleaning up after the loop.
2019-11-02 10:38:58 +01:00
$this -> rewind_posts ();
} elseif ( 0 === $this -> post_count ) {
2023-09-26 10:33:34 +02:00
$this -> before_loop = false ;
2019-11-02 10:38:58 +01:00
/**
* Fires if no results are found in a post query .
*
* @ since 4.9 . 0
*
2021-04-27 08:32:47 +02:00
* @ param WP_Query $query The WP_Query instance .
2019-11-02 10:38:58 +01:00
*/
do_action ( 'loop_no_results' , $this );
}
$this -> in_the_loop = false ;
return false ;
}
/**
2023-09-26 10:33:34 +02:00
* Rewinds the posts and resets post index .
2019-11-02 10:38:58 +01:00
*
* @ since 1.5 . 0
*/
public function rewind_posts () {
$this -> current_post = - 1 ;
if ( $this -> post_count > 0 ) {
$this -> post = $this -> posts [ 0 ];
}
}
/**
2023-09-26 10:33:34 +02:00
* Iterates current comment index and returns WP_Comment object .
2019-11-02 10:38:58 +01:00
*
* @ since 2.2 . 0
*
* @ return WP_Comment Comment object .
*/
public function next_comment () {
2023-12-07 09:44:11 +01:00
++ $this -> current_comment ;
2019-11-02 10:38:58 +01:00
2021-04-27 08:32:47 +02:00
/** @var WP_Comment */
2019-11-02 10:38:58 +01:00
$this -> comment = $this -> comments [ $this -> current_comment ];
return $this -> comment ;
}
/**
* Sets up the current comment .
*
* @ since 2.2 . 0
2020-09-15 14:29:22 +02:00
*
2019-11-15 22:59:44 +01:00
* @ global WP_Comment $comment Global comment object .
2019-11-02 10:38:58 +01:00
*/
public function the_comment () {
global $comment ;
$comment = $this -> next_comment ();
2025-04-25 12:30:07 +02:00
if ( 0 === $this -> current_comment ) {
2019-11-02 10:38:58 +01:00
/**
* Fires once the comment loop is started .
*
* @ since 2.2 . 0
*/
do_action ( 'comment_loop_start' );
}
}
/**
2023-09-26 10:33:34 +02:00
* Determines whether there are more comments available .
2019-11-02 10:38:58 +01:00
*
* Automatically rewinds comments when finished .
*
* @ since 2.2 . 0
*
2020-09-15 14:29:22 +02:00
* @ return bool True if comments are available , false if no more comments .
2019-11-02 10:38:58 +01:00
*/
public function have_comments () {
if ( $this -> current_comment + 1 < $this -> comment_count ) {
return true ;
2025-04-25 12:30:07 +02:00
} elseif ( $this -> current_comment + 1 === $this -> comment_count ) {
2019-11-02 10:38:58 +01:00
$this -> rewind_comments ();
}
return false ;
}
/**
2023-09-26 10:33:34 +02:00
* Rewinds the comments , resets the comment index and comment to first .
2019-11-02 10:38:58 +01:00
*
* @ since 2.2 . 0
*/
public function rewind_comments () {
$this -> current_comment = - 1 ;
if ( $this -> comment_count > 0 ) {
$this -> comment = $this -> comments [ 0 ];
}
}
/**
* Sets up the WordPress query by parsing query string .
*
* @ since 1.5 . 0
*
2020-09-15 14:29:22 +02:00
* @ see WP_Query :: parse_query () for all available arguments .
*
2019-11-02 10:38:58 +01:00
* @ param string | array $query URL query string or array of query arguments .
* @ return WP_Post [] | int [] Array of post objects or post IDs .
*/
public function query ( $query ) {
$this -> init ();
2019-11-15 22:59:44 +01:00
$this -> query = wp_parse_args ( $query );
$this -> query_vars = $this -> query ;
2019-11-02 10:38:58 +01:00
return $this -> get_posts ();
}
/**
2020-12-10 14:06:04 +01:00
* Retrieves the currently queried object .
2019-11-02 10:38:58 +01:00
*
* If queried object is not set , then the queried object will be set from
* the category , tag , taxonomy , posts page , single post , page , or author
* query variable . After it is set up , it will be returned .
*
* @ since 1.5 . 0
*
2020-12-10 14:06:04 +01:00
* @ return WP_Term | WP_Post_Type | WP_Post | WP_User | null The queried object .
2019-11-02 10:38:58 +01:00
*/
public function get_queried_object () {
if ( isset ( $this -> queried_object ) ) {
return $this -> queried_object ;
}
$this -> queried_object = null ;
$this -> queried_object_id = null ;
if ( $this -> is_category || $this -> is_tag || $this -> is_tax ) {
if ( $this -> is_category ) {
2022-06-16 14:03:35 +02:00
$cat = $this -> get ( 'cat' );
$category_name = $this -> get ( 'category_name' );
if ( $cat ) {
$term = get_term ( $cat , 'category' );
} elseif ( $category_name ) {
$term = get_term_by ( 'slug' , $category_name , 'category' );
2019-11-02 10:38:58 +01:00
}
} elseif ( $this -> is_tag ) {
2022-06-16 14:03:35 +02:00
$tag_id = $this -> get ( 'tag_id' );
$tag = $this -> get ( 'tag' );
if ( $tag_id ) {
$term = get_term ( $tag_id , 'post_tag' );
} elseif ( $tag ) {
$term = get_term_by ( 'slug' , $tag , 'post_tag' );
2019-11-02 10:38:58 +01:00
}
} else {
// For other tax queries, grab the first term from the first clause.
if ( ! empty ( $this -> tax_query -> queried_terms ) ) {
$queried_taxonomies = array_keys ( $this -> tax_query -> queried_terms );
$matched_taxonomy = reset ( $queried_taxonomies );
$query = $this -> tax_query -> queried_terms [ $matched_taxonomy ];
if ( ! empty ( $query [ 'terms' ] ) ) {
2020-09-15 14:29:22 +02:00
if ( 'term_id' === $query [ 'field' ] ) {
2019-11-02 10:38:58 +01:00
$term = get_term ( reset ( $query [ 'terms' ] ), $matched_taxonomy );
} else {
$term = get_term_by ( $query [ 'field' ], reset ( $query [ 'terms' ] ), $matched_taxonomy );
}
}
}
}
if ( ! empty ( $term ) && ! is_wp_error ( $term ) ) {
$this -> queried_object = $term ;
$this -> queried_object_id = ( int ) $term -> term_id ;
if ( $this -> is_category && 'category' === $this -> queried_object -> taxonomy ) {
_make_cat_compat ( $this -> queried_object );
}
}
} elseif ( $this -> is_post_type_archive ) {
$post_type = $this -> get ( 'post_type' );
2022-06-16 14:03:35 +02:00
2019-11-02 10:38:58 +01:00
if ( is_array ( $post_type ) ) {
$post_type = reset ( $post_type );
}
2022-06-16 14:03:35 +02:00
2019-11-02 10:38:58 +01:00
$this -> queried_object = get_post_type_object ( $post_type );
} elseif ( $this -> is_posts_page ) {
2022-06-16 14:03:35 +02:00
$page_for_posts = get_option ( 'page_for_posts' );
2019-11-02 10:38:58 +01:00
$this -> queried_object = get_post ( $page_for_posts );
$this -> queried_object_id = ( int ) $this -> queried_object -> ID ;
} elseif ( $this -> is_singular && ! empty ( $this -> post ) ) {
$this -> queried_object = $this -> post ;
$this -> queried_object_id = ( int ) $this -> post -> ID ;
} elseif ( $this -> is_author ) {
2022-06-16 14:03:35 +02:00
$author = ( int ) $this -> get ( 'author' );
$author_name = $this -> get ( 'author_name' );
if ( $author ) {
$this -> queried_object_id = $author ;
} elseif ( $author_name ) {
$user = get_user_by ( 'slug' , $author_name );
if ( $user ) {
$this -> queried_object_id = $user -> ID ;
}
}
$this -> queried_object = get_userdata ( $this -> queried_object_id );
2019-11-02 10:38:58 +01:00
}
return $this -> queried_object ;
}
/**
2020-12-10 14:06:04 +01:00
* Retrieves the ID of the currently queried object .
2019-11-02 10:38:58 +01:00
*
* @ since 1.5 . 0
*
* @ return int
*/
public function get_queried_object_id () {
$this -> get_queried_object ();
if ( isset ( $this -> queried_object_id ) ) {
return $this -> queried_object_id ;
}
return 0 ;
}
/**
* Constructor .
*
* Sets up the WordPress query , if parameter is not empty .
*
* @ since 1.5 . 0
*
2020-09-15 14:29:22 +02:00
* @ see WP_Query :: parse_query () for all available arguments .
*
2019-11-02 10:38:58 +01:00
* @ param string | array $query URL query string or array of vars .
*/
public function __construct ( $query = '' ) {
if ( ! empty ( $query ) ) {
$this -> query ( $query );
}
}
/**
2023-09-26 10:33:34 +02:00
* Makes private properties readable for backward compatibility .
2019-11-02 10:38:58 +01:00
*
* @ since 4.0 . 0
*
* @ param string $name Property to get .
* @ return mixed Property .
*/
public function __get ( $name ) {
2020-09-15 14:29:22 +02:00
if ( in_array ( $name , $this -> compat_fields , true ) ) {
2019-11-02 10:38:58 +01:00
return $this -> $name ;
}
}
/**
2023-09-26 10:33:34 +02:00
* Makes private properties checkable for backward compatibility .
2019-11-02 10:38:58 +01:00
*
* @ since 4.0 . 0
*
* @ param string $name Property to check if set .
* @ return bool Whether the property is set .
*/
public function __isset ( $name ) {
2020-09-15 14:29:22 +02:00
if ( in_array ( $name , $this -> compat_fields , true ) ) {
2019-11-02 10:38:58 +01:00
return isset ( $this -> $name );
}
2025-04-25 12:30:07 +02:00
return false ;
2019-11-02 10:38:58 +01:00
}
/**
2023-09-26 10:33:34 +02:00
* Makes private / protected methods readable for backward compatibility .
2019-11-02 10:38:58 +01:00
*
* @ since 4.0 . 0
*
2020-09-15 14:29:22 +02:00
* @ param string $name Method to call .
* @ param array $arguments Arguments to pass when calling .
2019-11-02 10:38:58 +01:00
* @ return mixed | false Return value of the callback , false otherwise .
*/
public function __call ( $name , $arguments ) {
2020-09-15 14:29:22 +02:00
if ( in_array ( $name , $this -> compat_methods , true ) ) {
2019-11-15 22:59:44 +01:00
return $this -> $name ( ... $arguments );
2019-11-02 10:38:58 +01:00
}
return false ;
}
/**
2023-09-26 10:33:34 +02:00
* Determines whether the query is for an existing archive page .
2019-11-02 10:38:58 +01:00
*
2020-12-10 14:06:04 +01:00
* Archive pages include category , tag , author , date , custom post type ,
* and custom taxonomy based archives .
2019-11-02 10:38:58 +01:00
*
* @ since 3.1 . 0
*
2020-12-10 14:06:04 +01:00
* @ see WP_Query :: is_category ()
* @ see WP_Query :: is_tag ()
* @ see WP_Query :: is_author ()
* @ see WP_Query :: is_date ()
* @ see WP_Query :: is_post_type_archive ()
* @ see WP_Query :: is_tax ()
*
2020-09-15 14:29:22 +02:00
* @ return bool Whether the query is for an existing archive page .
2019-11-02 10:38:58 +01:00
*/
public function is_archive () {
return ( bool ) $this -> is_archive ;
}
/**
2023-09-26 10:33:34 +02:00
* Determines whether the query is for an existing post type archive page .
2019-11-02 10:38:58 +01:00
*
* @ since 3.1 . 0
*
2020-05-06 17:23:38 +02:00
* @ param string | string [] $post_types Optional . Post type or array of posts types
* to check against . Default empty .
2020-09-15 14:29:22 +02:00
* @ return bool Whether the query is for an existing post type archive page .
2019-11-02 10:38:58 +01:00
*/
public function is_post_type_archive ( $post_types = '' ) {
if ( empty ( $post_types ) || ! $this -> is_post_type_archive ) {
return ( bool ) $this -> is_post_type_archive ;
}
$post_type = $this -> get ( 'post_type' );
if ( is_array ( $post_type ) ) {
$post_type = reset ( $post_type );
}
$post_type_object = get_post_type_object ( $post_type );
2022-12-15 17:47:31 +01:00
if ( ! $post_type_object ) {
return false ;
}
2020-09-15 14:29:22 +02:00
return in_array ( $post_type_object -> name , ( array ) $post_types , true );
2019-11-02 10:38:58 +01:00
}
/**
2023-09-26 10:33:34 +02:00
* Determines whether the query is for an existing attachment page .
2019-11-02 10:38:58 +01:00
*
* @ since 3.1 . 0
*
2020-05-06 17:23:38 +02:00
* @ param int | string | int [] | string [] $attachment Optional . Attachment ID , title , slug , or array of such
* to check against . Default empty .
2020-09-15 14:29:22 +02:00
* @ return bool Whether the query is for an existing attachment page .
2019-11-02 10:38:58 +01:00
*/
public function is_attachment ( $attachment = '' ) {
if ( ! $this -> is_attachment ) {
return false ;
}
if ( empty ( $attachment ) ) {
return true ;
}
$attachment = array_map ( 'strval' , ( array ) $attachment );
$post_obj = $this -> get_queried_object ();
2022-12-15 17:47:31 +01:00
if ( ! $post_obj ) {
return false ;
}
2019-11-02 10:38:58 +01:00
2020-09-15 14:29:22 +02:00
if ( in_array ( ( string ) $post_obj -> ID , $attachment , true ) ) {
2019-11-02 10:38:58 +01:00
return true ;
2020-09-15 14:29:22 +02:00
} elseif ( in_array ( $post_obj -> post_title , $attachment , true ) ) {
2019-11-02 10:38:58 +01:00
return true ;
2020-09-15 14:29:22 +02:00
} elseif ( in_array ( $post_obj -> post_name , $attachment , true ) ) {
2019-11-02 10:38:58 +01:00
return true ;
}
return false ;
}
/**
2023-09-26 10:33:34 +02:00
* Determines whether the query is for an existing author archive page .
2019-11-02 10:38:58 +01:00
*
* If the $author parameter is specified , this function will additionally
* check if the query is for one of the authors specified .
*
* @ since 3.1 . 0
*
2020-05-06 17:23:38 +02:00
* @ param int | string | int [] | string [] $author Optional . User ID , nickname , nicename , or array of such
* to check against . Default empty .
2020-09-15 14:29:22 +02:00
* @ return bool Whether the query is for an existing author archive page .
2019-11-02 10:38:58 +01:00
*/
public function is_author ( $author = '' ) {
if ( ! $this -> is_author ) {
return false ;
}
if ( empty ( $author ) ) {
return true ;
}
$author_obj = $this -> get_queried_object ();
2022-12-15 17:47:31 +01:00
if ( ! $author_obj ) {
return false ;
}
2019-11-02 10:38:58 +01:00
$author = array_map ( 'strval' , ( array ) $author );
2020-09-15 14:29:22 +02:00
if ( in_array ( ( string ) $author_obj -> ID , $author , true ) ) {
2019-11-02 10:38:58 +01:00
return true ;
2020-09-15 14:29:22 +02:00
} elseif ( in_array ( $author_obj -> nickname , $author , true ) ) {
2019-11-02 10:38:58 +01:00
return true ;
2020-09-15 14:29:22 +02:00
} elseif ( in_array ( $author_obj -> user_nicename , $author , true ) ) {
2019-11-02 10:38:58 +01:00
return true ;
}
return false ;
}
/**
2023-09-26 10:33:34 +02:00
* Determines whether the query is for an existing category archive page .
2019-11-02 10:38:58 +01:00
*
* If the $category parameter is specified , this function will additionally
* check if the query is for one of the categories specified .
*
* @ since 3.1 . 0
*
2020-05-06 17:23:38 +02:00
* @ param int | string | int [] | string [] $category Optional . Category ID , name , slug , or array of such
* to check against . Default empty .
2020-09-15 14:29:22 +02:00
* @ return bool Whether the query is for an existing category archive page .
2019-11-02 10:38:58 +01:00
*/
public function is_category ( $category = '' ) {
if ( ! $this -> is_category ) {
return false ;
}
if ( empty ( $category ) ) {
return true ;
}
$cat_obj = $this -> get_queried_object ();
2022-12-15 17:47:31 +01:00
if ( ! $cat_obj ) {
return false ;
}
2019-11-02 10:38:58 +01:00
$category = array_map ( 'strval' , ( array ) $category );
2020-09-15 14:29:22 +02:00
if ( in_array ( ( string ) $cat_obj -> term_id , $category , true ) ) {
2019-11-02 10:38:58 +01:00
return true ;
2020-09-15 14:29:22 +02:00
} elseif ( in_array ( $cat_obj -> name , $category , true ) ) {
2019-11-02 10:38:58 +01:00
return true ;
2020-09-15 14:29:22 +02:00
} elseif ( in_array ( $cat_obj -> slug , $category , true ) ) {
2019-11-02 10:38:58 +01:00
return true ;
}
return false ;
}
/**
2023-09-26 10:33:34 +02:00
* Determines whether the query is for an existing tag archive page .
2019-11-02 10:38:58 +01:00
*
* If the $tag parameter is specified , this function will additionally
* check if the query is for one of the tags specified .
*
* @ since 3.1 . 0
*
2020-05-06 17:23:38 +02:00
* @ param int | string | int [] | string [] $tag Optional . Tag ID , name , slug , or array of such
* to check against . Default empty .
2020-09-15 14:29:22 +02:00
* @ return bool Whether the query is for an existing tag archive page .
2019-11-02 10:38:58 +01:00
*/
public function is_tag ( $tag = '' ) {
if ( ! $this -> is_tag ) {
return false ;
}
if ( empty ( $tag ) ) {
return true ;
}
$tag_obj = $this -> get_queried_object ();
2022-12-15 17:47:31 +01:00
if ( ! $tag_obj ) {
return false ;
}
2019-11-02 10:38:58 +01:00
$tag = array_map ( 'strval' , ( array ) $tag );
2020-09-15 14:29:22 +02:00
if ( in_array ( ( string ) $tag_obj -> term_id , $tag , true ) ) {
2019-11-02 10:38:58 +01:00
return true ;
2020-09-15 14:29:22 +02:00
} elseif ( in_array ( $tag_obj -> name , $tag , true ) ) {
2019-11-02 10:38:58 +01:00
return true ;
2020-09-15 14:29:22 +02:00
} elseif ( in_array ( $tag_obj -> slug , $tag , true ) ) {
2019-11-02 10:38:58 +01:00
return true ;
}
return false ;
}
/**
2023-09-26 10:33:34 +02:00
* Determines whether the query is for an existing custom taxonomy archive page .
2019-11-02 10:38:58 +01:00
*
* If the $taxonomy parameter is specified , this function will additionally
* check if the query is for that specific $taxonomy .
*
* If the $term parameter is specified in addition to the $taxonomy parameter ,
* this function will additionally check if the query is for one of the terms
* specified .
*
* @ since 3.1 . 0
*
2022-04-02 10:26:41 +02:00
* @ global WP_Taxonomy [] $wp_taxonomies Registered taxonomies .
2019-11-02 10:38:58 +01:00
*
2020-05-06 17:23:38 +02:00
* @ param string | string [] $taxonomy Optional . Taxonomy slug or slugs to check against .
* Default empty .
* @ param int | string | int [] | string [] $term Optional . Term ID , name , slug , or array of such
* to check against . Default empty .
2020-09-15 14:29:22 +02:00
* @ return bool Whether the query is for an existing custom taxonomy archive page .
* True for custom taxonomy archive pages , false for built - in taxonomies
2020-05-06 17:23:38 +02:00
* ( category and tag archives ) .
2019-11-02 10:38:58 +01:00
*/
public function is_tax ( $taxonomy = '' , $term = '' ) {
global $wp_taxonomies ;
if ( ! $this -> is_tax ) {
return false ;
}
if ( empty ( $taxonomy ) ) {
return true ;
}
$queried_object = $this -> get_queried_object ();
$tax_array = array_intersect ( array_keys ( $wp_taxonomies ), ( array ) $taxonomy );
$term_array = ( array ) $term ;
// Check that the taxonomy matches.
2020-09-15 14:29:22 +02:00
if ( ! ( isset ( $queried_object -> taxonomy ) && count ( $tax_array ) && in_array ( $queried_object -> taxonomy , $tax_array , true ) ) ) {
2019-11-02 10:38:58 +01:00
return false ;
}
2020-05-06 17:23:38 +02:00
// Only a taxonomy provided.
2019-11-02 10:38:58 +01:00
if ( empty ( $term ) ) {
return true ;
}
return isset ( $queried_object -> term_id ) &&
count (
array_intersect (
array ( $queried_object -> term_id , $queried_object -> name , $queried_object -> slug ),
$term_array
)
);
}
/**
2023-09-26 10:33:34 +02:00
* Determines whether the current URL is within the comments popup window .
2019-11-02 10:38:58 +01:00
*
* @ since 3.1 . 0
* @ deprecated 4.5 . 0
*
2020-09-15 14:29:22 +02:00
* @ return false Always returns false .
2019-11-02 10:38:58 +01:00
*/
public function is_comments_popup () {
_deprecated_function ( __FUNCTION__ , '4.5.0' );
return false ;
}
/**
2023-09-26 10:33:34 +02:00
* Determines whether the query is for an existing date archive .
2019-11-02 10:38:58 +01:00
*
* @ since 3.1 . 0
*
2020-09-15 14:29:22 +02:00
* @ return bool Whether the query is for an existing date archive .
2019-11-02 10:38:58 +01:00
*/
public function is_date () {
return ( bool ) $this -> is_date ;
}
/**
2023-09-26 10:33:34 +02:00
* Determines whether the query is for an existing day archive .
2019-11-02 10:38:58 +01:00
*
* @ since 3.1 . 0
*
2020-09-15 14:29:22 +02:00
* @ return bool Whether the query is for an existing day archive .
2019-11-02 10:38:58 +01:00
*/
public function is_day () {
return ( bool ) $this -> is_day ;
}
/**
2023-09-26 10:33:34 +02:00
* Determines whether the query is for a feed .
2019-11-02 10:38:58 +01:00
*
* @ since 3.1 . 0
*
2020-05-06 17:23:38 +02:00
* @ param string | string [] $feeds Optional . Feed type or array of feed types
* to check against . Default empty .
2020-09-15 14:29:22 +02:00
* @ return bool Whether the query is for a feed .
2019-11-02 10:38:58 +01:00
*/
public function is_feed ( $feeds = '' ) {
if ( empty ( $feeds ) || ! $this -> is_feed ) {
return ( bool ) $this -> is_feed ;
}
2020-09-15 14:29:22 +02:00
2025-12-12 13:15:55 +01:00
$query_var = $this -> get ( 'feed' );
if ( 'feed' === $query_var ) {
$query_var = get_default_feed ();
2019-11-02 10:38:58 +01:00
}
2020-09-15 14:29:22 +02:00
2025-12-12 13:15:55 +01:00
return in_array ( $query_var , ( array ) $feeds , true );
2019-11-02 10:38:58 +01:00
}
/**
2023-09-26 10:33:34 +02:00
* Determines whether the query is for a comments feed .
2019-11-02 10:38:58 +01:00
*
* @ since 3.1 . 0
*
2020-09-15 14:29:22 +02:00
* @ return bool Whether the query is for a comments feed .
2019-11-02 10:38:58 +01:00
*/
public function is_comment_feed () {
return ( bool ) $this -> is_comment_feed ;
}
/**
2023-09-26 10:33:34 +02:00
* Determines whether the query is for the front page of the site .
2019-11-02 10:38:58 +01:00
*
* This is for what is displayed at your site ' s main URL .
*
* Depends on the site 's "Front page displays" Reading Settings ' show_on_front ' and ' page_on_front ' .
*
* If you set a static page for the front page of your site , this function will return
* true when viewing that page .
*
2023-12-07 09:44:11 +01:00
* Otherwise the same as { @ see WP_Query :: is_home ()} .
2019-11-02 10:38:58 +01:00
*
* @ since 3.1 . 0
*
2020-09-15 14:29:22 +02:00
* @ return bool Whether the query is for the front page of the site .
2019-11-02 10:38:58 +01:00
*/
public function is_front_page () {
2020-05-06 17:23:38 +02:00
// Most likely case.
2020-09-15 14:29:22 +02:00
if ( 'posts' === get_option ( 'show_on_front' ) && $this -> is_home () ) {
2019-11-02 10:38:58 +01:00
return true ;
2020-09-15 14:29:22 +02:00
} elseif ( 'page' === get_option ( 'show_on_front' ) && get_option ( 'page_on_front' )
&& $this -> is_page ( get_option ( 'page_on_front' ) )
) {
2019-11-02 10:38:58 +01:00
return true ;
} else {
return false ;
}
}
/**
2023-09-26 10:33:34 +02:00
* Determines whether the query is for the blog homepage .
2019-11-02 10:38:58 +01:00
*
* This is the page which shows the time based blog content of your site .
*
* Depends on the site 's "Front page displays" Reading Settings ' show_on_front ' and ' page_for_posts ' .
*
* If you set a static page for the front page of your site , this function will return
* true only on the page you set as the " Posts page " .
*
* @ since 3.1 . 0
*
2020-12-10 14:06:04 +01:00
* @ see WP_Query :: is_front_page ()
*
2020-09-15 14:29:22 +02:00
* @ return bool Whether the query is for the blog homepage .
2019-11-02 10:38:58 +01:00
*/
public function is_home () {
return ( bool ) $this -> is_home ;
}
/**
2023-09-26 10:33:34 +02:00
* Determines whether the query is for the Privacy Policy page .
2019-11-02 10:38:58 +01:00
*
* This is the page which shows the Privacy Policy content of your site .
*
* Depends on the site 's "Change your Privacy Policy page" Privacy Settings ' wp_page_for_privacy_policy ' .
*
* This function will return true only on the page you set as the " Privacy Policy page " .
*
* @ since 5.2 . 0
*
2020-09-15 14:29:22 +02:00
* @ return bool Whether the query is for the Privacy Policy page .
2019-11-02 10:38:58 +01:00
*/
public function is_privacy_policy () {
2020-09-15 14:29:22 +02:00
if ( get_option ( 'wp_page_for_privacy_policy' )
&& $this -> is_page ( get_option ( 'wp_page_for_privacy_policy' ) )
) {
2019-11-02 10:38:58 +01:00
return true ;
} else {
return false ;
}
}
/**
2023-09-26 10:33:34 +02:00
* Determines whether the query is for an existing month archive .
2019-11-02 10:38:58 +01:00
*
* @ since 3.1 . 0
*
2020-09-15 14:29:22 +02:00
* @ return bool Whether the query is for an existing month archive .
2019-11-02 10:38:58 +01:00
*/
public function is_month () {
return ( bool ) $this -> is_month ;
}
/**
2023-09-26 10:33:34 +02:00
* Determines whether the query is for an existing single page .
2019-11-02 10:38:58 +01:00
*
* If the $page parameter is specified , this function will additionally
* check if the query is for one of the pages specified .
*
2020-12-10 14:06:04 +01:00
* @ since 3.1 . 0
*
2019-11-02 10:38:58 +01:00
* @ see WP_Query :: is_single ()
* @ see WP_Query :: is_singular ()
*
2020-05-06 17:23:38 +02:00
* @ param int | string | int [] | string [] $page Optional . Page ID , title , slug , path , or array of such
* to check against . Default empty .
2019-11-02 10:38:58 +01:00
* @ return bool Whether the query is for an existing single page .
*/
public function is_page ( $page = '' ) {
if ( ! $this -> is_page ) {
return false ;
}
if ( empty ( $page ) ) {
return true ;
}
$page_obj = $this -> get_queried_object ();
2022-12-15 17:47:31 +01:00
if ( ! $page_obj ) {
return false ;
}
2019-11-02 10:38:58 +01:00
$page = array_map ( 'strval' , ( array ) $page );
2020-09-15 14:29:22 +02:00
if ( in_array ( ( string ) $page_obj -> ID , $page , true ) ) {
2019-11-02 10:38:58 +01:00
return true ;
2020-09-15 14:29:22 +02:00
} elseif ( in_array ( $page_obj -> post_title , $page , true ) ) {
2019-11-02 10:38:58 +01:00
return true ;
2020-09-15 14:29:22 +02:00
} elseif ( in_array ( $page_obj -> post_name , $page , true ) ) {
2019-11-02 10:38:58 +01:00
return true ;
} else {
foreach ( $page as $pagepath ) {
if ( ! strpos ( $pagepath , '/' ) ) {
continue ;
}
2025-04-25 12:30:07 +02:00
2019-11-02 10:38:58 +01:00
$pagepath_obj = get_page_by_path ( $pagepath );
2025-04-25 12:30:07 +02:00
if ( $pagepath_obj && ( $pagepath_obj -> ID === $page_obj -> ID ) ) {
2019-11-02 10:38:58 +01:00
return true ;
}
}
}
return false ;
}
/**
2023-09-26 10:33:34 +02:00
* Determines whether the query is for a paged result and not for the first page .
2019-11-02 10:38:58 +01:00
*
* @ since 3.1 . 0
*
2020-09-15 14:29:22 +02:00
* @ return bool Whether the query is for a paged result .
2019-11-02 10:38:58 +01:00
*/
public function is_paged () {
return ( bool ) $this -> is_paged ;
}
/**
2023-09-26 10:33:34 +02:00
* Determines whether the query is for a post or page preview .
2019-11-02 10:38:58 +01:00
*
* @ since 3.1 . 0
*
2020-09-15 14:29:22 +02:00
* @ return bool Whether the query is for a post or page preview .
2019-11-02 10:38:58 +01:00
*/
public function is_preview () {
return ( bool ) $this -> is_preview ;
}
/**
2023-09-26 10:33:34 +02:00
* Determines whether the query is for the robots . txt file .
2019-11-02 10:38:58 +01:00
*
* @ since 3.1 . 0
*
2020-09-15 14:29:22 +02:00
* @ return bool Whether the query is for the robots . txt file .
2019-11-02 10:38:58 +01:00
*/
public function is_robots () {
return ( bool ) $this -> is_robots ;
}
2020-05-06 17:23:38 +02:00
/**
2023-09-26 10:33:34 +02:00
* Determines whether the query is for the favicon . ico file .
2020-05-06 17:23:38 +02:00
*
* @ since 5.4 . 0
*
2020-09-15 14:29:22 +02:00
* @ return bool Whether the query is for the favicon . ico file .
2020-05-06 17:23:38 +02:00
*/
public function is_favicon () {
return ( bool ) $this -> is_favicon ;
}
2019-11-02 10:38:58 +01:00
/**
2023-09-26 10:33:34 +02:00
* Determines whether the query is for a search .
2019-11-02 10:38:58 +01:00
*
* @ since 3.1 . 0
*
2020-09-15 14:29:22 +02:00
* @ return bool Whether the query is for a search .
2019-11-02 10:38:58 +01:00
*/
public function is_search () {
return ( bool ) $this -> is_search ;
}
/**
2023-09-26 10:33:34 +02:00
* Determines whether the query is for an existing single post .
2019-11-02 10:38:58 +01:00
*
* Works for any post type excluding pages .
*
* If the $post parameter is specified , this function will additionally
* check if the query is for one of the Posts specified .
*
2020-12-10 14:06:04 +01:00
* @ since 3.1 . 0
*
2019-11-02 10:38:58 +01:00
* @ see WP_Query :: is_page ()
* @ see WP_Query :: is_singular ()
*
2020-05-06 17:23:38 +02:00
* @ param int | string | int [] | string [] $post Optional . Post ID , title , slug , path , or array of such
* to check against . Default empty .
2019-11-02 10:38:58 +01:00
* @ return bool Whether the query is for an existing single post .
*/
public function is_single ( $post = '' ) {
if ( ! $this -> is_single ) {
return false ;
}
if ( empty ( $post ) ) {
return true ;
}
$post_obj = $this -> get_queried_object ();
2022-12-15 17:47:31 +01:00
if ( ! $post_obj ) {
return false ;
}
2019-11-02 10:38:58 +01:00
$post = array_map ( 'strval' , ( array ) $post );
2020-09-15 14:29:22 +02:00
if ( in_array ( ( string ) $post_obj -> ID , $post , true ) ) {
2019-11-02 10:38:58 +01:00
return true ;
2020-09-15 14:29:22 +02:00
} elseif ( in_array ( $post_obj -> post_title , $post , true ) ) {
2019-11-02 10:38:58 +01:00
return true ;
2020-09-15 14:29:22 +02:00
} elseif ( in_array ( $post_obj -> post_name , $post , true ) ) {
2019-11-02 10:38:58 +01:00
return true ;
} else {
foreach ( $post as $postpath ) {
if ( ! strpos ( $postpath , '/' ) ) {
continue ;
}
2025-04-25 12:30:07 +02:00
2019-11-02 10:38:58 +01:00
$postpath_obj = get_page_by_path ( $postpath , OBJECT , $post_obj -> post_type );
2025-04-25 12:30:07 +02:00
if ( $postpath_obj && ( $postpath_obj -> ID === $post_obj -> ID ) ) {
2019-11-02 10:38:58 +01:00
return true ;
}
}
}
return false ;
}
/**
2023-09-26 10:33:34 +02:00
* Determines whether the query is for an existing single post of any post type
* ( post , attachment , page , custom post types ) .
2019-11-02 10:38:58 +01:00
*
* If the $post_types parameter is specified , this function will additionally
* check if the query is for one of the Posts Types specified .
*
2020-12-10 14:06:04 +01:00
* @ since 3.1 . 0
*
2019-11-02 10:38:58 +01:00
* @ see WP_Query :: is_page ()
* @ see WP_Query :: is_single ()
*
2020-05-06 17:23:38 +02:00
* @ param string | string [] $post_types Optional . Post type or array of post types
* to check against . Default empty .
* @ return bool Whether the query is for an existing single post
* or any of the given post types .
2019-11-02 10:38:58 +01:00
*/
public function is_singular ( $post_types = '' ) {
if ( empty ( $post_types ) || ! $this -> is_singular ) {
return ( bool ) $this -> is_singular ;
}
$post_obj = $this -> get_queried_object ();
2022-12-15 17:47:31 +01:00
if ( ! $post_obj ) {
return false ;
}
2019-11-02 10:38:58 +01:00
2020-09-15 14:29:22 +02:00
return in_array ( $post_obj -> post_type , ( array ) $post_types , true );
2019-11-02 10:38:58 +01:00
}
/**
2023-09-26 10:33:34 +02:00
* Determines whether the query is for a specific time .
2019-11-02 10:38:58 +01:00
*
* @ since 3.1 . 0
*
2020-09-15 14:29:22 +02:00
* @ return bool Whether the query is for a specific time .
2019-11-02 10:38:58 +01:00
*/
public function is_time () {
return ( bool ) $this -> is_time ;
}
/**
2023-09-26 10:33:34 +02:00
* Determines whether the query is for a trackback endpoint call .
2019-11-02 10:38:58 +01:00
*
* @ since 3.1 . 0
*
2020-09-15 14:29:22 +02:00
* @ return bool Whether the query is for a trackback endpoint call .
2019-11-02 10:38:58 +01:00
*/
public function is_trackback () {
return ( bool ) $this -> is_trackback ;
}
/**
2023-09-26 10:33:34 +02:00
* Determines whether the query is for an existing year archive .
2019-11-02 10:38:58 +01:00
*
* @ since 3.1 . 0
*
2020-09-15 14:29:22 +02:00
* @ return bool Whether the query is for an existing year archive .
2019-11-02 10:38:58 +01:00
*/
public function is_year () {
return ( bool ) $this -> is_year ;
}
/**
2023-09-26 10:33:34 +02:00
* Determines whether the query is a 404 ( returns no results ) .
2019-11-02 10:38:58 +01:00
*
* @ since 3.1 . 0
*
2020-09-15 14:29:22 +02:00
* @ return bool Whether the query is a 404 error .
2019-11-02 10:38:58 +01:00
*/
public function is_404 () {
return ( bool ) $this -> is_404 ;
}
/**
2023-09-26 10:33:34 +02:00
* Determines whether the query is for an embedded post .
2019-11-02 10:38:58 +01:00
*
* @ since 4.4 . 0
*
2020-09-15 14:29:22 +02:00
* @ return bool Whether the query is for an embedded post .
2019-11-02 10:38:58 +01:00
*/
public function is_embed () {
return ( bool ) $this -> is_embed ;
}
/**
2023-09-26 10:33:34 +02:00
* Determines whether the query is the main query .
2019-11-02 10:38:58 +01:00
*
* @ since 3.3 . 0
*
2024-04-17 11:32:24 +02:00
* @ global WP_Query $wp_the_query WordPress Query object .
2019-11-02 10:38:58 +01:00
*
2020-09-15 14:29:22 +02:00
* @ return bool Whether the query is the main query .
2019-11-02 10:38:58 +01:00
*/
public function is_main_query () {
global $wp_the_query ;
return $wp_the_query === $this ;
}
/**
2023-09-26 10:33:34 +02:00
* Sets up global post data .
2019-11-02 10:38:58 +01:00
*
* @ since 4.1 . 0
* @ since 4.4 . 0 Added the ability to pass a post ID to `$post` .
*
2019-11-15 22:59:44 +01:00
* @ global int $id
* @ global WP_User $authordata
* @ global string $currentday
* @ global string $currentmonth
* @ global int $page
* @ global array $pages
* @ global int $multipage
* @ global int $more
* @ global int $numpages
2019-11-02 10:38:58 +01:00
*
* @ param WP_Post | object | int $post WP_Post instance or Post ID / object .
* @ return true True when finished .
*/
public function setup_postdata ( $post ) {
global $id , $authordata , $currentday , $currentmonth , $page , $pages , $multipage , $more , $numpages ;
if ( ! ( $post instanceof WP_Post ) ) {
$post = get_post ( $post );
}
if ( ! $post ) {
return ;
}
$elements = $this -> generate_postdata ( $post );
if ( false === $elements ) {
return ;
}
$id = $elements [ 'id' ];
$authordata = $elements [ 'authordata' ];
$currentday = $elements [ 'currentday' ];
$currentmonth = $elements [ 'currentmonth' ];
$page = $elements [ 'page' ];
$pages = $elements [ 'pages' ];
$multipage = $elements [ 'multipage' ];
$more = $elements [ 'more' ];
$numpages = $elements [ 'numpages' ];
/**
2020-09-15 14:29:22 +02:00
* Fires once the post data has been set up .
2019-11-02 10:38:58 +01:00
*
* @ since 2.8 . 0
2021-04-27 08:32:47 +02:00
* @ since 4.1 . 0 Introduced `$query` parameter .
2019-11-02 10:38:58 +01:00
*
2021-04-27 08:32:47 +02:00
* @ param WP_Post $post The Post object ( passed by reference ) .
* @ param WP_Query $query The current Query object ( passed by reference ) .
2019-11-02 10:38:58 +01:00
*/
do_action_ref_array ( 'the_post' , array ( & $post , & $this ) );
return true ;
}
/**
2023-09-26 10:33:34 +02:00
* Generates post data .
2019-11-02 10:38:58 +01:00
*
* @ since 5.2 . 0
*
* @ param WP_Post | object | int $post WP_Post instance or Post ID / object .
2021-04-27 08:32:47 +02:00
* @ return array | false Elements of post or false on failure .
2019-11-02 10:38:58 +01:00
*/
public function generate_postdata ( $post ) {
if ( ! ( $post instanceof WP_Post ) ) {
$post = get_post ( $post );
}
if ( ! $post ) {
return false ;
}
$id = ( int ) $post -> ID ;
$authordata = get_userdata ( $post -> post_author );
2023-09-26 10:33:34 +02:00
$currentday = false ;
$currentmonth = false ;
$post_date = $post -> post_date ;
if ( ! empty ( $post_date ) && '0000-00-00 00:00:00' !== $post_date ) {
// Avoid using mysql2date for performance reasons.
$currentmonth = substr ( $post_date , 5 , 2 );
$day = substr ( $post_date , 8 , 2 );
$year = substr ( $post_date , 2 , 2 );
$currentday = sprintf ( '%s.%s.%s' , $day , $currentmonth , $year );
}
$numpages = 1 ;
$multipage = 0 ;
$page = $this -> get ( 'page' );
2019-11-02 10:38:58 +01:00
if ( ! $page ) {
$page = 1 ;
}
/*
* Force full post content when viewing the permalink for the $post ,
* or when on an RSS feed . Otherwise respect the 'more' tag .
*/
2020-05-06 17:23:38 +02:00
if ( get_queried_object_id () === $post -> ID && ( $this -> is_page () || $this -> is_single () ) ) {
2019-11-02 10:38:58 +01:00
$more = 1 ;
} elseif ( $this -> is_feed () ) {
$more = 1 ;
} else {
$more = 0 ;
}
$content = $post -> post_content ;
2023-09-26 10:33:34 +02:00
if ( str_contains ( $content , '<!--nextpage-->' ) ) {
2019-11-02 10:38:58 +01:00
$content = str_replace ( " \n <!--nextpage--> \n " , '<!--nextpage-->' , $content );
$content = str_replace ( " \n <!--nextpage--> " , '<!--nextpage-->' , $content );
$content = str_replace ( " <!--nextpage--> \n " , '<!--nextpage-->' , $content );
// Remove the nextpage block delimiters, to avoid invalid block structures in the split content.
$content = str_replace ( '<!-- wp:nextpage -->' , '' , $content );
$content = str_replace ( '<!-- /wp:nextpage -->' , '' , $content );
// Ignore nextpage at the beginning of the content.
2023-09-26 10:33:34 +02:00
if ( str_starts_with ( $content , '<!--nextpage-->' ) ) {
2019-11-02 10:38:58 +01:00
$content = substr ( $content , 15 );
}
$pages = explode ( '<!--nextpage-->' , $content );
} else {
$pages = array ( $post -> post_content );
}
/**
* Filters the " pages " derived from splitting the post content .
*
* " Pages " are determined by splitting the post content based on the presence
* of `<!-- nextpage -->` tags .
*
* @ since 4.4 . 0
*
* @ param string [] $pages Array of " pages " from the post content split by `<!-- nextpage -->` tags .
* @ param WP_Post $post Current post object .
*/
$pages = apply_filters ( 'content_pagination' , $pages , $post );
$numpages = count ( $pages );
if ( $numpages > 1 ) {
if ( $page > 1 ) {
$more = 1 ;
}
$multipage = 1 ;
} else {
$multipage = 0 ;
}
$elements = compact ( 'id' , 'authordata' , 'currentday' , 'currentmonth' , 'page' , 'pages' , 'multipage' , 'more' , 'numpages' );
return $elements ;
}
2022-12-15 17:47:31 +01:00
/**
2023-09-26 10:33:34 +02:00
* Generates cache key .
2022-12-15 17:47:31 +01:00
*
* @ since 6.1 . 0
*
* @ global wpdb $wpdb WordPress database abstraction object .
*
* @ param array $args Query arguments .
* @ param string $sql SQL statement .
* @ return string Cache key .
*/
protected function generate_cache_key ( array $args , $sql ) {
global $wpdb ;
unset (
$args [ 'cache_results' ],
$args [ 'fields' ],
$args [ 'lazy_load_term_meta' ],
$args [ 'update_post_meta_cache' ],
$args [ 'update_post_term_cache' ],
$args [ 'update_menu_item_cache' ],
$args [ 'suppress_filters' ]
);
2025-02-28 08:42:11 +01:00
if ( empty ( $args [ 'post_type' ] ) ) {
if ( $this -> is_attachment ) {
$args [ 'post_type' ] = 'attachment' ;
} elseif ( $this -> is_page ) {
$args [ 'post_type' ] = 'page' ;
} else {
$args [ 'post_type' ] = 'post' ;
}
} elseif ( 'any' === $args [ 'post_type' ] ) {
$args [ 'post_type' ] = array_values ( get_post_types ( array ( 'exclude_from_search' => false ) ) );
}
$args [ 'post_type' ] = ( array ) $args [ 'post_type' ];
// Sort post types to ensure same cache key generation.
sort ( $args [ 'post_type' ] );
2025-04-25 12:30:07 +02:00
/*
* Sort arrays that can be used for ordering prior to cache key generation .
*
* These arrays are sorted in the query generator for the purposes of the
* WHERE clause but the arguments are not modified as they can be used for
2025-12-12 13:15:55 +01:00
* the orderby clause .
2025-04-25 12:30:07 +02:00
*
* Their use in the orderby clause will generate a different SQL query so
* they can be sorted for the cache key generation .
*/
$sortable_arrays_with_int_values = array (
'post__in' ,
'post_parent__in' ,
);
foreach ( $sortable_arrays_with_int_values as $key ) {
if ( isset ( $args [ $key ] ) && is_array ( $args [ $key ] ) ) {
$args [ $key ] = array_unique ( array_map ( 'absint' , $args [ $key ] ) );
sort ( $args [ $key ] );
}
}
// Sort and unique the 'post_name__in' for cache key generation.
if ( isset ( $args [ 'post_name__in' ] ) && is_array ( $args [ 'post_name__in' ] ) ) {
$args [ 'post_name__in' ] = array_unique ( $args [ 'post_name__in' ] );
sort ( $args [ 'post_name__in' ] );
}
2025-02-28 08:42:11 +01:00
if ( isset ( $args [ 'post_status' ] ) ) {
$args [ 'post_status' ] = ( array ) $args [ 'post_status' ];
// Sort post status to ensure same cache key generation.
sort ( $args [ 'post_status' ] );
}
// Add a default orderby value of date to ensure same cache key generation.
2025-12-12 13:15:55 +01:00
if ( ! isset ( $args [ 'orderby' ] ) ) {
2025-02-28 08:42:11 +01:00
$args [ 'orderby' ] = 'date' ;
}
2022-12-15 17:47:31 +01:00
$placeholder = $wpdb -> placeholder_escape ();
array_walk_recursive (
$args ,
/*
* Replace wpdb placeholders with the string used in the database
* query to avoid unreachable cache keys . This is necessary because
* the placeholder is randomly generated in each request .
*
* $value is passed by reference to allow it to be modified .
* array_walk_recursive () does not return an array .
*/
2023-09-26 10:33:34 +02:00
static function ( & $value ) use ( $wpdb , $placeholder ) {
2022-12-15 17:47:31 +01:00
if ( is_string ( $value ) && str_contains ( $value , $placeholder ) ) {
$value = $wpdb -> remove_placeholder_escape ( $value );
}
}
);
2025-02-28 08:42:11 +01:00
ksort ( $args );
2022-12-15 17:47:31 +01:00
// Replace wpdb placeholder in the SQL statement used by the cache key.
$sql = $wpdb -> remove_placeholder_escape ( $sql );
$key = md5 ( serialize ( $args ) . $sql );
2025-12-12 13:15:55 +01:00
$this -> query_cache_key = " wp_query: $key " ;
2025-04-25 12:30:07 +02:00
return $this -> query_cache_key ;
2022-12-15 17:47:31 +01:00
}
2019-11-02 10:38:58 +01:00
/**
* After looping through a nested query , this function
* restores the $post global to the current post in this query .
*
* @ since 3.7 . 0
*
2019-11-15 22:59:44 +01:00
* @ global WP_Post $post Global post object .
2019-11-02 10:38:58 +01:00
*/
public function reset_postdata () {
if ( ! empty ( $this -> post ) ) {
$GLOBALS [ 'post' ] = $this -> post ;
$this -> setup_postdata ( $this -> post );
}
}
/**
2023-09-26 10:33:34 +02:00
* Lazyloads term meta for posts in the loop .
2019-11-02 10:38:58 +01:00
*
* @ since 4.4 . 0
* @ deprecated 4.5 . 0 See wp_queue_posts_for_term_meta_lazyload () .
*
* @ param mixed $check
* @ param int $term_id
* @ return mixed
*/
public function lazyload_term_meta ( $check , $term_id ) {
_deprecated_function ( __METHOD__ , '4.5.0' );
return $check ;
}
/**
2023-09-26 10:33:34 +02:00
* Lazyloads comment meta for comments in the loop .
2019-11-02 10:38:58 +01:00
*
* @ since 4.4 . 0
2023-09-26 10:33:34 +02:00
* @ deprecated 4.5 . 0 See wp_lazyload_comment_meta () .
2019-11-02 10:38:58 +01:00
*
* @ param mixed $check
* @ param int $comment_id
* @ return mixed
*/
public function lazyload_comment_meta ( $check , $comment_id ) {
_deprecated_function ( __METHOD__ , '4.5.0' );
return $check ;
}
}