WordPress.org

Make WordPress Core

Ticket #37827: 37827.diff

File 37827.diff, 148.7 KB (added by wonderboymusic, 5 years ago)
  • src/wp-includes/class-wp-query.php

     
    11<?php
    22/**
    3  * WordPress Query API
     3 * Query API: WP_Query class
    44 *
    5  * The query API attempts to get which part of WordPress the user is on. It
    6  * also provides functionality for getting URL query information.
    7  *
    8  * @link https://codex.wordpress.org/The_Loop More information on The Loop.
    9  *
    105 * @package WordPress
    116 * @subpackage Query
     7 * @since 4.7.0
    128 */
    139
    1410/**
    15  * Retrieve variable in the WP_Query class.
    16  *
    17  * @since 1.5.0
    18  * @since 3.9.0 The `$default` argument was introduced.
    19  *
    20  * @global WP_Query $wp_query Global WP_Query instance.
    21  *
    22  * @param string $var       The variable key to retrieve.
    23  * @param mixed  $default   Optional. Value to return if the query variable is not set. Default empty.
    24  * @return mixed Contents of the query variable.
    25  */
    26 function get_query_var( $var, $default = '' ) {
    27         global $wp_query;
    28         return $wp_query->get( $var, $default );
    29 }
    30 
    31 /**
    32  * Retrieve the currently-queried object.
    33  *
    34  * Wrapper for WP_Query::get_queried_object().
    35  *
    36  * @since 3.1.0
    37  * @access public
    38  *
    39  * @global WP_Query $wp_query Global WP_Query instance.
    40  *
    41  * @return object Queried object.
    42  */
    43 function get_queried_object() {
    44         global $wp_query;
    45         return $wp_query->get_queried_object();
    46 }
    47 
    48 /**
    49  * Retrieve ID of the current queried object.
    50  *
    51  * Wrapper for WP_Query::get_queried_object_id().
    52  *
    53  * @since 3.1.0
    54  *
    55  * @global WP_Query $wp_query Global WP_Query instance.
    56  *
    57  * @return int ID of the queried object.
    58  */
    59 function get_queried_object_id() {
    60         global $wp_query;
    61         return $wp_query->get_queried_object_id();
    62 }
    63 
    64 /**
    65  * Set query variable.
    66  *
    67  * @since 2.2.0
    68  *
    69  * @global WP_Query $wp_query Global WP_Query instance.
    70  *
    71  * @param string $var   Query variable key.
    72  * @param mixed  $value Query variable value.
    73  */
    74 function set_query_var( $var, $value ) {
    75         global $wp_query;
    76         $wp_query->set( $var, $value );
    77 }
    78 
    79 /**
    80  * Sets up The Loop with query parameters.
    81  *
    82  * Note: This function will completely override the main query and isn't intended for use
    83  * by plugins or themes. Its overly-simplistic approach to modifying the main query can be
    84  * problematic and should be avoided wherever possible. In most cases, there are better,
    85  * more performant options for modifying the main query such as via the {@see 'pre_get_posts'}
    86  * action within WP_Query.
    87  *
    88  * This must not be used within the WordPress Loop.
    89  *
    90  * @since 1.5.0
    91  *
    92  * @global WP_Query $wp_query Global WP_Query instance.
    93  *
    94  * @param array|string $query Array or string of WP_Query arguments.
    95  * @return array List of post objects.
    96  */
    97 function query_posts($query) {
    98         $GLOBALS['wp_query'] = new WP_Query();
    99         return $GLOBALS['wp_query']->query($query);
    100 }
    101 
    102 /**
    103  * Destroys the previous query and sets up a new query.
    104  *
    105  * This should be used after query_posts() and before another query_posts().
    106  * This will remove obscure bugs that occur when the previous WP_Query object
    107  * is not destroyed properly before another is set up.
    108  *
    109  * @since 2.3.0
    110  *
    111  * @global WP_Query $wp_query     Global WP_Query instance.
    112  * @global WP_Query $wp_the_query Copy of the global WP_Query instance created during wp_reset_query().
    113  */
    114 function wp_reset_query() {
    115         $GLOBALS['wp_query'] = $GLOBALS['wp_the_query'];
    116         wp_reset_postdata();
    117 }
    118 
    119 /**
    120  * After looping through a separate query, this function restores
    121  * the $post global to the current post in the main query.
    122  *
    123  * @since 3.0.0
    124  *
    125  * @global WP_Query $wp_query Global WP_Query instance.
    126  */
    127 function wp_reset_postdata() {
    128         global $wp_query;
    129 
    130         if ( isset( $wp_query ) ) {
    131                 $wp_query->reset_postdata();
    132         }
    133 }
    134 
    135 /*
    136  * Query type checks.
    137  */
    138 
    139 /**
    140  * Is the query for an existing archive page?
    141  *
    142  * Month, Year, Category, Author, Post Type archive...
    143  *
    144  * @since 1.5.0
    145  *
    146  * @global WP_Query $wp_query Global WP_Query instance.
    147  *
    148  * @return bool
    149  */
    150 function is_archive() {
    151         global $wp_query;
    152 
    153         if ( ! isset( $wp_query ) ) {
    154                 _doing_it_wrong( __FUNCTION__, __( 'Conditional query tags do not work before the query is run. Before then, they always return false.' ), '3.1.0' );
    155                 return false;
    156         }
    157 
    158         return $wp_query->is_archive();
    159 }
    160 
    161 /**
    162  * Is the query for an existing post type archive page?
    163  *
    164  * @since 3.1.0
    165  *
    166  * @global WP_Query $wp_query Global WP_Query instance.
    167  *
    168  * @param string|array $post_types Optional. Post type or array of posts types to check against.
    169  * @return bool
    170  */
    171 function is_post_type_archive( $post_types = '' ) {
    172         global $wp_query;
    173 
    174         if ( ! isset( $wp_query ) ) {
    175                 _doing_it_wrong( __FUNCTION__, __( 'Conditional query tags do not work before the query is run. Before then, they always return false.' ), '3.1.0' );
    176                 return false;
    177         }
    178 
    179         return $wp_query->is_post_type_archive( $post_types );
    180 }
    181 
    182 /**
    183  * Is the query for an existing attachment page?
    184  *
    185  * @since 2.0.0
    186  *
    187  * @global WP_Query $wp_query Global WP_Query instance.
    188  *
    189  * @param int|string|array|object $attachment Attachment ID, title, slug, or array of such.
    190  * @return bool
    191  */
    192 function is_attachment( $attachment = '' ) {
    193         global $wp_query;
    194 
    195         if ( ! isset( $wp_query ) ) {
    196                 _doing_it_wrong( __FUNCTION__, __( 'Conditional query tags do not work before the query is run. Before then, they always return false.' ), '3.1.0' );
    197                 return false;
    198         }
    199 
    200         return $wp_query->is_attachment( $attachment );
    201 }
    202 
    203 /**
    204  * Is the query for an existing author archive page?
    205  *
    206  * If the $author parameter is specified, this function will additionally
    207  * check if the query is for one of the authors specified.
    208  *
    209  * @since 1.5.0
    210  *
    211  * @global WP_Query $wp_query Global WP_Query instance.
    212  *
    213  * @param mixed $author Optional. User ID, nickname, nicename, or array of User IDs, nicknames, and nicenames
    214  * @return bool
    215  */
    216 function is_author( $author = '' ) {
    217         global $wp_query;
    218 
    219         if ( ! isset( $wp_query ) ) {
    220                 _doing_it_wrong( __FUNCTION__, __( 'Conditional query tags do not work before the query is run. Before then, they always return false.' ), '3.1.0' );
    221                 return false;
    222         }
    223 
    224         return $wp_query->is_author( $author );
    225 }
    226 
    227 /**
    228  * Is the query for an existing category archive page?
    229  *
    230  * If the $category parameter is specified, this function will additionally
    231  * check if the query is for one of the categories specified.
    232  *
    233  * @since 1.5.0
    234  *
    235  * @global WP_Query $wp_query Global WP_Query instance.
    236  *
    237  * @param mixed $category Optional. Category ID, name, slug, or array of Category IDs, names, and slugs.
    238  * @return bool
    239  */
    240 function is_category( $category = '' ) {
    241         global $wp_query;
    242 
    243         if ( ! isset( $wp_query ) ) {
    244                 _doing_it_wrong( __FUNCTION__, __( 'Conditional query tags do not work before the query is run. Before then, they always return false.' ), '3.1.0' );
    245                 return false;
    246         }
    247 
    248         return $wp_query->is_category( $category );
    249 }
    250 
    251 /**
    252  * Is the query for an existing tag archive page?
    253  *
    254  * If the $tag parameter is specified, this function will additionally
    255  * check if the query is for one of the tags specified.
    256  *
    257  * @since 2.3.0
    258  *
    259  * @global WP_Query $wp_query Global WP_Query instance.
    260  *
    261  * @param mixed $tag Optional. Tag ID, name, slug, or array of Tag IDs, names, and slugs.
    262  * @return bool
    263  */
    264 function is_tag( $tag = '' ) {
    265         global $wp_query;
    266 
    267         if ( ! isset( $wp_query ) ) {
    268                 _doing_it_wrong( __FUNCTION__, __( 'Conditional query tags do not work before the query is run. Before then, they always return false.' ), '3.1.0' );
    269                 return false;
    270         }
    271 
    272         return $wp_query->is_tag( $tag );
    273 }
    274 
    275 /**
    276  * Is the query for an existing custom taxonomy archive page?
    277  *
    278  * If the $taxonomy parameter is specified, this function will additionally
    279  * check if the query is for that specific $taxonomy.
    280  *
    281  * If the $term parameter is specified in addition to the $taxonomy parameter,
    282  * this function will additionally check if the query is for one of the terms
    283  * specified.
    284  *
    285  * @since 2.5.0
    286  *
    287  * @global WP_Query $wp_query Global WP_Query instance.
    288  *
    289  * @param string|array     $taxonomy Optional. Taxonomy slug or slugs.
    290  * @param int|string|array $term     Optional. Term ID, name, slug or array of Term IDs, names, and slugs.
    291  * @return bool True for custom taxonomy archive pages, false for built-in taxonomies (category and tag archives).
    292  */
    293 function is_tax( $taxonomy = '', $term = '' ) {
    294         global $wp_query;
    295 
    296         if ( ! isset( $wp_query ) ) {
    297                 _doing_it_wrong( __FUNCTION__, __( 'Conditional query tags do not work before the query is run. Before then, they always return false.' ), '3.1.0' );
    298                 return false;
    299         }
    300 
    301         return $wp_query->is_tax( $taxonomy, $term );
    302 }
    303 
    304 /**
    305  * Is the query for an existing date archive?
    306  *
    307  * @since 1.5.0
    308  *
    309  * @global WP_Query $wp_query Global WP_Query instance.
    310  *
    311  * @return bool
    312  */
    313 function is_date() {
    314         global $wp_query;
    315 
    316         if ( ! isset( $wp_query ) ) {
    317                 _doing_it_wrong( __FUNCTION__, __( 'Conditional query tags do not work before the query is run. Before then, they always return false.' ), '3.1.0' );
    318                 return false;
    319         }
    320 
    321         return $wp_query->is_date();
    322 }
    323 
    324 /**
    325  * Is the query for an existing day archive?
    326  *
    327  * @since 1.5.0
    328  *
    329  * @global WP_Query $wp_query Global WP_Query instance.
    330  *
    331  * @return bool
    332  */
    333 function is_day() {
    334         global $wp_query;
    335 
    336         if ( ! isset( $wp_query ) ) {
    337                 _doing_it_wrong( __FUNCTION__, __( 'Conditional query tags do not work before the query is run. Before then, they always return false.' ), '3.1.0' );
    338                 return false;
    339         }
    340 
    341         return $wp_query->is_day();
    342 }
    343 
    344 /**
    345  * Is the query for a feed?
    346  *
    347  * @since 1.5.0
    348  *
    349  * @global WP_Query $wp_query Global WP_Query instance.
    350  *
    351  * @param string|array $feeds Optional feed types to check.
    352  * @return bool
    353  */
    354 function is_feed( $feeds = '' ) {
    355         global $wp_query;
    356 
    357         if ( ! isset( $wp_query ) ) {
    358                 _doing_it_wrong( __FUNCTION__, __( 'Conditional query tags do not work before the query is run. Before then, they always return false.' ), '3.1.0' );
    359                 return false;
    360         }
    361 
    362         return $wp_query->is_feed( $feeds );
    363 }
    364 
    365 /**
    366  * Is the query for a comments feed?
    367  *
    368  * @since 3.0.0
    369  *
    370  * @global WP_Query $wp_query Global WP_Query instance.
    371  *
    372  * @return bool
    373  */
    374 function is_comment_feed() {
    375         global $wp_query;
    376 
    377         if ( ! isset( $wp_query ) ) {
    378                 _doing_it_wrong( __FUNCTION__, __( 'Conditional query tags do not work before the query is run. Before then, they always return false.' ), '3.1.0' );
    379                 return false;
    380         }
    381 
    382         return $wp_query->is_comment_feed();
    383 }
    384 
    385 /**
    386  * Is the query for the front page of the site?
    387  *
    388  * This is for what is displayed at your site's main URL.
    389  *
    390  * Depends on the site's "Front page displays" Reading Settings 'show_on_front' and 'page_on_front'.
    391  *
    392  * If you set a static page for the front page of your site, this function will return
    393  * true when viewing that page.
    394  *
    395  * Otherwise the same as @see is_home()
    396  *
    397  * @since 2.5.0
    398  *
    399  * @global WP_Query $wp_query Global WP_Query instance.
    400  *
    401  * @return bool True, if front of site.
    402  */
    403 function is_front_page() {
    404         global $wp_query;
    405 
    406         if ( ! isset( $wp_query ) ) {
    407                 _doing_it_wrong( __FUNCTION__, __( 'Conditional query tags do not work before the query is run. Before then, they always return false.' ), '3.1.0' );
    408                 return false;
    409         }
    410 
    411         return $wp_query->is_front_page();
    412 }
    413 
    414 /**
    415  * Determines if the query is for the blog homepage.
    416  *
    417  * The blog homepage is the page that shows the time-based blog content of the site.
    418  *
    419  * is_home() is dependent on the site's "Front page displays" Reading Settings 'show_on_front'
    420  * and 'page_for_posts'.
    421  *
    422  * If a static page is set for the front page of the site, this function will return true only
    423  * on the page you set as the "Posts page".
    424  *
    425  * @since 1.5.0
    426  *
    427  * @see is_front_page()
    428  * @global WP_Query $wp_query Global WP_Query instance.
    429  *
    430  * @return bool True if blog view homepage, otherwise false.
    431  */
    432 function is_home() {
    433         global $wp_query;
    434 
    435         if ( ! isset( $wp_query ) ) {
    436                 _doing_it_wrong( __FUNCTION__, __( 'Conditional query tags do not work before the query is run. Before then, they always return false.' ), '3.1.0' );
    437                 return false;
    438         }
    439 
    440         return $wp_query->is_home();
    441 }
    442 
    443 /**
    444  * Is the query for an existing month archive?
    445  *
    446  * @since 1.5.0
    447  *
    448  * @global WP_Query $wp_query Global WP_Query instance.
    449  *
    450  * @return bool
    451  */
    452 function is_month() {
    453         global $wp_query;
    454 
    455         if ( ! isset( $wp_query ) ) {
    456                 _doing_it_wrong( __FUNCTION__, __( 'Conditional query tags do not work before the query is run. Before then, they always return false.' ), '3.1.0' );
    457                 return false;
    458         }
    459 
    460         return $wp_query->is_month();
    461 }
    462 
    463 /**
    464  * Is the query for an existing single page?
    465  *
    466  * If the $page parameter is specified, this function will additionally
    467  * check if the query is for one of the pages specified.
    468  *
    469  * @see is_single()
    470  * @see is_singular()
    471  *
    472  * @since 1.5.0
    473  *
    474  * @global WP_Query $wp_query Global WP_Query instance.
    475  *
    476  * @param int|string|array $page Optional. Page ID, title, slug, or array of such. Default empty.
    477  * @return bool Whether the query is for an existing single page.
    478  */
    479 function is_page( $page = '' ) {
    480         global $wp_query;
    481 
    482         if ( ! isset( $wp_query ) ) {
    483                 _doing_it_wrong( __FUNCTION__, __( 'Conditional query tags do not work before the query is run. Before then, they always return false.' ), '3.1.0' );
    484                 return false;
    485         }
    486 
    487         return $wp_query->is_page( $page );
    488 }
    489 
    490 /**
    491  * Is the query for paged result and not for the first page?
    492  *
    493  * @since 1.5.0
    494  *
    495  * @global WP_Query $wp_query Global WP_Query instance.
    496  *
    497  * @return bool
    498  */
    499 function is_paged() {
    500         global $wp_query;
    501 
    502         if ( ! isset( $wp_query ) ) {
    503                 _doing_it_wrong( __FUNCTION__, __( 'Conditional query tags do not work before the query is run. Before then, they always return false.' ), '3.1.0' );
    504                 return false;
    505         }
    506 
    507         return $wp_query->is_paged();
    508 }
    509 
    510 /**
    511  * Is the query for a post or page preview?
    512  *
    513  * @since 2.0.0
    514  *
    515  * @global WP_Query $wp_query Global WP_Query instance.
    516  *
    517  * @return bool
    518  */
    519 function is_preview() {
    520         global $wp_query;
    521 
    522         if ( ! isset( $wp_query ) ) {
    523                 _doing_it_wrong( __FUNCTION__, __( 'Conditional query tags do not work before the query is run. Before then, they always return false.' ), '3.1.0' );
    524                 return false;
    525         }
    526 
    527         return $wp_query->is_preview();
    528 }
    529 
    530 /**
    531  * Is the query for the robots file?
    532  *
    533  * @since 2.1.0
    534  *
    535  * @global WP_Query $wp_query Global WP_Query instance.
    536  *
    537  * @return bool
    538  */
    539 function is_robots() {
    540         global $wp_query;
    541 
    542         if ( ! isset( $wp_query ) ) {
    543                 _doing_it_wrong( __FUNCTION__, __( 'Conditional query tags do not work before the query is run. Before then, they always return false.' ), '3.1.0' );
    544                 return false;
    545         }
    546 
    547         return $wp_query->is_robots();
    548 }
    549 
    550 /**
    551  * Is the query for a search?
    552  *
    553  * @since 1.5.0
    554  *
    555  * @global WP_Query $wp_query Global WP_Query instance.
    556  *
    557  * @return bool
    558  */
    559 function is_search() {
    560         global $wp_query;
    561 
    562         if ( ! isset( $wp_query ) ) {
    563                 _doing_it_wrong( __FUNCTION__, __( 'Conditional query tags do not work before the query is run. Before then, they always return false.' ), '3.1.0' );
    564                 return false;
    565         }
    566 
    567         return $wp_query->is_search();
    568 }
    569 
    570 /**
    571  * Is the query for an existing single post?
    572  *
    573  * Works for any post type, except attachments and pages
    574  *
    575  * If the $post parameter is specified, this function will additionally
    576  * check if the query is for one of the Posts specified.
    577  *
    578  * @see is_page()
    579  * @see is_singular()
    580  *
    581  * @since 1.5.0
    582  *
    583  * @global WP_Query $wp_query Global WP_Query instance.
    584  *
    585  * @param int|string|array $post Optional. Post ID, title, slug, or array of such. Default empty.
    586  * @return bool Whether the query is for an existing single post.
    587  */
    588 function is_single( $post = '' ) {
    589         global $wp_query;
    590 
    591         if ( ! isset( $wp_query ) ) {
    592                 _doing_it_wrong( __FUNCTION__, __( 'Conditional query tags do not work before the query is run. Before then, they always return false.' ), '3.1.0' );
    593                 return false;
    594         }
    595 
    596         return $wp_query->is_single( $post );
    597 }
    598 
    599 /**
    600  * Is the query for an existing single post of any post type (post, attachment, page, ... )?
    601  *
    602  * If the $post_types parameter is specified, this function will additionally
    603  * check if the query is for one of the Posts Types specified.
    604  *
    605  * @see is_page()
    606  * @see is_single()
    607  *
    608  * @since 1.5.0
    609  *
    610  * @global WP_Query $wp_query Global WP_Query instance.
    611  *
    612  * @param string|array $post_types Optional. Post type or array of post types. Default empty.
    613  * @return bool Whether the query is for an existing single post of any of the given post types.
    614  */
    615 function is_singular( $post_types = '' ) {
    616         global $wp_query;
    617 
    618         if ( ! isset( $wp_query ) ) {
    619                 _doing_it_wrong( __FUNCTION__, __( 'Conditional query tags do not work before the query is run. Before then, they always return false.' ), '3.1.0' );
    620                 return false;
    621         }
    622 
    623         return $wp_query->is_singular( $post_types );
    624 }
    625 
    626 /**
    627  * Is the query for a specific time?
    628  *
    629  * @since 1.5.0
    630  *
    631  * @global WP_Query $wp_query Global WP_Query instance.
    632  *
    633  * @return bool
    634  */
    635 function is_time() {
    636         global $wp_query;
    637 
    638         if ( ! isset( $wp_query ) ) {
    639                 _doing_it_wrong( __FUNCTION__, __( 'Conditional query tags do not work before the query is run. Before then, they always return false.' ), '3.1.0' );
    640                 return false;
    641         }
    642 
    643         return $wp_query->is_time();
    644 }
    645 
    646 /**
    647  * Is the query for a trackback endpoint call?
    648  *
    649  * @since 1.5.0
    650  *
    651  * @global WP_Query $wp_query Global WP_Query instance.
    652  *
    653  * @return bool
    654  */
    655 function is_trackback() {
    656         global $wp_query;
    657 
    658         if ( ! isset( $wp_query ) ) {
    659                 _doing_it_wrong( __FUNCTION__, __( 'Conditional query tags do not work before the query is run. Before then, they always return false.' ), '3.1.0' );
    660                 return false;
    661         }
    662 
    663         return $wp_query->is_trackback();
    664 }
    665 
    666 /**
    667  * Is the query for an existing year archive?
    668  *
    669  * @since 1.5.0
    670  *
    671  * @global WP_Query $wp_query Global WP_Query instance.
    672  *
    673  * @return bool
    674  */
    675 function is_year() {
    676         global $wp_query;
    677 
    678         if ( ! isset( $wp_query ) ) {
    679                 _doing_it_wrong( __FUNCTION__, __( 'Conditional query tags do not work before the query is run. Before then, they always return false.' ), '3.1.0' );
    680                 return false;
    681         }
    682 
    683         return $wp_query->is_year();
    684 }
    685 
    686 /**
    687  * Is the query a 404 (returns no results)?
    688  *
    689  * @since 1.5.0
    690  *
    691  * @global WP_Query $wp_query Global WP_Query instance.
    692  *
    693  * @return bool
    694  */
    695 function is_404() {
    696         global $wp_query;
    697 
    698         if ( ! isset( $wp_query ) ) {
    699                 _doing_it_wrong( __FUNCTION__, __( 'Conditional query tags do not work before the query is run. Before then, they always return false.' ), '3.1.0' );
    700                 return false;
    701         }
    702 
    703         return $wp_query->is_404();
    704 }
    705 
    706 /**
    707  * Is the query for an embedded post?
    708  *
    709  * @since 4.4.0
    710  *
    711  * @global WP_Query $wp_query Global WP_Query instance.
    712  *
    713  * @return bool Whether we're in an embedded post or not.
    714  */
    715 function is_embed() {
    716         global $wp_query;
    717 
    718         if ( ! isset( $wp_query ) ) {
    719                 _doing_it_wrong( __FUNCTION__, __( 'Conditional query tags do not work before the query is run. Before then, they always return false.' ), '3.1.0' );
    720                 return false;
    721         }
    722 
    723         return $wp_query->is_embed();
    724 }
    725 
    726 /**
    727  * Is the query the main query?
    728  *
    729  * @since 3.3.0
    730  *
    731  * @global WP_Query $wp_query Global WP_Query instance.
    732  *
    733  * @return bool
    734  */
    735 function is_main_query() {
    736         if ( 'pre_get_posts' === current_filter() ) {
    737                 $message = sprintf(
    738                         /* translators: 1: pre_get_posts 2: WP_Query->is_main_query() 3: is_main_query() 4: link to codex is_main_query() page. */
    739                         __( 'In %1$s, use the %2$s method, not the %3$s function. See %4$s.' ),
    740                         '<code>pre_get_posts</code>',
    741                         '<code>WP_Query->is_main_query()</code>',
    742                         '<code>is_main_query()</code>',
    743                         __( 'https://codex.wordpress.org/Function_Reference/is_main_query' )
    744                 );
    745                 _doing_it_wrong( __FUNCTION__, $message, '3.7.0' );
    746         }
    747 
    748         global $wp_query;
    749         return $wp_query->is_main_query();
    750 }
    751 
    752 /*
    753  * The Loop. Post loop control.
    754  */
    755 
    756 /**
    757  * Whether current WordPress query has results to loop over.
    758  *
    759  * @since 1.5.0
    760  *
    761  * @global WP_Query $wp_query Global WP_Query instance.
    762  *
    763  * @return bool
    764  */
    765 function have_posts() {
    766         global $wp_query;
    767         return $wp_query->have_posts();
    768 }
    769 
    770 /**
    771  * Whether the caller is in the Loop.
    772  *
    773  * @since 2.0.0
    774  *
    775  * @global WP_Query $wp_query Global WP_Query instance.
    776  *
    777  * @return bool True if caller is within loop, false if loop hasn't started or ended.
    778  */
    779 function in_the_loop() {
    780         global $wp_query;
    781         return $wp_query->in_the_loop;
    782 }
    783 
    784 /**
    785  * Rewind the loop posts.
    786  *
    787  * @since 1.5.0
    788  *
    789  * @global WP_Query $wp_query Global WP_Query instance.
    790  */
    791 function rewind_posts() {
    792         global $wp_query;
    793         $wp_query->rewind_posts();
    794 }
    795 
    796 /**
    797  * Iterate the post index in the loop.
    798  *
    799  * @since 1.5.0
    800  *
    801  * @global WP_Query $wp_query Global WP_Query instance.
    802  */
    803 function the_post() {
    804         global $wp_query;
    805         $wp_query->the_post();
    806 }
    807 
    808 /*
    809  * Comments loop.
    810  */
    811 
    812 /**
    813  * Whether there are comments to loop over.
    814  *
    815  * @since 2.2.0
    816  *
    817  * @global WP_Query $wp_query Global WP_Query instance.
    818  *
    819  * @return bool
    820  */
    821 function have_comments() {
    822         global $wp_query;
    823         return $wp_query->have_comments();
    824 }
    825 
    826 /**
    827  * Iterate comment index in the comment loop.
    828  *
    829  * @since 2.2.0
    830  *
    831  * @global WP_Query $wp_query Global WP_Query instance.
    832  *
    833  * @return object
    834  */
    835 function the_comment() {
    836         global $wp_query;
    837         return $wp_query->the_comment();
    838 }
    839 
    840 /*
    841  * WP_Query
    842  */
    843 
    844 /**
    84511 * The WordPress Query class.
    84612 *
    84713 * @link https://codex.wordpress.org/Function_Reference/WP_Query Codex page.
     
    49284094                return $check;
    49294095        }
    49304096}
    4931 
    4932 /**
    4933  * Redirect old slugs to the correct permalink.
    4934  *
    4935  * Attempts to find the current slug from the past slugs.
    4936  *
    4937  * @since 2.1.0
    4938  *
    4939  * @global WP_Query   $wp_query   Global WP_Query instance.
    4940  * @global wpdb       $wpdb       WordPress database abstraction object.
    4941  */
    4942 function wp_old_slug_redirect() {
    4943         global $wp_query;
    4944 
    4945         if ( is_404() && '' !== $wp_query->query_vars['name'] ) :
    4946                 global $wpdb;
    4947 
    4948                 // Guess the current post_type based on the query vars.
    4949                 if ( get_query_var( 'post_type' ) ) {
    4950                         $post_type = get_query_var( 'post_type' );
    4951                 } elseif ( get_query_var( 'attachment' ) ) {
    4952                         $post_type = 'attachment';
    4953                 } elseif ( ! empty( $wp_query->query_vars['pagename'] ) ) {
    4954                         $post_type = 'page';
    4955                 } else {
    4956                         $post_type = 'post';
    4957                 }
    4958 
    4959                 if ( is_array( $post_type ) ) {
    4960                         if ( count( $post_type ) > 1 )
    4961                                 return;
    4962                         $post_type = reset( $post_type );
    4963                 }
    4964 
    4965                 // Do not attempt redirect for hierarchical post types
    4966                 if ( is_post_type_hierarchical( $post_type ) )
    4967                         return;
    4968 
    4969                 $query = $wpdb->prepare("SELECT post_id FROM $wpdb->postmeta, $wpdb->posts WHERE ID = post_id AND post_type = %s AND meta_key = '_wp_old_slug' AND meta_value = %s", $post_type, $wp_query->query_vars['name']);
    4970 
    4971                 // if year, monthnum, or day have been specified, make our query more precise
    4972                 // just in case there are multiple identical _wp_old_slug values
    4973                 if ( '' != $wp_query->query_vars['year'] )
    4974                         $query .= $wpdb->prepare(" AND YEAR(post_date) = %d", $wp_query->query_vars['year']);
    4975                 if ( '' != $wp_query->query_vars['monthnum'] )
    4976                         $query .= $wpdb->prepare(" AND MONTH(post_date) = %d", $wp_query->query_vars['monthnum']);
    4977                 if ( '' != $wp_query->query_vars['day'] )
    4978                         $query .= $wpdb->prepare(" AND DAYOFMONTH(post_date) = %d", $wp_query->query_vars['day']);
    4979 
    4980                 $id = (int) $wpdb->get_var($query);
    4981 
    4982                 if ( ! $id )
    4983                         return;
    4984 
    4985                 $link = get_permalink( $id );
    4986 
    4987                 if ( isset( $GLOBALS['wp_query']->query_vars['paged'] ) && $GLOBALS['wp_query']->query_vars['paged'] > 1 ) {
    4988                         $link = user_trailingslashit( trailingslashit( $link ) . 'page/' . $GLOBALS['wp_query']->query_vars['paged'] );
    4989                 } elseif( is_embed() ) {
    4990                         $link = user_trailingslashit( trailingslashit( $link ) . 'embed' );
    4991                 }
    4992 
    4993                 /**
    4994                  * Filters the old slug redirect URL.
    4995                  *
    4996                  * @since 4.4.0
    4997                  *
    4998                  * @param string $link The redirect URL.
    4999                  */
    5000                 $link = apply_filters( 'old_slug_redirect_url', $link );
    5001 
    5002                 if ( ! $link ) {
    5003                         return;
    5004                 }
    5005 
    5006                 wp_redirect( $link, 301 ); // Permanent redirect
    5007                 exit;
    5008         endif;
    5009 }
    5010 
    5011 /**
    5012  * Set up global post data.
    5013  *
    5014  * @since 1.5.0
    5015  * @since 4.4.0 Added the ability to pass a post ID to `$post`.
    5016  *
    5017  * @global WP_Query $wp_query Global WP_Query instance.
    5018  *
    5019  * @param WP_Post|object|int $post WP_Post instance or Post ID/object.
    5020  * @return bool True when finished.
    5021  */
    5022 function setup_postdata( $post ) {
    5023         global $wp_query;
    5024 
    5025         if ( ! empty( $wp_query ) && $wp_query instanceof WP_Query ) {
    5026                 return $wp_query->setup_postdata( $post );
    5027         }
    5028 
    5029         return false;
    5030 }
  • src/wp-includes/query.php

     
    837837        return $wp_query->the_comment();
    838838}
    839839
    840 /*
    841  * WP_Query
    842  */
    843 
    844840/**
    845  * The WordPress Query class.
    846  *
    847  * @link https://codex.wordpress.org/Function_Reference/WP_Query Codex page.
    848  *
    849  * @since 1.5.0
    850  * @since 4.5.0 Removed the `$comments_popup` property.
    851  */
    852 class WP_Query {
    853 
    854         /**
    855          * Query vars set by the user
    856          *
    857          * @since 1.5.0
    858          * @access public
    859          * @var array
    860          */
    861         public $query;
    862 
    863         /**
    864          * Query vars, after parsing
    865          *
    866          * @since 1.5.0
    867          * @access public
    868          * @var array
    869          */
    870         public $query_vars = array();
    871 
    872         /**
    873          * Taxonomy query, as passed to get_tax_sql()
    874          *
    875          * @since 3.1.0
    876          * @access public
    877          * @var object WP_Tax_Query
    878          */
    879         public $tax_query;
    880 
    881         /**
    882          * Metadata query container
    883          *
    884          * @since 3.2.0
    885          * @access public
    886          * @var object WP_Meta_Query
    887          */
    888         public $meta_query = false;
    889 
    890         /**
    891          * Date query container
    892          *
    893          * @since 3.7.0
    894          * @access public
    895          * @var object WP_Date_Query
    896          */
    897         public $date_query = false;
    898 
    899         /**
    900          * Holds the data for a single object that is queried.
    901          *
    902          * Holds the contents of a post, page, category, attachment.
    903          *
    904          * @since 1.5.0
    905          * @access public
    906          * @var object|array
    907          */
    908         public $queried_object;
    909 
    910         /**
    911          * The ID of the queried object.
    912          *
    913          * @since 1.5.0
    914          * @access public
    915          * @var int
    916          */
    917         public $queried_object_id;
    918 
    919         /**
    920          * Get post database query.
    921          *
    922          * @since 2.0.1
    923          * @access public
    924          * @var string
    925          */
    926         public $request;
    927 
    928         /**
    929          * List of posts.
    930          *
    931          * @since 1.5.0
    932          * @access public
    933          * @var array
    934          */
    935         public $posts;
    936 
    937         /**
    938          * The amount of posts for the current query.
    939          *
    940          * @since 1.5.0
    941          * @access public
    942          * @var int
    943          */
    944         public $post_count = 0;
    945 
    946         /**
    947          * Index of the current item in the loop.
    948          *
    949          * @since 1.5.0
    950          * @access public
    951          * @var int
    952          */
    953         public $current_post = -1;
    954 
    955         /**
    956          * Whether the loop has started and the caller is in the loop.
    957          *
    958          * @since 2.0.0
    959          * @access public
    960          * @var bool
    961          */
    962         public $in_the_loop = false;
    963 
    964         /**
    965          * The current post.
    966          *
    967          * @since 1.5.0
    968          * @access public
    969          * @var WP_Post
    970          */
    971         public $post;
    972 
    973         /**
    974          * The list of comments for current post.
    975          *
    976          * @since 2.2.0
    977          * @access public
    978          * @var array
    979          */
    980         public $comments;
    981 
    982         /**
    983          * The amount of comments for the posts.
    984          *
    985          * @since 2.2.0
    986          * @access public
    987          * @var int
    988          */
    989         public $comment_count = 0;
    990 
    991         /**
    992          * The index of the comment in the comment loop.
    993          *
    994          * @since 2.2.0
    995          * @access public
    996          * @var int
    997          */
    998         public $current_comment = -1;
    999 
    1000         /**
    1001          * Current comment ID.
    1002          *
    1003          * @since 2.2.0
    1004          * @access public
    1005          * @var int
    1006          */
    1007         public $comment;
    1008 
    1009         /**
    1010          * The amount of found posts for the current query.
    1011          *
    1012          * If limit clause was not used, equals $post_count.
    1013          *
    1014          * @since 2.1.0
    1015          * @access public
    1016          * @var int
    1017          */
    1018         public $found_posts = 0;
    1019 
    1020         /**
    1021          * The amount of pages.
    1022          *
    1023          * @since 2.1.0
    1024          * @access public
    1025          * @var int
    1026          */
    1027         public $max_num_pages = 0;
    1028 
    1029         /**
    1030          * The amount of comment pages.
    1031          *
    1032          * @since 2.7.0
    1033          * @access public
    1034          * @var int
    1035          */
    1036         public $max_num_comment_pages = 0;
    1037 
    1038         /**
    1039          * Set if query is single post.
    1040          *
    1041          * @since 1.5.0
    1042          * @access public
    1043          * @var bool
    1044          */
    1045         public $is_single = false;
    1046 
    1047         /**
    1048          * Set if query is preview of blog.
    1049          *
    1050          * @since 2.0.0
    1051          * @access public
    1052          * @var bool
    1053          */
    1054         public $is_preview = false;
    1055 
    1056         /**
    1057          * Set if query returns a page.
    1058          *
    1059          * @since 1.5.0
    1060          * @access public
    1061          * @var bool
    1062          */
    1063         public $is_page = false;
    1064 
    1065         /**
    1066          * Set if query is an archive list.
    1067          *
    1068          * @since 1.5.0
    1069          * @access public
    1070          * @var bool
    1071          */
    1072         public $is_archive = false;
    1073 
    1074         /**
    1075          * Set if query is part of a date.
    1076          *
    1077          * @since 1.5.0
    1078          * @access public
    1079          * @var bool
    1080          */
    1081         public $is_date = false;
    1082 
    1083         /**
    1084          * Set if query contains a year.
    1085          *
    1086          * @since 1.5.0
    1087          * @access public
    1088          * @var bool
    1089          */
    1090         public $is_year = false;
    1091 
    1092         /**
    1093          * Set if query contains a month.
    1094          *
    1095          * @since 1.5.0
    1096          * @access public
    1097          * @var bool
    1098          */
    1099         public $is_month = false;
    1100 
    1101         /**
    1102          * Set if query contains a day.
    1103          *
    1104          * @since 1.5.0
    1105          * @access public
    1106          * @var bool
    1107          */
    1108         public $is_day = false;
    1109 
    1110         /**
    1111          * Set if query contains time.
    1112          *
    1113          * @since 1.5.0
    1114          * @access public
    1115          * @var bool
    1116          */
    1117         public $is_time = false;
    1118 
    1119         /**
    1120          * Set if query contains an author.
    1121          *
    1122          * @since 1.5.0
    1123          * @access public
    1124          * @var bool
    1125          */
    1126         public $is_author = false;
    1127 
    1128         /**
    1129          * Set if query contains category.
    1130          *
    1131          * @since 1.5.0
    1132          * @access public
    1133          * @var bool
    1134          */
    1135         public $is_category = false;
    1136 
    1137         /**
    1138          * Set if query contains tag.
    1139          *
    1140          * @since 2.3.0
    1141          * @access public
    1142          * @var bool
    1143          */
    1144         public $is_tag = false;
    1145 
    1146         /**
    1147          * Set if query contains taxonomy.
    1148          *
    1149          * @since 2.5.0
    1150          * @access public
    1151          * @var bool
    1152          */
    1153         public $is_tax = false;
    1154 
    1155         /**
    1156          * Set if query was part of a search result.
    1157          *
    1158          * @since 1.5.0
    1159          * @access public
    1160          * @var bool
    1161          */
    1162         public $is_search = false;
    1163 
    1164         /**
    1165          * Set if query is feed display.
    1166          *
    1167          * @since 1.5.0
    1168          * @access public
    1169          * @var bool
    1170          */
    1171         public $is_feed = false;
    1172 
    1173         /**
    1174          * Set if query is comment feed display.
    1175          *
    1176          * @since 2.2.0
    1177          * @access public
    1178          * @var bool
    1179          */
    1180         public $is_comment_feed = false;
    1181 
    1182         /**
    1183          * Set if query is trackback.
    1184          *
    1185          * @since 1.5.0
    1186          * @access public
    1187          * @var bool
    1188          */
    1189         public $is_trackback = false;
    1190 
    1191         /**
    1192          * Set if query is blog homepage.
    1193          *
    1194          * @since 1.5.0
    1195          * @access public
    1196          * @var bool
    1197          */
    1198         public $is_home = false;
    1199 
    1200         /**
    1201          * Set if query couldn't found anything.
    1202          *
    1203          * @since 1.5.0
    1204          * @access public
    1205          * @var bool
    1206          */
    1207         public $is_404 = false;
    1208 
    1209         /**
    1210          * Set if query is embed.
    1211          *
    1212          * @since 4.4.0
    1213          * @access public
    1214          * @var bool
    1215          */
    1216         public $is_embed = false;
    1217 
    1218         /**
    1219          * Set if query is paged
    1220          *
    1221          * @since 1.5.0
    1222          * @access public
    1223          * @var bool
    1224          */
    1225         public $is_paged = false;
    1226 
    1227         /**
    1228          * Set if query is part of administration page.
    1229          *
    1230          * @since 1.5.0
    1231          * @access public
    1232          * @var bool
    1233          */
    1234         public $is_admin = false;
    1235 
    1236         /**
    1237          * Set if query is an attachment.
    1238          *
    1239          * @since 2.0.0
    1240          * @access public
    1241          * @var bool
    1242          */
    1243         public $is_attachment = false;
    1244 
    1245         /**
    1246          * Set if is single, is a page, or is an attachment.
    1247          *
    1248          * @since 2.1.0
    1249          * @access public
    1250          * @var bool
    1251          */
    1252         public $is_singular = false;
    1253 
    1254         /**
    1255          * Set if query is for robots.
    1256          *
    1257          * @since 2.1.0
    1258          * @access public
    1259          * @var bool
    1260          */
    1261         public $is_robots = false;
    1262 
    1263         /**
    1264          * Set if query contains posts.
    1265          *
    1266          * Basically, the homepage if the option isn't set for the static homepage.
    1267          *
    1268          * @since 2.1.0
    1269          * @access public
    1270          * @var bool
    1271          */
    1272         public $is_posts_page = false;
    1273 
    1274         /**
    1275          * Set if query is for a post type archive.
    1276          *
    1277          * @since 3.1.0
    1278          * @access public
    1279          * @var bool
    1280          */
    1281         public $is_post_type_archive = false;
    1282 
    1283         /**
    1284          * Stores the ->query_vars state like md5(serialize( $this->query_vars ) ) so we know
    1285          * whether we have to re-parse because something has changed
    1286          *
    1287          * @since 3.1.0
    1288          * @access private
    1289          * @var bool|string
    1290          */
    1291         private $query_vars_hash = false;
    1292 
    1293         /**
    1294          * Whether query vars have changed since the initial parse_query() call. Used to catch modifications to query vars made
    1295          * via pre_get_posts hooks.
    1296          *
    1297          * @since 3.1.1
    1298          * @access private
    1299          */
    1300         private $query_vars_changed = true;
    1301 
    1302         /**
    1303          * Set if post thumbnails are cached
    1304          *
    1305          * @since 3.2.0
    1306          * @access public
    1307          * @var bool
    1308          */
    1309          public $thumbnails_cached = false;
    1310 
    1311         /**
    1312          * Cached list of search stopwords.
    1313          *
    1314          * @since 3.7.0
    1315          * @var array
    1316          */
    1317         private $stopwords;
    1318 
    1319         private $compat_fields = array( 'query_vars_hash', 'query_vars_changed' );
    1320 
    1321         private $compat_methods = array( 'init_query_flags', 'parse_tax_query' );
    1322 
    1323         /**
    1324          * @since 4.7.0
    1325          * @access protected
    1326          * @var wpdb
    1327          */
    1328         protected $db;
    1329 
    1330         /**
    1331          * Resets query flags to false.
    1332          *
    1333          * The query flags are what page info WordPress was able to figure out.
    1334          *
    1335          * @since 2.0.0
    1336          * @access private
    1337          */
    1338         private function init_query_flags() {
    1339                 $this->is_single = false;
    1340                 $this->is_preview = false;
    1341                 $this->is_page = false;
    1342                 $this->is_archive = false;
    1343                 $this->is_date = false;
    1344                 $this->is_year = false;
    1345                 $this->is_month = false;
    1346                 $this->is_day = false;
    1347                 $this->is_time = false;
    1348                 $this->is_author = false;
    1349                 $this->is_category = false;
    1350                 $this->is_tag = false;
    1351                 $this->is_tax = false;
    1352                 $this->is_search = false;
    1353                 $this->is_feed = false;
    1354                 $this->is_comment_feed = false;
    1355                 $this->is_trackback = false;
    1356                 $this->is_home = false;
    1357                 $this->is_404 = false;
    1358                 $this->is_paged = false;
    1359                 $this->is_admin = false;
    1360                 $this->is_attachment = false;
    1361                 $this->is_singular = false;
    1362                 $this->is_robots = false;
    1363                 $this->is_posts_page = false;
    1364                 $this->is_post_type_archive = false;
    1365         }
    1366 
    1367         /**
    1368          * Initiates object properties and sets default values.
    1369          *
    1370          * @since 1.5.0
    1371          * @access public
    1372          */
    1373         public function init() {
    1374                 unset($this->posts);
    1375                 unset($this->query);
    1376                 $this->query_vars = array();
    1377                 unset($this->queried_object);
    1378                 unset($this->queried_object_id);
    1379                 $this->post_count = 0;
    1380                 $this->current_post = -1;
    1381                 $this->in_the_loop = false;
    1382                 unset( $this->request );
    1383                 unset( $this->post );
    1384                 unset( $this->comments );
    1385                 unset( $this->comment );
    1386                 $this->comment_count = 0;
    1387                 $this->current_comment = -1;
    1388                 $this->found_posts = 0;
    1389                 $this->max_num_pages = 0;
    1390                 $this->max_num_comment_pages = 0;
    1391 
    1392                 $this->init_query_flags();
    1393         }
    1394 
    1395         /**
    1396          * Reparse the query vars.
    1397          *
    1398          * @since 1.5.0
    1399          * @access public
    1400          */
    1401         public function parse_query_vars() {
    1402                 $this->parse_query();
    1403         }
    1404 
    1405         /**
    1406          * Fills in the query variables, which do not exist within the parameter.
    1407          *
    1408          * @since 2.1.0
    1409          * @since 4.4.0 Removed the `comments_popup` public query variable.
    1410          * @access public
    1411          *
    1412          * @param array $array Defined query variables.
    1413          * @return array Complete query variables with undefined ones filled in empty.
    1414          */
    1415         public function fill_query_vars($array) {
    1416                 $keys = array(
    1417                         'error'
    1418                         , 'm'
    1419                         , 'p'
    1420                         , 'post_parent'
    1421                         , 'subpost'
    1422                         , 'subpost_id'
    1423                         , 'attachment'
    1424                         , 'attachment_id'
    1425                         , 'name'
    1426                         , 'static'
    1427                         , 'pagename'
    1428                         , 'page_id'
    1429                         , 'second'
    1430                         , 'minute'
    1431                         , 'hour'
    1432                         , 'day'
    1433                         , 'monthnum'
    1434                         , 'year'
    1435                         , 'w'
    1436                         , 'category_name'
    1437                         , 'tag'
    1438                         , 'cat'
    1439                         , 'tag_id'
    1440                         , 'author'
    1441                         , 'author_name'
    1442                         , 'feed'
    1443                         , 'tb'
    1444                         , 'paged'
    1445                         , 'meta_key'
    1446                         , 'meta_value'
    1447                         , 'preview'
    1448                         , 's'
    1449                         , 'sentence'
    1450                         , 'title'
    1451                         , 'fields'
    1452                         , 'menu_order'
    1453                         , 'embed'
    1454                 );
    1455 
    1456                 foreach ( $keys as $key ) {
    1457                         if ( !isset($array[$key]) )
    1458                                 $array[$key] = '';
    1459                 }
    1460 
    1461                 $array_keys = array( 'category__in', 'category__not_in', 'category__and', 'post__in', 'post__not_in', 'post_name__in',
    1462                         'tag__in', 'tag__not_in', 'tag__and', 'tag_slug__in', 'tag_slug__and', 'post_parent__in', 'post_parent__not_in',
    1463                         'author__in', 'author__not_in' );
    1464 
    1465                 foreach ( $array_keys as $key ) {
    1466                         if ( !isset($array[$key]) )
    1467                                 $array[$key] = array();
    1468                 }
    1469                 return $array;
    1470         }
    1471 
    1472         /**
    1473          * Parse a query string and set query type booleans.
    1474          *
    1475          * @since 1.5.0
    1476          * @since 4.2.0 Introduced the ability to order by specific clauses of a `$meta_query`, by passing the clause's
    1477          *              array key to `$orderby`.
    1478          * @since 4.4.0 Introduced `$post_name__in` and `$title` parameters. `$s` was updated to support excluded
    1479          *              search terms, by prepending a hyphen.
    1480          * @since 4.5.0 Removed the `$comments_popup` parameter.
    1481          *              Introduced the `$comment_status` and `$ping_status` parameters.
    1482          *              Introduced `RAND(x)` syntax for `$orderby`, which allows an integer seed value to random sorts.
    1483          * @since 4.6.0 Added 'post_name__in' support for `$orderby`. Introduced the `$lazy_load_term_meta` argument.
    1484          * @access public
    1485          *
    1486          * @param string|array $query {
    1487          *     Optional. Array or string of Query parameters.
    1488          *
    1489          *     @type int          $attachment_id           Attachment post ID. Used for 'attachment' post_type.
    1490          *     @type int|string   $author                  Author ID, or comma-separated list of IDs.
    1491          *     @type string       $author_name             User 'user_nicename'.
    1492          *     @type array        $author__in              An array of author IDs to query from.
    1493          *     @type array        $author__not_in          An array of author IDs not to query from.
    1494          *     @type bool         $cache_results           Whether to cache post information. Default true.
    1495          *     @type int|string   $cat                     Category ID or comma-separated list of IDs (this or any children).
    1496          *     @type array        $category__and           An array of category IDs (AND in).
    1497          *     @type array        $category__in            An array of category IDs (OR in, no children).
    1498          *     @type array        $category__not_in        An array of category IDs (NOT in).
    1499          *     @type string       $category_name           Use category slug (not name, this or any children).
    1500          *     @type string       $comment_status          Comment status.
    1501          *     @type int          $comments_per_page       The number of comments to return per page.
    1502          *                                                 Default 'comments_per_page' option.
    1503          *     @type array        $date_query              An associative array of WP_Date_Query arguments.
    1504          *                                                 See WP_Date_Query::__construct().
    1505          *     @type int          $day                     Day of the month. Default empty. Accepts numbers 1-31.
    1506          *     @type bool         $exact                   Whether to search by exact keyword. Default false.
    1507          *     @type string|array $fields                  Which fields to return. Single field or all fields (string),
    1508          *                                                 or array of fields. 'id=>parent' uses 'id' and 'post_parent'.
    1509          *                                                 Default all fields. Accepts 'ids', 'id=>parent'.
    1510          *     @type int          $hour                    Hour of the day. Default empty. Accepts numbers 0-23.
    1511          *     @type int|bool     $ignore_sticky_posts     Whether to ignore sticky posts or not. Setting this to false
    1512          *                                                 excludes stickies from 'post__in'. Accepts 1|true, 0|false.
    1513          *                                                 Default 0|false.
    1514          *     @type int          $m                       Combination YearMonth. Accepts any four-digit year and month
    1515          *                                                 numbers 1-12. Default empty.
    1516          *     @type string       $meta_compare            Comparison operator to test the 'meta_value'.
    1517          *     @type string       $meta_key                Custom field key.
    1518          *     @type array        $meta_query              An associative array of WP_Meta_Query arguments. See WP_Meta_Query.
    1519          *     @type string       $meta_value              Custom field value.
    1520          *     @type int          $meta_value_num          Custom field value number.
    1521          *     @type int          $menu_order              The menu order of the posts.
    1522          *     @type int          $monthnum                The two-digit month. Default empty. Accepts numbers 1-12.
    1523          *     @type string       $name                    Post slug.
    1524          *     @type bool         $nopaging                Show all posts (true) or paginate (false). Default false.
    1525          *     @type bool         $no_found_rows           Whether to skip counting the total rows found. Enabling can improve
    1526          *                                                 performance. Default false.
    1527          *     @type int          $offset                  The number of posts to offset before retrieval.
    1528          *     @type string       $order                   Designates ascending or descending order of posts. Default 'DESC'.
    1529          *                                                 Accepts 'ASC', 'DESC'.
    1530          *     @type string|array $orderby                 Sort retrieved posts by parameter. One or more options may be
    1531          *                                                 passed. To use 'meta_value', or 'meta_value_num',
    1532          *                                                 'meta_key=keyname' must be also be defined. To sort by a
    1533          *                                                 specific `$meta_query` clause, use that clause's array key.
    1534          *                                                 Default 'date'. Accepts 'none', 'name', 'author', 'date',
    1535          *                                                 'title', 'modified', 'menu_order', 'parent', 'ID', 'rand',
    1536          *                                                 'RAND(x)' (where 'x' is an integer seed value),
    1537          *                                                 'comment_count', 'meta_value', 'meta_value_num', 'post__in',
    1538          *                                                 'post_name__in', 'post_parent__in', and the array keys
    1539          *                                                 of `$meta_query`.
    1540          *     @type int          $p                       Post ID.
    1541          *     @type int          $page                    Show the number of posts that would show up on page X of a
    1542          *                                                 static front page.
    1543          *     @type int          $paged                   The number of the current page.
    1544          *     @type int          $page_id                 Page ID.
    1545          *     @type string       $pagename                Page slug.
    1546          *     @type string       $perm                    Show posts if user has the appropriate capability.
    1547          *     @type string       $ping_status             Ping status.
    1548          *     @type array        $post__in                An array of post IDs to retrieve, sticky posts will be included
    1549          *     @type string       $post_mime_type          The mime type of the post. Used for 'attachment' post_type.
    1550          *     @type array        $post__not_in            An array of post IDs not to retrieve. Note: a string of comma-
    1551          *                                                 separated IDs will NOT work.
    1552          *     @type int          $post_parent             Page ID to retrieve child pages for. Use 0 to only retrieve
    1553          *                                                 top-level pages.
    1554          *     @type array        $post_parent__in         An array containing parent page IDs to query child pages from.
    1555          *     @type array        $post_parent__not_in     An array containing parent page IDs not to query child pages from.
    1556          *     @type string|array $post_type               A post type slug (string) or array of post type slugs.
    1557          *                                                 Default 'any' if using 'tax_query'.
    1558          *     @type string|array $post_status             A post status (string) or array of post statuses.
    1559          *     @type int          $posts_per_page          The number of posts to query for. Use -1 to request all posts.
    1560          *     @type int          $posts_per_archive_page  The number of posts to query for by archive page. Overrides
    1561          *                                                 'posts_per_page' when is_archive(), or is_search() are true.
    1562          *     @type array        $post_name__in           An array of post slugs that results must match.
    1563          *     @type string       $s                       Search keyword(s). Prepending a term with a hyphen will
    1564          *                                                 exclude posts matching that term. Eg, 'pillow -sofa' will
    1565          *                                                 return posts containing 'pillow' but not 'sofa'.
    1566          *     @type int          $second                  Second of the minute. Default empty. Accepts numbers 0-60.
    1567          *     @type bool         $sentence                Whether to search by phrase. Default false.
    1568          *     @type bool         $suppress_filters        Whether to suppress filters. Default false.
    1569          *     @type string       $tag                     Tag slug. Comma-separated (either), Plus-separated (all).
    1570          *     @type array        $tag__and                An array of tag ids (AND in).
    1571          *     @type array        $tag__in                 An array of tag ids (OR in).
    1572          *     @type array        $tag__not_in             An array of tag ids (NOT in).
    1573          *     @type int          $tag_id                  Tag id or comma-separated list of IDs.
    1574          *     @type array        $tag_slug__and           An array of tag slugs (AND in).
    1575          *     @type array        $tag_slug__in            An array of tag slugs (OR in). unless 'ignore_sticky_posts' is
    1576          *                                                 true. Note: a string of comma-separated IDs will NOT work.
    1577          *     @type array        $tax_query               An associative array of WP_Tax_Query arguments.
    1578          *                                                 See WP_Tax_Query->queries.
    1579          *     @type string       $title                   Post title.
    1580          *     @type bool         $update_post_meta_cache  Whether to update the post meta cache. Default true.
    1581          *     @type bool         $update_post_term_cache  Whether to update the post term cache. Default true.
    1582          *     @type bool         $lazy_load_term_meta     Whether to lazy-load term meta. Setting to false will
    1583          *                                                 disable cache priming for term meta, so that each
    1584          *                                                 get_term_meta() call will hit the database.
    1585          *                                                 Defaults to the value of `$update_post_term_cache`.
    1586          *     @type int          $w                       The week number of the year. Default empty. Accepts numbers 0-53.
    1587          *     @type int          $year                    The four-digit year. Default empty. Accepts any four-digit year.
    1588          * }
    1589          */
    1590         public function parse_query( $query =  '' ) {
    1591                 if ( ! empty( $query ) ) {
    1592                         $this->init();
    1593                         $this->query = $this->query_vars = wp_parse_args( $query );
    1594                 } elseif ( ! isset( $this->query ) ) {
    1595                         $this->query = $this->query_vars;
    1596                 }
    1597 
    1598                 $this->query_vars = $this->fill_query_vars($this->query_vars);
    1599                 $qv = &$this->query_vars;
    1600                 $this->query_vars_changed = true;
    1601 
    1602                 if ( ! empty($qv['robots']) )
    1603                         $this->is_robots = true;
    1604 
    1605                 if ( ! is_scalar( $qv['p'] ) || $qv['p'] < 0 ) {
    1606                         $qv['p'] = 0;
    1607                         $qv['error'] = '404';
    1608                 } else {
    1609                         $qv['p'] = intval( $qv['p'] );
    1610                 }
    1611 
    1612                 $qv['page_id'] =  absint($qv['page_id']);
    1613                 $qv['year'] = absint($qv['year']);
    1614                 $qv['monthnum'] = absint($qv['monthnum']);
    1615                 $qv['day'] = absint($qv['day']);
    1616                 $qv['w'] = absint($qv['w']);
    1617                 $qv['m'] = is_scalar( $qv['m'] ) ? preg_replace( '|[^0-9]|', '', $qv['m'] ) : '';
    1618                 $qv['paged'] = absint($qv['paged']);
    1619                 $qv['cat'] = preg_replace( '|[^0-9,-]|', '', $qv['cat'] ); // comma separated list of positive or negative integers
    1620                 $qv['author'] = preg_replace( '|[^0-9,-]|', '', $qv['author'] ); // comma separated list of positive or negative integers
    1621                 $qv['pagename'] = trim( $qv['pagename'] );
    1622                 $qv['name'] = trim( $qv['name'] );
    1623                 $qv['title'] = trim( $qv['title'] );
    1624                 if ( '' !== $qv['hour'] ) $qv['hour'] = absint($qv['hour']);
    1625                 if ( '' !== $qv['minute'] ) $qv['minute'] = absint($qv['minute']);
    1626                 if ( '' !== $qv['second'] ) $qv['second'] = absint($qv['second']);
    1627                 if ( '' !== $qv['menu_order'] ) $qv['menu_order'] = absint($qv['menu_order']);
    1628 
    1629                 // Fairly insane upper bound for search string lengths.
    1630                 if ( ! is_scalar( $qv['s'] ) || ( ! empty( $qv['s'] ) && strlen( $qv['s'] ) > 1600 ) ) {
    1631                         $qv['s'] = '';
    1632                 }
    1633 
    1634                 // Compat. Map subpost to attachment.
    1635                 if ( '' != $qv['subpost'] )
    1636                         $qv['attachment'] = $qv['subpost'];
    1637                 if ( '' != $qv['subpost_id'] )
    1638                         $qv['attachment_id'] = $qv['subpost_id'];
    1639 
    1640                 $qv['attachment_id'] = absint($qv['attachment_id']);
    1641 
    1642                 if ( ('' != $qv['attachment']) || !empty($qv['attachment_id']) ) {
    1643                         $this->is_single = true;
    1644                         $this->is_attachment = true;
    1645                 } elseif ( '' != $qv['name'] ) {
    1646                         $this->is_single = true;
    1647                 } elseif ( $qv['p'] ) {
    1648                         $this->is_single = true;
    1649                 } elseif ( ('' !== $qv['hour']) && ('' !== $qv['minute']) &&('' !== $qv['second']) && ('' != $qv['year']) && ('' != $qv['monthnum']) && ('' != $qv['day']) ) {
    1650                         // If year, month, day, hour, minute, and second are set, a single
    1651                         // post is being queried.
    1652                         $this->is_single = true;
    1653                 } elseif ( '' != $qv['static'] || '' != $qv['pagename'] || !empty($qv['page_id']) ) {
    1654                         $this->is_page = true;
    1655                         $this->is_single = false;
    1656                 } else {
    1657                         // Look for archive queries. Dates, categories, authors, search, post type archives.
    1658 
    1659                         if ( isset( $this->query['s'] ) ) {
    1660                                 $this->is_search = true;
    1661                         }
    1662 
    1663                         if ( '' !== $qv['second'] ) {
    1664                                 $this->is_time = true;
    1665                                 $this->is_date = true;
    1666                         }
    1667 
    1668                         if ( '' !== $qv['minute'] ) {
    1669                                 $this->is_time = true;
    1670                                 $this->is_date = true;
    1671                         }
    1672 
    1673                         if ( '' !== $qv['hour'] ) {
    1674                                 $this->is_time = true;
    1675                                 $this->is_date = true;
    1676                         }
    1677 
    1678                         if ( $qv['day'] ) {
    1679                                 if ( ! $this->is_date ) {
    1680                                         $date = sprintf( '%04d-%02d-%02d', $qv['year'], $qv['monthnum'], $qv['day'] );
    1681                                         if ( $qv['monthnum'] && $qv['year'] && ! wp_checkdate( $qv['monthnum'], $qv['day'], $qv['year'], $date ) ) {
    1682                                                 $qv['error'] = '404';
    1683                                         } else {
    1684                                                 $this->is_day = true;
    1685                                                 $this->is_date = true;
    1686                                         }
    1687                                 }
    1688                         }
    1689 
    1690                         if ( $qv['monthnum'] ) {
    1691                                 if ( ! $this->is_date ) {
    1692                                         if ( 12 < $qv['monthnum'] ) {
    1693                                                 $qv['error'] = '404';
    1694                                         } else {
    1695                                                 $this->is_month = true;
    1696                                                 $this->is_date = true;
    1697                                         }
    1698                                 }
    1699                         }
    1700 
    1701                         if ( $qv['year'] ) {
    1702                                 if ( ! $this->is_date ) {
    1703                                         $this->is_year = true;
    1704                                         $this->is_date = true;
    1705                                 }
    1706                         }
    1707 
    1708                         if ( $qv['m'] ) {
    1709                                 $this->is_date = true;
    1710                                 if ( strlen($qv['m']) > 9 ) {
    1711                                         $this->is_time = true;
    1712                                 } elseif ( strlen( $qv['m'] ) > 7 ) {
    1713                                         $this->is_day = true;
    1714                                 } elseif ( strlen( $qv['m'] ) > 5 ) {
    1715                                         $this->is_month = true;
    1716                                 } else {
    1717                                         $this->is_year = true;
    1718                                 }
    1719                         }
    1720 
    1721                         if ( '' != $qv['w'] ) {
    1722                                 $this->is_date = true;
    1723                         }
    1724 
    1725                         $this->query_vars_hash = false;
    1726                         $this->parse_tax_query( $qv );
    1727 
    1728                         foreach ( $this->tax_query->queries as $tax_query ) {
    1729                                 if ( ! is_array( $tax_query ) ) {
    1730                                         continue;
    1731                                 }
    1732 
    1733                                 if ( isset( $tax_query['operator'] ) && 'NOT IN' != $tax_query['operator'] ) {
    1734                                         switch ( $tax_query['taxonomy'] ) {
    1735                                                 case 'category':
    1736                                                         $this->is_category = true;
    1737                                                         break;
    1738                                                 case 'post_tag':
    1739                                                         $this->is_tag = true;
    1740                                                         break;
    1741                                                 default:
    1742                                                         $this->is_tax = true;
    1743                                         }
    1744                                 }
    1745                         }
    1746                         unset( $tax_query );
    1747 
    1748                         if ( empty($qv['author']) || ($qv['author'] == '0') ) {
    1749                                 $this->is_author = false;
    1750                         } else {
    1751                                 $this->is_author = true;
    1752                         }
    1753 
    1754                         if ( '' != $qv['author_name'] )
    1755                                 $this->is_author = true;
    1756 
    1757                         if ( !empty( $qv['post_type'] ) && ! is_array( $qv['post_type'] ) ) {
    1758                                 $post_type_obj = get_post_type_object( $qv['post_type'] );
    1759                                 if ( ! empty( $post_type_obj->has_archive ) )
    1760                                         $this->is_post_type_archive = true;
    1761                         }
    1762 
    1763                         if ( $this->is_post_type_archive || $this->is_date || $this->is_author || $this->is_category || $this->is_tag || $this->is_tax )
    1764                                 $this->is_archive = true;
    1765                 }
    1766 
    1767                 if ( '' != $qv['feed'] )
    1768                         $this->is_feed = true;
    1769 
    1770                 if ( '' != $qv['embed'] ) {
    1771                         $this->is_embed = true;
    1772                 }
    1773 
    1774                 if ( '' != $qv['tb'] )
    1775                         $this->is_trackback = true;
    1776 
    1777                 if ( '' != $qv['paged'] && ( intval($qv['paged']) > 1 ) )
    1778                         $this->is_paged = true;
    1779 
    1780                 // if we're previewing inside the write screen
    1781                 if ( '' != $qv['preview'] )
    1782                         $this->is_preview = true;
    1783 
    1784                 if ( is_admin() )
    1785                         $this->is_admin = true;
    1786 
    1787                 if ( false !== strpos($qv['feed'], 'comments-') ) {
    1788                         $qv['feed'] = str_replace('comments-', '', $qv['feed']);
    1789                         $qv['withcomments'] = 1;
    1790                 }
    1791 
    1792                 $this->is_singular = $this->is_single || $this->is_page || $this->is_attachment;
    1793 
    1794                 if ( $this->is_feed && ( !empty($qv['withcomments']) || ( empty($qv['withoutcomments']) && $this->is_singular ) ) )
    1795                         $this->is_comment_feed = true;
    1796 
    1797                 if ( !( $this->is_singular || $this->is_archive || $this->is_search || $this->is_feed || ( defined( 'REST_REQUEST' ) && REST_REQUEST ) || $this->is_trackback || $this->is_404 || $this->is_admin || $this->is_robots ) )
    1798                         $this->is_home = true;
    1799 
    1800                 // Correct is_* for page_on_front and page_for_posts
    1801                 if ( $this->is_home && 'page' == get_option('show_on_front') && get_option('page_on_front') ) {
    1802                         $_query = wp_parse_args($this->query);
    1803                         // pagename can be set and empty depending on matched rewrite rules. Ignore an empty pagename.
    1804                         if ( isset($_query['pagename']) && '' == $_query['pagename'] )
    1805                                 unset($_query['pagename']);
    1806 
    1807                         unset( $_query['embed'] );
    1808 
    1809                         if ( empty($_query) || !array_diff( array_keys($_query), array('preview', 'page', 'paged', 'cpage') ) ) {
    1810                                 $this->is_page = true;
    1811                                 $this->is_home = false;
    1812                                 $qv['page_id'] = get_option('page_on_front');
    1813                                 // Correct <!--nextpage--> for page_on_front
    1814                                 if ( !empty($qv['paged']) ) {
    1815                                         $qv['page'] = $qv['paged'];
    1816                                         unset($qv['paged']);
    1817                                 }
    1818                         }
    1819                 }
    1820 
    1821                 if ( '' != $qv['pagename'] ) {
    1822                         $this->queried_object = get_page_by_path( $qv['pagename'] );
    1823 
    1824                         if ( $this->queried_object && 'attachment' == $this->queried_object->post_type ) {
    1825                                 if ( preg_match( "/^[^%]*%(?:postname)%/", get_option( 'permalink_structure' ) ) ) {
    1826                                         // See if we also have a post with the same slug
    1827                                         $post = get_page_by_path( $qv['pagename'], OBJECT, 'post' );
    1828                                         if ( $post ) {
    1829                                                 $this->queried_object = $post;
    1830                                                 $this->is_page = false;
    1831                                                 $this->is_single = true;
    1832                                         }
    1833                                 }
    1834                         }
    1835 
    1836                         if ( ! empty( $this->queried_object ) ) {
    1837                                 $this->queried_object_id = (int) $this->queried_object->ID;
    1838                         } else {
    1839                                 unset( $this->queried_object );
    1840                         }
    1841 
    1842                         if  ( 'page' == get_option('show_on_front') && isset($this->queried_object_id) && $this->queried_object_id == get_option('page_for_posts') ) {
    1843                                 $this->is_page = false;
    1844                                 $this->is_home = true;
    1845                                 $this->is_posts_page = true;
    1846                         }
    1847                 }
    1848 
    1849                 if ( $qv['page_id'] ) {
    1850                         if  ( 'page' == get_option('show_on_front') && $qv['page_id'] == get_option('page_for_posts') ) {
    1851                                 $this->is_page = false;
    1852                                 $this->is_home = true;
    1853                                 $this->is_posts_page = true;
    1854                         }
    1855                 }
    1856 
    1857                 if ( !empty($qv['post_type']) ) {
    1858                         if ( is_array($qv['post_type']) )
    1859                                 $qv['post_type'] = array_map('sanitize_key', $qv['post_type']);
    1860                         else
    1861                                 $qv['post_type'] = sanitize_key($qv['post_type']);
    1862                 }
    1863 
    1864                 if ( ! empty( $qv['post_status'] ) ) {
    1865                         if ( is_array( $qv['post_status'] ) )
    1866                                 $qv['post_status'] = array_map('sanitize_key', $qv['post_status']);
    1867                         else
    1868                                 $qv['post_status'] = preg_replace('|[^a-z0-9_,-]|', '', $qv['post_status']);
    1869                 }
    1870 
    1871                 if ( $this->is_posts_page && ( ! isset($qv['withcomments']) || ! $qv['withcomments'] ) )
    1872                         $this->is_comment_feed = false;
    1873 
    1874                 $this->is_singular = $this->is_single || $this->is_page || $this->is_attachment;
    1875                 // Done correcting is_* for page_on_front and page_for_posts
    1876 
    1877                 if ( '404' == $qv['error'] )
    1878                         $this->set_404();
    1879 
    1880                 $this->is_embed = $this->is_embed && ( $this->is_singular || $this->is_404 );
    1881 
    1882                 $this->query_vars_hash = md5( serialize( $this->query_vars ) );
    1883                 $this->query_vars_changed = false;
    1884 
    1885                 /**
    1886                  * Fires after the main query vars have been parsed.
    1887                  *
    1888                  * @since 1.5.0
    1889                  *
    1890                  * @param WP_Query &$this The WP_Query instance (passed by reference).
    1891                  */
    1892                 do_action_ref_array( 'parse_query', array( &$this ) );
    1893         }
    1894 
    1895         /**
    1896          * Parses various taxonomy related query vars.
    1897          *
    1898          * For BC, this method is not marked as protected. See [28987].
    1899          *
    1900          * @access protected
    1901          * @since 3.1.0
    1902          *
    1903          * @param array $q The query variables. Passed by reference.
    1904          */
    1905         public function parse_tax_query( &$q ) {
    1906                 if ( ! empty( $q['tax_query'] ) && is_array( $q['tax_query'] ) ) {
    1907                         $tax_query = $q['tax_query'];
    1908                 } else {
    1909                         $tax_query = array();
    1910                 }
    1911 
    1912                 if ( !empty($q['taxonomy']) && !empty($q['term']) ) {
    1913                         $tax_query[] = array(
    1914                                 'taxonomy' => $q['taxonomy'],
    1915                                 'terms' => array( $q['term'] ),
    1916                                 'field' => 'slug',
    1917                         );
    1918                 }
    1919 
    1920                 foreach ( get_taxonomies( array() , 'objects' ) as $taxonomy => $t ) {
    1921                         if ( 'post_tag' == $taxonomy )
    1922                                 continue;       // Handled further down in the $q['tag'] block
    1923 
    1924                         if ( $t->query_var && !empty( $q[$t->query_var] ) ) {
    1925                                 $tax_query_defaults = array(
    1926                                         'taxonomy' => $taxonomy,
    1927                                         'field' => 'slug',
    1928                                 );
    1929 
    1930                                 if ( isset( $t->rewrite['hierarchical'] ) && $t->rewrite['hierarchical'] ) {
    1931                                         $q[$t->query_var] = wp_basename( $q[$t->query_var] );
    1932                                 }
    1933 
    1934                                 $term = $q[$t->query_var];
    1935 
    1936                                 if ( is_array( $term ) ) {
    1937                                         $term = implode( ',', $term );
    1938                                 }
    1939 
    1940                                 if ( strpos($term, '+') !== false ) {
    1941                                         $terms = preg_split( '/[+]+/', $term );
    1942                                         foreach ( $terms as $term ) {
    1943                                                 $tax_query[] = array_merge( $tax_query_defaults, array(
    1944                                                         'terms' => array( $term )
    1945                                                 ) );
    1946                                         }
    1947                                 } else {
    1948                                         $tax_query[] = array_merge( $tax_query_defaults, array(
    1949                                                 'terms' => preg_split( '/[,]+/', $term )
    1950                                         ) );
    1951                                 }
    1952                         }
    1953                 }
    1954 
    1955                 // If querystring 'cat' is an array, implode it.
    1956                 if ( is_array( $q['cat'] ) ) {
    1957                         $q['cat'] = implode( ',', $q['cat'] );
    1958                 }
    1959 
    1960                 // Category stuff
    1961                 if ( ! empty( $q['cat'] ) && ! $this->is_singular ) {
    1962                         $cat_in = $cat_not_in = array();
    1963 
    1964                         $cat_array = preg_split( '/[,\s]+/', urldecode( $q['cat'] ) );
    1965                         $cat_array = array_map( 'intval', $cat_array );
    1966                         $q['cat'] = implode( ',', $cat_array );
    1967 
    1968                         foreach ( $cat_array as $cat ) {
    1969                                 if ( $cat > 0 )
    1970                                         $cat_in[] = $cat;
    1971                                 elseif ( $cat < 0 )
    1972                                         $cat_not_in[] = abs( $cat );
    1973                         }
    1974 
    1975                         if ( ! empty( $cat_in ) ) {
    1976                                 $tax_query[] = array(
    1977                                         'taxonomy' => 'category',
    1978                                         'terms' => $cat_in,
    1979                                         'field' => 'term_id',
    1980                                         'include_children' => true
    1981                                 );
    1982                         }
    1983 
    1984                         if ( ! empty( $cat_not_in ) ) {
    1985                                 $tax_query[] = array(
    1986                                         'taxonomy' => 'category',
    1987                                         'terms' => $cat_not_in,
    1988                                         'field' => 'term_id',
    1989                                         'operator' => 'NOT IN',
    1990                                         'include_children' => true
    1991                                 );
    1992                         }
    1993                         unset( $cat_array, $cat_in, $cat_not_in );
    1994                 }
    1995 
    1996                 if ( ! empty( $q['category__and'] ) && 1 === count( (array) $q['category__and'] ) ) {
    1997                         $q['category__and'] = (array) $q['category__and'];
    1998                         if ( ! isset( $q['category__in'] ) )
    1999                                 $q['category__in'] = array();
    2000                         $q['category__in'][] = absint( reset( $q['category__and'] ) );
    2001                         unset( $q['category__and'] );
    2002                 }
    2003 
    2004                 if ( ! empty( $q['category__in'] ) ) {
    2005                         $q['category__in'] = array_map( 'absint', array_unique( (array) $q['category__in'] ) );
    2006                         $tax_query[] = array(
    2007                                 'taxonomy' => 'category',
    2008                                 'terms' => $q['category__in'],
    2009                                 'field' => 'term_id',
    2010                                 'include_children' => false
    2011                         );
    2012                 }
    2013 
    2014                 if ( ! empty($q['category__not_in']) ) {
    2015                         $q['category__not_in'] = array_map( 'absint', array_unique( (array) $q['category__not_in'] ) );
    2016                         $tax_query[] = array(
    2017                                 'taxonomy' => 'category',
    2018                                 'terms' => $q['category__not_in'],
    2019                                 'operator' => 'NOT IN',
    2020                                 'include_children' => false
    2021                         );
    2022                 }
    2023 
    2024                 if ( ! empty($q['category__and']) ) {
    2025                         $q['category__and'] = array_map( 'absint', array_unique( (array) $q['category__and'] ) );
    2026                         $tax_query[] = array(
    2027                                 'taxonomy' => 'category',
    2028                                 'terms' => $q['category__and'],
    2029                                 'field' => 'term_id',
    2030                                 'operator' => 'AND',
    2031                                 'include_children' => false
    2032                         );
    2033                 }
    2034 
    2035                 // If querystring 'tag' is array, implode it.
    2036                 if ( is_array( $q['tag'] ) ) {
    2037                         $q['tag'] = implode( ',', $q['tag'] );
    2038                 }
    2039 
    2040                 // Tag stuff
    2041                 if ( '' != $q['tag'] && !$this->is_singular && $this->query_vars_changed ) {
    2042                         if ( strpos($q['tag'], ',') !== false ) {
    2043                                 $tags = preg_split('/[,\r\n\t ]+/', $q['tag']);
    2044                                 foreach ( (array) $tags as $tag ) {
    2045                                         $tag = sanitize_term_field('slug', $tag, 0, 'post_tag', 'db');
    2046                                         $q['tag_slug__in'][] = $tag;
    2047                                 }
    2048                         } elseif ( preg_match('/[+\r\n\t ]+/', $q['tag'] ) || ! empty( $q['cat'] ) ) {
    2049                                 $tags = preg_split('/[+\r\n\t ]+/', $q['tag']);
    2050                                 foreach ( (array) $tags as $tag ) {
    2051                                         $tag = sanitize_term_field('slug', $tag, 0, 'post_tag', 'db');
    2052                                         $q['tag_slug__and'][] = $tag;
    2053                                 }
    2054                         } else {
    2055                                 $q['tag'] = sanitize_term_field('slug', $q['tag'], 0, 'post_tag', 'db');
    2056                                 $q['tag_slug__in'][] = $q['tag'];
    2057                         }
    2058                 }
    2059 
    2060                 if ( !empty($q['tag_id']) ) {
    2061                         $q['tag_id'] = absint( $q['tag_id'] );
    2062                         $tax_query[] = array(
    2063                                 'taxonomy' => 'post_tag',
    2064                                 'terms' => $q['tag_id']
    2065                         );
    2066                 }
    2067 
    2068                 if ( !empty($q['tag__in']) ) {
    2069                         $q['tag__in'] = array_map('absint', array_unique( (array) $q['tag__in'] ) );
    2070                         $tax_query[] = array(
    2071                                 'taxonomy' => 'post_tag',
    2072                                 'terms' => $q['tag__in']
    2073                         );
    2074                 }
    2075 
    2076                 if ( !empty($q['tag__not_in']) ) {
    2077                         $q['tag__not_in'] = array_map('absint', array_unique( (array) $q['tag__not_in'] ) );
    2078                         $tax_query[] = array(
    2079                                 'taxonomy' => 'post_tag',
    2080                                 'terms' => $q['tag__not_in'],
    2081                                 'operator' => 'NOT IN'
    2082                         );
    2083                 }
    2084 
    2085                 if ( !empty($q['tag__and']) ) {
    2086                         $q['tag__and'] = array_map('absint', array_unique( (array) $q['tag__and'] ) );
    2087                         $tax_query[] = array(
    2088                                 'taxonomy' => 'post_tag',
    2089                                 'terms' => $q['tag__and'],
    2090                                 'operator' => 'AND'
    2091                         );
    2092                 }
    2093 
    2094                 if ( !empty($q['tag_slug__in']) ) {
    2095                         $q['tag_slug__in'] = array_map('sanitize_title_for_query', array_unique( (array) $q['tag_slug__in'] ) );
    2096                         $tax_query[] = array(
    2097                                 'taxonomy' => 'post_tag',
    2098                                 'terms' => $q['tag_slug__in'],
    2099                                 'field' => 'slug'
    2100                         );
    2101                 }
    2102 
    2103                 if ( !empty($q['tag_slug__and']) ) {
    2104                         $q['tag_slug__and'] = array_map('sanitize_title_for_query', array_unique( (array) $q['tag_slug__and'] ) );
    2105                         $tax_query[] = array(
    2106                                 'taxonomy' => 'post_tag',
    2107                                 'terms' => $q['tag_slug__and'],
    2108                                 'field' => 'slug',
    2109                                 'operator' => 'AND'
    2110                         );
    2111                 }
    2112 
    2113                 $this->tax_query = new WP_Tax_Query( $tax_query );
    2114 
    2115                 /**
    2116                  * Fires after taxonomy-related query vars have been parsed.
    2117                  *
    2118                  * @since 3.7.0
    2119                  *
    2120                  * @param WP_Query $this The WP_Query instance.
    2121                  */
    2122                 do_action( 'parse_tax_query', $this );
    2123         }
    2124 
    2125         /**
    2126          * Generate SQL for the WHERE clause based on passed search terms.
    2127          *
    2128          * @since 3.7.0
    2129          *
    2130          * @param array $q Query variables.
    2131          * @return string WHERE clause.
    2132          */
    2133         protected function parse_search( &$q ) {
    2134                 $search = '';
    2135 
    2136                 // added slashes screw with quote grouping when done early, so done later
    2137                 $q['s'] = stripslashes( $q['s'] );
    2138                 if ( empty( $_GET['s'] ) && $this->is_main_query() )
    2139                         $q['s'] = urldecode( $q['s'] );
    2140                 // there are no line breaks in <input /> fields
    2141                 $q['s'] = str_replace( array( "\r", "\n" ), '', $q['s'] );
    2142                 $q['search_terms_count'] = 1;
    2143                 if ( ! empty( $q['sentence'] ) ) {
    2144                         $q['search_terms'] = array( $q['s'] );
    2145                 } else {
    2146                         if ( preg_match_all( '/".*?("|$)|((?<=[\t ",+])|^)[^\t ",+]+/', $q['s'], $matches ) ) {
    2147                                 $q['search_terms_count'] = count( $matches[0] );
    2148                                 $q['search_terms'] = $this->parse_search_terms( $matches[0] );
    2149                                 // if the search string has only short terms or stopwords, or is 10+ terms long, match it as sentence
    2150                                 if ( empty( $q['search_terms'] ) || count( $q['search_terms'] ) > 9 )
    2151                                         $q['search_terms'] = array( $q['s'] );
    2152                         } else {
    2153                                 $q['search_terms'] = array( $q['s'] );
    2154                         }
    2155                 }
    2156 
    2157                 $n = ! empty( $q['exact'] ) ? '' : '%';
    2158                 $searchand = '';
    2159                 $q['search_orderby_title'] = array();
    2160                 foreach ( $q['search_terms'] as $term ) {
    2161                         // Terms prefixed with '-' should be excluded.
    2162                         $include = '-' !== substr( $term, 0, 1 );
    2163                         if ( $include ) {
    2164                                 $like_op  = 'LIKE';
    2165                                 $andor_op = 'OR';
    2166                         } else {
    2167                                 $like_op  = 'NOT LIKE';
    2168                                 $andor_op = 'AND';
    2169                                 $term     = substr( $term, 1 );
    2170                         }
    2171 
    2172                         if ( $n && $include ) {
    2173                                 $like = '%' . $this->db->esc_like( $term ) . '%';
    2174                                 $q['search_orderby_title'][] = $this->db->prepare( "{$this->db->posts}.post_title LIKE %s", $like );
    2175                         }
    2176 
    2177                         $like = $n . $this->db->esc_like( $term ) . $n;
    2178                         $search .= $this->db->prepare( "{$searchand}(({$this->db->posts}.post_title $like_op %s) $andor_op ({$this->db->posts}.post_excerpt $like_op %s) $andor_op ({$this->db->posts}.post_content $like_op %s))", $like, $like, $like );
    2179                         $searchand = ' AND ';
    2180                 }
    2181 
    2182                 if ( ! empty( $search ) ) {
    2183                         $search = " AND ({$search}) ";
    2184                         if ( ! is_user_logged_in() ) {
    2185                                 $search .= " AND ({$this->db->posts}.post_password = '') ";
    2186                         }
    2187                 }
    2188 
    2189                 return $search;
    2190         }
    2191 
    2192         /**
    2193          * Check if the terms are suitable for searching.
    2194          *
    2195          * Uses an array of stopwords (terms) that are excluded from the separate
    2196          * term matching when searching for posts. The list of English stopwords is
    2197          * the approximate search engines list, and is translatable.
    2198          *
    2199          * @since 3.7.0
    2200          *
    2201          * @param array $terms Terms to check.
    2202          * @return array Terms that are not stopwords.
    2203          */
    2204         protected function parse_search_terms( $terms ) {
    2205                 $strtolower = function_exists( 'mb_strtolower' ) ? 'mb_strtolower' : 'strtolower';
    2206                 $checked = array();
    2207 
    2208                 $stopwords = $this->get_search_stopwords();
    2209 
    2210                 foreach ( $terms as $term ) {
    2211                         // keep before/after spaces when term is for exact match
    2212                         if ( preg_match( '/^".+"$/', $term ) )
    2213                                 $term = trim( $term, "\"'" );
    2214                         else
    2215                                 $term = trim( $term, "\"' " );
    2216 
    2217                         // Avoid single A-Z and single dashes.
    2218                         if ( ! $term || ( 1 === strlen( $term ) && preg_match( '/^[a-z\-]$/i', $term ) ) )
    2219                                 continue;
    2220 
    2221                         if ( in_array( call_user_func( $strtolower, $term ), $stopwords, true ) )
    2222                                 continue;
    2223 
    2224                         $checked[] = $term;
    2225                 }
    2226 
    2227                 return $checked;
    2228         }
    2229 
    2230         /**
    2231          * Retrieve stopwords used when parsing search terms.
    2232          *
    2233          * @since 3.7.0
    2234          *
    2235          * @return array Stopwords.
    2236          */
    2237         protected function get_search_stopwords() {
    2238                 if ( isset( $this->stopwords ) )
    2239                         return $this->stopwords;
    2240 
    2241                 /* translators: This is a comma-separated list of very common words that should be excluded from a search,
    2242                  * like a, an, and the. These are usually called "stopwords". You should not simply translate these individual
    2243                  * words into your language. Instead, look for and provide commonly accepted stopwords in your language.
    2244                  */
    2245                 $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',
    2246                         'Comma-separated list of search stopwords in your language' ) );
    2247 
    2248                 $stopwords = array();
    2249                 foreach ( $words as $word ) {
    2250                         $word = trim( $word, "\r\n\t " );
    2251                         if ( $word )
    2252                                 $stopwords[] = $word;
    2253                 }
    2254 
    2255                 /**
    2256                  * Filters stopwords used when parsing search terms.
    2257                  *
    2258                  * @since 3.7.0
    2259                  *
    2260                  * @param array $stopwords Stopwords.
    2261                  */
    2262                 $this->stopwords = apply_filters( 'wp_search_stopwords', $stopwords );
    2263                 return $this->stopwords;
    2264         }
    2265 
    2266         /**
    2267          * Generate SQL for the ORDER BY condition based on passed search terms.
    2268          *
    2269          * @param array $q Query variables.
    2270          * @return string ORDER BY clause.
    2271          */
    2272         protected function parse_search_order( &$q ) {
    2273                 if ( $q['search_terms_count'] > 1 ) {
    2274                         $num_terms = count( $q['search_orderby_title'] );
    2275 
    2276                         // If the search terms contain negative queries, don't bother ordering by sentence matches.
    2277                         $like = '';
    2278                         if ( ! preg_match( '/(?:\s|^)\-/', $q['s'] ) ) {
    2279                                 $like = '%' . $this->db->esc_like( $q['s'] ) . '%';
    2280                         }
    2281 
    2282                         $search_orderby = '';
    2283 
    2284                         // sentence match in 'post_title'
    2285                         if ( $like ) {
    2286                                 $search_orderby .= $this->db->prepare( "WHEN {$this->db->posts}.post_title LIKE %s THEN 1 ", $like );
    2287                         }
    2288 
    2289                         // sanity limit, sort as sentence when more than 6 terms
    2290                         // (few searches are longer than 6 terms and most titles are not)
    2291                         if ( $num_terms < 7 ) {
    2292                                 // all words in title
    2293                                 $search_orderby .= 'WHEN ' . implode( ' AND ', $q['search_orderby_title'] ) . ' THEN 2 ';
    2294                                 // any word in title, not needed when $num_terms == 1
    2295                                 if ( $num_terms > 1 )
    2296                                         $search_orderby .= 'WHEN ' . implode( ' OR ', $q['search_orderby_title'] ) . ' THEN 3 ';
    2297                         }
    2298 
    2299                         // Sentence match in 'post_content' and 'post_excerpt'.
    2300                         if ( $like ) {
    2301                                 $search_orderby .= $this->db->prepare( "WHEN {$this->db->posts}.post_excerpt LIKE %s THEN 4 ", $like );
    2302                                 $search_orderby .= $this->db->prepare( "WHEN {$this->db->posts}.post_content LIKE %s THEN 5 ", $like );
    2303                         }
    2304 
    2305                         if ( $search_orderby ) {
    2306                                 $search_orderby = '(CASE ' . $search_orderby . 'ELSE 6 END)';
    2307                         }
    2308                 } else {
    2309                         // single word or sentence search
    2310                         $search_orderby = reset( $q['search_orderby_title'] ) . ' DESC';
    2311                 }
    2312 
    2313                 return $search_orderby;
    2314         }
    2315 
    2316         /**
    2317          * If the passed orderby value is allowed, convert the alias to a
    2318          * properly-prefixed orderby value.
    2319          *
    2320          * @since 4.0.0
    2321          * @access protected
    2322          *
    2323          * @param string $orderby Alias for the field to order by.
    2324          * @return string|false Table-prefixed value to used in the ORDER clause. False otherwise.
    2325          */
    2326         protected function parse_orderby( $orderby ) {
    2327                 // Used to filter values.
    2328                 $allowed_keys = array(
    2329                         'post_name', 'post_author', 'post_date', 'post_title', 'post_modified',
    2330                         'post_parent', 'post_type', 'name', 'author', 'date', 'title', 'modified',
    2331                         'parent', 'type', 'ID', 'menu_order', 'comment_count', 'rand',
    2332                 );
    2333 
    2334                 $primary_meta_key = '';
    2335                 $primary_meta_query = false;
    2336                 $meta_clauses = $this->meta_query->get_clauses();
    2337                 if ( ! empty( $meta_clauses ) ) {
    2338                         $primary_meta_query = reset( $meta_clauses );
    2339 
    2340                         if ( ! empty( $primary_meta_query['key'] ) ) {
    2341                                 $primary_meta_key = $primary_meta_query['key'];
    2342                                 $allowed_keys[] = $primary_meta_key;
    2343                         }
    2344 
    2345                         $allowed_keys[] = 'meta_value';
    2346                         $allowed_keys[] = 'meta_value_num';
    2347                         $allowed_keys   = array_merge( $allowed_keys, array_keys( $meta_clauses ) );
    2348                 }
    2349 
    2350                 // If RAND() contains a seed value, sanitize and add to allowed keys.
    2351                 $rand_with_seed = false;
    2352                 if ( preg_match( '/RAND\(([0-9]+)\)/i', $orderby, $matches ) ) {
    2353                         $orderby = sprintf( 'RAND(%s)', intval( $matches[1] ) );
    2354                         $allowed_keys[] = $orderby;
    2355                         $rand_with_seed = true;
    2356                 }
    2357 
    2358                 if ( ! in_array( $orderby, $allowed_keys, true ) ) {
    2359                         return false;
    2360                 }
    2361 
    2362                 switch ( $orderby ) {
    2363                         case 'post_name':
    2364                         case 'post_author':
    2365                         case 'post_date':
    2366                         case 'post_title':
    2367                         case 'post_modified':
    2368                         case 'post_parent':
    2369                         case 'post_type':
    2370                         case 'ID':
    2371                         case 'menu_order':
    2372                         case 'comment_count':
    2373                                 $orderby_clause = "{$this->db->posts}.{$orderby}";
    2374                                 break;
    2375                         case 'rand':
    2376                                 $orderby_clause = 'RAND()';
    2377                                 break;
    2378                         case $primary_meta_key:
    2379                         case 'meta_value':
    2380                                 if ( ! empty( $primary_meta_query['type'] ) ) {
    2381                                         $orderby_clause = "CAST({$primary_meta_query['alias']}.meta_value AS {$primary_meta_query['cast']})";
    2382                                 } else {
    2383                                         $orderby_clause = "{$primary_meta_query['alias']}.meta_value";
    2384                                 }
    2385                                 break;
    2386                         case 'meta_value_num':
    2387                                 $orderby_clause = "{$primary_meta_query['alias']}.meta_value+0";
    2388                                 break;
    2389                         default:
    2390                                 if ( array_key_exists( $orderby, $meta_clauses ) ) {
    2391                                         // $orderby corresponds to a meta_query clause.
    2392                                         $meta_clause = $meta_clauses[ $orderby ];
    2393                                         $orderby_clause = "CAST({$meta_clause['alias']}.meta_value AS {$meta_clause['cast']})";
    2394                                 } elseif ( $rand_with_seed ) {
    2395                                         $orderby_clause = $orderby;
    2396                                 } else {
    2397                                         // Default: order by post field.
    2398                                         $orderby_clause = "{$this->db->posts}.post_" . sanitize_key( $orderby );
    2399                                 }
    2400 
    2401                                 break;
    2402                 }
    2403 
    2404                 return $orderby_clause;
    2405         }
    2406 
    2407         /**
    2408          * Parse an 'order' query variable and cast it to ASC or DESC as necessary.
    2409          *
    2410          * @since 4.0.0
    2411          * @access protected
    2412          *
    2413          * @param string $order The 'order' query variable.
    2414          * @return string The sanitized 'order' query variable.
    2415          */
    2416         protected function parse_order( $order ) {
    2417                 if ( ! is_string( $order ) || empty( $order ) ) {
    2418                         return 'DESC';
    2419                 }
    2420 
    2421                 if ( 'ASC' === strtoupper( $order ) ) {
    2422                         return 'ASC';
    2423                 } else {
    2424                         return 'DESC';
    2425                 }
    2426         }
    2427 
    2428         /**
    2429          * Sets the 404 property and saves whether query is feed.
    2430          *
    2431          * @since 2.0.0
    2432          * @access public
    2433          */
    2434         public function set_404() {
    2435                 $is_feed = $this->is_feed;
    2436 
    2437                 $this->init_query_flags();
    2438                 $this->is_404 = true;
    2439 
    2440                 $this->is_feed = $is_feed;
    2441         }
    2442 
    2443         /**
    2444          * Retrieve query variable.
    2445          *
    2446          * @since 1.5.0
    2447          * @since 3.9.0 The `$default` argument was introduced.
    2448          *
    2449          * @access public
    2450          *
    2451          * @param string $query_var Query variable key.
    2452          * @param mixed  $default   Optional. Value to return if the query variable is not set. Default empty.
    2453          * @return mixed Contents of the query variable.
    2454          */
    2455         public function get( $query_var, $default = '' ) {
    2456                 if ( isset( $this->query_vars[ $query_var ] ) ) {
    2457                         return $this->query_vars[ $query_var ];
    2458                 }
    2459 
    2460                 return $default;
    2461         }
    2462 
    2463         /**
    2464          * Set query variable.
    2465          *
    2466          * @since 1.5.0
    2467          * @access public
    2468          *
    2469          * @param string $query_var Query variable key.
    2470          * @param mixed  $value     Query variable value.
    2471          */
    2472         public function set($query_var, $value) {
    2473                 $this->query_vars[$query_var] = $value;
    2474         }
    2475 
    2476         /**
    2477          * Retrieve the posts based on query variables.
    2478          *
    2479          * There are a few filters and actions that can be used to modify the post
    2480          * database query.
    2481          *
    2482          * @since 1.5.0
    2483          * @access public
    2484          *
    2485          * @return array List of posts.
    2486          */
    2487         public function get_posts() {
    2488                 $this->parse_query();
    2489 
    2490                 /**
    2491                  * Fires after the query variable object is created, but before the actual query is run.
    2492                  *
    2493                  * Note: If using conditional tags, use the method versions within the passed instance
    2494                  * (e.g. $this->is_main_query() instead of is_main_query()). This is because the functions
    2495                  * like is_main_query() test against the global $wp_query instance, not the passed one.
    2496                  *
    2497                  * @since 2.0.0
    2498                  *
    2499                  * @param WP_Query &$this The WP_Query instance (passed by reference).
    2500                  */
    2501                 do_action_ref_array( 'pre_get_posts', array( &$this ) );
    2502 
    2503                 // Shorthand.
    2504                 $q = &$this->query_vars;
    2505 
    2506                 // Fill again in case pre_get_posts unset some vars.
    2507                 $q = $this->fill_query_vars($q);
    2508 
    2509                 // Parse meta query
    2510                 $this->meta_query = new WP_Meta_Query();
    2511                 $this->meta_query->parse_query_vars( $q );
    2512 
    2513                 // Set a flag if a pre_get_posts hook changed the query vars.
    2514                 $hash = md5( serialize( $this->query_vars ) );
    2515                 if ( $hash != $this->query_vars_hash ) {
    2516                         $this->query_vars_changed = true;
    2517                         $this->query_vars_hash = $hash;
    2518                 }
    2519                 unset($hash);
    2520 
    2521                 // First let's clear some variables
    2522                 $distinct = '';
    2523                 $whichauthor = '';
    2524                 $whichmimetype = '';
    2525                 $where = '';
    2526                 $limits = '';
    2527                 $join = '';
    2528                 $search = '';
    2529                 $groupby = '';
    2530                 $post_status_join = false;
    2531                 $page = 1;
    2532 
    2533                 if ( isset( $q['caller_get_posts'] ) ) {
    2534                         _deprecated_argument( 'WP_Query', '3.1.0', __( '"caller_get_posts" is deprecated. Use "ignore_sticky_posts" instead.' ) );
    2535                         if ( !isset( $q['ignore_sticky_posts'] ) )
    2536                                 $q['ignore_sticky_posts'] = $q['caller_get_posts'];
    2537                 }
    2538 
    2539                 if ( !isset( $q['ignore_sticky_posts'] ) )
    2540                         $q['ignore_sticky_posts'] = false;
    2541 
    2542                 if ( !isset($q['suppress_filters']) )
    2543                         $q['suppress_filters'] = false;
    2544 
    2545                 if ( !isset($q['cache_results']) ) {
    2546                         if ( wp_using_ext_object_cache() )
    2547                                 $q['cache_results'] = false;
    2548                         else
    2549                                 $q['cache_results'] = true;
    2550                 }
    2551 
    2552                 if ( !isset($q['update_post_term_cache']) )
    2553                         $q['update_post_term_cache'] = true;
    2554 
    2555                 if ( ! isset( $q['lazy_load_term_meta'] ) ) {
    2556                         $q['lazy_load_term_meta'] = $q['update_post_term_cache'];
    2557                 }
    2558 
    2559                 if ( !isset($q['update_post_meta_cache']) )
    2560                         $q['update_post_meta_cache'] = true;
    2561 
    2562                 if ( !isset($q['post_type']) ) {
    2563                         if ( $this->is_search )
    2564                                 $q['post_type'] = 'any';
    2565                         else
    2566                                 $q['post_type'] = '';
    2567                 }
    2568                 $post_type = $q['post_type'];
    2569                 if ( empty( $q['posts_per_page'] ) ) {
    2570                         $q['posts_per_page'] = get_option( 'posts_per_page' );
    2571                 }
    2572                 if ( isset($q['showposts']) && $q['showposts'] ) {
    2573                         $q['showposts'] = (int) $q['showposts'];
    2574                         $q['posts_per_page'] = $q['showposts'];
    2575                 }
    2576                 if ( (isset($q['posts_per_archive_page']) && $q['posts_per_archive_page'] != 0) && ($this->is_archive || $this->is_search) )
    2577                         $q['posts_per_page'] = $q['posts_per_archive_page'];
    2578                 if ( !isset($q['nopaging']) ) {
    2579                         if ( $q['posts_per_page'] == -1 ) {
    2580                                 $q['nopaging'] = true;
    2581                         } else {
    2582                                 $q['nopaging'] = false;
    2583                         }
    2584                 }
    2585 
    2586                 if ( $this->is_feed ) {
    2587                         // This overrides posts_per_page.
    2588                         if ( ! empty( $q['posts_per_rss'] ) ) {
    2589                                 $q['posts_per_page'] = $q['posts_per_rss'];
    2590                         } else {
    2591                                 $q['posts_per_page'] = get_option( 'posts_per_rss' );
    2592                         }
    2593                         $q['nopaging'] = false;
    2594                 }
    2595                 $q['posts_per_page'] = (int) $q['posts_per_page'];
    2596                 if ( $q['posts_per_page'] < -1 )
    2597                         $q['posts_per_page'] = abs($q['posts_per_page']);
    2598                 elseif ( $q['posts_per_page'] == 0 )
    2599                         $q['posts_per_page'] = 1;
    2600 
    2601                 if ( !isset($q['comments_per_page']) || $q['comments_per_page'] == 0 )
    2602                         $q['comments_per_page'] = get_option('comments_per_page');
    2603 
    2604                 if ( $this->is_home && (empty($this->query) || $q['preview'] == 'true') && ( 'page' == get_option('show_on_front') ) && get_option('page_on_front') ) {
    2605                         $this->is_page = true;
    2606                         $this->is_home = false;
    2607                         $q['page_id'] = get_option('page_on_front');
    2608                 }
    2609 
    2610                 if ( isset($q['page']) ) {
    2611                         $q['page'] = trim($q['page'], '/');
    2612                         $q['page'] = absint($q['page']);
    2613                 }
    2614 
    2615                 // If true, forcibly turns off SQL_CALC_FOUND_ROWS even when limits are present.
    2616                 if ( isset($q['no_found_rows']) )
    2617                         $q['no_found_rows'] = (bool) $q['no_found_rows'];
    2618                 else
    2619                         $q['no_found_rows'] = false;
    2620 
    2621                 switch ( $q['fields'] ) {
    2622                         case 'ids':
    2623                                 $fields = "{$this->db->posts}.ID";
    2624                                 break;
    2625                         case 'id=>parent':
    2626                                 $fields = "{$this->db->posts}.ID, {$this->db->posts}.post_parent";
    2627                                 break;
    2628                         default:
    2629                                 $fields = "{$this->db->posts}.*";
    2630                 }
    2631 
    2632                 if ( '' !== $q['menu_order'] ) {
    2633                         $where .= " AND {$this->db->posts}.menu_order = " . $q['menu_order'];
    2634                 }
    2635                 // The "m" parameter is meant for months but accepts datetimes of varying specificity
    2636                 if ( $q['m'] ) {
    2637                         $where .= " AND YEAR({$this->db->posts}.post_date)=" . substr($q['m'], 0, 4);
    2638                         if ( strlen($q['m']) > 5 ) {
    2639                                 $where .= " AND MONTH({$this->db->posts}.post_date)=" . substr($q['m'], 4, 2);
    2640                         }
    2641                         if ( strlen($q['m']) > 7 ) {
    2642                                 $where .= " AND DAYOFMONTH({$this->db->posts}.post_date)=" . substr($q['m'], 6, 2);
    2643                         }
    2644                         if ( strlen($q['m']) > 9 ) {
    2645                                 $where .= " AND HOUR({$this->db->posts}.post_date)=" . substr($q['m'], 8, 2);
    2646                         }
    2647                         if ( strlen($q['m']) > 11 ) {
    2648                                 $where .= " AND MINUTE({$this->db->posts}.post_date)=" . substr($q['m'], 10, 2);
    2649                         }
    2650                         if ( strlen($q['m']) > 13 ) {
    2651                                 $where .= " AND SECOND({$this->db->posts}.post_date)=" . substr($q['m'], 12, 2);
    2652                         }
    2653                 }
    2654 
    2655                 // Handle the other individual date parameters
    2656                 $date_parameters = array();
    2657 
    2658                 if ( '' !== $q['hour'] )
    2659                         $date_parameters['hour'] = $q['hour'];
    2660 
    2661                 if ( '' !== $q['minute'] )
    2662                         $date_parameters['minute'] = $q['minute'];
    2663 
    2664                 if ( '' !== $q['second'] )
    2665                         $date_parameters['second'] = $q['second'];
    2666 
    2667                 if ( $q['year'] )
    2668                         $date_parameters['year'] = $q['year'];
    2669 
    2670                 if ( $q['monthnum'] )
    2671                         $date_parameters['monthnum'] = $q['monthnum'];
    2672 
    2673                 if ( $q['w'] )
    2674                         $date_parameters['week'] = $q['w'];
    2675 
    2676                 if ( $q['day'] )
    2677                         $date_parameters['day'] = $q['day'];
    2678 
    2679                 if ( $date_parameters ) {
    2680                         $date_query = new WP_Date_Query( array( $date_parameters ) );
    2681                         $where .= $date_query->get_sql();
    2682                 }
    2683                 unset( $date_parameters, $date_query );
    2684 
    2685                 // Handle complex date queries
    2686                 if ( ! empty( $q['date_query'] ) ) {
    2687                         $this->date_query = new WP_Date_Query( $q['date_query'] );
    2688                         $where .= $this->date_query->get_sql();
    2689                 }
    2690 
    2691 
    2692                 // If we've got a post_type AND it's not "any" post_type.
    2693                 if ( !empty($q['post_type']) && 'any' != $q['post_type'] ) {
    2694                         foreach ( (array)$q['post_type'] as $_post_type ) {
    2695                                 $ptype_obj = get_post_type_object($_post_type);
    2696                                 if ( !$ptype_obj || !$ptype_obj->query_var || empty($q[ $ptype_obj->query_var ]) )
    2697                                         continue;
    2698 
    2699                                 if ( ! $ptype_obj->hierarchical ) {
    2700                                         // Non-hierarchical post types can directly use 'name'.
    2701                                         $q['name'] = $q[ $ptype_obj->query_var ];
    2702                                 } else {
    2703                                         // Hierarchical post types will operate through 'pagename'.
    2704                                         $q['pagename'] = $q[ $ptype_obj->query_var ];
    2705                                         $q['name'] = '';
    2706                                 }
    2707 
    2708                                 // Only one request for a slug is possible, this is why name & pagename are overwritten above.
    2709                                 break;
    2710                         } //end foreach
    2711                         unset($ptype_obj);
    2712                 }
    2713 
    2714                 if ( '' !== $q['title'] ) {
    2715                         $where .= $this->db->prepare( " AND {$this->db->posts}.post_title = %s", stripslashes( $q['title'] ) );
    2716                 }
    2717 
    2718                 // Parameters related to 'post_name'.
    2719                 if ( '' != $q['name'] ) {
    2720                         $q['name'] = sanitize_title_for_query( $q['name'] );
    2721                         $where .= " AND {$this->db->posts}.post_name = '" . $q['name'] . "'";
    2722                 } elseif ( '' != $q['pagename'] ) {
    2723                         if ( isset($this->queried_object_id) ) {
    2724                                 $reqpage = $this->queried_object_id;
    2725                         } else {
    2726                                 if ( 'page' != $q['post_type'] ) {
    2727                                         foreach ( (array)$q['post_type'] as $_post_type ) {
    2728                                                 $ptype_obj = get_post_type_object($_post_type);
    2729                                                 if ( !$ptype_obj || !$ptype_obj->hierarchical )
    2730                                                         continue;
    2731 
    2732                                                 $reqpage = get_page_by_path($q['pagename'], OBJECT, $_post_type);
    2733                                                 if ( $reqpage )
    2734                                                         break;
    2735                                         }
    2736                                         unset($ptype_obj);
    2737                                 } else {
    2738                                         $reqpage = get_page_by_path($q['pagename']);
    2739                                 }
    2740                                 if ( !empty($reqpage) )
    2741                                         $reqpage = $reqpage->ID;
    2742                                 else
    2743                                         $reqpage = 0;
    2744                         }
    2745 
    2746                         $page_for_posts = get_option('page_for_posts');
    2747                         if  ( ('page' != get_option('show_on_front') ) || empty($page_for_posts) || ( $reqpage != $page_for_posts ) ) {
    2748                                 $q['pagename'] = sanitize_title_for_query( wp_basename( $q['pagename'] ) );
    2749                                 $q['name'] = $q['pagename'];
    2750                                 $where .= " AND ({$this->db->posts}.ID = '$reqpage')";
    2751                                 $reqpage_obj = get_post( $reqpage );
    2752                                 if ( is_object($reqpage_obj) && 'attachment' == $reqpage_obj->post_type ) {
    2753                                         $this->is_attachment = true;
    2754                                         $post_type = $q['post_type'] = 'attachment';
    2755                                         $this->is_page = true;
    2756                                         $q['attachment_id'] = $reqpage;
    2757                                 }
    2758                         }
    2759                 } elseif ( '' != $q['attachment'] ) {
    2760                         $q['attachment'] = sanitize_title_for_query( wp_basename( $q['attachment'] ) );
    2761                         $q['name'] = $q['attachment'];
    2762                         $where .= " AND {$this->db->posts}.post_name = '" . $q['attachment'] . "'";
    2763                 } elseif ( is_array( $q['post_name__in'] ) && ! empty( $q['post_name__in'] ) ) {
    2764                         $q['post_name__in'] = array_map( 'sanitize_title_for_query', $q['post_name__in'] );
    2765                         $post_name__in = "'" . implode( "','", $q['post_name__in'] ) . "'";
    2766                         $where .= " AND {$this->db->posts}.post_name IN ($post_name__in)";
    2767                 }
    2768 
    2769                 // If an attachment is requested by number, let it supersede any post number.
    2770                 if ( $q['attachment_id'] )
    2771                         $q['p'] = absint($q['attachment_id']);
    2772 
    2773                 // If a post number is specified, load that post
    2774                 if ( $q['p'] ) {
    2775                         $where .= " AND {$this->db->posts}.ID = " . $q['p'];
    2776                 } elseif ( $q['post__in'] ) {
    2777                         $post__in = implode(',', array_map( 'absint', $q['post__in'] ));
    2778                         $where .= " AND {$this->db->posts}.ID IN ($post__in)";
    2779                 } elseif ( $q['post__not_in'] ) {
    2780                         $post__not_in = implode(',',  array_map( 'absint', $q['post__not_in'] ));
    2781                         $where .= " AND {$this->db->posts}.ID NOT IN ($post__not_in)";
    2782                 }
    2783 
    2784                 if ( is_numeric( $q['post_parent'] ) ) {
    2785                         $where .= $this->db->prepare( " AND {$this->db->posts}.post_parent = %d ", $q['post_parent'] );
    2786                 } elseif ( $q['post_parent__in'] ) {
    2787                         $post_parent__in = implode( ',', array_map( 'absint', $q['post_parent__in'] ) );
    2788                         $where .= " AND {$this->db->posts}.post_parent IN ($post_parent__in)";
    2789                 } elseif ( $q['post_parent__not_in'] ) {
    2790                         $post_parent__not_in = implode( ',',  array_map( 'absint', $q['post_parent__not_in'] ) );
    2791                         $where .= " AND {$this->db->posts}.post_parent NOT IN ($post_parent__not_in)";
    2792                 }
    2793 
    2794                 if ( $q['page_id'] ) {
    2795                         if  ( ('page' != get_option('show_on_front') ) || ( $q['page_id'] != get_option('page_for_posts') ) ) {
    2796                                 $q['p'] = $q['page_id'];
    2797                                 $where = " AND {$this->db->posts}.ID = " . $q['page_id'];
    2798                         }
    2799                 }
    2800 
    2801                 // If a search pattern is specified, load the posts that match.
    2802                 if ( strlen( $q['s'] ) ) {
    2803                         $search = $this->parse_search( $q );
    2804                 }
    2805 
    2806                 if ( ! $q['suppress_filters'] ) {
    2807                         /**
    2808                          * Filters the search SQL that is used in the WHERE clause of WP_Query.
    2809                          *
    2810                          * @since 3.0.0
    2811                          *
    2812                          * @param string   $search Search SQL for WHERE clause.
    2813                          * @param WP_Query $this   The current WP_Query object.
    2814                          */
    2815                         $search = apply_filters_ref_array( 'posts_search', array( $search, &$this ) );
    2816                 }
    2817 
    2818                 // Taxonomies
    2819                 if ( !$this->is_singular ) {
    2820                         $this->parse_tax_query( $q );
    2821 
    2822                         $clauses = $this->tax_query->get_sql( $this->db->posts, 'ID' );
    2823 
    2824                         $join .= $clauses['join'];
    2825                         $where .= $clauses['where'];
    2826                 }
    2827 
    2828                 if ( $this->is_tax ) {
    2829                         if ( empty($post_type) ) {
    2830                                 // Do a fully inclusive search for currently registered post types of queried taxonomies
    2831                                 $post_type = array();
    2832                                 $taxonomies = array_keys( $this->tax_query->queried_terms );
    2833                                 foreach ( get_post_types( array( 'exclude_from_search' => false ) ) as $pt ) {
    2834                                         $object_taxonomies = $pt === 'attachment' ? get_taxonomies_for_attachments() : get_object_taxonomies( $pt );
    2835                                         if ( array_intersect( $taxonomies, $object_taxonomies ) )
    2836                                                 $post_type[] = $pt;
    2837                                 }
    2838                                 if ( ! $post_type )
    2839                                         $post_type = 'any';
    2840                                 elseif ( count( $post_type ) == 1 )
    2841                                         $post_type = $post_type[0];
    2842 
    2843                                 $post_status_join = true;
    2844                         } elseif ( in_array('attachment', (array) $post_type) ) {
    2845                                 $post_status_join = true;
    2846                         }
    2847                 }
    2848 
    2849                 /*
    2850                  * Ensure that 'taxonomy', 'term', 'term_id', 'cat', and
    2851                  * 'category_name' vars are set for backward compatibility.
    2852                  */
    2853                 if ( ! empty( $this->tax_query->queried_terms ) ) {
    2854 
    2855                         /*
    2856                          * Set 'taxonomy', 'term', and 'term_id' to the
    2857                          * first taxonomy other than 'post_tag' or 'category'.
    2858                          */
    2859                         if ( ! isset( $q['taxonomy'] ) ) {
    2860                                 foreach ( $this->tax_query->queried_terms as $queried_taxonomy => $queried_items ) {
    2861                                         if ( empty( $queried_items['terms'][0] ) ) {
    2862                                                 continue;
    2863                                         }
    2864 
    2865                                         if ( ! in_array( $queried_taxonomy, array( 'category', 'post_tag' ) ) ) {
    2866                                                 $q['taxonomy'] = $queried_taxonomy;
    2867 
    2868                                                 if ( 'slug' === $queried_items['field'] ) {
    2869                                                         $q['term'] = $queried_items['terms'][0];
    2870                                                 } else {
    2871                                                         $q['term_id'] = $queried_items['terms'][0];
    2872                                                 }
    2873 
    2874                                                 // Take the first one we find.
    2875                                                 break;
    2876                                         }
    2877                                 }
    2878                         }
    2879 
    2880                         // 'cat', 'category_name', 'tag_id'
    2881                         foreach ( $this->tax_query->queried_terms as $queried_taxonomy => $queried_items ) {
    2882                                 if ( empty( $queried_items['terms'][0] ) ) {
    2883                                         continue;
    2884                                 }
    2885 
    2886                                 if ( 'category' === $queried_taxonomy ) {
    2887                                         $the_cat = get_term_by( $queried_items['field'], $queried_items['terms'][0], 'category' );
    2888                                         if ( $the_cat ) {
    2889                                                 $this->set( 'cat', $the_cat->term_id );
    2890                                                 $this->set( 'category_name', $the_cat->slug );
    2891                                         }
    2892                                         unset( $the_cat );
    2893                                 }
    2894 
    2895                                 if ( 'post_tag' === $queried_taxonomy ) {
    2896                                         $the_tag = get_term_by( $queried_items['field'], $queried_items['terms'][0], 'post_tag' );
    2897                                         if ( $the_tag ) {
    2898                                                 $this->set( 'tag_id', $the_tag->term_id );
    2899                                         }
    2900                                         unset( $the_tag );
    2901                                 }
    2902                         }
    2903                 }
    2904 
    2905                 if ( !empty( $this->tax_query->queries ) || !empty( $this->meta_query->queries ) ) {
    2906                         $groupby = "{$this->db->posts}.ID";
    2907                 }
    2908 
    2909                 // Author/user stuff
    2910 
    2911                 if ( ! empty( $q['author'] ) && $q['author'] != '0' ) {
    2912                         $q['author'] = addslashes_gpc( '' . urldecode( $q['author'] ) );
    2913                         $authors = array_unique( array_map( 'intval', preg_split( '/[,\s]+/', $q['author'] ) ) );
    2914                         foreach ( $authors as $author ) {
    2915                                 $key = $author > 0 ? 'author__in' : 'author__not_in';
    2916                                 $q[$key][] = abs( $author );
    2917                         }
    2918                         $q['author'] = implode( ',', $authors );
    2919                 }
    2920 
    2921                 if ( ! empty( $q['author__not_in'] ) ) {
    2922                         $author__not_in = implode( ',', array_map( 'absint', array_unique( (array) $q['author__not_in'] ) ) );
    2923                         $where .= " AND {$this->db->posts}.post_author NOT IN ($author__not_in) ";
    2924                 } elseif ( ! empty( $q['author__in'] ) ) {
    2925                         $author__in = implode( ',', array_map( 'absint', array_unique( (array) $q['author__in'] ) ) );
    2926                         $where .= " AND {$this->db->posts}.post_author IN ($author__in) ";
    2927                 }
    2928 
    2929                 // Author stuff for nice URLs
    2930 
    2931                 if ( '' != $q['author_name'] ) {
    2932                         if ( strpos($q['author_name'], '/') !== false ) {
    2933                                 $q['author_name'] = explode('/', $q['author_name']);
    2934                                 if ( $q['author_name'][ count($q['author_name'])-1 ] ) {
    2935                                         $q['author_name'] = $q['author_name'][count($q['author_name'])-1]; // no trailing slash
    2936                                 } else {
    2937                                         $q['author_name'] = $q['author_name'][count($q['author_name'])-2]; // there was a trailing slash
    2938                                 }
    2939                         }
    2940                         $q['author_name'] = sanitize_title_for_query( $q['author_name'] );
    2941                         $q['author'] = get_user_by('slug', $q['author_name']);
    2942                         if ( $q['author'] )
    2943                                 $q['author'] = $q['author']->ID;
    2944                         $whichauthor .= " AND ({$this->db->posts}.post_author = " . absint($q['author']) . ')';
    2945                 }
    2946 
    2947                 // MIME-Type stuff for attachment browsing
    2948 
    2949                 if ( isset( $q['post_mime_type'] ) && '' != $q['post_mime_type'] ) {
    2950                         $whichmimetype = wp_post_mime_type_where( $q['post_mime_type'], $this->db->posts );
    2951                 }
    2952                 $where .= $search . $whichauthor . $whichmimetype;
    2953 
    2954                 if ( ! empty( $this->meta_query->queries ) ) {
    2955                         $clauses = $this->meta_query->get_sql( 'post', $this->db->posts, 'ID', $this );
    2956                         $join   .= $clauses['join'];
    2957                         $where  .= $clauses['where'];
    2958                 }
    2959 
    2960                 $rand = ( isset( $q['orderby'] ) && 'rand' === $q['orderby'] );
    2961                 if ( ! isset( $q['order'] ) ) {
    2962                         $q['order'] = $rand ? '' : 'DESC';
    2963                 } else {
    2964                         $q['order'] = $rand ? '' : $this->parse_order( $q['order'] );
    2965                 }
    2966 
    2967                 // Order by.
    2968                 if ( empty( $q['orderby'] ) ) {
    2969                         /*
    2970                          * Boolean false or empty array blanks out ORDER BY,
    2971                          * while leaving the value unset or otherwise empty sets the default.
    2972                          */
    2973                         if ( isset( $q['orderby'] ) && ( is_array( $q['orderby'] ) || false === $q['orderby'] ) ) {
    2974                                 $orderby = '';
    2975                         } else {
    2976                                 $orderby = "{$this->db->posts}.post_date " . $q['order'];
    2977                         }
    2978                 } elseif ( 'none' == $q['orderby'] ) {
    2979                         $orderby = '';
    2980                 } elseif ( $q['orderby'] == 'post__in' && ! empty( $post__in ) ) {
    2981                         $orderby = "FIELD( {$this->db->posts}.ID, $post__in )";
    2982                 } elseif ( $q['orderby'] == 'post_parent__in' && ! empty( $post_parent__in ) ) {
    2983                         $orderby = "FIELD( {$this->db->posts}.post_parent, $post_parent__in )";
    2984                 } elseif ( $q['orderby'] == 'post_name__in' && ! empty( $post_name__in ) ) {
    2985                         $orderby = "FIELD( {$this->db->posts}.post_name, $post_name__in )";
    2986                 } else {
    2987                         $orderby_array = array();
    2988                         if ( is_array( $q['orderby'] ) ) {
    2989                                 foreach ( $q['orderby'] as $_orderby => $order ) {
    2990                                         $orderby = addslashes_gpc( urldecode( $_orderby ) );
    2991                                         $parsed  = $this->parse_orderby( $orderby );
    2992 
    2993                                         if ( ! $parsed ) {
    2994                                                 continue;
    2995                                         }
    2996 
    2997                                         $orderby_array[] = $parsed . ' ' . $this->parse_order( $order );
    2998                                 }
    2999                                 $orderby = implode( ', ', $orderby_array );
    3000 
    3001                         } else {
    3002                                 $q['orderby'] = urldecode( $q['orderby'] );
    3003                                 $q['orderby'] = addslashes_gpc( $q['orderby'] );
    3004 
    3005                                 foreach ( explode( ' ', $q['orderby'] ) as $i => $orderby ) {
    3006                                         $parsed = $this->parse_orderby( $orderby );
    3007                                         // Only allow certain values for safety.
    3008                                         if ( ! $parsed ) {
    3009                                                 continue;
    3010                                         }
    3011 
    3012                                         $orderby_array[] = $parsed;
    3013                                 }
    3014                                 $orderby = implode( ' ' . $q['order'] . ', ', $orderby_array );
    3015 
    3016                                 if ( empty( $orderby ) ) {
    3017                                         $orderby = "{$this->db->posts}.post_date " . $q['order'];
    3018                                 } elseif ( ! empty( $q['order'] ) ) {
    3019                                         $orderby .= " {$q['order']}";
    3020                                 }
    3021                         }
    3022                 }
    3023 
    3024                 // Order search results by relevance only when another "orderby" is not specified in the query.
    3025                 if ( ! empty( $q['s'] ) ) {
    3026                         $search_orderby = '';
    3027                         if ( ! empty( $q['search_orderby_title'] ) && ( empty( $q['orderby'] ) && ! $this->is_feed ) || ( isset( $q['orderby'] ) && 'relevance' === $q['orderby'] ) )
    3028                                 $search_orderby = $this->parse_search_order( $q );
    3029 
    3030                         if ( ! $q['suppress_filters'] ) {
    3031                                 /**
    3032                                  * Filters the ORDER BY used when ordering search results.
    3033                                  *
    3034                                  * @since 3.7.0
    3035                                  *
    3036                                  * @param string   $search_orderby The ORDER BY clause.
    3037                                  * @param WP_Query $this           The current WP_Query instance.
    3038                                  */
    3039                                 $search_orderby = apply_filters( 'posts_search_orderby', $search_orderby, $this );
    3040                         }
    3041 
    3042                         if ( $search_orderby )
    3043                                 $orderby = $orderby ? $search_orderby . ', ' . $orderby : $search_orderby;
    3044                 }
    3045 
    3046                 if ( is_array( $post_type ) && count( $post_type ) > 1 ) {
    3047                         $post_type_cap = 'multiple_post_type';
    3048                 } else {
    3049                         if ( is_array( $post_type ) )
    3050                                 $post_type = reset( $post_type );
    3051                         $post_type_object = get_post_type_object( $post_type );
    3052                         if ( empty( $post_type_object ) )
    3053                                 $post_type_cap = $post_type;
    3054                 }
    3055 
    3056                 if ( isset( $q['post_password'] ) ) {
    3057                         $where .= $this->db->prepare( " AND {$this->db->posts}.post_password = %s", $q['post_password'] );
    3058                         if ( empty( $q['perm'] ) ) {
    3059                                 $q['perm'] = 'readable';
    3060                         }
    3061                 } elseif ( isset( $q['has_password'] ) ) {
    3062                         $where .= sprintf( " AND {$this->db->posts}.post_password %s ''", $q['has_password'] ? '!=' : '=' );
    3063                 }
    3064 
    3065                 if ( ! empty( $q['comment_status'] ) ) {
    3066                         $where .= $this->db->prepare( " AND {$this->db->posts}.comment_status = %s ", $q['comment_status'] );
    3067                 }
    3068 
    3069                 if ( ! empty( $q['ping_status'] ) )  {
    3070                         $where .= $this->db->prepare( " AND {$this->db->posts}.ping_status = %s ", $q['ping_status'] );
    3071                 }
    3072 
    3073                 if ( 'any' == $post_type ) {
    3074                         $in_search_post_types = get_post_types( array('exclude_from_search' => false) );
    3075                         if ( empty( $in_search_post_types ) ) {
    3076                                 $where .= ' AND 1=0 ';
    3077                         } else {
    3078                                 $where .= " AND {$this->db->posts}.post_type IN ('" . join("', '", $in_search_post_types ) . "')";
    3079                         }
    3080                 } elseif ( !empty( $post_type ) && is_array( $post_type ) ) {
    3081                         $where .= " AND {$this->db->posts}.post_type IN ('" . join("', '", $post_type) . "')";
    3082                 } elseif ( ! empty( $post_type ) ) {
    3083                         $where .= " AND {$this->db->posts}.post_type = '$post_type'";
    3084                         $post_type_object = get_post_type_object ( $post_type );
    3085                 } elseif ( $this->is_attachment ) {
    3086                         $where .= " AND {$this->db->posts}.post_type = 'attachment'";
    3087                         $post_type_object = get_post_type_object ( 'attachment' );
    3088                 } elseif ( $this->is_page ) {
    3089                         $where .= " AND {$this->db->posts}.post_type = 'page'";
    3090                         $post_type_object = get_post_type_object ( 'page' );
    3091                 } else {
    3092                         $where .= " AND {$this->db->posts}.post_type = 'post'";
    3093                         $post_type_object = get_post_type_object ( 'post' );
    3094                 }
    3095 
    3096                 $edit_cap = 'edit_post';
    3097                 $read_cap = 'read_post';
    3098 
    3099                 if ( ! empty( $post_type_object ) ) {
    3100                         $edit_others_cap = $post_type_object->cap->edit_others_posts;
    3101                         $read_private_cap = $post_type_object->cap->read_private_posts;
    3102                 } else {
    3103                         $edit_others_cap = 'edit_others_' . $post_type_cap . 's';
    3104                         $read_private_cap = 'read_private_' . $post_type_cap . 's';
    3105                 }
    3106 
    3107                 $user_id = get_current_user_id();
    3108 
    3109                 $q_status = array();
    3110                 if ( ! empty( $q['post_status'] ) ) {
    3111                         $statuswheres = array();
    3112                         $q_status = $q['post_status'];
    3113                         if ( ! is_array( $q_status ) )
    3114                                 $q_status = explode(',', $q_status);
    3115                         $r_status = array();
    3116                         $p_status = array();
    3117                         $e_status = array();
    3118                         if ( in_array( 'any', $q_status ) ) {
    3119                                 foreach ( get_post_stati( array( 'exclude_from_search' => true ) ) as $status ) {
    3120                                         if ( ! in_array( $status, $q_status ) ) {
    3121                                                 $e_status[] = "{$this->db->posts}.post_status <> '$status'";
    3122                                         }
    3123                                 }
    3124                         } else {
    3125                                 foreach ( get_post_stati() as $status ) {
    3126                                         if ( in_array( $status, $q_status ) ) {
    3127                                                 if ( 'private' == $status ) {
    3128                                                         $p_status[] = "{$this->db->posts}.post_status = '$status'";
    3129                                                 } else {
    3130                                                         $r_status[] = "{$this->db->posts}.post_status = '$status'";
    3131                                                 }
    3132                                         }
    3133                                 }
    3134                         }
    3135 
    3136                         if ( empty($q['perm'] ) || 'readable' != $q['perm'] ) {
    3137                                 $r_status = array_merge($r_status, $p_status);
    3138                                 unset($p_status);
    3139                         }
    3140 
    3141                         if ( !empty($e_status) ) {
    3142                                 $statuswheres[] = "(" . join( ' AND ', $e_status ) . ")";
    3143                         }
    3144                         if ( !empty($r_status) ) {
    3145                                 if ( !empty($q['perm'] ) && 'editable' == $q['perm'] && !current_user_can($edit_others_cap) ) {
    3146                                         $statuswheres[] = "({$this->db->posts}.post_author = $user_id " . "AND (" . join( ' OR ', $r_status ) . "))";
    3147                                 } else {
    3148                                         $statuswheres[] = "(" . join( ' OR ', $r_status ) . ")";
    3149                                 }
    3150                         }
    3151                         if ( !empty($p_status) ) {
    3152                                 if ( !empty($q['perm'] ) && 'readable' == $q['perm'] && !current_user_can($read_private_cap) ) {
    3153                                         $statuswheres[] = "({$this->db->posts}.post_author = $user_id " . "AND (" . join( ' OR ', $p_status ) . "))";
    3154                                 } else {
    3155                                         $statuswheres[] = "(" . join( ' OR ', $p_status ) . ")";
    3156                                 }
    3157                         }
    3158                         if ( $post_status_join ) {
    3159                                 $join .= " LEFT JOIN {$this->db->posts} AS p2 ON ({$this->db->posts}.post_parent = p2.ID) ";
    3160                                 foreach ( $statuswheres as $index => $statuswhere ) {
    3161                                         $statuswheres[$index] = "($statuswhere OR ({$this->db->posts}.post_status = 'inherit' AND " . str_replace( $this->db->posts, 'p2', $statuswhere ) . "))";
    3162                                 }
    3163                         }
    3164                         $where_status = implode( ' OR ', $statuswheres );
    3165                         if ( ! empty( $where_status ) ) {
    3166                                 $where .= " AND ($where_status)";
    3167                         }
    3168                 } elseif ( !$this->is_singular ) {
    3169                         $where .= " AND ({$this->db->posts}.post_status = 'publish'";
    3170 
    3171                         // Add public states.
    3172                         $public_states = get_post_stati( array('public' => true) );
    3173                         foreach ( (array) $public_states as $state ) {
    3174                                 if ( 'publish' == $state ) // Publish is hard-coded above.
    3175                                         continue;
    3176                                 $where .= " OR {$this->db->posts}.post_status = '$state'";
    3177                         }
    3178 
    3179                         if ( $this->is_admin ) {
    3180                                 // Add protected states that should show in the admin all list.
    3181                                 $admin_all_states = get_post_stati( array('protected' => true, 'show_in_admin_all_list' => true) );
    3182                                 foreach ( (array) $admin_all_states as $state ) {
    3183                                         $where .= " OR {$this->db->posts}.post_status = '$state'";
    3184                                 }
    3185                         }
    3186 
    3187                         if ( is_user_logged_in() ) {
    3188                                 // Add private states that are limited to viewing by the author of a post or someone who has caps to read private states.
    3189                                 $private_states = get_post_stati( array('private' => true) );
    3190                                 foreach ( (array) $private_states as $state ) {
    3191                                         $where .= current_user_can( $read_private_cap ) ? " OR {$this->db->posts}.post_status = '$state'" : " OR {$this->db->posts}.post_author = $user_id AND {$this->db->posts}.post_status = '$state'";
    3192                                 }
    3193                         }
    3194 
    3195                         $where .= ')';
    3196                 }
    3197 
    3198                 /*
    3199                  * Apply filters on where and join prior to paging so that any
    3200                  * manipulations to them are reflected in the paging by day queries.
    3201                  */
    3202                 if ( !$q['suppress_filters'] ) {
    3203                         /**
    3204                          * Filters the WHERE clause of the query.
    3205                          *
    3206                          * @since 1.5.0
    3207                          *
    3208                          * @param string   $where The WHERE clause of the query.
    3209                          * @param WP_Query &$this The WP_Query instance (passed by reference).
    3210                          */
    3211                         $where = apply_filters_ref_array( 'posts_where', array( $where, &$this ) );
    3212 
    3213                         /**
    3214                          * Filters the JOIN clause of the query.
    3215                          *
    3216                          * @since 1.5.0
    3217                          *
    3218                          * @param string   $where The JOIN clause of the query.
    3219                          * @param WP_Query &$this The WP_Query instance (passed by reference).
    3220                          */
    3221                         $join = apply_filters_ref_array( 'posts_join', array( $join, &$this ) );
    3222                 }
    3223 
    3224                 // Paging
    3225                 if ( empty($q['nopaging']) && !$this->is_singular ) {
    3226                         $page = absint($q['paged']);
    3227                         if ( !$page )
    3228                                 $page = 1;
    3229 
    3230                         // If 'offset' is provided, it takes precedence over 'paged'.
    3231                         if ( isset( $q['offset'] ) && is_numeric( $q['offset'] ) ) {
    3232                                 $q['offset'] = absint( $q['offset'] );
    3233                                 $pgstrt = $q['offset'] . ', ';
    3234                         } else {
    3235                                 $pgstrt = absint( ( $page - 1 ) * $q['posts_per_page'] ) . ', ';
    3236                         }
    3237                         $limits = 'LIMIT ' . $pgstrt . $q['posts_per_page'];
    3238                 }
    3239 
    3240                 // Comments feeds
    3241                 if ( $this->is_comment_feed && ! $this->is_singular ) {
    3242                         if ( $this->is_archive || $this->is_search ) {
    3243                                 $cjoin = "JOIN {$this->db->posts} ON ({$this->db->comments}.comment_post_ID = {$this->db->posts}.ID) $join ";
    3244                                 $cwhere = "WHERE comment_approved = '1' $where";
    3245                                 $cgroupby = "{$this->db->comments}.comment_id";
    3246                         } else { // Other non singular e.g. front
    3247                                 $cjoin = "JOIN {$this->db->posts} ON ( {$this->db->comments}.comment_post_ID = {$this->db->posts}.ID )";
    3248                                 $cwhere = "WHERE ( post_status = 'publish' OR ( post_status = 'inherit' && post_type = 'attachment' ) ) AND comment_approved = '1'";
    3249                                 $cgroupby = '';
    3250                         }
    3251 
    3252                         if ( !$q['suppress_filters'] ) {
    3253                                 /**
    3254                                  * Filters the JOIN clause of the comments feed query before sending.
    3255                                  *
    3256                                  * @since 2.2.0
    3257                                  *
    3258                                  * @param string   $cjoin The JOIN clause of the query.
    3259                                  * @param WP_Query &$this The WP_Query instance (passed by reference).
    3260                                  */
    3261                                 $cjoin = apply_filters_ref_array( 'comment_feed_join', array( $cjoin, &$this ) );
    3262 
    3263                                 /**
    3264                                  * Filters the WHERE clause of the comments feed query before sending.
    3265                                  *
    3266                                  * @since 2.2.0
    3267                                  *
    3268                                  * @param string   $cwhere The WHERE clause of the query.
    3269                                  * @param WP_Query &$this  The WP_Query instance (passed by reference).
    3270                                  */
    3271                                 $cwhere = apply_filters_ref_array( 'comment_feed_where', array( $cwhere, &$this ) );
    3272 
    3273                                 /**
    3274                                  * Filters the GROUP BY clause of the comments feed query before sending.
    3275                                  *
    3276                                  * @since 2.2.0
    3277                                  *
    3278                                  * @param string   $cgroupby The GROUP BY clause of the query.
    3279                                  * @param WP_Query &$this    The WP_Query instance (passed by reference).
    3280                                  */
    3281                                 $cgroupby = apply_filters_ref_array( 'comment_feed_groupby', array( $cgroupby, &$this ) );
    3282 
    3283                                 /**
    3284                                  * Filters the ORDER BY clause of the comments feed query before sending.
    3285                                  *
    3286                                  * @since 2.8.0
    3287                                  *
    3288                                  * @param string   $corderby The ORDER BY clause of the query.
    3289                                  * @param WP_Query &$this    The WP_Query instance (passed by reference).
    3290                                  */
    3291                                 $corderby = apply_filters_ref_array( 'comment_feed_orderby', array( 'comment_date_gmt DESC', &$this ) );
    3292 
    3293                                 /**
    3294                                  * Filters the LIMIT clause of the comments feed query before sending.
    3295                                  *
    3296                                  * @since 2.8.0
    3297                                  *
    3298                                  * @param string   $climits The JOIN clause of the query.
    3299                                  * @param WP_Query &$this   The WP_Query instance (passed by reference).
    3300                                  */
    3301                                 $climits = apply_filters_ref_array( 'comment_feed_limits', array( 'LIMIT ' . get_option('posts_per_rss'), &$this ) );
    3302                         }
    3303                         $cgroupby = ( ! empty( $cgroupby ) ) ? 'GROUP BY ' . $cgroupby : '';
    3304                         $corderby = ( ! empty( $corderby ) ) ? 'ORDER BY ' . $corderby : '';
    3305 
    3306                         $comments = (array) $this->db->get_results("SELECT $distinct {$this->db->comments}.* FROM {$this->db->comments} $cjoin $cwhere $cgroupby $corderby $climits");
    3307                         // Convert to WP_Comment
    3308                         $this->comments = array_map( 'get_comment', $comments );
    3309                         $this->comment_count = count($this->comments);
    3310 
    3311                         $post_ids = array();
    3312 
    3313                         foreach ( $this->comments as $comment )
    3314                                 $post_ids[] = (int) $comment->comment_post_ID;
    3315 
    3316                         $post_ids = join(',', $post_ids);
    3317                         $join = '';
    3318                         if ( $post_ids ) {
    3319                                 $where = "AND {$this->db->posts}.ID IN ($post_ids) ";
    3320                         } else {
    3321                                 $where = "AND 0";
    3322                         }
    3323                 }
    3324 
    3325                 $pieces = array( 'where', 'groupby', 'join', 'orderby', 'distinct', 'fields', 'limits' );
    3326 
    3327                 /*
    3328                  * Apply post-paging filters on where and join. Only plugins that
    3329                  * manipulate paging queries should use these hooks.
    3330                  */
    3331                 if ( !$q['suppress_filters'] ) {
    3332                         /**
    3333                          * Filters the WHERE clause of the query.
    3334                          *
    3335                          * Specifically for manipulating paging queries.
    3336                          *
    3337                          * @since 1.5.0
    3338                          *
    3339                          * @param string   $where The WHERE clause of the query.
    3340                          * @param WP_Query &$this The WP_Query instance (passed by reference).
    3341                          */
    3342                         $where = apply_filters_ref_array( 'posts_where_paged', array( $where, &$this ) );
    3343 
    3344                         /**
    3345                          * Filters the GROUP BY clause of the query.
    3346                          *
    3347                          * @since 2.0.0
    3348                          *
    3349                          * @param string   $groupby The GROUP BY clause of the query.
    3350                          * @param WP_Query &$this   The WP_Query instance (passed by reference).
    3351                          */
    3352                         $groupby = apply_filters_ref_array( 'posts_groupby', array( $groupby, &$this ) );
    3353 
    3354                         /**
    3355                          * Filters the JOIN clause of the query.
    3356                          *
    3357                          * Specifically for manipulating paging queries.
    3358                          *
    3359                          * @since 1.5.0
    3360                          *
    3361                          * @param string   $join  The JOIN clause of the query.
    3362                          * @param WP_Query &$this The WP_Query instance (passed by reference).
    3363                          */
    3364                         $join = apply_filters_ref_array( 'posts_join_paged', array( $join, &$this ) );
    3365 
    3366                         /**
    3367                          * Filters the ORDER BY clause of the query.
    3368                          *
    3369                          * @since 1.5.1
    3370                          *
    3371                          * @param string   $orderby The ORDER BY clause of the query.
    3372                          * @param WP_Query &$this   The WP_Query instance (passed by reference).
    3373                          */
    3374                         $orderby = apply_filters_ref_array( 'posts_orderby', array( $orderby, &$this ) );
    3375 
    3376                         /**
    3377                          * Filters the DISTINCT clause of the query.
    3378                          *
    3379                          * @since 2.1.0
    3380                          *
    3381                          * @param string   $distinct The DISTINCT clause of the query.
    3382                          * @param WP_Query &$this    The WP_Query instance (passed by reference).
    3383                          */
    3384                         $distinct = apply_filters_ref_array( 'posts_distinct', array( $distinct, &$this ) );
    3385 
    3386                         /**
    3387                          * Filters the LIMIT clause of the query.
    3388                          *
    3389                          * @since 2.1.0
    3390                          *
    3391                          * @param string   $limits The LIMIT clause of the query.
    3392                          * @param WP_Query &$this  The WP_Query instance (passed by reference).
    3393                          */
    3394                         $limits = apply_filters_ref_array( 'post_limits', array( $limits, &$this ) );
    3395 
    3396                         /**
    3397                          * Filters the SELECT clause of the query.
    3398                          *
    3399                          * @since 2.1.0
    3400                          *
    3401                          * @param string   $fields The SELECT clause of the query.
    3402                          * @param WP_Query &$this  The WP_Query instance (passed by reference).
    3403                          */
    3404                         $fields = apply_filters_ref_array( 'posts_fields', array( $fields, &$this ) );
    3405 
    3406                         /**
    3407                          * Filters all query clauses at once, for convenience.
    3408                          *
    3409                          * Covers the WHERE, GROUP BY, JOIN, ORDER BY, DISTINCT,
    3410                          * fields (SELECT), and LIMITS clauses.
    3411                          *
    3412                          * @since 3.1.0
    3413                          *
    3414                          * @param array    $clauses The list of clauses for the query.
    3415                          * @param WP_Query &$this   The WP_Query instance (passed by reference).
    3416                          */
    3417                         $clauses = (array) apply_filters_ref_array( 'posts_clauses', array( compact( $pieces ), &$this ) );
    3418 
    3419                         $where = isset( $clauses[ 'where' ] ) ? $clauses[ 'where' ] : '';
    3420                         $groupby = isset( $clauses[ 'groupby' ] ) ? $clauses[ 'groupby' ] : '';
    3421                         $join = isset( $clauses[ 'join' ] ) ? $clauses[ 'join' ] : '';
    3422                         $orderby = isset( $clauses[ 'orderby' ] ) ? $clauses[ 'orderby' ] : '';
    3423                         $distinct = isset( $clauses[ 'distinct' ] ) ? $clauses[ 'distinct' ] : '';
    3424                         $fields = isset( $clauses[ 'fields' ] ) ? $clauses[ 'fields' ] : '';
    3425                         $limits = isset( $clauses[ 'limits' ] ) ? $clauses[ 'limits' ] : '';
    3426                 }
    3427 
    3428                 /**
    3429                  * Fires to announce the query's current selection parameters.
    3430                  *
    3431                  * For use by caching plugins.
    3432                  *
    3433                  * @since 2.3.0
    3434                  *
    3435                  * @param string $selection The assembled selection query.
    3436                  */
    3437                 do_action( 'posts_selection', $where . $groupby . $orderby . $limits . $join );
    3438 
    3439                 /*
    3440                  * Filters again for the benefit of caching plugins.
    3441                  * Regular plugins should use the hooks above.
    3442                  */
    3443                 if ( !$q['suppress_filters'] ) {
    3444                         /**
    3445                          * Filters the WHERE clause of the query.
    3446                          *
    3447                          * For use by caching plugins.
    3448                          *
    3449                          * @since 2.5.0
    3450                          *
    3451                          * @param string   $where The WHERE clause of the query.
    3452                          * @param WP_Query &$this The WP_Query instance (passed by reference).
    3453                          */
    3454                         $where = apply_filters_ref_array( 'posts_where_request', array( $where, &$this ) );
    3455 
    3456                         /**
    3457                          * Filters the GROUP BY clause of the query.
    3458                          *
    3459                          * For use by caching plugins.
    3460                          *
    3461                          * @since 2.5.0
    3462                          *
    3463                          * @param string   $groupby The GROUP BY clause of the query.
    3464                          * @param WP_Query &$this   The WP_Query instance (passed by reference).
    3465                          */
    3466                         $groupby = apply_filters_ref_array( 'posts_groupby_request', array( $groupby, &$this ) );
    3467 
    3468                         /**
    3469                          * Filters the JOIN clause of the query.
    3470                          *
    3471                          * For use by caching plugins.
    3472                          *
    3473                          * @since 2.5.0
    3474                          *
    3475                          * @param string   $join  The JOIN clause of the query.
    3476                          * @param WP_Query &$this The WP_Query instance (passed by reference).
    3477                          */
    3478                         $join = apply_filters_ref_array( 'posts_join_request', array( $join, &$this ) );
    3479 
    3480                         /**
    3481                          * Filters the ORDER BY clause of the query.
    3482                          *
    3483                          * For use by caching plugins.
    3484                          *
    3485                          * @since 2.5.0
    3486                          *
    3487                          * @param string   $orderby The ORDER BY clause of the query.
    3488                          * @param WP_Query &$this   The WP_Query instance (passed by reference).
    3489                          */
    3490                         $orderby = apply_filters_ref_array( 'posts_orderby_request', array( $orderby, &$this ) );
    3491 
    3492                         /**
    3493                          * Filters the DISTINCT clause of the query.
    3494                          *
    3495                          * For use by caching plugins.
    3496                          *
    3497                          * @since 2.5.0
    3498                          *
    3499                          * @param string   $distinct The DISTINCT clause of the query.
    3500                          * @param WP_Query &$this    The WP_Query instance (passed by reference).
    3501                          */
    3502                         $distinct = apply_filters_ref_array( 'posts_distinct_request', array( $distinct, &$this ) );
    3503 
    3504                         /**
    3505                          * Filters the SELECT clause of the query.
    3506                          *
    3507                          * For use by caching plugins.
    3508                          *
    3509                          * @since 2.5.0
    3510                          *
    3511                          * @param string   $fields The SELECT clause of the query.
    3512                          * @param WP_Query &$this  The WP_Query instance (passed by reference).
    3513                          */
    3514                         $fields = apply_filters_ref_array( 'posts_fields_request', array( $fields, &$this ) );
    3515 
    3516                         /**
    3517                          * Filters the LIMIT clause of the query.
    3518                          *
    3519                          * For use by caching plugins.
    3520                          *
    3521                          * @since 2.5.0
    3522                          *
    3523                          * @param string   $limits The LIMIT clause of the query.
    3524                          * @param WP_Query &$this  The WP_Query instance (passed by reference).
    3525                          */
    3526                         $limits = apply_filters_ref_array( 'post_limits_request', array( $limits, &$this ) );
    3527 
    3528                         /**
    3529                          * Filters all query clauses at once, for convenience.
    3530                          *
    3531                          * For use by caching plugins.
    3532                          *
    3533                          * Covers the WHERE, GROUP BY, JOIN, ORDER BY, DISTINCT,
    3534                          * fields (SELECT), and LIMITS clauses.
    3535                          *
    3536                          * @since 3.1.0
    3537                          *
    3538                          * @param array    $pieces The pieces of the query.
    3539                          * @param WP_Query &$this  The WP_Query instance (passed by reference).
    3540                          */
    3541                         $clauses = (array) apply_filters_ref_array( 'posts_clauses_request', array( compact( $pieces ), &$this ) );
    3542 
    3543                         $where = isset( $clauses[ 'where' ] ) ? $clauses[ 'where' ] : '';
    3544                         $groupby = isset( $clauses[ 'groupby' ] ) ? $clauses[ 'groupby' ] : '';
    3545                         $join = isset( $clauses[ 'join' ] ) ? $clauses[ 'join' ] : '';
    3546                         $orderby = isset( $clauses[ 'orderby' ] ) ? $clauses[ 'orderby' ] : '';
    3547                         $distinct = isset( $clauses[ 'distinct' ] ) ? $clauses[ 'distinct' ] : '';
    3548                         $fields = isset( $clauses[ 'fields' ] ) ? $clauses[ 'fields' ] : '';
    3549                         $limits = isset( $clauses[ 'limits' ] ) ? $clauses[ 'limits' ] : '';
    3550                 }
    3551 
    3552                 if ( ! empty($groupby) )
    3553                         $groupby = 'GROUP BY ' . $groupby;
    3554                 if ( !empty( $orderby ) )
    3555                         $orderby = 'ORDER BY ' . $orderby;
    3556 
    3557                 $found_rows = '';
    3558                 if ( !$q['no_found_rows'] && !empty($limits) )
    3559                         $found_rows = 'SQL_CALC_FOUND_ROWS';
    3560 
    3561                 $this->request = $old_request = "SELECT $found_rows $distinct $fields FROM {$this->db->posts} $join WHERE 1=1 $where $groupby $orderby $limits";
    3562 
    3563                 if ( !$q['suppress_filters'] ) {
    3564                         /**
    3565                          * Filters the completed SQL query before sending.
    3566                          *
    3567                          * @since 2.0.0
    3568                          *
    3569                          * @param string   $request The complete SQL query.
    3570                          * @param WP_Query &$this   The WP_Query instance (passed by reference).
    3571                          */
    3572                         $this->request = apply_filters_ref_array( 'posts_request', array( $this->request, &$this ) );
    3573                 }
    3574 
    3575                 /**
    3576                  * Filters the posts array before the query takes place.
    3577                  *
    3578                  * Return a non-null value to bypass WordPress's default post queries.
    3579                  *
    3580                  * Filtering functions that require pagination information are encouraged to set
    3581                  * the `found_posts` and `max_num_pages` properties of the WP_Query object,
    3582                  * passed to the filter by reference. If WP_Query does not perform a database
    3583                  * query, it will not have enough information to generate these values itself.
    3584                  *
    3585                  * @since 4.6.0
    3586                  *
    3587                  * @param array|null $posts Return an array of post data to short-circuit WP's query,
    3588                  *                          or null to allow WP to run its normal queries.
    3589                  * @param WP_Query   $this  The WP_Query instance, passed by reference.
    3590                  */
    3591                 $this->posts = apply_filters_ref_array( 'posts_pre_query', array( null, &$this ) );
    3592 
    3593                 if ( 'ids' == $q['fields'] ) {
    3594                         if ( null === $this->posts ) {
    3595                                 $this->posts = $this->db->get_col( $this->request );
    3596                         }
    3597 
    3598                         $this->posts = array_map( 'intval', $this->posts );
    3599                         $this->post_count = count( $this->posts );
    3600                         $this->set_found_posts( $q, $limits );
    3601 
    3602                         return $this->posts;
    3603                 }
    3604 
    3605                 if ( 'id=>parent' == $q['fields'] ) {
    3606                         if ( null === $this->posts ) {
    3607                                 $this->posts = $this->db->get_results( $this->request );
    3608                         }
    3609 
    3610                         $this->post_count = count( $this->posts );
    3611                         $this->set_found_posts( $q, $limits );
    3612 
    3613                         $r = array();
    3614                         foreach ( $this->posts as $key => $post ) {
    3615                                 $this->posts[ $key ]->ID = (int) $post->ID;
    3616                                 $this->posts[ $key ]->post_parent = (int) $post->post_parent;
    3617 
    3618                                 $r[ (int) $post->ID ] = (int) $post->post_parent;
    3619                         }
    3620 
    3621                         return $r;
    3622                 }
    3623 
    3624                 if ( null === $this->posts ) {
    3625                         $split_the_query = ( $old_request == $this->request && "{$this->db->posts}.*" == $fields && !empty( $limits ) && $q['posts_per_page'] < 500 );
    3626 
    3627                         /**
    3628                          * Filters whether to split the query.
    3629                          *
    3630                          * Splitting the query will cause it to fetch just the IDs of the found posts
    3631                          * (and then individually fetch each post by ID), rather than fetching every
    3632                          * complete row at once. One massive result vs. many small results.
    3633                          *
    3634                          * @since 3.4.0
    3635                          *
    3636                          * @param bool     $split_the_query Whether or not to split the query.
    3637                          * @param WP_Query $this            The WP_Query instance.
    3638                          */
    3639                         $split_the_query = apply_filters( 'split_the_query', $split_the_query, $this );
    3640 
    3641                         if ( $split_the_query ) {
    3642                                 // First get the IDs and then fill in the objects
    3643 
    3644                                 $this->request = "SELECT $found_rows $distinct {$this->db->posts}.ID FROM {$this->db->posts} $join WHERE 1=1 $where $groupby $orderby $limits";
    3645 
    3646                                 /**
    3647                                  * Filters the Post IDs SQL request before sending.
    3648                                  *
    3649                                  * @since 3.4.0
    3650                                  *
    3651                                  * @param string   $request The post ID request.
    3652                                  * @param WP_Query $this    The WP_Query instance.
    3653                                  */
    3654                                 $this->request = apply_filters( 'posts_request_ids', $this->request, $this );
    3655 
    3656                                 $ids = $this->db->get_col( $this->request );
    3657 
    3658                                 if ( $ids ) {
    3659                                         $this->posts = $ids;
    3660                                         $this->set_found_posts( $q, $limits );
    3661                                         _prime_post_caches( $ids, $q['update_post_term_cache'], $q['update_post_meta_cache'] );
    3662                                 } else {
    3663                                         $this->posts = array();
    3664                                 }
    3665                         } else {
    3666                                 $this->posts = $this->db->get_results( $this->request );
    3667                                 $this->set_found_posts( $q, $limits );
    3668                         }
    3669                 }
    3670 
    3671                 // Convert to WP_Post objects.
    3672                 if ( $this->posts ) {
    3673                         $this->posts = array_map( 'get_post', $this->posts );
    3674                 }
    3675 
    3676                 if ( ! $q['suppress_filters'] ) {
    3677                         /**
    3678                          * Filters the raw post results array, prior to status checks.
    3679                          *
    3680                          * @since 2.3.0
    3681                          *
    3682                          * @param array    $posts The post results array.
    3683                          * @param WP_Query &$this The WP_Query instance (passed by reference).
    3684                          */
    3685                         $this->posts = apply_filters_ref_array( 'posts_results', array( $this->posts, &$this ) );
    3686                 }
    3687 
    3688                 if ( !empty($this->posts) && $this->is_comment_feed && $this->is_singular ) {
    3689                         /** This filter is documented in wp-includes/query.php */
    3690                         $cjoin = apply_filters_ref_array( 'comment_feed_join', array( '', &$this ) );
    3691 
    3692                         /** This filter is documented in wp-includes/query.php */
    3693                         $cwhere = apply_filters_ref_array( 'comment_feed_where', array( "WHERE comment_post_ID = '{$this->posts[0]->ID}' AND comment_approved = '1'", &$this ) );
    3694 
    3695                         /** This filter is documented in wp-includes/query.php */
    3696                         $cgroupby = apply_filters_ref_array( 'comment_feed_groupby', array( '', &$this ) );
    3697                         $cgroupby = ( ! empty( $cgroupby ) ) ? 'GROUP BY ' . $cgroupby : '';
    3698 
    3699                         /** This filter is documented in wp-includes/query.php */
    3700                         $corderby = apply_filters_ref_array( 'comment_feed_orderby', array( 'comment_date_gmt DESC', &$this ) );
    3701                         $corderby = ( ! empty( $corderby ) ) ? 'ORDER BY ' . $corderby : '';
    3702 
    3703                         /** This filter is documented in wp-includes/query.php */
    3704                         $climits = apply_filters_ref_array( 'comment_feed_limits', array( 'LIMIT ' . get_option('posts_per_rss'), &$this ) );
    3705 
    3706                         $comments_request = "SELECT {$this->db->comments}.* FROM {$this->db->comments} $cjoin $cwhere $cgroupby $corderby $climits";
    3707                         $comments = $this->db->get_results($comments_request);
    3708                         // Convert to WP_Comment
    3709                         $this->comments = array_map( 'get_comment', $comments );
    3710                         $this->comment_count = count($this->comments);
    3711                 }
    3712 
    3713                 // Check post status to determine if post should be displayed.
    3714                 if ( !empty($this->posts) && ($this->is_single || $this->is_page) ) {
    3715                         $status = get_post_status($this->posts[0]);
    3716                         if ( 'attachment' === $this->posts[0]->post_type && 0 === (int) $this->posts[0]->post_parent ) {
    3717                                 $this->is_page = false;
    3718                                 $this->is_single = true;
    3719                                 $this->is_attachment = true;
    3720                         }
    3721                         $post_status_obj = get_post_status_object($status);
    3722 
    3723                         // If the post_status was specifically requested, let it pass through.
    3724                         if ( !$post_status_obj->public && ! in_array( $status, $q_status ) ) {
    3725 
    3726                                 if ( ! is_user_logged_in() ) {
    3727                                         // User must be logged in to view unpublished posts.
    3728                                         $this->posts = array();
    3729                                 } else {
    3730                                         if  ( $post_status_obj->protected ) {
    3731                                                 // User must have edit permissions on the draft to preview.
    3732                                                 if ( ! current_user_can($edit_cap, $this->posts[0]->ID) ) {
    3733                                                         $this->posts = array();
    3734                                                 } else {
    3735                                                         $this->is_preview = true;
    3736                                                         if ( 'future' != $status )
    3737                                                                 $this->posts[0]->post_date = current_time('mysql');
    3738                                                 }
    3739                                         } elseif ( $post_status_obj->private ) {
    3740                                                 if ( ! current_user_can($read_cap, $this->posts[0]->ID) )
    3741                                                         $this->posts = array();
    3742                                         } else {
    3743                                                 $this->posts = array();
    3744                                         }
    3745                                 }
    3746                         }
    3747 
    3748                         if ( $this->is_preview && $this->posts && current_user_can( $edit_cap, $this->posts[0]->ID ) ) {
    3749                                 /**
    3750                                  * Filters the single post for preview mode.
    3751                                  *
    3752                                  * @since 2.7.0
    3753                                  *
    3754                                  * @param WP_Post  $post_preview  The Post object.
    3755                                  * @param WP_Query &$this         The WP_Query instance (passed by reference).
    3756                                  */
    3757                                 $this->posts[0] = get_post( apply_filters_ref_array( 'the_preview', array( $this->posts[0], &$this ) ) );
    3758                         }
    3759                 }
    3760 
    3761                 // Put sticky posts at the top of the posts array
    3762                 $sticky_posts = get_option('sticky_posts');
    3763                 if ( $this->is_home && $page <= 1 && is_array($sticky_posts) && !empty($sticky_posts) && !$q['ignore_sticky_posts'] ) {
    3764                         $num_posts = count($this->posts);
    3765                         $sticky_offset = 0;
    3766                         // Loop over posts and relocate stickies to the front.
    3767                         for ( $i = 0; $i < $num_posts; $i++ ) {
    3768                                 if ( in_array($this->posts[$i]->ID, $sticky_posts) ) {
    3769                                         $sticky_post = $this->posts[$i];
    3770                                         // Remove sticky from current position
    3771                                         array_splice($this->posts, $i, 1);
    3772                                         // Move to front, after other stickies
    3773                                         array_splice($this->posts, $sticky_offset, 0, array($sticky_post));
    3774                                         // Increment the sticky offset. The next sticky will be placed at this offset.
    3775                                         $sticky_offset++;
    3776                                         // Remove post from sticky posts array
    3777                                         $offset = array_search($sticky_post->ID, $sticky_posts);
    3778                                         unset( $sticky_posts[$offset] );
    3779                                 }
    3780                         }
    3781 
    3782                         // If any posts have been excluded specifically, Ignore those that are sticky.
    3783                         if ( !empty($sticky_posts) && !empty($q['post__not_in']) )
    3784                                 $sticky_posts = array_diff($sticky_posts, $q['post__not_in']);
    3785 
    3786                         // Fetch sticky posts that weren't in the query results
    3787                         if ( !empty($sticky_posts) ) {
    3788                                 $stickies = get_posts( array(
    3789                                         'post__in' => $sticky_posts,
    3790                                         'post_type' => $post_type,
    3791                                         'post_status' => 'publish',
    3792                                         'nopaging' => true
    3793                                 ) );
    3794 
    3795                                 foreach ( $stickies as $sticky_post ) {
    3796                                         array_splice( $this->posts, $sticky_offset, 0, array( $sticky_post ) );
    3797                                         $sticky_offset++;
    3798                                 }
    3799                         }
    3800                 }
    3801 
    3802                 // If comments have been fetched as part of the query, make sure comment meta lazy-loading is set up.
    3803                 if ( ! empty( $this->comments ) ) {
    3804                         wp_queue_comments_for_comment_meta_lazyload( $this->comments );
    3805                 }
    3806 
    3807                 if ( ! $q['suppress_filters'] ) {
    3808                         /**
    3809                          * Filters the array of retrieved posts after they've been fetched and
    3810                          * internally processed.
    3811                          *
    3812                          * @since 1.5.0
    3813                          *
    3814                          * @param array    $posts The array of retrieved posts.
    3815                          * @param WP_Query &$this The WP_Query instance (passed by reference).
    3816                          */
    3817                         $this->posts = apply_filters_ref_array( 'the_posts', array( $this->posts, &$this ) );
    3818                 }
    3819 
    3820                 // Ensure that any posts added/modified via one of the filters above are
    3821                 // of the type WP_Post and are filtered.
    3822                 if ( $this->posts ) {
    3823                         $this->post_count = count( $this->posts );
    3824 
    3825                         $this->posts = array_map( 'get_post', $this->posts );
    3826 
    3827                         if ( $q['cache_results'] )
    3828                                 update_post_caches($this->posts, $post_type, $q['update_post_term_cache'], $q['update_post_meta_cache']);
    3829 
    3830                         $this->post = reset( $this->posts );
    3831                 } else {
    3832                         $this->post_count = 0;
    3833                         $this->posts = array();
    3834                 }
    3835 
    3836                 if ( $q['lazy_load_term_meta'] ) {
    3837                         wp_queue_posts_for_term_meta_lazyload( $this->posts );
    3838                 }
    3839 
    3840                 return $this->posts;
    3841         }
    3842 
    3843         /**
    3844          * Set up the amount of found posts and the number of pages (if limit clause was used)
    3845          * for the current query.
    3846          *
    3847          * @since 3.5.0
    3848          * @access private
    3849          *
    3850          * @param array  $q      Query variables.
    3851          * @param string $limits LIMIT clauses of the query.
    3852          */
    3853         private function set_found_posts( $q, $limits ) {
    3854                 // Bail if posts is an empty array. Continue if posts is an empty string,
    3855                 // null, or false to accommodate caching plugins that fill posts later.
    3856                 if ( $q['no_found_rows'] || ( is_array( $this->posts ) && ! $this->posts ) )
    3857                         return;
    3858 
    3859                 if ( ! empty( $limits ) ) {
    3860                         /**
    3861                          * Filters the query to run for retrieving the found posts.
    3862                          *
    3863                          * @since 2.1.0
    3864                          *
    3865                          * @param string   $found_posts The query to run to find the found posts.
    3866                          * @param WP_Query &$this       The WP_Query instance (passed by reference).
    3867                          */
    3868                         $this->found_posts = $this->db->get_var( apply_filters_ref_array( 'found_posts_query', array( 'SELECT FOUND_ROWS()', &$this ) ) );
    3869                 } else {
    3870                         $this->found_posts = count( $this->posts );
    3871                 }
    3872 
    3873                 /**
    3874                  * Filters the number of found posts for the query.
    3875                  *
    3876                  * @since 2.1.0
    3877                  *
    3878                  * @param int      $found_posts The number of posts found.
    3879                  * @param WP_Query &$this       The WP_Query instance (passed by reference).
    3880                  */
    3881                 $this->found_posts = apply_filters_ref_array( 'found_posts', array( $this->found_posts, &$this ) );
    3882 
    3883                 if ( ! empty( $limits ) )
    3884                         $this->max_num_pages = ceil( $this->found_posts / $q['posts_per_page'] );
    3885         }
    3886 
    3887         /**
    3888          * Set up the next post and iterate current post index.
    3889          *
    3890          * @since 1.5.0
    3891          * @access public
    3892          *
    3893          * @return WP_Post Next post.
    3894          */
    3895         public function next_post() {
    3896 
    3897                 $this->current_post++;
    3898 
    3899                 $this->post = $this->posts[$this->current_post];
    3900                 return $this->post;
    3901         }
    3902 
    3903         /**
    3904          * Sets up the current post.
    3905          *
    3906          * Retrieves the next post, sets up the post, sets the 'in the loop'
    3907          * property to true.
    3908          *
    3909          * @since 1.5.0
    3910          * @access public
    3911          *
    3912          * @global WP_Post $post
    3913          */
    3914         public function the_post() {
    3915                 global $post;
    3916                 $this->in_the_loop = true;
    3917 
    3918                 if ( $this->current_post == -1 ) // loop has just started
    3919                         /**
    3920                          * Fires once the loop is started.
    3921                          *
    3922                          * @since 2.0.0
    3923                          *
    3924                          * @param WP_Query &$this The WP_Query instance (passed by reference).
    3925                          */
    3926                         do_action_ref_array( 'loop_start', array( &$this ) );
    3927 
    3928                 $post = $this->next_post();
    3929                 $this->setup_postdata( $post );
    3930         }
    3931 
    3932         /**
    3933          * Determines whether there are more posts available in the loop.
    3934          *
    3935          * Calls the {@see 'loop_end'} action when the loop is complete.
    3936          *
    3937          * @since 1.5.0
    3938          * @access public
    3939          *
    3940          * @return bool True if posts are available, false if end of loop.
    3941          */
    3942         public function have_posts() {
    3943                 if ( $this->current_post + 1 < $this->post_count ) {
    3944                         return true;
    3945                 } elseif ( $this->current_post + 1 == $this->post_count && $this->post_count > 0 ) {
    3946                         /**
    3947                          * Fires once the loop has ended.
    3948                          *
    3949                          * @since 2.0.0
    3950                          *
    3951                          * @param WP_Query &$this The WP_Query instance (passed by reference).
    3952                          */
    3953                         do_action_ref_array( 'loop_end', array( &$this ) );
    3954                         // Do some cleaning up after the loop
    3955                         $this->rewind_posts();
    3956                 }
    3957 
    3958                 $this->in_the_loop = false;
    3959                 return false;
    3960         }
    3961 
    3962         /**
    3963          * Rewind the posts and reset post index.
    3964          *
    3965          * @since 1.5.0
    3966          * @access public
    3967          */
    3968         public function rewind_posts() {
    3969                 $this->current_post = -1;
    3970                 if ( $this->post_count > 0 ) {
    3971                         $this->post = $this->posts[0];
    3972                 }
    3973         }
    3974 
    3975         /**
    3976          * Iterate current comment index and return WP_Comment object.
    3977          *
    3978          * @since 2.2.0
    3979          * @access public
    3980          *
    3981          * @return WP_Comment Comment object.
    3982          */
    3983         public function next_comment() {
    3984                 $this->current_comment++;
    3985 
    3986                 $this->comment = $this->comments[$this->current_comment];
    3987                 return $this->comment;
    3988         }
    3989 
    3990         /**
    3991          * Sets up the current comment.
    3992          *
    3993          * @since 2.2.0
    3994          * @access public
    3995          * @global WP_Comment $comment Current comment.
    3996          */
    3997         public function the_comment() {
    3998                 global $comment;
    3999 
    4000                 $comment = $this->next_comment();
    4001 
    4002                 if ( $this->current_comment == 0 ) {
    4003                         /**
    4004                          * Fires once the comment loop is started.
    4005                          *
    4006                          * @since 2.2.0
    4007                          */
    4008                         do_action( 'comment_loop_start' );
    4009                 }
    4010         }
    4011 
    4012         /**
    4013          * Whether there are more comments available.
    4014          *
    4015          * Automatically rewinds comments when finished.
    4016          *
    4017          * @since 2.2.0
    4018          * @access public
    4019          *
    4020          * @return bool True, if more comments. False, if no more posts.
    4021          */
    4022         public function have_comments() {
    4023                 if ( $this->current_comment + 1 < $this->comment_count ) {
    4024                         return true;
    4025                 } elseif ( $this->current_comment + 1 == $this->comment_count ) {
    4026                         $this->rewind_comments();
    4027                 }
    4028 
    4029                 return false;
    4030         }
    4031 
    4032         /**
    4033          * Rewind the comments, resets the comment index and comment to first.
    4034          *
    4035          * @since 2.2.0
    4036          * @access public
    4037          */
    4038         public function rewind_comments() {
    4039                 $this->current_comment = -1;
    4040                 if ( $this->comment_count > 0 ) {
    4041                         $this->comment = $this->comments[0];
    4042                 }
    4043         }
    4044 
    4045         /**
    4046          * Sets up the WordPress query by parsing query string.
    4047          *
    4048          * @since 1.5.0
    4049          * @access public
    4050          *
    4051          * @param string $query URL query string.
    4052          * @return array List of posts.
    4053          */
    4054         public function query( $query ) {
    4055                 $this->init();
    4056                 $this->query = $this->query_vars = wp_parse_args( $query );
    4057                 return $this->get_posts();
    4058         }
    4059 
    4060         /**
    4061          * Retrieve queried object.
    4062          *
    4063          * If queried object is not set, then the queried object will be set from
    4064          * the category, tag, taxonomy, posts page, single post, page, or author
    4065          * query variable. After it is set up, it will be returned.
    4066          *
    4067          * @since 1.5.0
    4068          * @access public
    4069          *
    4070          * @return object
    4071          */
    4072         public function get_queried_object() {
    4073                 if ( isset($this->queried_object) )
    4074                         return $this->queried_object;
    4075 
    4076                 $this->queried_object = null;
    4077                 $this->queried_object_id = null;
    4078 
    4079                 if ( $this->is_category || $this->is_tag || $this->is_tax ) {
    4080                         if ( $this->is_category ) {
    4081                                 if ( $this->get( 'cat' ) ) {
    4082                                         $term = get_term( $this->get( 'cat' ), 'category' );
    4083                                 } elseif ( $this->get( 'category_name' ) ) {
    4084                                         $term = get_term_by( 'slug', $this->get( 'category_name' ), 'category' );
    4085                                 }
    4086                         } elseif ( $this->is_tag ) {
    4087                                 if ( $this->get( 'tag_id' ) ) {
    4088                                         $term = get_term( $this->get( 'tag_id' ), 'post_tag' );
    4089                                 } elseif ( $this->get( 'tag' ) ) {
    4090                                         $term = get_term_by( 'slug', $this->get( 'tag' ), 'post_tag' );
    4091                                 }
    4092                         } else {
    4093                                 // For other tax queries, grab the first term from the first clause.
    4094                                 $tax_query_in_and = wp_list_filter( $this->tax_query->queried_terms, array( 'operator' => 'NOT IN' ), 'NOT' );
    4095 
    4096                                 if ( ! empty( $tax_query_in_and ) ) {
    4097                                         $queried_taxonomies = array_keys( $tax_query_in_and );
    4098                                         $matched_taxonomy = reset( $queried_taxonomies );
    4099                                         $query = $tax_query_in_and[ $matched_taxonomy ];
    4100 
    4101                                         if ( $query['terms'] ) {
    4102                                                 if ( 'term_id' == $query['field'] ) {
    4103                                                         $term = get_term( reset( $query['terms'] ), $matched_taxonomy );
    4104                                                 } else {
    4105                                                         $term = get_term_by( $query['field'], reset( $query['terms'] ), $matched_taxonomy );
    4106                                                 }
    4107                                         }
    4108                                 }
    4109                         }
    4110 
    4111                         if ( ! empty( $term ) && ! is_wp_error( $term ) )  {
    4112                                 $this->queried_object = $term;
    4113                                 $this->queried_object_id = (int) $term->term_id;
    4114 
    4115                                 if ( $this->is_category && 'category' === $this->queried_object->taxonomy )
    4116                                         _make_cat_compat( $this->queried_object );
    4117                         }
    4118                 } elseif ( $this->is_post_type_archive ) {
    4119                         $post_type = $this->get( 'post_type' );
    4120                         if ( is_array( $post_type ) )
    4121                                 $post_type = reset( $post_type );
    4122                         $this->queried_object = get_post_type_object( $post_type );
    4123                 } elseif ( $this->is_posts_page ) {
    4124                         $page_for_posts = get_option('page_for_posts');
    4125                         $this->queried_object = get_post( $page_for_posts );
    4126                         $this->queried_object_id = (int) $this->queried_object->ID;
    4127                 } elseif ( $this->is_singular && ! empty( $this->post ) ) {
    4128                         $this->queried_object = $this->post;
    4129                         $this->queried_object_id = (int) $this->post->ID;
    4130                 } elseif ( $this->is_author ) {
    4131                         $this->queried_object_id = (int) $this->get('author');
    4132                         $this->queried_object = get_userdata( $this->queried_object_id );
    4133                 }
    4134 
    4135                 return $this->queried_object;
    4136         }
    4137 
    4138         /**
    4139          * Retrieve ID of the current queried object.
    4140          *
    4141          * @since 1.5.0
    4142          * @access public
    4143          *
    4144          * @return int
    4145          */
    4146         public function get_queried_object_id() {
    4147                 $this->get_queried_object();
    4148 
    4149                 if ( isset($this->queried_object_id) ) {
    4150                         return $this->queried_object_id;
    4151                 }
    4152 
    4153                 return 0;
    4154         }
    4155 
    4156         /**
    4157          * Constructor.
    4158          *
    4159          * Sets up the WordPress query, if parameter is not empty.
    4160          *
    4161          * @since 1.5.0
    4162          * @access public
    4163          *
    4164          * @param string|array $query URL query string or array of vars.
    4165          */
    4166         public function __construct( $query = '' ) {
    4167                 $this->db = $GLOBALS['wpdb'];
    4168 
    4169                 if ( ! empty( $query ) ) {
    4170                         $this->query( $query );
    4171                 }
    4172         }
    4173 
    4174         /**
    4175          * Make private properties readable for backward compatibility.
    4176          *
    4177          * @since 4.0.0
    4178          * @access public
    4179          *
    4180          * @param string $name Property to get.
    4181          * @return mixed Property.
    4182          */
    4183         public function __get( $name ) {
    4184                 if ( in_array( $name, $this->compat_fields ) ) {
    4185                         return $this->$name;
    4186                 }
    4187         }
    4188 
    4189         /**
    4190          * Make private properties checkable for backward compatibility.
    4191          *
    4192          * @since 4.0.0
    4193          * @access public
    4194          *
    4195          * @param string $name Property to check if set.
    4196          * @return bool Whether the property is set.
    4197          */
    4198         public function __isset( $name ) {
    4199                 if ( in_array( $name, $this->compat_fields ) ) {
    4200                         return isset( $this->$name );
    4201                 }
    4202         }
    4203 
    4204         /**
    4205          * Make private/protected methods readable for backward compatibility.
    4206          *
    4207          * @since 4.0.0
    4208          * @access public
    4209          *
    4210          * @param callable $name      Method to call.
    4211          * @param array    $arguments Arguments to pass when calling.
    4212          * @return mixed|false Return value of the callback, false otherwise.
    4213          */
    4214         public function __call( $name, $arguments ) {
    4215                 if ( in_array( $name, $this->compat_methods ) ) {
    4216                         return call_user_func_array( array( $this, $name ), $arguments );
    4217                 }
    4218                 return false;
    4219         }
    4220 
    4221         /**
    4222          * Is the query for an existing archive page?
    4223          *
    4224          * Month, Year, Category, Author, Post Type archive...
    4225          *
    4226          * @since 3.1.0
    4227          *
    4228          * @return bool
    4229          */
    4230         public function is_archive() {
    4231                 return (bool) $this->is_archive;
    4232         }
    4233 
    4234         /**
    4235          * Is the query for an existing post type archive page?
    4236          *
    4237          * @since 3.1.0
    4238          *
    4239          * @param mixed $post_types Optional. Post type or array of posts types to check against.
    4240          * @return bool
    4241          */
    4242         public function is_post_type_archive( $post_types = '' ) {
    4243                 if ( empty( $post_types ) || ! $this->is_post_type_archive )
    4244                         return (bool) $this->is_post_type_archive;
    4245 
    4246                 $post_type = $this->get( 'post_type' );
    4247                 if ( is_array( $post_type ) )
    4248                         $post_type = reset( $post_type );
    4249                 $post_type_object = get_post_type_object( $post_type );
    4250 
    4251                 return in_array( $post_type_object->name, (array) $post_types );
    4252         }
    4253 
    4254         /**
    4255          * Is the query for an existing attachment page?
    4256          *
    4257          * @since 3.1.0
    4258          *
    4259          * @param mixed $attachment Attachment ID, title, slug, or array of such.
    4260          * @return bool
    4261          */
    4262         public function is_attachment( $attachment = '' ) {
    4263                 if ( ! $this->is_attachment ) {
    4264                         return false;
    4265                 }
    4266 
    4267                 if ( empty( $attachment ) ) {
    4268                         return true;
    4269                 }
    4270 
    4271                 $attachment = array_map( 'strval', (array) $attachment );
    4272 
    4273                 $post_obj = $this->get_queried_object();
    4274 
    4275                 if ( in_array( (string) $post_obj->ID, $attachment ) ) {
    4276                         return true;
    4277                 } elseif ( in_array( $post_obj->post_title, $attachment ) ) {
    4278                         return true;
    4279                 } elseif ( in_array( $post_obj->post_name, $attachment ) ) {
    4280                         return true;
    4281                 }
    4282                 return false;
    4283         }
    4284 
    4285         /**
    4286          * Is the query for an existing author archive page?
    4287          *
    4288          * If the $author parameter is specified, this function will additionally
    4289          * check if the query is for one of the authors specified.
    4290          *
    4291          * @since 3.1.0
    4292          *
    4293          * @param mixed $author Optional. User ID, nickname, nicename, or array of User IDs, nicknames, and nicenames
    4294          * @return bool
    4295          */
    4296         public function is_author( $author = '' ) {
    4297                 if ( !$this->is_author )
    4298                         return false;
    4299 
    4300                 if ( empty($author) )
    4301                         return true;
    4302 
    4303                 $author_obj = $this->get_queried_object();
    4304 
    4305                 $author = array_map( 'strval', (array) $author );
    4306 
    4307                 if ( in_array( (string) $author_obj->ID, $author ) )
    4308                         return true;
    4309                 elseif ( in_array( $author_obj->nickname, $author ) )
    4310                         return true;
    4311                 elseif ( in_array( $author_obj->user_nicename, $author ) )
    4312                         return true;
    4313 
    4314                 return false;
    4315         }
    4316 
    4317         /**
    4318          * Is the query for an existing category archive page?
    4319          *
    4320          * If the $category parameter is specified, this function will additionally
    4321          * check if the query is for one of the categories specified.
    4322          *
    4323          * @since 3.1.0
    4324          *
    4325          * @param mixed $category Optional. Category ID, name, slug, or array of Category IDs, names, and slugs.
    4326          * @return bool
    4327          */
    4328         public function is_category( $category = '' ) {
    4329                 if ( !$this->is_category )
    4330                         return false;
    4331 
    4332                 if ( empty($category) )
    4333                         return true;
    4334 
    4335                 $cat_obj = $this->get_queried_object();
    4336 
    4337                 $category = array_map( 'strval', (array) $category );
    4338 
    4339                 if ( in_array( (string) $cat_obj->term_id, $category ) )
    4340                         return true;
    4341                 elseif ( in_array( $cat_obj->name, $category ) )
    4342                         return true;
    4343                 elseif ( in_array( $cat_obj->slug, $category ) )
    4344                         return true;
    4345 
    4346                 return false;
    4347         }
    4348 
    4349         /**
    4350          * Is the query for an existing tag archive page?
    4351          *
    4352          * If the $tag parameter is specified, this function will additionally
    4353          * check if the query is for one of the tags specified.
    4354          *
    4355          * @since 3.1.0
    4356          *
    4357          * @param mixed $tag Optional. Tag ID, name, slug, or array of Tag IDs, names, and slugs.
    4358          * @return bool
    4359          */
    4360         public function is_tag( $tag = '' ) {
    4361                 if ( ! $this->is_tag )
    4362                         return false;
    4363 
    4364                 if ( empty( $tag ) )
    4365                         return true;
    4366 
    4367                 $tag_obj = $this->get_queried_object();
    4368 
    4369                 $tag = array_map( 'strval', (array) $tag );
    4370 
    4371                 if ( in_array( (string) $tag_obj->term_id, $tag ) )
    4372                         return true;
    4373                 elseif ( in_array( $tag_obj->name, $tag ) )
    4374                         return true;
    4375                 elseif ( in_array( $tag_obj->slug, $tag ) )
    4376                         return true;
    4377 
    4378                 return false;
    4379         }
    4380 
    4381         /**
    4382          * Is the query for an existing custom taxonomy archive page?
    4383          *
    4384          * If the $taxonomy parameter is specified, this function will additionally
    4385          * check if the query is for that specific $taxonomy.
    4386          *
    4387          * If the $term parameter is specified in addition to the $taxonomy parameter,
    4388          * this function will additionally check if the query is for one of the terms
    4389          * specified.
    4390          *
    4391          * @since 3.1.0
    4392          *
    4393          * @global array $wp_taxonomies
    4394          *
    4395          * @param mixed $taxonomy Optional. Taxonomy slug or slugs.
    4396          * @param mixed $term     Optional. Term ID, name, slug or array of Term IDs, names, and slugs.
    4397          * @return bool True for custom taxonomy archive pages, false for built-in taxonomies (category and tag archives).
    4398          */
    4399         public function is_tax( $taxonomy = '', $term = '' ) {
    4400                 global $wp_taxonomies;
    4401 
    4402                 if ( !$this->is_tax )
    4403                         return false;
    4404 
    4405                 if ( empty( $taxonomy ) )
    4406                         return true;
    4407 
    4408                 $queried_object = $this->get_queried_object();
    4409                 $tax_array = array_intersect( array_keys( $wp_taxonomies ), (array) $taxonomy );
    4410                 $term_array = (array) $term;
    4411 
    4412                 // Check that the taxonomy matches.
    4413                 if ( ! ( isset( $queried_object->taxonomy ) && count( $tax_array ) && in_array( $queried_object->taxonomy, $tax_array ) ) )
    4414                         return false;
    4415 
    4416                 // Only a Taxonomy provided.
    4417                 if ( empty( $term ) )
    4418                         return true;
    4419 
    4420                 return isset( $queried_object->term_id ) &&
    4421                         count( array_intersect(
    4422                                 array( $queried_object->term_id, $queried_object->name, $queried_object->slug ),
    4423                                 $term_array
    4424                         ) );
    4425         }
    4426 
    4427         /**
    4428          * Whether the current URL is within the comments popup window.
    4429          *
    4430          * @since 3.1.0
    4431          * @deprecated 4.5.0
    4432          *
    4433          * @return bool
    4434          */
    4435         public function is_comments_popup() {
    4436                 _deprecated_function( __FUNCTION__, '4.5.0' );
    4437 
    4438                 return false;
    4439         }
    4440 
    4441         /**
    4442          * Is the query for an existing date archive?
    4443          *
    4444          * @since 3.1.0
    4445          *
    4446          * @return bool
    4447          */
    4448         public function is_date() {
    4449                 return (bool) $this->is_date;
    4450         }
    4451 
    4452         /**
    4453          * Is the query for an existing day archive?
    4454          *
    4455          * @since 3.1.0
    4456          *
    4457          * @return bool
    4458          */
    4459         public function is_day() {
    4460                 return (bool) $this->is_day;
    4461         }
    4462 
    4463         /**
    4464          * Is the query for a feed?
    4465          *
    4466          * @since 3.1.0
    4467          *
    4468          * @param string|array $feeds Optional feed types to check.
    4469          * @return bool
    4470          */
    4471         public function is_feed( $feeds = '' ) {
    4472                 if ( empty( $feeds ) || ! $this->is_feed )
    4473                         return (bool) $this->is_feed;
    4474                 $qv = $this->get( 'feed' );
    4475                 if ( 'feed' == $qv )
    4476                         $qv = get_default_feed();
    4477                 return in_array( $qv, (array) $feeds );
    4478         }
    4479 
    4480         /**
    4481          * Is the query for a comments feed?
    4482          *
    4483          * @since 3.1.0
    4484          *
    4485          * @return bool
    4486          */
    4487         public function is_comment_feed() {
    4488                 return (bool) $this->is_comment_feed;
    4489         }
    4490 
    4491         /**
    4492          * Is the query for the front page of the site?
    4493          *
    4494          * This is for what is displayed at your site's main URL.
    4495          *
    4496          * Depends on the site's "Front page displays" Reading Settings 'show_on_front' and 'page_on_front'.
    4497          *
    4498          * If you set a static page for the front page of your site, this function will return
    4499          * true when viewing that page.
    4500          *
    4501          * Otherwise the same as @see WP_Query::is_home()
    4502          *
    4503          * @since 3.1.0
    4504          *
    4505          * @return bool True, if front of site.
    4506          */
    4507         public function is_front_page() {
    4508                 // most likely case
    4509                 if ( 'posts' == get_option( 'show_on_front') && $this->is_home() )
    4510                         return true;
    4511                 elseif ( 'page' == get_option( 'show_on_front') && get_option( 'page_on_front' ) && $this->is_page( get_option( 'page_on_front' ) ) )
    4512                         return true;
    4513                 else
    4514                         return false;
    4515         }
    4516 
    4517         /**
    4518          * Is the query for the blog homepage?
    4519          *
    4520          * This is the page which shows the time based blog content of your site.
    4521          *
    4522          * Depends on the site's "Front page displays" Reading Settings 'show_on_front' and 'page_for_posts'.
    4523          *
    4524          * If you set a static page for the front page of your site, this function will return
    4525          * true only on the page you set as the "Posts page".
    4526          *
    4527          * @see WP_Query::is_front_page()
    4528          *
    4529          * @since 3.1.0
    4530          *
    4531          * @return bool True if blog view homepage.
    4532          */
    4533         public function is_home() {
    4534                 return (bool) $this->is_home;
    4535         }
    4536 
    4537         /**
    4538          * Is the query for an existing month archive?
    4539          *
    4540          * @since 3.1.0
    4541          *
    4542          * @return bool
    4543          */
    4544         public function is_month() {
    4545                 return (bool) $this->is_month;
    4546         }
    4547 
    4548         /**
    4549          * Is the query for an existing single page?
    4550          *
    4551          * If the $page parameter is specified, this function will additionally
    4552          * check if the query is for one of the pages specified.
    4553          *
    4554          * @see WP_Query::is_single()
    4555          * @see WP_Query::is_singular()
    4556          *
    4557          * @since 3.1.0
    4558          *
    4559          * @param int|string|array $page Optional. Page ID, title, slug, path, or array of such. Default empty.
    4560          * @return bool Whether the query is for an existing single page.
    4561          */
    4562         public function is_page( $page = '' ) {
    4563                 if ( !$this->is_page )
    4564                         return false;
    4565 
    4566                 if ( empty( $page ) )
    4567                         return true;
    4568 
    4569                 $page_obj = $this->get_queried_object();
    4570 
    4571                 $page = array_map( 'strval', (array) $page );
    4572 
    4573                 if ( in_array( (string) $page_obj->ID, $page ) ) {
    4574                         return true;
    4575                 } elseif ( in_array( $page_obj->post_title, $page ) ) {
    4576                         return true;
    4577                 } elseif ( in_array( $page_obj->post_name, $page ) ) {
    4578                         return true;
    4579                 } else {
    4580                         foreach ( $page as $pagepath ) {
    4581                                 if ( ! strpos( $pagepath, '/' ) ) {
    4582                                         continue;
    4583                                 }
    4584                                 $pagepath_obj = get_page_by_path( $pagepath );
    4585 
    4586                                 if ( $pagepath_obj && ( $pagepath_obj->ID == $page_obj->ID ) ) {
    4587                                         return true;
    4588                                 }
    4589                         }
    4590                 }
    4591 
    4592                 return false;
    4593         }
    4594 
    4595         /**
    4596          * Is the query for paged result and not for the first page?
    4597          *
    4598          * @since 3.1.0
    4599          *
    4600          * @return bool
    4601          */
    4602         public function is_paged() {
    4603                 return (bool) $this->is_paged;
    4604         }
    4605 
    4606         /**
    4607          * Is the query for a post or page preview?
    4608          *
    4609          * @since 3.1.0
    4610          *
    4611          * @return bool
    4612          */
    4613         public function is_preview() {
    4614                 return (bool) $this->is_preview;
    4615         }
    4616 
    4617         /**
    4618          * Is the query for the robots file?
    4619          *
    4620          * @since 3.1.0
    4621          *
    4622          * @return bool
    4623          */
    4624         public function is_robots() {
    4625                 return (bool) $this->is_robots;
    4626         }
    4627 
    4628         /**
    4629          * Is the query for a search?
    4630          *
    4631          * @since 3.1.0
    4632          *
    4633          * @return bool
    4634          */
    4635         public function is_search() {
    4636                 return (bool) $this->is_search;
    4637         }
    4638 
    4639         /**
    4640          * Is the query for an existing single post?
    4641          *
    4642          * Works for any post type, except attachments and pages
    4643          *
    4644          * If the $post parameter is specified, this function will additionally
    4645          * check if the query is for one of the Posts specified.
    4646          *
    4647          * @see WP_Query::is_page()
    4648          * @see WP_Query::is_singular()
    4649          *
    4650          * @since 3.1.0
    4651          *
    4652          * @param int|string|array $post Optional. Post ID, title, slug, path, or array of such. Default empty.
    4653          * @return bool Whether the query is for an existing single post.
    4654          */
    4655         public function is_single( $post = '' ) {
    4656                 if ( !$this->is_single )
    4657                         return false;
    4658 
    4659                 if ( empty($post) )
    4660                         return true;
    4661 
    4662                 $post_obj = $this->get_queried_object();
    4663 
    4664                 $post = array_map( 'strval', (array) $post );
    4665 
    4666                 if ( in_array( (string) $post_obj->ID, $post ) ) {
    4667                         return true;
    4668                 } elseif ( in_array( $post_obj->post_title, $post ) ) {
    4669                         return true;
    4670                 } elseif ( in_array( $post_obj->post_name, $post ) ) {
    4671                         return true;
    4672                 } else {
    4673                         foreach ( $post as $postpath ) {
    4674                                 if ( ! strpos( $postpath, '/' ) ) {
    4675                                         continue;
    4676                                 }
    4677                                 $postpath_obj = get_page_by_path( $postpath, OBJECT, $post_obj->post_type );
    4678 
    4679                                 if ( $postpath_obj && ( $postpath_obj->ID == $post_obj->ID ) ) {
    4680                                         return true;
    4681                                 }
    4682                         }
    4683                 }
    4684                 return false;
    4685         }
    4686 
    4687         /**
    4688          * Is the query for an existing single post of any post type (post, attachment, page, ... )?
    4689          *
    4690          * If the $post_types parameter is specified, this function will additionally
    4691          * check if the query is for one of the Posts Types specified.
    4692          *
    4693          * @see WP_Query::is_page()
    4694          * @see WP_Query::is_single()
    4695          *
    4696          * @since 3.1.0
    4697          *
    4698          * @param string|array $post_types Optional. Post type or array of post types. Default empty.
    4699          * @return bool Whether the query is for an existing single post of any of the given post types.
    4700          */
    4701         public function is_singular( $post_types = '' ) {
    4702                 if ( empty( $post_types ) || !$this->is_singular )
    4703                         return (bool) $this->is_singular;
    4704 
    4705                 $post_obj = $this->get_queried_object();
    4706 
    4707                 return in_array( $post_obj->post_type, (array) $post_types );
    4708         }
    4709 
    4710         /**
    4711          * Is the query for a specific time?
    4712          *
    4713          * @since 3.1.0
    4714          *
    4715          * @return bool
    4716          */
    4717         public function is_time() {
    4718                 return (bool) $this->is_time;
    4719         }
    4720 
    4721         /**
    4722          * Is the query for a trackback endpoint call?
    4723          *
    4724          * @since 3.1.0
    4725          *
    4726          * @return bool
    4727          */
    4728         public function is_trackback() {
    4729                 return (bool) $this->is_trackback;
    4730         }
    4731 
    4732         /**
    4733          * Is the query for an existing year archive?
    4734          *
    4735          * @since 3.1.0
    4736          *
    4737          * @return bool
    4738          */
    4739         public function is_year() {
    4740                 return (bool) $this->is_year;
    4741         }
    4742 
    4743         /**
    4744          * Is the query a 404 (returns no results)?
    4745          *
    4746          * @since 3.1.0
    4747          *
    4748          * @return bool
    4749          */
    4750         public function is_404() {
    4751                 return (bool) $this->is_404;
    4752         }
    4753 
    4754         /**
    4755          * Is the query for an embedded post?
    4756          *
    4757          * @since 4.4.0
    4758          *
    4759          * @return bool
    4760          */
    4761         public function is_embed() {
    4762                 return (bool) $this->is_embed;
    4763         }
    4764 
    4765         /**
    4766          * Is the query the main query?
    4767          *
    4768          * @since 3.3.0
    4769          *
    4770          * @global WP_Query $wp_query Global WP_Query instance.
    4771          *
    4772          * @return bool
    4773          */
    4774         public function is_main_query() {
    4775                 global $wp_the_query;
    4776                 return $wp_the_query === $this;
    4777         }
    4778 
    4779         /**
    4780          * Set up global post data.
    4781          *
    4782          * @since 4.1.0
    4783          * @since 4.4.0 Added the ability to pass a post ID to `$post`.
    4784          *
    4785          * @global int             $id
    4786          * @global WP_User         $authordata
    4787          * @global string|int|bool $currentday
    4788          * @global string|int|bool $currentmonth
    4789          * @global int             $page
    4790          * @global array           $pages
    4791          * @global int             $multipage
    4792          * @global int             $more
    4793          * @global int             $numpages
    4794          *
    4795          * @param WP_Post|object|int $post WP_Post instance or Post ID/object.
    4796          * @return true True when finished.
    4797          */
    4798         public function setup_postdata( $post ) {
    4799                 global $id, $authordata, $currentday, $currentmonth, $page, $pages, $multipage, $more, $numpages;
    4800 
    4801                 if ( ! ( $post instanceof WP_Post ) ) {
    4802                         $post = get_post( $post );
    4803                 }
    4804 
    4805                 if ( ! $post ) {
    4806                         return;
    4807                 }
    4808 
    4809                 $id = (int) $post->ID;
    4810 
    4811                 $authordata = get_userdata($post->post_author);
    4812 
    4813                 $currentday = mysql2date('d.m.y', $post->post_date, false);
    4814                 $currentmonth = mysql2date('m', $post->post_date, false);
    4815                 $numpages = 1;
    4816                 $multipage = 0;
    4817                 $page = $this->get( 'page' );
    4818                 if ( ! $page )
    4819                         $page = 1;
    4820 
    4821                 /*
    4822                  * Force full post content when viewing the permalink for the $post,
    4823                  * or when on an RSS feed. Otherwise respect the 'more' tag.
    4824                  */
    4825                 if ( $post->ID === get_queried_object_id() && ( $this->is_page() || $this->is_single() ) ) {
    4826                         $more = 1;
    4827                 } elseif ( $this->is_feed() ) {
    4828                         $more = 1;
    4829                 } else {
    4830                         $more = 0;
    4831                 }
    4832 
    4833                 $content = $post->post_content;
    4834                 if ( false !== strpos( $content, '<!--nextpage-->' ) ) {
    4835                         $content = str_replace( "\n<!--nextpage-->\n", '<!--nextpage-->', $content );
    4836                         $content = str_replace( "\n<!--nextpage-->", '<!--nextpage-->', $content );
    4837                         $content = str_replace( "<!--nextpage-->\n", '<!--nextpage-->', $content );
    4838 
    4839                         // Ignore nextpage at the beginning of the content.
    4840                         if ( 0 === strpos( $content, '<!--nextpage-->' ) )
    4841                                 $content = substr( $content, 15 );
    4842 
    4843                         $pages = explode('<!--nextpage-->', $content);
    4844                 } else {
    4845                         $pages = array( $post->post_content );
    4846                 }
    4847 
    4848                 /**
    4849                  * Filters the "pages" derived from splitting the post content.
    4850                  *
    4851                  * "Pages" are determined by splitting the post content based on the presence
    4852                  * of `<!-- nextpage -->` tags.
    4853                  *
    4854                  * @since 4.4.0
    4855                  *
    4856                  * @param array   $pages Array of "pages" derived from the post content.
    4857                  *                       of `<!-- nextpage -->` tags..
    4858                  * @param WP_Post $post  Current post object.
    4859                  */
    4860                 $pages = apply_filters( 'content_pagination', $pages, $post );
    4861 
    4862                 $numpages = count( $pages );
    4863 
    4864                 if ( $numpages > 1 ) {
    4865                         if ( $page > 1 ) {
    4866                                 $more = 1;
    4867                         }
    4868                         $multipage = 1;
    4869                 } else {
    4870                         $multipage = 0;
    4871                 }
    4872 
    4873                 /**
    4874                  * Fires once the post data has been setup.
    4875                  *
    4876                  * @since 2.8.0
    4877                  * @since 4.1.0 Introduced `$this` parameter.
    4878                  *
    4879                  * @param WP_Post  &$post The Post object (passed by reference).
    4880                  * @param WP_Query &$this The current Query object (passed by reference).
    4881                  */
    4882                 do_action_ref_array( 'the_post', array( &$post, &$this ) );
    4883 
    4884                 return true;
    4885         }
    4886         /**
    4887          * After looping through a nested query, this function
    4888          * restores the $post global to the current post in this query.
    4889          *
    4890          * @since 3.7.0
    4891          *
    4892          * @global WP_Post $post
    4893          */
    4894         public function reset_postdata() {
    4895                 if ( ! empty( $this->post ) ) {
    4896                         $GLOBALS['post'] = $this->post;
    4897                         $this->setup_postdata( $this->post );
    4898                 }
    4899         }
    4900 
    4901         /**
    4902          * Lazyload term meta for posts in the loop.
    4903          *
    4904          * @since 4.4.0
    4905          * @deprecated 4.5.0 See wp_queue_posts_for_term_meta_lazyload().
    4906          *
    4907          * @param mixed $check
    4908          * @param int   $term_id
    4909          * @return mixed
    4910          */
    4911         public function lazyload_term_meta( $check, $term_id ) {
    4912                 _deprecated_function( __METHOD__, '4.5.0' );
    4913                 return $check;
    4914         }
    4915 
    4916         /**
    4917          * Lazyload comment meta for comments in the loop.
    4918          *
    4919          * @since 4.4.0
    4920          * @deprecated 4.5.0 See wp_queue_comments_for_comment_meta_lazyload().
    4921          *
    4922          * @param mixed $check
    4923          * @param int   $comment_id
    4924          * @return mixed
    4925          */
    4926         public function lazyload_comment_meta( $check, $comment_id ) {
    4927                 _deprecated_function( __METHOD__, '4.5.0' );
    4928                 return $check;
    4929         }
    4930 }
    4931 
    4932 /**
    4933841 * Redirect old slugs to the correct permalink.
    4934842 *
    4935843 * Attempts to find the current slug from the past slugs.
  • src/wp-settings.php

     
    140140require( ABSPATH . WPINC . '/class-wp-roles.php' );
    141141require( ABSPATH . WPINC . '/class-wp-role.php' );
    142142require( ABSPATH . WPINC . '/class-wp-user.php' );
     143require( ABSPATH . WPINC . '/class-wp-query.php' );
    143144require( ABSPATH . WPINC . '/query.php' );
    144145require( ABSPATH . WPINC . '/date.php' );
    145146require( ABSPATH . WPINC . '/theme.php' );