[ Index ]

PHP Cross Reference of WordPress

title

Body

[close]

/wp-includes/ -> class-wp-query.php (source)

   1  <?php
   2  /**
   3   * Query API: WP_Query class
   4   *
   5   * @package WordPress
   6   * @subpackage Query
   7   * @since 4.7.0
   8   */
   9  
  10  /**
  11   * The WordPress Query class.
  12   *
  13   * @link https://developer.wordpress.org/reference/classes/wp_query/
  14   *
  15   * @since 1.5.0
  16   * @since 4.5.0 Removed the `$comments_popup` property.
  17   */
  18  class WP_Query {
  19  
  20      /**
  21       * Query vars set by the user.
  22       *
  23       * @since 1.5.0
  24       * @var array
  25       */
  26      public $query;
  27  
  28      /**
  29       * Query vars, after parsing.
  30       *
  31       * @since 1.5.0
  32       * @var array
  33       */
  34      public $query_vars = array();
  35  
  36      /**
  37       * Taxonomy query, as passed to get_tax_sql().
  38       *
  39       * @since 3.1.0
  40       * @var WP_Tax_Query A taxonomy query instance.
  41       */
  42      public $tax_query;
  43  
  44      /**
  45       * Metadata query container.
  46       *
  47       * @since 3.2.0
  48       * @var WP_Meta_Query A meta query instance.
  49       */
  50      public $meta_query = false;
  51  
  52      /**
  53       * Date query container.
  54       *
  55       * @since 3.7.0
  56       * @var WP_Date_Query A date query instance.
  57       */
  58      public $date_query = false;
  59  
  60      /**
  61       * Holds the data for a single object that is queried.
  62       *
  63       * Holds the contents of a post, page, category, attachment.
  64       *
  65       * @since 1.5.0
  66       * @var WP_Term|WP_Post_Type|WP_Post|WP_User|null
  67       */
  68      public $queried_object;
  69  
  70      /**
  71       * The ID of the queried object.
  72       *
  73       * @since 1.5.0
  74       * @var int
  75       */
  76      public $queried_object_id;
  77  
  78      /**
  79       * SQL for the database query.
  80       *
  81       * @since 2.0.1
  82       * @var string
  83       */
  84      public $request;
  85  
  86      /**
  87       * Array of post objects or post IDs.
  88       *
  89       * @since 1.5.0
  90       * @var WP_Post[]|int[]
  91       */
  92      public $posts;
  93  
  94      /**
  95       * The number of posts for the current query.
  96       *
  97       * @since 1.5.0
  98       * @var int
  99       */
 100      public $post_count = 0;
 101  
 102      /**
 103       * Index of the current item in the loop.
 104       *
 105       * @since 1.5.0
 106       * @var int
 107       */
 108      public $current_post = -1;
 109  
 110      /**
 111       * Whether the loop has started and the caller is in the loop.
 112       *
 113       * @since 2.0.0
 114       * @var bool
 115       */
 116      public $in_the_loop = false;
 117  
 118      /**
 119       * The current post.
 120       *
 121       * This property does not get populated when the `fields` argument is set to
 122       * `ids` or `id=>parent`.
 123       *
 124       * @since 1.5.0
 125       * @var WP_Post|null
 126       */
 127      public $post;
 128  
 129      /**
 130       * The list of comments for current post.
 131       *
 132       * @since 2.2.0
 133       * @var WP_Comment[]
 134       */
 135      public $comments;
 136  
 137      /**
 138       * The number of comments for the posts.
 139       *
 140       * @since 2.2.0
 141       * @var int
 142       */
 143      public $comment_count = 0;
 144  
 145      /**
 146       * The index of the comment in the comment loop.
 147       *
 148       * @since 2.2.0
 149       * @var int
 150       */
 151      public $current_comment = -1;
 152  
 153      /**
 154       * Current comment object.
 155       *
 156       * @since 2.2.0
 157       * @var WP_Comment
 158       */
 159      public $comment;
 160  
 161      /**
 162       * The number of found posts for the current query.
 163       *
 164       * If limit clause was not used, equals $post_count.
 165       *
 166       * @since 2.1.0
 167       * @var int
 168       */
 169      public $found_posts = 0;
 170  
 171      /**
 172       * The number of pages.
 173       *
 174       * @since 2.1.0
 175       * @var int
 176       */
 177      public $max_num_pages = 0;
 178  
 179      /**
 180       * The number of comment pages.
 181       *
 182       * @since 2.7.0
 183       * @var int
 184       */
 185      public $max_num_comment_pages = 0;
 186  
 187      /**
 188       * Signifies whether the current query is for a single post.
 189       *
 190       * @since 1.5.0
 191       * @var bool
 192       */
 193      public $is_single = false;
 194  
 195      /**
 196       * Signifies whether the current query is for a preview.
 197       *
 198       * @since 2.0.0
 199       * @var bool
 200       */
 201      public $is_preview = false;
 202  
 203      /**
 204       * Signifies whether the current query is for a page.
 205       *
 206       * @since 1.5.0
 207       * @var bool
 208       */
 209      public $is_page = false;
 210  
 211      /**
 212       * Signifies whether the current query is for an archive.
 213       *
 214       * @since 1.5.0
 215       * @var bool
 216       */
 217      public $is_archive = false;
 218  
 219      /**
 220       * Signifies whether the current query is for a date archive.
 221       *
 222       * @since 1.5.0
 223       * @var bool
 224       */
 225      public $is_date = false;
 226  
 227      /**
 228       * Signifies whether the current query is for a year archive.
 229       *
 230       * @since 1.5.0
 231       * @var bool
 232       */
 233      public $is_year = false;
 234  
 235      /**
 236       * Signifies whether the current query is for a month archive.
 237       *
 238       * @since 1.5.0
 239       * @var bool
 240       */
 241      public $is_month = false;
 242  
 243      /**
 244       * Signifies whether the current query is for a day archive.
 245       *
 246       * @since 1.5.0
 247       * @var bool
 248       */
 249      public $is_day = false;
 250  
 251      /**
 252       * Signifies whether the current query is for a specific time.
 253       *
 254       * @since 1.5.0
 255       * @var bool
 256       */
 257      public $is_time = false;
 258  
 259      /**
 260       * Signifies whether the current query is for an author archive.
 261       *
 262       * @since 1.5.0
 263       * @var bool
 264       */
 265      public $is_author = false;
 266  
 267      /**
 268       * Signifies whether the current query is for a category archive.
 269       *
 270       * @since 1.5.0
 271       * @var bool
 272       */
 273      public $is_category = false;
 274  
 275      /**
 276       * Signifies whether the current query is for a tag archive.
 277       *
 278       * @since 2.3.0
 279       * @var bool
 280       */
 281      public $is_tag = false;
 282  
 283      /**
 284       * Signifies whether the current query is for a taxonomy archive.
 285       *
 286       * @since 2.5.0
 287       * @var bool
 288       */
 289      public $is_tax = false;
 290  
 291      /**
 292       * Signifies whether the current query is for a search.
 293       *
 294       * @since 1.5.0
 295       * @var bool
 296       */
 297      public $is_search = false;
 298  
 299      /**
 300       * Signifies whether the current query is for a feed.
 301       *
 302       * @since 1.5.0
 303       * @var bool
 304       */
 305      public $is_feed = false;
 306  
 307      /**
 308       * Signifies whether the current query is for a comment feed.
 309       *
 310       * @since 2.2.0
 311       * @var bool
 312       */
 313      public $is_comment_feed = false;
 314  
 315      /**
 316       * Signifies whether the current query is for trackback endpoint call.
 317       *
 318       * @since 1.5.0
 319       * @var bool
 320       */
 321      public $is_trackback = false;
 322  
 323      /**
 324       * Signifies whether the current query is for the site homepage.
 325       *
 326       * @since 1.5.0
 327       * @var bool
 328       */
 329      public $is_home = false;
 330  
 331      /**
 332       * Signifies whether the current query is for the Privacy Policy page.
 333       *
 334       * @since 5.2.0
 335       * @var bool
 336       */
 337      public $is_privacy_policy = false;
 338  
 339      /**
 340       * Signifies whether the current query couldn't find anything.
 341       *
 342       * @since 1.5.0
 343       * @var bool
 344       */
 345      public $is_404 = false;
 346  
 347      /**
 348       * Signifies whether the current query is for an embed.
 349       *
 350       * @since 4.4.0
 351       * @var bool
 352       */
 353      public $is_embed = false;
 354  
 355      /**
 356       * Signifies whether the current query is for a paged result and not for the first page.
 357       *
 358       * @since 1.5.0
 359       * @var bool
 360       */
 361      public $is_paged = false;
 362  
 363      /**
 364       * Signifies whether the current query is for an administrative interface page.
 365       *
 366       * @since 1.5.0
 367       * @var bool
 368       */
 369      public $is_admin = false;
 370  
 371      /**
 372       * Signifies whether the current query is for an attachment page.
 373       *
 374       * @since 2.0.0
 375       * @var bool
 376       */
 377      public $is_attachment = false;
 378  
 379      /**
 380       * Signifies whether the current query is for an existing single post of any post type
 381       * (post, attachment, page, custom post types).
 382       *
 383       * @since 2.1.0
 384       * @var bool
 385       */
 386      public $is_singular = false;
 387  
 388      /**
 389       * Signifies whether the current query is for the robots.txt file.
 390       *
 391       * @since 2.1.0
 392       * @var bool
 393       */
 394      public $is_robots = false;
 395  
 396      /**
 397       * Signifies whether the current query is for the favicon.ico file.
 398       *
 399       * @since 5.4.0
 400       * @var bool
 401       */
 402      public $is_favicon = false;
 403  
 404      /**
 405       * Signifies whether the current query is for the page_for_posts page.
 406       *
 407       * Basically, the homepage if the option isn't set for the static homepage.
 408       *
 409       * @since 2.1.0
 410       * @var bool
 411       */
 412      public $is_posts_page = false;
 413  
 414      /**
 415       * Signifies whether the current query is for a post type archive.
 416       *
 417       * @since 3.1.0
 418       * @var bool
 419       */
 420      public $is_post_type_archive = false;
 421  
 422      /**
 423       * Stores the ->query_vars state like md5(serialize( $this->query_vars ) ) so we know
 424       * whether we have to re-parse because something has changed
 425       *
 426       * @since 3.1.0
 427       * @var bool|string
 428       */
 429      private $query_vars_hash = false;
 430  
 431      /**
 432       * Whether query vars have changed since the initial parse_query() call. Used to catch modifications to query vars made
 433       * via pre_get_posts hooks.
 434       *
 435       * @since 3.1.1
 436       */
 437      private $query_vars_changed = true;
 438  
 439      /**
 440       * Set if post thumbnails are cached
 441       *
 442       * @since 3.2.0
 443       * @var bool
 444       */
 445      public $thumbnails_cached = false;
 446  
 447      /**
 448       * Cached list of search stopwords.
 449       *
 450       * @since 3.7.0
 451       * @var array
 452       */
 453      private $stopwords;
 454  
 455      private $compat_fields = array( 'query_vars_hash', 'query_vars_changed' );
 456  
 457      private $compat_methods = array( 'init_query_flags', 'parse_tax_query' );
 458  
 459      /**
 460       * Resets query flags to false.
 461       *
 462       * The query flags are what page info WordPress was able to figure out.
 463       *
 464       * @since 2.0.0
 465       */
 466  	private function init_query_flags() {
 467          $this->is_single            = false;
 468          $this->is_preview           = false;
 469          $this->is_page              = false;
 470          $this->is_archive           = false;
 471          $this->is_date              = false;
 472          $this->is_year              = false;
 473          $this->is_month             = false;
 474          $this->is_day               = false;
 475          $this->is_time              = false;
 476          $this->is_author            = false;
 477          $this->is_category          = false;
 478          $this->is_tag               = false;
 479          $this->is_tax               = false;
 480          $this->is_search            = false;
 481          $this->is_feed              = false;
 482          $this->is_comment_feed      = false;
 483          $this->is_trackback         = false;
 484          $this->is_home              = false;
 485          $this->is_privacy_policy    = false;
 486          $this->is_404               = false;
 487          $this->is_paged             = false;
 488          $this->is_admin             = false;
 489          $this->is_attachment        = false;
 490          $this->is_singular          = false;
 491          $this->is_robots            = false;
 492          $this->is_favicon           = false;
 493          $this->is_posts_page        = false;
 494          $this->is_post_type_archive = false;
 495      }
 496  
 497      /**
 498       * Initiates object properties and sets default values.
 499       *
 500       * @since 1.5.0
 501       */
 502  	public function init() {
 503          unset( $this->posts );
 504          unset( $this->query );
 505          $this->query_vars = array();
 506          unset( $this->queried_object );
 507          unset( $this->queried_object_id );
 508          $this->post_count   = 0;
 509          $this->current_post = -1;
 510          $this->in_the_loop  = false;
 511          unset( $this->request );
 512          unset( $this->post );
 513          unset( $this->comments );
 514          unset( $this->comment );
 515          $this->comment_count         = 0;
 516          $this->current_comment       = -1;
 517          $this->found_posts           = 0;
 518          $this->max_num_pages         = 0;
 519          $this->max_num_comment_pages = 0;
 520  
 521          $this->init_query_flags();
 522      }
 523  
 524      /**
 525       * Reparse the query vars.
 526       *
 527       * @since 1.5.0
 528       */
 529  	public function parse_query_vars() {
 530          $this->parse_query();
 531      }
 532  
 533      /**
 534       * Fills in the query variables, which do not exist within the parameter.
 535       *
 536       * @since 2.1.0
 537       * @since 4.5.0 Removed the `comments_popup` public query variable.
 538       *
 539       * @param array $query_vars Defined query variables.
 540       * @return array Complete query variables with undefined ones filled in empty.
 541       */
 542  	public function fill_query_vars( $query_vars ) {
 543          $keys = array(
 544              'error',
 545              'm',
 546              'p',
 547              'post_parent',
 548              'subpost',
 549              'subpost_id',
 550              'attachment',
 551              'attachment_id',
 552              'name',
 553              'pagename',
 554              'page_id',
 555              'second',
 556              'minute',
 557              'hour',
 558              'day',
 559              'monthnum',
 560              'year',
 561              'w',
 562              'category_name',
 563              'tag',
 564              'cat',
 565              'tag_id',
 566              'author',
 567              'author_name',
 568              'feed',
 569              'tb',
 570              'paged',
 571              'meta_key',
 572              'meta_value',
 573              'preview',
 574              's',
 575              'sentence',
 576              'title',
 577              'fields',
 578              'menu_order',
 579              'embed',
 580          );
 581  
 582          foreach ( $keys as $key ) {
 583              if ( ! isset( $query_vars[ $key ] ) ) {
 584                  $query_vars[ $key ] = '';
 585              }
 586          }
 587  
 588          $array_keys = array(
 589              'category__in',
 590              'category__not_in',
 591              'category__and',
 592              'post__in',
 593              'post__not_in',
 594              'post_name__in',
 595              'tag__in',
 596              'tag__not_in',
 597              'tag__and',
 598              'tag_slug__in',
 599              'tag_slug__and',
 600              'post_parent__in',
 601              'post_parent__not_in',
 602              'author__in',
 603              'author__not_in',
 604          );
 605  
 606          foreach ( $array_keys as $key ) {
 607              if ( ! isset( $query_vars[ $key ] ) ) {
 608                  $query_vars[ $key ] = array();
 609              }
 610          }
 611  
 612          return $query_vars;
 613      }
 614  
 615      /**
 616       * Parse a query string and set query type booleans.
 617       *
 618       * @since 1.5.0
 619       * @since 4.2.0 Introduced the ability to order by specific clauses of a `$meta_query`, by passing the clause's
 620       *              array key to `$orderby`.
 621       * @since 4.4.0 Introduced `$post_name__in` and `$title` parameters. `$s` was updated to support excluded
 622       *              search terms, by prepending a hyphen.
 623       * @since 4.5.0 Removed the `$comments_popup` parameter.
 624       *              Introduced the `$comment_status` and `$ping_status` parameters.
 625       *              Introduced `RAND(x)` syntax for `$orderby`, which allows an integer seed value to random sorts.
 626       * @since 4.6.0 Added 'post_name__in' support for `$orderby`. Introduced the `$lazy_load_term_meta` argument.
 627       * @since 4.9.0 Introduced the `$comment_count` parameter.
 628       * @since 5.1.0 Introduced the `$meta_compare_key` parameter.
 629       * @since 5.3.0 Introduced the `$meta_type_key` parameter.
 630       *
 631       * @param string|array $query {
 632       *     Optional. Array or string of Query parameters.
 633       *
 634       *     @type int             $attachment_id           Attachment post ID. Used for 'attachment' post_type.
 635       *     @type int|string      $author                  Author ID, or comma-separated list of IDs.
 636       *     @type string          $author_name             User 'user_nicename'.
 637       *     @type int[]           $author__in              An array of author IDs to query from.
 638       *     @type int[]           $author__not_in          An array of author IDs not to query from.
 639       *     @type bool            $cache_results           Whether to cache post information. Default true.
 640       *     @type int|string      $cat                     Category ID or comma-separated list of IDs (this or any children).
 641       *     @type int[]           $category__and           An array of category IDs (AND in).
 642       *     @type int[]           $category__in            An array of category IDs (OR in, no children).
 643       *     @type int[]           $category__not_in        An array of category IDs (NOT in).
 644       *     @type string          $category_name           Use category slug (not name, this or any children).
 645       *     @type array|int       $comment_count           Filter results by comment count. Provide an integer to match
 646       *                                                    comment count exactly. Provide an array with integer 'value'
 647       *                                                    and 'compare' operator ('=', '!=', '>', '>=', '<', '<=' ) to
 648       *                                                    compare against comment_count in a specific way.
 649       *     @type string          $comment_status          Comment status.
 650       *     @type int             $comments_per_page       The number of comments to return per page.
 651       *                                                    Default 'comments_per_page' option.
 652       *     @type array           $date_query              An associative array of WP_Date_Query arguments.
 653       *                                                    See WP_Date_Query::__construct().
 654       *     @type int             $day                     Day of the month. Default empty. Accepts numbers 1-31.
 655       *     @type bool            $exact                   Whether to search by exact keyword. Default false.
 656       *     @type string          $fields                  Post fields to query for. Accepts:
 657       *                                                    - '' Returns an array of complete post objects (`WP_Post[]`).
 658       *                                                    - 'ids' Returns an array of post IDs (`int[]`).
 659       *                                                    - 'id=>parent' Returns an associative array of parent post IDs,
 660       *                                                      keyed by post ID (`int[]`).
 661       *                                                    Default ''.
 662       *     @type int             $hour                    Hour of the day. Default empty. Accepts numbers 0-23.
 663       *     @type int|bool        $ignore_sticky_posts     Whether to ignore sticky posts or not. Setting this to false
 664       *                                                    excludes stickies from 'post__in'. Accepts 1|true, 0|false.
 665       *                                                    Default false.
 666       *     @type int             $m                       Combination YearMonth. Accepts any four-digit year and month
 667       *                                                    numbers 1-12. Default empty.
 668       *     @type string|string[] $meta_key                Meta key or keys to filter by.
 669       *     @type string|string[] $meta_value              Meta value or values to filter by.
 670       *     @type string          $meta_compare            MySQL operator used for comparing the meta value.
 671       *                                                    See WP_Meta_Query::__construct for accepted values and default value.
 672       *     @type string          $meta_compare_key        MySQL operator used for comparing the meta key.
 673       *                                                    See WP_Meta_Query::__construct for accepted values and default value.
 674       *     @type string          $meta_type               MySQL data type that the meta_value column will be CAST to for comparisons.
 675       *                                                    See WP_Meta_Query::__construct for accepted values and default value.
 676       *     @type string          $meta_type_key           MySQL data type that the meta_key column will be CAST to for comparisons.
 677       *                                                    See WP_Meta_Query::__construct for accepted values and default value.
 678       *     @type array           $meta_query              An associative array of WP_Meta_Query arguments.
 679       *                                                    See WP_Meta_Query::__construct for accepted values.
 680       *     @type int             $menu_order              The menu order of the posts.
 681       *     @type int             $minute                  Minute of the hour. Default empty. Accepts numbers 0-59.
 682       *     @type int             $monthnum                The two-digit month. Default empty. Accepts numbers 1-12.
 683       *     @type string          $name                    Post slug.
 684       *     @type bool            $nopaging                Show all posts (true) or paginate (false). Default false.
 685       *     @type bool            $no_found_rows           Whether to skip counting the total rows found. Enabling can improve
 686       *                                                    performance. Default false.
 687       *     @type int             $offset                  The number of posts to offset before retrieval.
 688       *     @type string          $order                   Designates ascending or descending order of posts. Default 'DESC'.
 689       *                                                    Accepts 'ASC', 'DESC'.
 690       *     @type string|array    $orderby                 Sort retrieved posts by parameter. One or more options may be passed.
 691       *                                                    To use 'meta_value', or 'meta_value_num', 'meta_key=keyname' must be
 692       *                                                    also be defined. To sort by a specific `$meta_query` clause, use that
 693       *                                                    clause's array key. Accepts:
 694       *                                                    - 'none'
 695       *                                                    - 'name'
 696       *                                                    - 'author'
 697       *                                                    - 'date'
 698       *                                                    - 'title'
 699       *                                                    - 'modified'
 700       *                                                    - 'menu_order'
 701       *                                                    - 'parent'
 702       *                                                    - 'ID'
 703       *                                                    - 'rand'
 704       *                                                    - 'relevance'
 705       *                                                    - 'RAND(x)' (where 'x' is an integer seed value)
 706       *                                                    - 'comment_count'
 707       *                                                    - 'meta_value'
 708       *                                                    - 'meta_value_num'
 709       *                                                    - 'post__in'
 710       *                                                    - 'post_name__in'
 711       *                                                    - 'post_parent__in'
 712       *                                                    - The array keys of `$meta_query`.
 713       *                                                    Default is 'date', except when a search is being performed, when
 714       *                                                    the default is 'relevance'.
 715       *     @type int             $p                       Post ID.
 716       *     @type int             $page                    Show the number of posts that would show up on page X of a
 717       *                                                    static front page.
 718       *     @type int             $paged                   The number of the current page.
 719       *     @type int             $page_id                 Page ID.
 720       *     @type string          $pagename                Page slug.
 721       *     @type string          $perm                    Show posts if user has the appropriate capability.
 722       *     @type string          $ping_status             Ping status.
 723       *     @type int[]           $post__in                An array of post IDs to retrieve, sticky posts will be included.
 724       *     @type int[]           $post__not_in            An array of post IDs not to retrieve. Note: a string of comma-
 725       *                                                    separated IDs will NOT work.
 726       *     @type string          $post_mime_type          The mime type of the post. Used for 'attachment' post_type.
 727       *     @type string[]        $post_name__in           An array of post slugs that results must match.
 728       *     @type int             $post_parent             Page ID to retrieve child pages for. Use 0 to only retrieve
 729       *                                                    top-level pages.
 730       *     @type int[]           $post_parent__in         An array containing parent page IDs to query child pages from.
 731       *     @type int[]           $post_parent__not_in     An array containing parent page IDs not to query child pages from.
 732       *     @type string|string[] $post_type               A post type slug (string) or array of post type slugs.
 733       *                                                    Default 'any' if using 'tax_query'.
 734       *     @type string|string[] $post_status             A post status (string) or array of post statuses.
 735       *     @type int             $posts_per_page          The number of posts to query for. Use -1 to request all posts.
 736       *     @type int             $posts_per_archive_page  The number of posts to query for by archive page. Overrides
 737       *                                                    'posts_per_page' when is_archive(), or is_search() are true.
 738       *     @type string          $s                       Search keyword(s). Prepending a term with a hyphen will
 739       *                                                    exclude posts matching that term. Eg, 'pillow -sofa' will
 740       *                                                    return posts containing 'pillow' but not 'sofa'. The
 741       *                                                    character used for exclusion can be modified using the
 742       *                                                    the 'wp_query_search_exclusion_prefix' filter.
 743       *     @type int             $second                  Second of the minute. Default empty. Accepts numbers 0-59.
 744       *     @type bool            $sentence                Whether to search by phrase. Default false.
 745       *     @type bool            $suppress_filters        Whether to suppress filters. Default false.
 746       *     @type string          $tag                     Tag slug. Comma-separated (either), Plus-separated (all).
 747       *     @type int[]           $tag__and                An array of tag IDs (AND in).
 748       *     @type int[]           $tag__in                 An array of tag IDs (OR in).
 749       *     @type int[]           $tag__not_in             An array of tag IDs (NOT in).
 750       *     @type int             $tag_id                  Tag id or comma-separated list of IDs.
 751       *     @type string[]        $tag_slug__and           An array of tag slugs (AND in).
 752       *     @type string[]        $tag_slug__in            An array of tag slugs (OR in). unless 'ignore_sticky_posts' is
 753       *                                                    true. Note: a string of comma-separated IDs will NOT work.
 754       *     @type array           $tax_query               An associative array of WP_Tax_Query arguments.
 755       *                                                    See WP_Tax_Query->__construct().
 756       *     @type string          $title                   Post title.
 757       *     @type bool            $update_post_meta_cache  Whether to update the post meta cache. Default true.
 758       *     @type bool            $update_post_term_cache  Whether to update the post term cache. Default true.
 759       *     @type bool            $lazy_load_term_meta     Whether to lazy-load term meta. Setting to false will
 760       *                                                    disable cache priming for term meta, so that each
 761       *                                                    get_term_meta() call will hit the database.
 762       *                                                    Defaults to the value of `$update_post_term_cache`.
 763       *     @type int             $w                       The week number of the year. Default empty. Accepts numbers 0-53.
 764       *     @type int             $year                    The four-digit year. Default empty. Accepts any four-digit year.
 765       * }
 766       */
 767  	public function parse_query( $query = '' ) {
 768          if ( ! empty( $query ) ) {
 769              $this->init();
 770              $this->query      = wp_parse_args( $query );
 771              $this->query_vars = $this->query;
 772          } elseif ( ! isset( $this->query ) ) {
 773              $this->query = $this->query_vars;
 774          }
 775  
 776          $this->query_vars         = $this->fill_query_vars( $this->query_vars );
 777          $qv                       = &$this->query_vars;
 778          $this->query_vars_changed = true;
 779  
 780          if ( ! empty( $qv['robots'] ) ) {
 781              $this->is_robots = true;
 782          } elseif ( ! empty( $qv['favicon'] ) ) {
 783              $this->is_favicon = true;
 784          }
 785  
 786          if ( ! is_scalar( $qv['p'] ) || (int) $qv['p'] < 0 ) {
 787              $qv['p']     = 0;
 788              $qv['error'] = '404';
 789          } else {
 790              $qv['p'] = (int) $qv['p'];
 791          }
 792  
 793          $qv['page_id']  = absint( $qv['page_id'] );
 794          $qv['year']     = absint( $qv['year'] );
 795          $qv['monthnum'] = absint( $qv['monthnum'] );
 796          $qv['day']      = absint( $qv['day'] );
 797          $qv['w']        = absint( $qv['w'] );
 798          $qv['m']        = is_scalar( $qv['m'] ) ? preg_replace( '|[^0-9]|', '', $qv['m'] ) : '';
 799          $qv['paged']    = absint( $qv['paged'] );
 800          $qv['cat']      = preg_replace( '|[^0-9,-]|', '', $qv['cat'] );    // Comma-separated list of positive or negative integers.
 801          $qv['author']   = preg_replace( '|[^0-9,-]|', '', $qv['author'] ); // Comma-separated list of positive or negative integers.
 802          $qv['pagename'] = trim( $qv['pagename'] );
 803          $qv['name']     = trim( $qv['name'] );
 804          $qv['title']    = trim( $qv['title'] );
 805          if ( '' !== $qv['hour'] ) {
 806              $qv['hour'] = absint( $qv['hour'] );
 807          }
 808          if ( '' !== $qv['minute'] ) {
 809              $qv['minute'] = absint( $qv['minute'] );
 810          }
 811          if ( '' !== $qv['second'] ) {
 812              $qv['second'] = absint( $qv['second'] );
 813          }
 814          if ( '' !== $qv['menu_order'] ) {
 815              $qv['menu_order'] = absint( $qv['menu_order'] );
 816          }
 817  
 818          // Fairly large, potentially too large, upper bound for search string lengths.
 819          if ( ! is_scalar( $qv['s'] ) || ( ! empty( $qv['s'] ) && strlen( $qv['s'] ) > 1600 ) ) {
 820              $qv['s'] = '';
 821          }
 822  
 823          // Compat. Map subpost to attachment.
 824          if ( '' != $qv['subpost'] ) {
 825              $qv['attachment'] = $qv['subpost'];
 826          }
 827          if ( '' != $qv['subpost_id'] ) {
 828              $qv['attachment_id'] = $qv['subpost_id'];
 829          }
 830  
 831          $qv['attachment_id'] = absint( $qv['attachment_id'] );
 832  
 833          if ( ( '' !== $qv['attachment'] ) || ! empty( $qv['attachment_id'] ) ) {
 834              $this->is_single     = true;
 835              $this->is_attachment = true;
 836          } elseif ( '' !== $qv['name'] ) {
 837              $this->is_single = true;
 838          } elseif ( $qv['p'] ) {
 839              $this->is_single = true;
 840          } elseif ( '' !== $qv['pagename'] || ! empty( $qv['page_id'] ) ) {
 841              $this->is_page   = true;
 842              $this->is_single = false;
 843          } else {
 844              // Look for archive queries. Dates, categories, authors, search, post type archives.
 845  
 846              if ( isset( $this->query['s'] ) ) {
 847                  $this->is_search = true;
 848              }
 849  
 850              if ( '' !== $qv['second'] ) {
 851                  $this->is_time = true;
 852                  $this->is_date = true;
 853              }
 854  
 855              if ( '' !== $qv['minute'] ) {
 856                  $this->is_time = true;
 857                  $this->is_date = true;
 858              }
 859  
 860              if ( '' !== $qv['hour'] ) {
 861                  $this->is_time = true;
 862                  $this->is_date = true;
 863              }
 864  
 865              if ( $qv['day'] ) {
 866                  if ( ! $this->is_date ) {
 867                      $date = sprintf( '%04d-%02d-%02d', $qv['year'], $qv['monthnum'], $qv['day'] );
 868                      if ( $qv['monthnum'] && $qv['year'] && ! wp_checkdate( $qv['monthnum'], $qv['day'], $qv['year'], $date ) ) {
 869                          $qv['error'] = '404';
 870                      } else {
 871                          $this->is_day  = true;
 872                          $this->is_date = true;
 873                      }
 874                  }
 875              }
 876  
 877              if ( $qv['monthnum'] ) {
 878                  if ( ! $this->is_date ) {
 879                      if ( 12 < $qv['monthnum'] ) {
 880                          $qv['error'] = '404';
 881                      } else {
 882                          $this->is_month = true;
 883                          $this->is_date  = true;
 884                      }
 885                  }
 886              }
 887  
 888              if ( $qv['year'] ) {
 889                  if ( ! $this->is_date ) {
 890                      $this->is_year = true;
 891                      $this->is_date = true;
 892                  }
 893              }
 894  
 895              if ( $qv['m'] ) {
 896                  $this->is_date = true;
 897                  if ( strlen( $qv['m'] ) > 9 ) {
 898                      $this->is_time = true;
 899                  } elseif ( strlen( $qv['m'] ) > 7 ) {
 900                      $this->is_day = true;
 901                  } elseif ( strlen( $qv['m'] ) > 5 ) {
 902                      $this->is_month = true;
 903                  } else {
 904                      $this->is_year = true;
 905                  }
 906              }
 907  
 908              if ( $qv['w'] ) {
 909                  $this->is_date = true;
 910              }
 911  
 912              $this->query_vars_hash = false;
 913              $this->parse_tax_query( $qv );
 914  
 915              foreach ( $this->tax_query->queries as $tax_query ) {
 916                  if ( ! is_array( $tax_query ) ) {
 917                      continue;
 918                  }
 919  
 920                  if ( isset( $tax_query['operator'] ) && 'NOT IN' !== $tax_query['operator'] ) {
 921                      switch ( $tax_query['taxonomy'] ) {
 922                          case 'category':
 923                              $this->is_category = true;
 924                              break;
 925                          case 'post_tag':
 926                              $this->is_tag = true;
 927                              break;
 928                          default:
 929                              $this->is_tax = true;
 930                      }
 931                  }
 932              }
 933              unset( $tax_query );
 934  
 935              if ( empty( $qv['author'] ) || ( '0' == $qv['author'] ) ) {
 936                  $this->is_author = false;
 937              } else {
 938                  $this->is_author = true;
 939              }
 940  
 941              if ( '' !== $qv['author_name'] ) {
 942                  $this->is_author = true;
 943              }
 944  
 945              if ( ! empty( $qv['post_type'] ) && ! is_array( $qv['post_type'] ) ) {
 946                  $post_type_obj = get_post_type_object( $qv['post_type'] );
 947                  if ( ! empty( $post_type_obj->has_archive ) ) {
 948                      $this->is_post_type_archive = true;
 949                  }
 950              }
 951  
 952              if ( $this->is_post_type_archive || $this->is_date || $this->is_author || $this->is_category || $this->is_tag || $this->is_tax ) {
 953                  $this->is_archive = true;
 954              }
 955          }
 956  
 957          if ( '' != $qv['feed'] ) {
 958              $this->is_feed = true;
 959          }
 960  
 961          if ( '' != $qv['embed'] ) {
 962              $this->is_embed = true;
 963          }
 964  
 965          if ( '' != $qv['tb'] ) {
 966              $this->is_trackback = true;
 967          }
 968  
 969          if ( '' != $qv['paged'] && ( (int) $qv['paged'] > 1 ) ) {
 970              $this->is_paged = true;
 971          }
 972  
 973          // If we're previewing inside the write screen.
 974          if ( '' != $qv['preview'] ) {
 975              $this->is_preview = true;
 976          }
 977  
 978          if ( is_admin() ) {
 979              $this->is_admin = true;
 980          }
 981  
 982          if ( false !== strpos( $qv['feed'], 'comments-' ) ) {
 983              $qv['feed']         = str_replace( 'comments-', '', $qv['feed'] );
 984              $qv['withcomments'] = 1;
 985          }
 986  
 987          $this->is_singular = $this->is_single || $this->is_page || $this->is_attachment;
 988  
 989          if ( $this->is_feed && ( ! empty( $qv['withcomments'] ) || ( empty( $qv['withoutcomments'] ) && $this->is_singular ) ) ) {
 990              $this->is_comment_feed = true;
 991          }
 992  
 993          if ( ! ( $this->is_singular || $this->is_archive || $this->is_search || $this->is_feed
 994                  || ( defined( 'REST_REQUEST' ) && REST_REQUEST && $this->is_main_query() )
 995                  || $this->is_trackback || $this->is_404 || $this->is_admin || $this->is_robots || $this->is_favicon ) ) {
 996              $this->is_home = true;
 997          }
 998  
 999          // Correct `is_*` for 'page_on_front' and 'page_for_posts'.
1000          if ( $this->is_home && 'page' === get_option( 'show_on_front' ) && get_option( 'page_on_front' ) ) {
1001              $_query = wp_parse_args( $this->query );
1002              // 'pagename' can be set and empty depending on matched rewrite rules. Ignore an empty 'pagename'.
1003              if ( isset( $_query['pagename'] ) && '' === $_query['pagename'] ) {
1004                  unset( $_query['pagename'] );
1005              }
1006  
1007              unset( $_query['embed'] );
1008  
1009              if ( empty( $_query ) || ! array_diff( array_keys( $_query ), array( 'preview', 'page', 'paged', 'cpage' ) ) ) {
1010                  $this->is_page = true;
1011                  $this->is_home = false;
1012                  $qv['page_id'] = get_option( 'page_on_front' );
1013                  // Correct <!--nextpage--> for 'page_on_front'.
1014                  if ( ! empty( $qv['paged'] ) ) {
1015                      $qv['page'] = $qv['paged'];
1016                      unset( $qv['paged'] );
1017                  }
1018              }
1019          }
1020  
1021          if ( '' !== $qv['pagename'] ) {
1022              $this->queried_object = get_page_by_path( $qv['pagename'] );
1023  
1024              if ( $this->queried_object && 'attachment' === $this->queried_object->post_type ) {
1025                  if ( preg_match( '/^[^%]*%(?:postname)%/', get_option( 'permalink_structure' ) ) ) {
1026                      // See if we also have a post with the same slug.
1027                      $post = get_page_by_path( $qv['pagename'], OBJECT, 'post' );
1028                      if ( $post ) {
1029                          $this->queried_object = $post;
1030                          $this->is_page        = false;
1031                          $this->is_single      = true;
1032                      }
1033                  }
1034              }
1035  
1036              if ( ! empty( $this->queried_object ) ) {
1037                  $this->queried_object_id = (int) $this->queried_object->ID;
1038              } else {
1039                  unset( $this->queried_object );
1040              }
1041  
1042              if ( 'page' === get_option( 'show_on_front' ) && isset( $this->queried_object_id ) && get_option( 'page_for_posts' ) == $this->queried_object_id ) {
1043                  $this->is_page       = false;
1044                  $this->is_home       = true;
1045                  $this->is_posts_page = true;
1046              }
1047  
1048              if ( isset( $this->queried_object_id ) && get_option( 'wp_page_for_privacy_policy' ) == $this->queried_object_id ) {
1049                  $this->is_privacy_policy = true;
1050              }
1051          }
1052  
1053          if ( $qv['page_id'] ) {
1054              if ( 'page' === get_option( 'show_on_front' ) && get_option( 'page_for_posts' ) == $qv['page_id'] ) {
1055                  $this->is_page       = false;
1056                  $this->is_home       = true;
1057                  $this->is_posts_page = true;
1058              }
1059  
1060              if ( get_option( 'wp_page_for_privacy_policy' ) == $qv['page_id'] ) {
1061                  $this->is_privacy_policy = true;
1062              }
1063          }
1064  
1065          if ( ! empty( $qv['post_type'] ) ) {
1066              if ( is_array( $qv['post_type'] ) ) {
1067                  $qv['post_type'] = array_map( 'sanitize_key', $qv['post_type'] );
1068              } else {
1069                  $qv['post_type'] = sanitize_key( $qv['post_type'] );
1070              }
1071          }
1072  
1073          if ( ! empty( $qv['post_status'] ) ) {
1074              if ( is_array( $qv['post_status'] ) ) {
1075                  $qv['post_status'] = array_map( 'sanitize_key', $qv['post_status'] );
1076              } else {
1077                  $qv['post_status'] = preg_replace( '|[^a-z0-9_,-]|', '', $qv['post_status'] );
1078              }
1079          }
1080  
1081          if ( $this->is_posts_page && ( ! isset( $qv['withcomments'] ) || ! $qv['withcomments'] ) ) {
1082              $this->is_comment_feed = false;
1083          }
1084  
1085          $this->is_singular = $this->is_single || $this->is_page || $this->is_attachment;
1086          // Done correcting `is_*` for 'page_on_front' and 'page_for_posts'.
1087  
1088          if ( '404' == $qv['error'] ) {
1089              $this->set_404();
1090          }
1091  
1092          $this->is_embed = $this->is_embed && ( $this->is_singular || $this->is_404 );
1093  
1094          $this->query_vars_hash    = md5( serialize( $this->query_vars ) );
1095          $this->query_vars_changed = false;
1096  
1097          /**
1098           * Fires after the main query vars have been parsed.
1099           *
1100           * @since 1.5.0
1101           *
1102           * @param WP_Query $query The WP_Query instance (passed by reference).
1103           */
1104          do_action_ref_array( 'parse_query', array( &$this ) );
1105      }
1106  
1107      /**
1108       * Parses various taxonomy related query vars.
1109       *
1110       * For BC, this method is not marked as protected. See [28987].
1111       *
1112       * @since 3.1.0
1113       *
1114       * @param array $q The query variables. Passed by reference.
1115       */
1116  	public function parse_tax_query( &$q ) {
1117          if ( ! empty( $q['tax_query'] ) && is_array( $q['tax_query'] ) ) {
1118              $tax_query = $q['tax_query'];
1119          } else {
1120              $tax_query = array();
1121          }
1122  
1123          if ( ! empty( $q['taxonomy'] ) && ! empty( $q['term'] ) ) {
1124              $tax_query[] = array(
1125                  'taxonomy' => $q['taxonomy'],
1126                  'terms'    => array( $q['term'] ),
1127                  'field'    => 'slug',
1128              );
1129          }
1130  
1131          foreach ( get_taxonomies( array(), 'objects' ) as $taxonomy => $t ) {
1132              if ( 'post_tag' === $taxonomy ) {
1133                  continue; // Handled further down in the $q['tag'] block.
1134              }
1135  
1136              if ( $t->query_var && ! empty( $q[ $t->query_var ] ) ) {
1137                  $tax_query_defaults = array(
1138                      'taxonomy' => $taxonomy,
1139                      'field'    => 'slug',
1140                  );
1141  
1142                  if ( ! empty( $t->rewrite['hierarchical'] ) ) {
1143                      $q[ $t->query_var ] = wp_basename( $q[ $t->query_var ] );
1144                  }
1145  
1146                  $term = $q[ $t->query_var ];
1147  
1148                  if ( is_array( $term ) ) {
1149                      $term = implode( ',', $term );
1150                  }
1151  
1152                  if ( strpos( $term, '+' ) !== false ) {
1153                      $terms = preg_split( '/[+]+/', $term );
1154                      foreach ( $terms as $term ) {
1155                          $tax_query[] = array_merge(
1156                              $tax_query_defaults,
1157                              array(
1158                                  'terms' => array( $term ),
1159                              )
1160                          );
1161                      }
1162                  } else {
1163                      $tax_query[] = array_merge(
1164                          $tax_query_defaults,
1165                          array(
1166                              'terms' => preg_split( '/[,]+/', $term ),
1167                          )
1168                      );
1169                  }
1170              }
1171          }
1172  
1173          // If query string 'cat' is an array, implode it.
1174          if ( is_array( $q['cat'] ) ) {
1175              $q['cat'] = implode( ',', $q['cat'] );
1176          }
1177  
1178          // Category stuff.
1179  
1180          if ( ! empty( $q['cat'] ) && ! $this->is_singular ) {
1181              $cat_in     = array();
1182              $cat_not_in = array();
1183  
1184              $cat_array = preg_split( '/[,\s]+/', urldecode( $q['cat'] ) );
1185              $cat_array = array_map( 'intval', $cat_array );
1186              $q['cat']  = implode( ',', $cat_array );
1187  
1188              foreach ( $cat_array as $cat ) {
1189                  if ( $cat > 0 ) {
1190                      $cat_in[] = $cat;
1191                  } elseif ( $cat < 0 ) {
1192                      $cat_not_in[] = abs( $cat );
1193                  }
1194              }
1195  
1196              if ( ! empty( $cat_in ) ) {
1197                  $tax_query[] = array(
1198                      'taxonomy'         => 'category',
1199                      'terms'            => $cat_in,
1200                      'field'            => 'term_id',
1201                      'include_children' => true,
1202                  );
1203              }
1204  
1205              if ( ! empty( $cat_not_in ) ) {
1206                  $tax_query[] = array(
1207                      'taxonomy'         => 'category',
1208                      'terms'            => $cat_not_in,
1209                      'field'            => 'term_id',
1210                      'operator'         => 'NOT IN',
1211                      'include_children' => true,
1212                  );
1213              }
1214              unset( $cat_array, $cat_in, $cat_not_in );
1215          }
1216  
1217          if ( ! empty( $q['category__and'] ) && 1 === count( (array) $q['category__and'] ) ) {
1218              $q['category__and'] = (array) $q['category__and'];
1219              if ( ! isset( $q['category__in'] ) ) {
1220                  $q['category__in'] = array();
1221              }
1222              $q['category__in'][] = absint( reset( $q['category__and'] ) );
1223              unset( $q['category__and'] );
1224          }
1225  
1226          if ( ! empty( $q['category__in'] ) ) {
1227              $q['category__in'] = array_map( 'absint', array_unique( (array) $q['category__in'] ) );
1228              $tax_query[]       = array(
1229                  'taxonomy'         => 'category',
1230                  'terms'            => $q['category__in'],
1231                  'field'            => 'term_id',
1232                  'include_children' => false,
1233              );
1234          }
1235  
1236          if ( ! empty( $q['category__not_in'] ) ) {
1237              $q['category__not_in'] = array_map( 'absint', array_unique( (array) $q['category__not_in'] ) );
1238              $tax_query[]           = array(
1239                  'taxonomy'         => 'category',
1240                  'terms'            => $q['category__not_in'],
1241                  'operator'         => 'NOT IN',
1242                  'include_children' => false,
1243              );
1244          }
1245  
1246          if ( ! empty( $q['category__and'] ) ) {
1247              $q['category__and'] = array_map( 'absint', array_unique( (array) $q['category__and'] ) );
1248              $tax_query[]        = array(
1249                  'taxonomy'         => 'category',
1250                  'terms'            => $q['category__and'],
1251                  'field'            => 'term_id',
1252                  'operator'         => 'AND',
1253                  'include_children' => false,
1254              );
1255          }
1256  
1257          // If query string 'tag' is array, implode it.
1258          if ( is_array( $q['tag'] ) ) {
1259              $q['tag'] = implode( ',', $q['tag'] );
1260          }
1261  
1262          // Tag stuff.
1263  
1264          if ( '' !== $q['tag'] && ! $this->is_singular && $this->query_vars_changed ) {
1265              if ( strpos( $q['tag'], ',' ) !== false ) {
1266                  $tags = preg_split( '/[,\r\n\t ]+/', $q['tag'] );
1267                  foreach ( (array) $tags as $tag ) {
1268                      $tag                 = sanitize_term_field( 'slug', $tag, 0, 'post_tag', 'db' );
1269                      $q['tag_slug__in'][] = $tag;
1270                  }
1271              } elseif ( preg_match( '/[+\r\n\t ]+/', $q['tag'] ) || ! empty( $q['cat'] ) ) {
1272                  $tags = preg_split( '/[+\r\n\t ]+/', $q['tag'] );
1273                  foreach ( (array) $tags as $tag ) {
1274                      $tag                  = sanitize_term_field( 'slug', $tag, 0, 'post_tag', 'db' );
1275                      $q['tag_slug__and'][] = $tag;
1276                  }
1277              } else {
1278                  $q['tag']            = sanitize_term_field( 'slug', $q['tag'], 0, 'post_tag', 'db' );
1279                  $q['tag_slug__in'][] = $q['tag'];
1280              }
1281          }
1282  
1283          if ( ! empty( $q['tag_id'] ) ) {
1284              $q['tag_id'] = absint( $q['tag_id'] );
1285              $tax_query[] = array(
1286                  'taxonomy' => 'post_tag',
1287                  'terms'    => $q['tag_id'],
1288              );
1289          }
1290  
1291          if ( ! empty( $q['tag__in'] ) ) {
1292              $q['tag__in'] = array_map( 'absint', array_unique( (array) $q['tag__in'] ) );
1293              $tax_query[]  = array(
1294                  'taxonomy' => 'post_tag',
1295                  'terms'    => $q['tag__in'],
1296              );
1297          }
1298  
1299          if ( ! empty( $q['tag__not_in'] ) ) {
1300              $q['tag__not_in'] = array_map( 'absint', array_unique( (array) $q['tag__not_in'] ) );
1301              $tax_query[]      = array(
1302                  'taxonomy' => 'post_tag',
1303                  'terms'    => $q['tag__not_in'],
1304                  'operator' => 'NOT IN',
1305              );
1306          }
1307  
1308          if ( ! empty( $q['tag__and'] ) ) {
1309              $q['tag__and'] = array_map( 'absint', array_unique( (array) $q['tag__and'] ) );
1310              $tax_query[]   = array(
1311                  'taxonomy' => 'post_tag',
1312                  'terms'    => $q['tag__and'],
1313                  'operator' => 'AND',
1314              );
1315          }
1316  
1317          if ( ! empty( $q['tag_slug__in'] ) ) {
1318              $q['tag_slug__in'] = array_map( 'sanitize_title_for_query', array_unique( (array) $q['tag_slug__in'] ) );
1319              $tax_query[]       = array(
1320                  'taxonomy' => 'post_tag',
1321                  'terms'    => $q['tag_slug__in'],
1322                  'field'    => 'slug',
1323              );
1324          }
1325  
1326          if ( ! empty( $q['tag_slug__and'] ) ) {
1327              $q['tag_slug__and'] = array_map( 'sanitize_title_for_query', array_unique( (array) $q['tag_slug__and'] ) );
1328              $tax_query[]        = array(
1329                  'taxonomy' => 'post_tag',
1330                  'terms'    => $q['tag_slug__and'],
1331                  'field'    => 'slug',
1332                  'operator' => 'AND',
1333              );
1334          }
1335  
1336          $this->tax_query = new WP_Tax_Query( $tax_query );
1337  
1338          /**
1339           * Fires after taxonomy-related query vars have been parsed.
1340           *
1341           * @since 3.7.0
1342           *
1343           * @param WP_Query $query The WP_Query instance.
1344           */
1345          do_action( 'parse_tax_query', $this );
1346      }
1347  
1348      /**
1349       * Generates SQL for the WHERE clause based on passed search terms.
1350       *
1351       * @since 3.7.0
1352       *
1353       * @global wpdb $wpdb WordPress database abstraction object.
1354       *
1355       * @param array $q Query variables.
1356       * @return string WHERE clause.
1357       */
1358  	protected function parse_search( &$q ) {
1359          global $wpdb;
1360  
1361          $search = '';
1362  
1363          // Added slashes screw with quote grouping when done early, so done later.
1364          $q['s'] = stripslashes( $q['s'] );
1365          if ( empty( $_GET['s'] ) && $this->is_main_query() ) {
1366              $q['s'] = urldecode( $q['s'] );
1367          }
1368          // There are no line breaks in <input /> fields.
1369          $q['s']                  = str_replace( array( "\r", "\n" ), '', $q['s'] );
1370          $q['search_terms_count'] = 1;
1371          if ( ! empty( $q['sentence'] ) ) {
1372              $q['search_terms'] = array( $q['s'] );
1373          } else {
1374              if ( preg_match_all( '/".*?("|$)|((?<=[\t ",+])|^)[^\t ",+]+/', $q['s'], $matches ) ) {
1375                  $q['search_terms_count'] = count( $matches[0] );
1376                  $q['search_terms']       = $this->parse_search_terms( $matches[0] );
1377                  // If the search string has only short terms or stopwords, or is 10+ terms long, match it as sentence.
1378                  if ( empty( $q['search_terms'] ) || count( $q['search_terms'] ) > 9 ) {
1379                      $q['search_terms'] = array( $q['s'] );
1380                  }
1381              } else {
1382                  $q['search_terms'] = array( $q['s'] );
1383              }
1384          }
1385  
1386          $n                         = ! empty( $q['exact'] ) ? '' : '%';
1387          $searchand                 = '';
1388          $q['search_orderby_title'] = array();
1389  
1390          /**
1391           * Filters the prefix that indicates that a search term should be excluded from results.
1392           *
1393           * @since 4.7.0
1394           *
1395           * @param string $exclusion_prefix The prefix. Default '-'. Returning
1396           *                                 an empty value disables exclusions.
1397           */
1398          $exclusion_prefix = apply_filters( 'wp_query_search_exclusion_prefix', '-' );
1399  
1400          foreach ( $q['search_terms'] as $term ) {
1401              // If there is an $exclusion_prefix, terms prefixed with it should be excluded.
1402              $exclude = $exclusion_prefix && ( substr( $term, 0, 1 ) === $exclusion_prefix );
1403              if ( $exclude ) {
1404                  $like_op  = 'NOT LIKE';
1405                  $andor_op = 'AND';
1406                  $term     = substr( $term, 1 );
1407              } else {
1408                  $like_op  = 'LIKE';
1409                  $andor_op = 'OR';
1410              }
1411  
1412              if ( $n && ! $exclude ) {
1413                  $like                        = '%' . $wpdb->esc_like( $term ) . '%';
1414                  $q['search_orderby_title'][] = $wpdb->prepare( "{$wpdb->posts}.post_title LIKE %s", $like );
1415              }
1416  
1417              $like      = $n . $wpdb->esc_like( $term ) . $n;
1418              $search   .= $wpdb->prepare( "{$searchand}(({$wpdb->posts}.post_title $like_op %s) $andor_op ({$wpdb->posts}.post_excerpt $like_op %s) $andor_op ({$wpdb->posts}.post_content $like_op %s))", $like, $like, $like );
1419              $searchand = ' AND ';
1420          }
1421  
1422          if ( ! empty( $search ) ) {
1423              $search = " AND ({$search}) ";
1424              if ( ! is_user_logged_in() ) {
1425                  $search .= " AND ({$wpdb->posts}.post_password = '') ";
1426              }
1427          }
1428  
1429          return $search;
1430      }
1431  
1432      /**
1433       * Check if the terms are suitable for searching.
1434       *
1435       * Uses an array of stopwords (terms) that are excluded from the separate
1436       * term matching when searching for posts. The list of English stopwords is
1437       * the approximate search engines list, and is translatable.
1438       *
1439       * @since 3.7.0
1440       *
1441       * @param string[] $terms Array of terms to check.
1442       * @return string[] Terms that are not stopwords.
1443       */
1444  	protected function parse_search_terms( $terms ) {
1445          $strtolower = function_exists( 'mb_strtolower' ) ? 'mb_strtolower' : 'strtolower';
1446          $checked    = array();
1447  
1448          $stopwords = $this->get_search_stopwords();
1449  
1450          foreach ( $terms as $term ) {
1451              // Keep before/after spaces when term is for exact match.
1452              if ( preg_match( '/^".+"$/', $term ) ) {
1453                  $term = trim( $term, "\"'" );
1454              } else {
1455                  $term = trim( $term, "\"' " );
1456              }
1457  
1458              // Avoid single A-Z and single dashes.
1459              if ( ! $term || ( 1 === strlen( $term ) && preg_match( '/^[a-z\-]$/i', $term ) ) ) {
1460                  continue;
1461              }
1462  
1463              if ( in_array( call_user_func( $strtolower, $term ), $stopwords, true ) ) {
1464                  continue;
1465              }
1466  
1467              $checked[] = $term;
1468          }
1469  
1470          return $checked;
1471      }
1472  
1473      /**
1474       * Retrieve stopwords used when parsing search terms.
1475       *
1476       * @since 3.7.0
1477       *
1478       * @return string[] Stopwords.
1479       */
1480  	protected function get_search_stopwords() {
1481          if ( isset( $this->stopwords ) ) {
1482              return $this->stopwords;
1483          }
1484  
1485          /*
1486           * translators: This is a comma-separated list of very common words that should be excluded from a search,
1487           * like a, an, and the. These are usually called "stopwords". You should not simply translate these individual
1488           * words into your language. Instead, look for and provide commonly accepted stopwords in your language.
1489           */
1490          $words = explode(
1491              ',',
1492              _x(
1493                  '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',
1494                  'Comma-separated list of search stopwords in your language'
1495              )
1496          );
1497  
1498          $stopwords = array();
1499          foreach ( $words as $word ) {
1500              $word = trim( $word, "\r\n\t " );
1501              if ( $word ) {
1502                  $stopwords[] = $word;
1503              }
1504          }
1505  
1506          /**
1507           * Filters stopwords used when parsing search terms.
1508           *
1509           * @since 3.7.0
1510           *
1511           * @param string[] $stopwords Array of stopwords.
1512           */
1513          $this->stopwords = apply_filters( 'wp_search_stopwords', $stopwords );
1514          return $this->stopwords;
1515      }
1516  
1517      /**
1518       * Generates SQL for the ORDER BY condition based on passed search terms.
1519       *
1520       * @since 3.7.0
1521       *
1522       * @global wpdb $wpdb WordPress database abstraction object.
1523       *
1524       * @param array $q Query variables.
1525       * @return string ORDER BY clause.
1526       */
1527  	protected function parse_search_order( &$q ) {
1528          global $wpdb;
1529  
1530          if ( $q['search_terms_count'] > 1 ) {
1531              $num_terms = count( $q['search_orderby_title'] );
1532  
1533              // If the search terms contain negative queries, don't bother ordering by sentence matches.
1534              $like = '';
1535              if ( ! preg_match( '/(?:\s|^)\-/', $q['s'] ) ) {
1536                  $like = '%' . $wpdb->esc_like( $q['s'] ) . '%';
1537              }
1538  
1539              $search_orderby = '';
1540  
1541              // Sentence match in 'post_title'.
1542              if ( $like ) {
1543                  $search_orderby .= $wpdb->prepare( "WHEN {$wpdb->posts}.post_title LIKE %s THEN 1 ", $like );
1544              }
1545  
1546              // Sanity limit, sort as sentence when more than 6 terms
1547              // (few searches are longer than 6 terms and most titles are not).
1548              if ( $num_terms < 7 ) {
1549                  // All words in title.
1550                  $search_orderby .= 'WHEN ' . implode( ' AND ', $q['search_orderby_title'] ) . ' THEN 2 ';
1551                  // Any word in title, not needed when $num_terms == 1.
1552                  if ( $num_terms > 1 ) {
1553                      $search_orderby .= 'WHEN ' . implode( ' OR ', $q['search_orderby_title'] ) . ' THEN 3 ';
1554                  }
1555              }
1556  
1557              // Sentence match in 'post_content' and 'post_excerpt'.
1558              if ( $like ) {
1559                  $search_orderby .= $wpdb->prepare( "WHEN {$wpdb->posts}.post_excerpt LIKE %s THEN 4 ", $like );
1560                  $search_orderby .= $wpdb->prepare( "WHEN {$wpdb->posts}.post_content LIKE %s THEN 5 ", $like );
1561              }
1562  
1563              if ( $search_orderby ) {
1564                  $search_orderby = '(CASE ' . $search_orderby . 'ELSE 6 END)';
1565              }
1566          } else {
1567              // Single word or sentence search.
1568              $search_orderby = reset( $q['search_orderby_title'] ) . ' DESC';
1569          }
1570  
1571          return $search_orderby;
1572      }
1573  
1574      /**
1575       * Converts the given orderby alias (if allowed) to a properly-prefixed value.
1576       *
1577       * @since 4.0.0
1578       *
1579       * @global wpdb $wpdb WordPress database abstraction object.
1580       *
1581       * @param string $orderby Alias for the field to order by.
1582       * @return string|false Table-prefixed value to used in the ORDER clause. False otherwise.
1583       */
1584  	protected function parse_orderby( $orderby ) {
1585          global $wpdb;
1586  
1587          // Used to filter values.
1588          $allowed_keys = array(
1589              'post_name',
1590              'post_author',
1591              'post_date',
1592              'post_title',
1593              'post_modified',
1594              'post_parent',
1595              'post_type',
1596              'name',
1597              'author',
1598              'date',
1599              'title',
1600              'modified',
1601              'parent',
1602              'type',
1603              'ID',
1604              'menu_order',
1605              'comment_count',
1606              'rand',
1607              'post__in',
1608              'post_parent__in',
1609              'post_name__in',
1610          );
1611  
1612          $primary_meta_key   = '';
1613          $primary_meta_query = false;
1614          $meta_clauses       = $this->meta_query->get_clauses();
1615          if ( ! empty( $meta_clauses ) ) {
1616              $primary_meta_query = reset( $meta_clauses );
1617  
1618              if ( ! empty( $primary_meta_query['key'] ) ) {
1619                  $primary_meta_key = $primary_meta_query['key'];
1620                  $allowed_keys[]   = $primary_meta_key;
1621              }
1622  
1623              $allowed_keys[] = 'meta_value';
1624              $allowed_keys[] = 'meta_value_num';
1625              $allowed_keys   = array_merge( $allowed_keys, array_keys( $meta_clauses ) );
1626          }
1627  
1628          // If RAND() contains a seed value, sanitize and add to allowed keys.
1629          $rand_with_seed = false;
1630          if ( preg_match( '/RAND\(([0-9]+)\)/i', $orderby, $matches ) ) {
1631              $orderby        = sprintf( 'RAND(%s)', (int) $matches[1] );
1632              $allowed_keys[] = $orderby;
1633              $rand_with_seed = true;
1634          }
1635  
1636          if ( ! in_array( $orderby, $allowed_keys, true ) ) {
1637              return false;
1638          }
1639  
1640          $orderby_clause = '';
1641  
1642          switch ( $orderby ) {
1643              case 'post_name':
1644              case 'post_author':
1645              case 'post_date':
1646              case 'post_title':
1647              case 'post_modified':
1648              case 'post_parent':
1649              case 'post_type':
1650              case 'ID':
1651              case 'menu_order':
1652              case 'comment_count':
1653                  $orderby_clause = "{$wpdb->posts}.{$orderby}";
1654                  break;
1655              case 'rand':
1656                  $orderby_clause = 'RAND()';
1657                  break;
1658              case $primary_meta_key:
1659              case 'meta_value':
1660                  if ( ! empty( $primary_meta_query['type'] ) ) {
1661                      $orderby_clause = "CAST({$primary_meta_query['alias']}.meta_value AS {$primary_meta_query['cast']})";
1662                  } else {
1663                      $orderby_clause = "{$primary_meta_query['alias']}.meta_value";
1664                  }
1665                  break;
1666              case 'meta_value_num':
1667                  $orderby_clause = "{$primary_meta_query['alias']}.meta_value+0";
1668                  break;
1669              case 'post__in':
1670                  if ( ! empty( $this->query_vars['post__in'] ) ) {
1671                      $orderby_clause = "FIELD({$wpdb->posts}.ID," . implode( ',', array_map( 'absint', $this->query_vars['post__in'] ) ) . ')';
1672                  }
1673                  break;
1674              case 'post_parent__in':
1675                  if ( ! empty( $this->query_vars['post_parent__in'] ) ) {
1676                      $orderby_clause = "FIELD( {$wpdb->posts}.post_parent," . implode( ', ', array_map( 'absint', $this->query_vars['post_parent__in'] ) ) . ' )';
1677                  }
1678                  break;
1679              case 'post_name__in':
1680                  if ( ! empty( $this->query_vars['post_name__in'] ) ) {
1681                      $post_name__in        = array_map( 'sanitize_title_for_query', $this->query_vars['post_name__in'] );
1682                      $post_name__in_string = "'" . implode( "','", $post_name__in ) . "'";
1683                      $orderby_clause       = "FIELD( {$wpdb->posts}.post_name," . $post_name__in_string . ' )';
1684                  }
1685                  break;
1686              default:
1687                  if ( array_key_exists( $orderby, $meta_clauses ) ) {
1688                      // $orderby corresponds to a meta_query clause.
1689                      $meta_clause    = $meta_clauses[ $orderby ];
1690                      $orderby_clause = "CAST({$meta_clause['alias']}.meta_value AS {$meta_clause['cast']})";
1691                  } elseif ( $rand_with_seed ) {
1692                      $orderby_clause = $orderby;
1693                  } else {
1694                      // Default: order by post field.
1695                      $orderby_clause = "{$wpdb->posts}.post_" . sanitize_key( $orderby );
1696                  }
1697  
1698                  break;
1699          }
1700  
1701          return $orderby_clause;
1702      }
1703  
1704      /**
1705       * Parse an 'order' query variable and cast it to ASC or DESC as necessary.
1706       *
1707       * @since 4.0.0
1708       *
1709       * @param string $order The 'order' query variable.
1710       * @return string The sanitized 'order' query variable.
1711       */
1712  	protected function parse_order( $order ) {
1713          if ( ! is_string( $order ) || empty( $order ) ) {
1714              return 'DESC';
1715          }
1716  
1717          if ( 'ASC' === strtoupper( $order ) ) {
1718              return 'ASC';
1719          } else {
1720              return 'DESC';
1721          }
1722      }
1723  
1724      /**
1725       * Sets the 404 property and saves whether query is feed.
1726       *
1727       * @since 2.0.0
1728       */
1729  	public function set_404() {
1730          $is_feed = $this->is_feed;
1731  
1732          $this->init_query_flags();
1733          $this->is_404 = true;
1734  
1735          $this->is_feed = $is_feed;
1736  
1737          /**
1738           * Fires after a 404 is triggered.
1739           *
1740           * @since 5.5.0
1741           *
1742           * @param WP_Query $query The WP_Query instance (passed by reference).
1743           */
1744          do_action_ref_array( 'set_404', array( $this ) );
1745      }
1746  
1747      /**
1748       * Retrieves the value of a query variable.
1749       *
1750       * @since 1.5.0
1751       * @since 3.9.0 The `$default_value` argument was introduced.
1752       *
1753       * @param string $query_var     Query variable key.
1754       * @param mixed  $default_value Optional. Value to return if the query variable is not set. Default empty string.
1755       * @return mixed Contents of the query variable.
1756       */
1757  	public function get( $query_var, $default_value = '' ) {
1758          if ( isset( $this->query_vars[ $query_var ] ) ) {
1759              return $this->query_vars[ $query_var ];
1760          }
1761  
1762          return $default_value;
1763      }
1764  
1765      /**
1766       * Sets the value of a query variable.
1767       *
1768       * @since 1.5.0
1769       *
1770       * @param string $query_var Query variable key.
1771       * @param mixed  $value     Query variable value.
1772       */
1773  	public function set( $query_var, $value ) {
1774          $this->query_vars[ $query_var ] = $value;
1775      }
1776  
1777      /**
1778       * Retrieves an array of posts based on query variables.
1779       *
1780       * There are a few filters and actions that can be used to modify the post
1781       * database query.
1782       *
1783       * @since 1.5.0
1784       *
1785       * @global wpdb $wpdb WordPress database abstraction object.
1786       *
1787       * @return WP_Post[]|int[] Array of post objects or post IDs.
1788       */
1789  	public function get_posts() {
1790          global $wpdb;
1791  
1792          $this->parse_query();
1793  
1794          /**
1795           * Fires after the query variable object is created, but before the actual query is run.
1796           *
1797           * Note: If using conditional tags, use the method versions within the passed instance
1798           * (e.g. $this->is_main_query() instead of is_main_query()). This is because the functions
1799           * like is_main_query() test against the global $wp_query instance, not the passed one.
1800           *
1801           * @since 2.0.0
1802           *
1803           * @param WP_Query $query The WP_Query instance (passed by reference).
1804           */
1805          do_action_ref_array( 'pre_get_posts', array( &$this ) );
1806  
1807          // Shorthand.
1808          $q = &$this->query_vars;
1809  
1810          // Fill again in case 'pre_get_posts' unset some vars.
1811          $q = $this->fill_query_vars( $q );
1812  
1813          // Parse meta query.
1814          $this->meta_query = new WP_Meta_Query();
1815          $this->meta_query->parse_query_vars( $q );
1816  
1817          // Set a flag if a 'pre_get_posts' hook changed the query vars.
1818          $hash = md5( serialize( $this->query_vars ) );
1819          if ( $hash != $this->query_vars_hash ) {
1820              $this->query_vars_changed = true;
1821              $this->query_vars_hash    = $hash;
1822          }
1823          unset( $hash );
1824  
1825          // First let's clear some variables.
1826          $distinct         = '';
1827          $whichauthor      = '';
1828          $whichmimetype    = '';
1829          $where            = '';
1830          $limits           = '';
1831          $join             = '';
1832          $search           = '';
1833          $groupby          = '';
1834          $post_status_join = false;
1835          $page             = 1;
1836  
1837          if ( isset( $q['caller_get_posts'] ) ) {
1838              _deprecated_argument(
1839                  'WP_Query',
1840                  '3.1.0',
1841                  sprintf(
1842                      /* translators: 1: caller_get_posts, 2: ignore_sticky_posts */
1843                      __( '%1$s is deprecated. Use %2$s instead.' ),
1844                      '<code>caller_get_posts</code>',
1845                      '<code>ignore_sticky_posts</code>'
1846                  )
1847              );
1848  
1849              if ( ! isset( $q['ignore_sticky_posts'] ) ) {
1850                  $q['ignore_sticky_posts'] = $q['caller_get_posts'];
1851              }
1852          }
1853  
1854          if ( ! isset( $q['ignore_sticky_posts'] ) ) {
1855              $q['ignore_sticky_posts'] = false;
1856          }
1857  
1858          if ( ! isset( $q['suppress_filters'] ) ) {
1859              $q['suppress_filters'] = false;
1860          }
1861  
1862          if ( ! isset( $q['cache_results'] ) ) {
1863              if ( wp_using_ext_object_cache() ) {
1864                  $q['cache_results'] = false;
1865              } else {
1866                  $q['cache_results'] = true;
1867              }
1868          }
1869  
1870          if ( ! isset( $q['update_post_term_cache'] ) ) {
1871              $q['update_post_term_cache'] = true;
1872          }
1873  
1874          if ( ! isset( $q['lazy_load_term_meta'] ) ) {
1875              $q['lazy_load_term_meta'] = $q['update_post_term_cache'];
1876          }
1877  
1878          if ( ! isset( $q['update_post_meta_cache'] ) ) {
1879              $q['update_post_meta_cache'] = true;
1880          }
1881  
1882          if ( ! isset( $q['post_type'] ) ) {
1883              if ( $this->is_search ) {
1884                  $q['post_type'] = 'any';
1885              } else {
1886                  $q['post_type'] = '';
1887              }
1888          }
1889          $post_type = $q['post_type'];
1890          if ( empty( $q['posts_per_page'] ) ) {
1891              $q['posts_per_page'] = get_option( 'posts_per_page' );
1892          }
1893          if ( isset( $q['showposts'] ) && $q['showposts'] ) {
1894              $q['showposts']      = (int) $q['showposts'];
1895              $q['posts_per_page'] = $q['showposts'];
1896          }
1897          if ( ( isset( $q['posts_per_archive_page'] ) && 0 != $q['posts_per_archive_page'] ) && ( $this->is_archive || $this->is_search ) ) {
1898              $q['posts_per_page'] = $q['posts_per_archive_page'];
1899          }
1900          if ( ! isset( $q['nopaging'] ) ) {
1901              if ( -1 == $q['posts_per_page'] ) {
1902                  $q['nopaging'] = true;
1903              } else {
1904                  $q['nopaging'] = false;
1905              }
1906          }
1907  
1908          if ( $this->is_feed ) {
1909              // This overrides 'posts_per_page'.
1910              if ( ! empty( $q['posts_per_rss'] ) ) {
1911                  $q['posts_per_page'] = $q['posts_per_rss'];
1912              } else {
1913                  $q['posts_per_page'] = get_option( 'posts_per_rss' );
1914              }
1915              $q['nopaging'] = false;
1916          }
1917          $q['posts_per_page'] = (int) $q['posts_per_page'];
1918          if ( $q['posts_per_page'] < -1 ) {
1919              $q['posts_per_page'] = abs( $q['posts_per_page'] );
1920          } elseif ( 0 == $q['posts_per_page'] ) {
1921              $q['posts_per_page'] = 1;
1922          }
1923  
1924          if ( ! isset( $q['comments_per_page'] ) || 0 == $q['comments_per_page'] ) {
1925              $q['comments_per_page'] = get_option( 'comments_per_page' );
1926          }
1927  
1928          if ( $this->is_home && ( empty( $this->query ) || 'true' === $q['preview'] ) && ( 'page' === get_option( 'show_on_front' ) ) && get_option( 'page_on_front' ) ) {
1929              $this->is_page = true;
1930              $this->is_home = false;
1931              $q['page_id']  = get_option( 'page_on_front' );
1932          }
1933  
1934          if ( isset( $q['page'] ) ) {
1935              $q['page'] = trim( $q['page'], '/' );
1936              $q['page'] = absint( $q['page'] );
1937          }
1938  
1939          // If true, forcibly turns off SQL_CALC_FOUND_ROWS even when limits are present.
1940          if ( isset( $q['no_found_rows'] ) ) {
1941              $q['no_found_rows'] = (bool) $q['no_found_rows'];
1942          } else {
1943              $q['no_found_rows'] = false;
1944          }
1945  
1946          switch ( $q['fields'] ) {
1947              case 'ids':
1948                  $fields = "{$wpdb->posts}.ID";
1949                  break;
1950              case 'id=>parent':
1951                  $fields = "{$wpdb->posts}.ID, {$wpdb->posts}.post_parent";
1952                  break;
1953              default:
1954                  $fields = "{$wpdb->posts}.*";
1955          }
1956  
1957          if ( '' !== $q['menu_order'] ) {
1958              $where .= " AND {$wpdb->posts}.menu_order = " . $q['menu_order'];
1959          }
1960          // The "m" parameter is meant for months but accepts datetimes of varying specificity.
1961          if ( $q['m'] ) {
1962              $where .= " AND YEAR({$wpdb->posts}.post_date)=" . substr( $q['m'], 0, 4 );
1963              if ( strlen( $q['m'] ) > 5 ) {
1964                  $where .= " AND MONTH({$wpdb->posts}.post_date)=" . substr( $q['m'], 4, 2 );
1965              }
1966              if ( strlen( $q['m'] ) > 7 ) {
1967                  $where .= " AND DAYOFMONTH({$wpdb->posts}.post_date)=" . substr( $q['m'], 6, 2 );
1968              }
1969              if ( strlen( $q['m'] ) > 9 ) {
1970                  $where .= " AND HOUR({$wpdb->posts}.post_date)=" . substr( $q['m'], 8, 2 );
1971              }
1972              if ( strlen( $q['m'] ) > 11 ) {
1973                  $where .= " AND MINUTE({$wpdb->posts}.post_date)=" . substr( $q['m'], 10, 2 );
1974              }
1975              if ( strlen( $q['m'] ) > 13 ) {
1976                  $where .= " AND SECOND({$wpdb->posts}.post_date)=" . substr( $q['m'], 12, 2 );
1977              }
1978          }
1979  
1980          // Handle the other individual date parameters.
1981          $date_parameters = array();
1982  
1983          if ( '' !== $q['hour'] ) {
1984              $date_parameters['hour'] = $q['hour'];
1985          }
1986  
1987          if ( '' !== $q['minute'] ) {
1988              $date_parameters['minute'] = $q['minute'];
1989          }
1990  
1991          if ( '' !== $q['second'] ) {
1992              $date_parameters['second'] = $q['second'];
1993          }
1994  
1995          if ( $q['year'] ) {
1996              $date_parameters['year'] = $q['year'];
1997          }
1998  
1999          if ( $q['monthnum'] ) {
2000              $date_parameters['monthnum'] = $q['monthnum'];
2001          }
2002  
2003          if ( $q['w'] ) {
2004              $date_parameters['week'] = $q['w'];
2005          }
2006  
2007          if ( $q['day'] ) {
2008              $date_parameters['day'] = $q['day'];
2009          }
2010  
2011          if ( $date_parameters ) {
2012              $date_query = new WP_Date_Query( array( $date_parameters ) );
2013              $where     .= $date_query->get_sql();
2014          }
2015          unset( $date_parameters, $date_query );
2016  
2017          // Handle complex date queries.
2018          if ( ! empty( $q['date_query'] ) ) {
2019              $this->date_query = new WP_Date_Query( $q['date_query'] );
2020              $where           .= $this->date_query->get_sql();
2021          }
2022  
2023          // If we've got a post_type AND it's not "any" post_type.
2024          if ( ! empty( $q['post_type'] ) && 'any' !== $q['post_type'] ) {
2025              foreach ( (array) $q['post_type'] as $_post_type ) {
2026                  $ptype_obj = get_post_type_object( $_post_type );
2027                  if ( ! $ptype_obj || ! $ptype_obj->query_var || empty( $q[ $ptype_obj->query_var ] ) ) {
2028                      continue;
2029                  }
2030  
2031                  if ( ! $ptype_obj->hierarchical ) {
2032                      // Non-hierarchical post types can directly use 'name'.
2033                      $q['name'] = $q[ $ptype_obj->query_var ];
2034                  } else {
2035                      // Hierarchical post types will operate through 'pagename'.
2036                      $q['pagename'] = $q[ $ptype_obj->query_var ];
2037                      $q['name']     = '';
2038                  }
2039  
2040                  // Only one request for a slug is possible, this is why name & pagename are overwritten above.
2041                  break;
2042              } // End foreach.
2043              unset( $ptype_obj );
2044          }
2045  
2046          if ( '' !== $q['title'] ) {
2047              $where .= $wpdb->prepare( " AND {$wpdb->posts}.post_title = %s", stripslashes( $q['title'] ) );
2048          }
2049  
2050          // Parameters related to 'post_name'.
2051          if ( '' !== $q['name'] ) {
2052              $q['name'] = sanitize_title_for_query( $q['name'] );
2053              $where    .= " AND {$wpdb->posts}.post_name = '" . $q['name'] . "'";
2054          } elseif ( '' !== $q['pagename'] ) {
2055              if ( isset( $this->queried_object_id ) ) {
2056                  $reqpage = $this->queried_object_id;
2057              } else {
2058                  if ( 'page' !== $q['post_type'] ) {
2059                      foreach ( (array) $q['post_type'] as $_post_type ) {
2060                          $ptype_obj = get_post_type_object( $_post_type );
2061                          if ( ! $ptype_obj || ! $ptype_obj->hierarchical ) {
2062                              continue;
2063                          }
2064  
2065                          $reqpage = get_page_by_path( $q['pagename'], OBJECT, $_post_type );
2066                          if ( $reqpage ) {
2067                              break;
2068                          }
2069                      }
2070                      unset( $ptype_obj );
2071                  } else {
2072                      $reqpage = get_page_by_path( $q['pagename'] );
2073                  }
2074                  if ( ! empty( $reqpage ) ) {
2075                      $reqpage = $reqpage->ID;
2076                  } else {
2077                      $reqpage = 0;
2078                  }
2079              }
2080  
2081              $page_for_posts = get_option( 'page_for_posts' );
2082              if ( ( 'page' !== get_option( 'show_on_front' ) ) || empty( $page_for_posts ) || ( $reqpage != $page_for_posts ) ) {
2083                  $q['pagename'] = sanitize_title_for_query( wp_basename( $q['pagename'] ) );
2084                  $q['name']     = $q['pagename'];
2085                  $where        .= " AND ({$wpdb->posts}.ID = '$reqpage')";
2086                  $reqpage_obj   = get_post( $reqpage );
2087                  if ( is_object( $reqpage_obj ) && 'attachment' === $reqpage_obj->post_type ) {
2088                      $this->is_attachment = true;
2089                      $post_type           = 'attachment';
2090                      $q['post_type']      = 'attachment';
2091                      $this->is_page       = true;
2092                      $q['attachment_id']  = $reqpage;
2093                  }
2094              }
2095          } elseif ( '' !== $q['attachment'] ) {
2096              $q['attachment'] = sanitize_title_for_query( wp_basename( $q['attachment'] ) );
2097              $q['name']       = $q['attachment'];
2098              $where          .= " AND {$wpdb->posts}.post_name = '" . $q['attachment'] . "'";
2099          } elseif ( is_array( $q['post_name__in'] ) && ! empty( $q['post_name__in'] ) ) {
2100              $q['post_name__in'] = array_map( 'sanitize_title_for_query', $q['post_name__in'] );
2101              $post_name__in      = "'" . implode( "','", $q['post_name__in'] ) . "'";
2102              $where             .= " AND {$wpdb->posts}.post_name IN ($post_name__in)";
2103          }
2104  
2105          // If an attachment is requested by number, let it supersede any post number.
2106          if ( $q['attachment_id'] ) {
2107              $q['p'] = absint( $q['attachment_id'] );
2108          }
2109  
2110          // If a post number is specified, load that post.
2111          if ( $q['p'] ) {
2112              $where .= " AND {$wpdb->posts}.ID = " . $q['p'];
2113          } elseif ( $q['post__in'] ) {
2114              $post__in = implode( ',', array_map( 'absint', $q['post__in'] ) );
2115              $where   .= " AND {$wpdb->posts}.ID IN ($post__in)";
2116          } elseif ( $q['post__not_in'] ) {
2117              $post__not_in = implode( ',', array_map( 'absint', $q['post__not_in'] ) );
2118              $where       .= " AND {$wpdb->posts}.ID NOT IN ($post__not_in)";
2119          }
2120  
2121          if ( is_numeric( $q['post_parent'] ) ) {
2122              $where .= $wpdb->prepare( " AND {$wpdb->posts}.post_parent = %d ", $q['post_parent'] );
2123          } elseif ( $q['post_parent__in'] ) {
2124              $post_parent__in = implode( ',', array_map( 'absint', $q['post_parent__in'] ) );
2125              $where          .= " AND {$wpdb->posts}.post_parent IN ($post_parent__in)";
2126          } elseif ( $q['post_parent__not_in'] ) {
2127              $post_parent__not_in = implode( ',', array_map( 'absint', $q['post_parent__not_in'] ) );
2128              $where              .= " AND {$wpdb->posts}.post_parent NOT IN ($post_parent__not_in)";
2129          }
2130  
2131          if ( $q['page_id'] ) {
2132              if ( ( 'page' !== get_option( 'show_on_front' ) ) || ( get_option( 'page_for_posts' ) != $q['page_id'] ) ) {
2133                  $q['p'] = $q['page_id'];
2134                  $where  = " AND {$wpdb->posts}.ID = " . $q['page_id'];
2135              }
2136          }
2137  
2138          // If a search pattern is specified, load the posts that match.
2139          if ( strlen( $q['s'] ) ) {
2140              $search = $this->parse_search( $q );
2141          }
2142  
2143          if ( ! $q['suppress_filters'] ) {
2144              /**
2145               * Filters the search SQL that is used in the WHERE clause of WP_Query.
2146               *
2147               * @since 3.0.0
2148               *
2149               * @param string   $search Search SQL for WHERE clause.
2150               * @param WP_Query $query  The current WP_Query object.
2151               */
2152              $search = apply_filters_ref_array( 'posts_search', array( $search, &$this ) );
2153          }
2154  
2155          // Taxonomies.
2156          if ( ! $this->is_singular ) {
2157              $this->parse_tax_query( $q );
2158  
2159              $clauses = $this->tax_query->get_sql( $wpdb->posts, 'ID' );
2160  
2161              $join  .= $clauses['join'];
2162              $where .= $clauses['where'];
2163          }
2164  
2165          if ( $this->is_tax ) {
2166              if ( empty( $post_type ) ) {
2167                  // Do a fully inclusive search for currently registered post types of queried taxonomies.
2168                  $post_type  = array();
2169                  $taxonomies = array_keys( $this->tax_query->queried_terms );
2170                  foreach ( get_post_types( array( 'exclude_from_search' => false ) ) as $pt ) {
2171                      $object_taxonomies = 'attachment' === $pt ? get_taxonomies_for_attachments() : get_object_taxonomies( $pt );
2172                      if ( array_intersect( $taxonomies, $object_taxonomies ) ) {
2173                          $post_type[] = $pt;
2174                      }
2175                  }
2176                  if ( ! $post_type ) {
2177                      $post_type = 'any';
2178                  } elseif ( count( $post_type ) == 1 ) {
2179                      $post_type = $post_type[0];
2180                  }
2181  
2182                  $post_status_join = true;
2183              } elseif ( in_array( 'attachment', (array) $post_type, true ) ) {
2184                  $post_status_join = true;
2185              }
2186          }
2187  
2188          /*
2189           * Ensure that 'taxonomy', 'term', 'term_id', 'cat', and
2190           * 'category_name' vars are set for backward compatibility.
2191           */
2192          if ( ! empty( $this->tax_query->queried_terms ) ) {
2193  
2194              /*
2195               * Set 'taxonomy', 'term', and 'term_id' to the
2196               * first taxonomy other than 'post_tag' or 'category'.
2197               */
2198              if ( ! isset( $q['taxonomy'] ) ) {
2199                  foreach ( $this->tax_query->queried_terms as $queried_taxonomy => $queried_items ) {
2200                      if ( empty( $queried_items['terms'][0] ) ) {
2201                          continue;
2202                      }
2203  
2204                      if ( ! in_array( $queried_taxonomy, array( 'category', 'post_tag' ), true ) ) {
2205                          $q['taxonomy'] = $queried_taxonomy;
2206  
2207                          if ( 'slug' === $queried_items['field'] ) {
2208                              $q['term'] = $queried_items['terms'][0];
2209                          } else {
2210                              $q['term_id'] = $queried_items['terms'][0];
2211                          }
2212  
2213                          // Take the first one we find.
2214                          break;
2215                      }
2216                  }
2217              }
2218  
2219              // 'cat', 'category_name', 'tag_id'.
2220              foreach ( $this->tax_query->queried_terms as $queried_taxonomy => $queried_items ) {
2221                  if ( empty( $queried_items['terms'][0] ) ) {
2222                      continue;
2223                  }
2224  
2225                  if ( 'category' === $queried_taxonomy ) {
2226                      $the_cat = get_term_by( $queried_items['field'], $queried_items['terms'][0], 'category' );
2227                      if ( $the_cat ) {
2228                          $this->set( 'cat', $the_cat->term_id );
2229                          $this->set( 'category_name', $the_cat->slug );
2230                      }
2231                      unset( $the_cat );
2232                  }
2233  
2234                  if ( 'post_tag' === $queried_taxonomy ) {
2235                      $the_tag = get_term_by( $queried_items['field'], $queried_items['terms'][0], 'post_tag' );
2236                      if ( $the_tag ) {
2237                          $this->set( 'tag_id', $the_tag->term_id );
2238                      }
2239                      unset( $the_tag );
2240                  }
2241              }
2242          }
2243  
2244          if ( ! empty( $this->tax_query->queries ) || ! empty( $this->meta_query->queries ) ) {
2245              $groupby = "{$wpdb->posts}.ID";
2246          }
2247  
2248          // Author/user stuff.
2249  
2250          if ( ! empty( $q['author'] ) && '0' != $q['author'] ) {
2251              $q['author'] = addslashes_gpc( '' . urldecode( $q['author'] ) );
2252              $authors     = array_unique( array_map( 'intval', preg_split( '/[,\s]+/', $q['author'] ) ) );
2253              foreach ( $authors as $author ) {
2254                  $key         = $author > 0 ? 'author__in' : 'author__not_in';
2255                  $q[ $key ][] = abs( $author );
2256              }
2257              $q['author'] = implode( ',', $authors );
2258          }
2259  
2260          if ( ! empty( $q['author__not_in'] ) ) {
2261              $author__not_in = implode( ',', array_map( 'absint', array_unique( (array) $q['author__not_in'] ) ) );
2262              $where         .= " AND {$wpdb->posts}.post_author NOT IN ($author__not_in) ";
2263          } elseif ( ! empty( $q['author__in'] ) ) {
2264              $author__in = implode( ',', array_map( 'absint', array_unique( (array) $q['author__in'] ) ) );
2265              $where     .= " AND {$wpdb->posts}.post_author IN ($author__in) ";
2266          }
2267  
2268          // Author stuff for nice URLs.
2269  
2270          if ( '' !== $q['author_name'] ) {
2271              if ( strpos( $q['author_name'], '/' ) !== false ) {
2272                  $q['author_name'] = explode( '/', $q['author_name'] );
2273                  if ( $q['author_name'][ count( $q['author_name'] ) - 1 ] ) {
2274                      $q['author_name'] = $q['author_name'][ count( $q['author_name'] ) - 1 ]; // No trailing slash.
2275                  } else {
2276                      $q['author_name'] = $q['author_name'][ count( $q['author_name'] ) - 2 ]; // There was a trailing slash.
2277                  }
2278              }
2279              $q['author_name'] = sanitize_title_for_query( $q['author_name'] );
2280              $q['author']      = get_user_by( 'slug', $q['author_name'] );
2281              if ( $q['author'] ) {
2282                  $q['author'] = $q['author']->ID;
2283              }
2284              $whichauthor .= " AND ({$wpdb->posts}.post_author = " . absint( $q['author'] ) . ')';
2285          }
2286  
2287          // Matching by comment count.
2288          if ( isset( $q['comment_count'] ) ) {
2289              // Numeric comment count is converted to array format.
2290              if ( is_numeric( $q['comment_count'] ) ) {
2291                  $q['comment_count'] = array(
2292                      'value' => (int) $q['comment_count'],
2293                  );
2294              }
2295  
2296              if ( isset( $q['comment_count']['value'] ) ) {
2297                  $q['comment_count'] = array_merge(
2298                      array(
2299                          'compare' => '=',
2300                      ),
2301                      $q['comment_count']
2302                  );
2303  
2304                  // Fallback for invalid compare operators is '='.
2305                  $compare_operators = array( '=', '!=', '>', '>=', '<', '<=' );
2306                  if ( ! in_array( $q['comment_count']['compare'], $compare_operators, true ) ) {
2307                      $q['comment_count']['compare'] = '=';
2308                  }
2309  
2310                  $where .= $wpdb->prepare( " AND {$wpdb->posts}.comment_count {$q['comment_count']['compare']} %d", $q['comment_count']['value'] );
2311              }
2312          }
2313  
2314          // MIME-Type stuff for attachment browsing.
2315  
2316          if ( isset( $q['post_mime_type'] ) && '' !== $q['post_mime_type'] ) {
2317              $whichmimetype = wp_post_mime_type_where( $q['post_mime_type'], $wpdb->posts );
2318          }
2319          $where .= $search . $whichauthor . $whichmimetype;
2320  
2321          if ( ! empty( $this->meta_query->queries ) ) {
2322              $clauses = $this->meta_query->get_sql( 'post', $wpdb->posts, 'ID', $this );
2323              $join   .= $clauses['join'];
2324              $where  .= $clauses['where'];
2325          }
2326  
2327          $rand = ( isset( $q['orderby'] ) && 'rand' === $q['orderby'] );
2328          if ( ! isset( $q['order'] ) ) {
2329              $q['order'] = $rand ? '' : 'DESC';
2330          } else {
2331              $q['order'] = $rand ? '' : $this->parse_order( $q['order'] );
2332          }
2333  
2334          // These values of orderby should ignore the 'order' parameter.
2335          $force_asc = array( 'post__in', 'post_name__in', 'post_parent__in' );
2336          if ( isset( $q['orderby'] ) && in_array( $q['orderby'], $force_asc, true ) ) {
2337              $q['order'] = '';
2338          }
2339  
2340          // Order by.
2341          if ( empty( $q['orderby'] ) ) {
2342              /*
2343               * Boolean false or empty array blanks out ORDER BY,
2344               * while leaving the value unset or otherwise empty sets the default.
2345               */
2346              if ( isset( $q['orderby'] ) && ( is_array( $q['orderby'] ) || false === $q['orderby'] ) ) {
2347                  $orderby = '';
2348              } else {
2349                  $orderby = "{$wpdb->posts}.post_date " . $q['order'];
2350              }
2351          } elseif ( 'none' === $q['orderby'] ) {
2352              $orderby = '';
2353          } else {
2354              $orderby_array = array();
2355              if ( is_array( $q['orderby'] ) ) {
2356                  foreach ( $q['orderby'] as $_orderby => $order ) {
2357                      $orderby = addslashes_gpc( urldecode( $_orderby ) );
2358                      $parsed  = $this->parse_orderby( $orderby );
2359  
2360                      if ( ! $parsed ) {
2361                          continue;
2362                      }
2363  
2364                      $orderby_array[] = $parsed . ' ' . $this->parse_order( $order );
2365                  }
2366                  $orderby = implode( ', ', $orderby_array );
2367  
2368              } else {
2369                  $q['orderby'] = urldecode( $q['orderby'] );
2370                  $q['orderby'] = addslashes_gpc( $q['orderby'] );
2371  
2372                  foreach ( explode( ' ', $q['orderby'] ) as $i => $orderby ) {
2373                      $parsed = $this->parse_orderby( $orderby );
2374                      // Only allow certain values for safety.
2375                      if ( ! $parsed ) {
2376                          continue;
2377                      }
2378  
2379                      $orderby_array[] = $parsed;
2380                  }
2381                  $orderby = implode( ' ' . $q['order'] . ', ', $orderby_array );
2382  
2383                  if ( empty( $orderby ) ) {
2384                      $orderby = "{$wpdb->posts}.post_date " . $q['order'];
2385                  } elseif ( ! empty( $q['order'] ) ) {
2386                      $orderby .= " {$q['order']}";
2387                  }
2388              }
2389          }
2390  
2391          // Order search results by relevance only when another "orderby" is not specified in the query.
2392          if ( ! empty( $q['s'] ) ) {
2393              $search_orderby = '';
2394              if ( ! empty( $q['search_orderby_title'] ) && ( empty( $q['orderby'] ) && ! $this->is_feed ) || ( isset( $q['orderby'] ) && 'relevance' === $q['orderby'] ) ) {
2395                  $search_orderby = $this->parse_search_order( $q );
2396              }
2397  
2398              if ( ! $q['suppress_filters'] ) {
2399                  /**
2400                   * Filters the ORDER BY used when ordering search results.
2401                   *
2402                   * @since 3.7.0
2403                   *
2404                   * @param string   $search_orderby The ORDER BY clause.
2405                   * @param WP_Query $query          The current WP_Query instance.
2406                   */
2407                  $search_orderby = apply_filters( 'posts_search_orderby', $search_orderby, $this );
2408              }
2409  
2410              if ( $search_orderby ) {
2411                  $orderby = $orderby ? $search_orderby . ', ' . $orderby : $search_orderby;
2412              }
2413          }
2414  
2415          if ( is_array( $post_type ) && count( $post_type ) > 1 ) {
2416              $post_type_cap = 'multiple_post_type';
2417          } else {
2418              if ( is_array( $post_type ) ) {
2419                  $post_type = reset( $post_type );
2420              }
2421              $post_type_object = get_post_type_object( $post_type );
2422              if ( empty( $post_type_object ) ) {
2423                  $post_type_cap = $post_type;
2424              }
2425          }
2426  
2427          if ( isset( $q['post_password'] ) ) {
2428              $where .= $wpdb->prepare( " AND {$wpdb->posts}.post_password = %s", $q['post_password'] );
2429              if ( empty( $q['perm'] ) ) {
2430                  $q['perm'] = 'readable';
2431              }
2432          } elseif ( isset( $q['has_password'] ) ) {
2433              $where .= sprintf( " AND {$wpdb->posts}.post_password %s ''", $q['has_password'] ? '!=' : '=' );
2434          }
2435  
2436          if ( ! empty( $q['comment_status'] ) ) {
2437              $where .= $wpdb->prepare( " AND {$wpdb->posts}.comment_status = %s ", $q['comment_status'] );
2438          }
2439  
2440          if ( ! empty( $q['ping_status'] ) ) {
2441              $where .= $wpdb->prepare( " AND {$wpdb->posts}.ping_status = %s ", $q['ping_status'] );
2442          }
2443  
2444          $skip_post_status = false;
2445          if ( 'any' === $post_type ) {
2446              $in_search_post_types = get_post_types( array( 'exclude_from_search' => false ) );
2447              if ( empty( $in_search_post_types ) ) {
2448                  $post_type_where  = ' AND 1=0 ';
2449                  $skip_post_status = true;
2450              } else {
2451                  $post_type_where = " AND {$wpdb->posts}.post_type IN ('" . implode( "', '", array_map( 'esc_sql', $in_search_post_types ) ) . "')";
2452              }
2453          } elseif ( ! empty( $post_type ) && is_array( $post_type ) ) {
2454              $post_type_where = " AND {$wpdb->posts}.post_type IN ('" . implode( "', '", esc_sql( $post_type ) ) . "')";
2455          } elseif ( ! empty( $post_type ) ) {
2456              $post_type_where  = $wpdb->prepare( " AND {$wpdb->posts}.post_type = %s", $post_type );
2457              $post_type_object = get_post_type_object( $post_type );
2458          } elseif ( $this->is_attachment ) {
2459              $post_type_where  = " AND {$wpdb->posts}.post_type = 'attachment'";
2460              $post_type_object = get_post_type_object( 'attachment' );
2461          } elseif ( $this->is_page ) {
2462              $post_type_where  = " AND {$wpdb->posts}.post_type = 'page'";
2463              $post_type_object = get_post_type_object( 'page' );
2464          } else {
2465              $post_type_where  = " AND {$wpdb->posts}.post_type = 'post'";
2466              $post_type_object = get_post_type_object( 'post' );
2467          }
2468  
2469          $edit_cap = 'edit_post';
2470          $read_cap = 'read_post';
2471  
2472          if ( ! empty( $post_type_object ) ) {
2473              $edit_others_cap  = $post_type_object->cap->edit_others_posts;
2474              $read_private_cap = $post_type_object->cap->read_private_posts;
2475          } else {
2476              $edit_others_cap  = 'edit_others_' . $post_type_cap . 's';
2477              $read_private_cap = 'read_private_' . $post_type_cap . 's';
2478          }
2479  
2480          $user_id = get_current_user_id();
2481  
2482          $q_status = array();
2483          if ( $skip_post_status ) {
2484              $where .= $post_type_where;
2485          } elseif ( ! empty( $q['post_status'] ) ) {
2486  
2487              $where .= $post_type_where;
2488  
2489              $statuswheres = array();
2490              $q_status     = $q['post_status'];
2491              if ( ! is_array( $q_status ) ) {
2492                  $q_status = explode( ',', $q_status );
2493              }
2494              $r_status = array();
2495              $p_status = array();
2496              $e_status = array();
2497              if ( in_array( 'any', $q_status, true ) ) {
2498                  foreach ( get_post_stati( array( 'exclude_from_search' => true ) ) as $status ) {
2499                      if ( ! in_array( $status, $q_status, true ) ) {
2500                          $e_status[] = "{$wpdb->posts}.post_status <> '$status'";
2501                      }
2502                  }
2503              } else {
2504                  foreach ( get_post_stati() as $status ) {
2505                      if ( in_array( $status, $q_status, true ) ) {
2506                          if ( 'private' === $status ) {
2507                              $p_status[] = "{$wpdb->posts}.post_status = '$status'";
2508                          } else {
2509                              $r_status[] = "{$wpdb->posts}.post_status = '$status'";
2510                          }
2511                      }
2512                  }
2513              }
2514  
2515              if ( empty( $q['perm'] ) || 'readable' !== $q['perm'] ) {
2516                  $r_status = array_merge( $r_status, $p_status );
2517                  unset( $p_status );
2518              }
2519  
2520              if ( ! empty( $e_status ) ) {
2521                  $statuswheres[] = '(' . implode( ' AND ', $e_status ) . ')';
2522              }
2523              if ( ! empty( $r_status ) ) {
2524                  if ( ! empty( $q['perm'] ) && 'editable' === $q['perm'] && ! current_user_can( $edit_others_cap ) ) {
2525                      $statuswheres[] = "({$wpdb->posts}.post_author = $user_id " . 'AND (' . implode( ' OR ', $r_status ) . '))';
2526                  } else {
2527                      $statuswheres[] = '(' . implode( ' OR ', $r_status ) . ')';
2528                  }
2529              }
2530              if ( ! empty( $p_status ) ) {
2531                  if ( ! empty( $q['perm'] ) && 'readable' === $q['perm'] && ! current_user_can( $read_private_cap ) ) {
2532                      $statuswheres[] = "({$wpdb->posts}.post_author = $user_id " . 'AND (' . implode( ' OR ', $p_status ) . '))';
2533                  } else {
2534                      $statuswheres[] = '(' . implode( ' OR ', $p_status ) . ')';
2535                  }
2536              }
2537              if ( $post_status_join ) {
2538                  $join .= " LEFT JOIN {$wpdb->posts} AS p2 ON ({$wpdb->posts}.post_parent = p2.ID) ";
2539                  foreach ( $statuswheres as $index => $statuswhere ) {
2540                      $statuswheres[ $index ] = "($statuswhere OR ({$wpdb->posts}.post_status = 'inherit' AND " . str_replace( $wpdb->posts, 'p2', $statuswhere ) . '))';
2541                  }
2542              }
2543              $where_status = implode( ' OR ', $statuswheres );
2544              if ( ! empty( $where_status ) ) {
2545                  $where .= " AND ($where_status)";
2546              }
2547          } elseif ( ! $this->is_singular ) {
2548              if ( 'any' === $post_type ) {
2549                  $queried_post_types = get_post_types( array( 'exclude_from_search' => false ) );
2550              } elseif ( is_array( $post_type ) ) {
2551                  $queried_post_types = $post_type;
2552              } elseif ( ! empty( $post_type ) ) {
2553                  $queried_post_types = array( $post_type );
2554              } else {
2555                  $queried_post_types = array( 'post' );
2556              }
2557  
2558              if ( ! empty( $queried_post_types ) ) {
2559  
2560                  $status_type_clauses = array();
2561  
2562                  foreach ( $queried_post_types as $queried_post_type ) {
2563  
2564                      $queried_post_type_object = get_post_type_object( $queried_post_type );
2565  
2566                      $type_where = '(' . $wpdb->prepare( "{$wpdb->posts}.post_type = %s AND (", $queried_post_type );
2567  
2568                      // Public statuses.
2569                      $public_statuses = get_post_stati( array( 'public' => true ) );
2570                      $status_clauses  = array();
2571                      foreach ( $public_statuses as $public_status ) {
2572                          $status_clauses[] = "{$wpdb->posts}.post_status = '$public_status'";
2573                      }
2574                      $type_where .= implode( ' OR ', $status_clauses );
2575  
2576                      // Add protected states that should show in the admin all list.
2577                      if ( $this->is_admin ) {
2578                          $admin_all_statuses = get_post_stati(
2579                              array(
2580                                  'protected'              => true,
2581                                  'show_in_admin_all_list' => true,
2582                              )
2583                          );
2584                          foreach ( $admin_all_statuses as $admin_all_status ) {
2585                              $type_where .= " OR {$wpdb->posts}.post_status = '$admin_all_status'";
2586                          }
2587                      }
2588  
2589                      // Add private states that are visible to current user.
2590                      if ( is_user_logged_in() && $queried_post_type_object instanceof WP_Post_Type ) {
2591                          $read_private_cap = $queried_post_type_object->cap->read_private_posts;
2592                          $private_statuses = get_post_stati( array( 'private' => true ) );
2593                          foreach ( $private_statuses as $private_status ) {
2594                              $type_where .= current_user_can( $read_private_cap ) ? " \nOR {$wpdb->posts}.post_status = '$private_status'" : " \nOR ({$wpdb->posts}.post_author = $user_id AND {$wpdb->posts}.post_status = '$private_status')";
2595                          }
2596                      }
2597  
2598                      $type_where .= '))';
2599  
2600                      $status_type_clauses[] = $type_where;
2601                  }
2602  
2603                  if ( ! empty( $status_type_clauses ) ) {
2604                      $where .= ' AND (' . implode( ' OR ', $status_type_clauses ) . ')';
2605                  }
2606              } else {
2607                  $where .= ' AND 1=0 ';
2608              }
2609          } else {
2610              $where .= $post_type_where;
2611          }
2612  
2613          /*
2614           * Apply filters on where and join prior to paging so that any
2615           * manipulations to them are reflected in the paging by day queries.
2616           */
2617          if ( ! $q['suppress_filters'] ) {
2618              /**
2619               * Filters the WHERE clause of the query.
2620               *
2621               * @since 1.5.0
2622               *
2623               * @param string   $where The WHERE clause of the query.
2624               * @param WP_Query $query The WP_Query instance (passed by reference).
2625               */
2626              $where = apply_filters_ref_array( 'posts_where', array( $where, &$this ) );
2627  
2628              /**
2629               * Filters the JOIN clause of the query.
2630               *
2631               * @since 1.5.0
2632               *
2633               * @param string   $join  The JOIN clause of the query.
2634               * @param WP_Query $query The WP_Query instance (passed by reference).
2635               */
2636              $join = apply_filters_ref_array( 'posts_join', array( $join, &$this ) );
2637          }
2638  
2639          // Paging.
2640          if ( empty( $q['nopaging'] ) && ! $this->is_singular ) {
2641              $page = absint( $q['paged'] );
2642              if ( ! $page ) {
2643                  $page = 1;
2644              }
2645  
2646              // If 'offset' is provided, it takes precedence over 'paged'.
2647              if ( isset( $q['offset'] ) && is_numeric( $q['offset'] ) ) {
2648                  $q['offset'] = absint( $q['offset'] );
2649                  $pgstrt      = $q['offset'] . ', ';
2650              } else {
2651                  $pgstrt = absint( ( $page - 1 ) * $q['posts_per_page'] ) . ', ';
2652              }
2653              $limits = 'LIMIT ' . $pgstrt . $q['posts_per_page'];
2654          }
2655  
2656          // Comments feeds.
2657          if ( $this->is_comment_feed && ! $this->is_singular ) {
2658              if ( $this->is_archive || $this->is_search ) {
2659                  $cjoin    = "JOIN {$wpdb->posts} ON ( {$wpdb->comments}.comment_post_ID = {$wpdb->posts}.ID ) $join ";
2660                  $cwhere   = "WHERE comment_approved = '1' $where";
2661                  $cgroupby = "{$wpdb->comments}.comment_id";
2662              } else { // Other non-singular, e.g. front.
2663                  $cjoin    = "JOIN {$wpdb->posts} ON ( {$wpdb->comments}.comment_post_ID = {$wpdb->posts}.ID )";
2664                  $cwhere   = "WHERE ( post_status = 'publish' OR ( post_status = 'inherit' AND post_type = 'attachment' ) ) AND comment_approved = '1'";
2665                  $cgroupby = '';
2666              }
2667  
2668              if ( ! $q['suppress_filters'] ) {
2669                  /**
2670                   * Filters the JOIN clause of the comments feed query before sending.
2671                   *
2672                   * @since 2.2.0
2673                   *
2674                   * @param string   $cjoin The JOIN clause of the query.
2675                   * @param WP_Query $query The WP_Query instance (passed by reference).
2676                   */
2677                  $cjoin = apply_filters_ref_array( 'comment_feed_join', array( $cjoin, &$this ) );
2678  
2679                  /**
2680                   * Filters the WHERE clause of the comments feed query before sending.
2681                   *
2682                   * @since 2.2.0
2683                   *
2684                   * @param string   $cwhere The WHERE clause of the query.
2685                   * @param WP_Query $query  The WP_Query instance (passed by reference).
2686                   */
2687                  $cwhere = apply_filters_ref_array( 'comment_feed_where', array( $cwhere, &$this ) );
2688  
2689                  /**
2690                   * Filters the GROUP BY clause of the comments feed query before sending.
2691                   *
2692                   * @since 2.2.0
2693                   *
2694                   * @param string   $cgroupby The GROUP BY clause of the query.
2695                   * @param WP_Query $query    The WP_Query instance (passed by reference).
2696                   */
2697                  $cgroupby = apply_filters_ref_array( 'comment_feed_groupby', array( $cgroupby, &$this ) );
2698  
2699                  /**
2700                   * Filters the ORDER BY clause of the comments feed query before sending.
2701                   *
2702                   * @since 2.8.0
2703                   *
2704                   * @param string   $corderby The ORDER BY clause of the query.
2705                   * @param WP_Query $query    The WP_Query instance (passed by reference).
2706                   */
2707                  $corderby = apply_filters_ref_array( 'comment_feed_orderby', array( 'comment_date_gmt DESC', &$this ) );
2708  
2709                  /**
2710                   * Filters the LIMIT clause of the comments feed query before sending.
2711                   *
2712                   * @since 2.8.0
2713                   *
2714                   * @param string   $climits The JOIN clause of the query.
2715                   * @param WP_Query $query   The WP_Query instance (passed by reference).
2716                   */
2717                  $climits = apply_filters_ref_array( 'comment_feed_limits', array( 'LIMIT ' . get_option( 'posts_per_rss' ), &$this ) );
2718              }
2719  
2720              $cgroupby = ( ! empty( $cgroupby ) ) ? 'GROUP BY ' . $cgroupby : '';
2721              $corderby = ( ! empty( $corderby ) ) ? 'ORDER BY ' . $corderby : '';
2722              $climits  = ( ! empty( $climits ) ) ? $climits : '';
2723  
2724              $comments_request = "SELECT $distinct {$wpdb->comments}.comment_ID FROM {$wpdb->comments} $cjoin $cwhere $cgroupby $corderby $climits";
2725  
2726              $key          = md5( $comments_request );
2727              $last_changed = wp_cache_get_last_changed( 'comment' ) . ':' . wp_cache_get_last_changed( 'posts' );
2728  
2729              $cache_key   = "comment_feed:$key:$last_changed";
2730              $comment_ids = wp_cache_get( $cache_key, 'comment' );
2731              if ( false === $comment_ids ) {
2732                  $comment_ids = $wpdb->get_col( $comments_request );
2733                  wp_cache_add( $cache_key, $comment_ids, 'comment' );
2734              }
2735              _prime_comment_caches( $comment_ids, false );
2736  
2737              // Convert to WP_Comment.
2738              /** @var WP_Comment[] */
2739              $this->comments      = array_map( 'get_comment', $comment_ids );
2740              $this->comment_count = count( $this->comments );
2741  
2742              $post_ids = array();
2743  
2744              foreach ( $this->comments as $comment ) {
2745                  $post_ids[] = (int) $comment->comment_post_ID;
2746              }
2747  
2748              $post_ids = implode( ',', $post_ids );
2749              $join     = '';
2750              if ( $post_ids ) {
2751                  $where = "AND {$wpdb->posts}.ID IN ($post_ids) ";
2752              } else {
2753                  $where = 'AND 0';
2754              }
2755          }
2756  
2757          /*
2758           * Apply post-paging filters on where and join. Only plugins that
2759           * manipulate paging queries should use these hooks.
2760           */
2761          if ( ! $q['suppress_filters'] ) {
2762              /**
2763               * Filters the WHERE clause of the query.
2764               *
2765               * Specifically for manipulating paging queries.
2766               *
2767               * @since 1.5.0
2768               *
2769               * @param string   $where The WHERE clause of the query.
2770               * @param WP_Query $query The WP_Query instance (passed by reference).
2771               */
2772              $where = apply_filters_ref_array( 'posts_where_paged', array( $where, &$this ) );
2773  
2774              /**
2775               * Filters the GROUP BY clause of the query.
2776               *
2777               * @since 2.0.0
2778               *
2779               * @param string   $groupby The GROUP BY clause of the query.
2780               * @param WP_Query $query   The WP_Query instance (passed by reference).
2781               */
2782              $groupby = apply_filters_ref_array( 'posts_groupby', array( $groupby, &$this ) );
2783  
2784              /**
2785               * Filters the JOIN clause of the query.
2786               *
2787               * Specifically for manipulating paging queries.
2788               *
2789               * @since 1.5.0
2790               *
2791               * @param string   $join  The JOIN clause of the query.
2792               * @param WP_Query $query The WP_Query instance (passed by reference).
2793               */
2794              $join = apply_filters_ref_array( 'posts_join_paged', array( $join, &$this ) );
2795  
2796              /**
2797               * Filters the ORDER BY clause of the query.
2798               *
2799               * @since 1.5.1
2800               *
2801               * @param string   $orderby The ORDER BY clause of the query.
2802               * @param WP_Query $query   The WP_Query instance (passed by reference).
2803               */
2804              $orderby = apply_filters_ref_array( 'posts_orderby', array( $orderby, &$this ) );
2805  
2806              /**
2807               * Filters the DISTINCT clause of the query.
2808               *
2809               * @since 2.1.0
2810               *
2811               * @param string   $distinct The DISTINCT clause of the query.
2812               * @param WP_Query $query    The WP_Query instance (passed by reference).
2813               */
2814              $distinct = apply_filters_ref_array( 'posts_distinct', array( $distinct, &$this ) );
2815  
2816              /**
2817               * Filters the LIMIT clause of the query.
2818               *
2819               * @since 2.1.0
2820               *
2821               * @param string   $limits The LIMIT clause of the query.
2822               * @param WP_Query $query  The WP_Query instance (passed by reference).
2823               */
2824              $limits = apply_filters_ref_array( 'post_limits', array( $limits, &$this ) );
2825  
2826              /**
2827               * Filters the SELECT clause of the query.
2828               *
2829               * @since 2.1.0
2830               *
2831               * @param string   $fields The SELECT clause of the query.
2832               * @param WP_Query $query  The WP_Query instance (passed by reference).
2833               */
2834              $fields = apply_filters_ref_array( 'posts_fields', array( $fields, &$this ) );
2835  
2836              $clauses = array( 'where', 'groupby', 'join', 'orderby', 'distinct', 'fields', 'limits' );
2837  
2838              /**
2839               * Filters all query clauses at once, for convenience.
2840               *
2841               * Covers the WHERE, GROUP BY, JOIN, ORDER BY, DISTINCT,
2842               * fields (SELECT), and LIMIT clauses.
2843               *
2844               * @since 3.1.0
2845               *
2846               * @param string[] $clauses {
2847               *     Associative array of the clauses for the query.
2848               *
2849               *     @type string $where    The WHERE clause of the query.
2850               *     @type string $groupby  The GROUP BY clause of the query.
2851               *     @type string $join     The JOIN clause of the query.
2852               *     @type string $orderby  The ORDER BY clause of the query.
2853               *     @type string $distinct The DISTINCT clause of the query.
2854               *     @type string $fields   The SELECT clause of the query.
2855               *     @type string $limits   The LIMIT clause of the query.
2856               * }
2857               * @param WP_Query $query   The WP_Query instance (passed by reference).
2858               */
2859              $clauses = (array) apply_filters_ref_array( 'posts_clauses', array( compact( $clauses ), &$this ) );
2860  
2861              $where    = isset( $clauses['where'] ) ? $clauses['where'] : '';
2862              $groupby  = isset( $clauses['groupby'] ) ? $clauses['groupby'] : '';
2863              $join     = isset( $clauses['join'] ) ? $clauses['join'] : '';
2864              $orderby  = isset( $clauses['orderby'] ) ? $clauses['orderby'] : '';
2865              $distinct = isset( $clauses['distinct'] ) ? $clauses['distinct'] : '';
2866              $fields   = isset( $clauses['fields'] ) ? $clauses['fields'] : '';
2867              $limits   = isset( $clauses['limits'] ) ? $clauses['limits'] : '';
2868          }
2869  
2870          /**
2871           * Fires to announce the query's current selection parameters.
2872           *
2873           * For use by caching plugins.
2874           *
2875           * @since 2.3.0
2876           *
2877           * @param string $selection The assembled selection query.
2878           */
2879          do_action( 'posts_selection', $where . $groupby . $orderby . $limits . $join );
2880  
2881          /*
2882           * Filters again for the benefit of caching plugins.
2883           * Regular plugins should use the hooks above.
2884           */
2885          if ( ! $q['suppress_filters'] ) {
2886              /**
2887               * Filters the WHERE clause of the query.
2888               *
2889               * For use by caching plugins.
2890               *
2891               * @since 2.5.0
2892               *
2893               * @param string   $where The WHERE clause of the query.
2894               * @param WP_Query $query The WP_Query instance (passed by reference).
2895               */
2896              $where = apply_filters_ref_array( 'posts_where_request', array( $where, &$this ) );
2897  
2898              /**
2899               * Filters the GROUP BY clause of the query.
2900               *
2901               * For use by caching plugins.
2902               *
2903               * @since 2.5.0
2904               *
2905               * @param string   $groupby The GROUP BY clause of the query.
2906               * @param WP_Query $query   The WP_Query instance (passed by reference).
2907               */
2908              $groupby = apply_filters_ref_array( 'posts_groupby_request', array( $groupby, &$this ) );
2909  
2910              /**
2911               * Filters the JOIN clause of the query.
2912               *
2913               * For use by caching plugins.
2914               *
2915               * @since 2.5.0
2916               *
2917               * @param string   $join  The JOIN clause of the query.
2918               * @param WP_Query $query The WP_Query instance (passed by reference).
2919               */
2920              $join = apply_filters_ref_array( 'posts_join_request', array( $join, &$this ) );
2921  
2922              /**
2923               * Filters the ORDER BY clause of the query.
2924               *
2925               * For use by caching plugins.
2926               *
2927               * @since 2.5.0
2928               *
2929               * @param string   $orderby The ORDER BY clause of the query.
2930               * @param WP_Query $query   The WP_Query instance (passed by reference).
2931               */
2932              $orderby = apply_filters_ref_array( 'posts_orderby_request', array( $orderby, &$this ) );
2933  
2934              /**
2935               * Filters the DISTINCT clause of the query.
2936               *
2937               * For use by caching plugins.
2938               *
2939               * @since 2.5.0
2940               *
2941               * @param string   $distinct The DISTINCT clause of the query.
2942               * @param WP_Query $query    The WP_Query instance (passed by reference).
2943               */
2944              $distinct = apply_filters_ref_array( 'posts_distinct_request', array( $distinct, &$this ) );
2945  
2946              /**
2947               * Filters the SELECT clause of the query.
2948               *
2949               * For use by caching plugins.
2950               *
2951               * @since 2.5.0
2952               *
2953               * @param string   $fields The SELECT clause of the query.
2954               * @param WP_Query $query  The WP_Query instance (passed by reference).
2955               */
2956              $fields = apply_filters_ref_array( 'posts_fields_request', array( $fields, &$this ) );
2957  
2958              /**
2959               * Filters the LIMIT clause of the query.
2960               *
2961               * For use by caching plugins.
2962               *
2963               * @since 2.5.0
2964               *
2965               * @param string   $limits The LIMIT clause of the query.
2966               * @param WP_Query $query  The WP_Query instance (passed by reference).
2967               */
2968              $limits = apply_filters_ref_array( 'post_limits_request', array( $limits, &$this ) );
2969  
2970              $clauses = array( 'where', 'groupby', 'join', 'orderby', 'distinct', 'fields', 'limits' );
2971  
2972              /**
2973               * Filters all query clauses at once, for convenience.
2974               *
2975               * For use by caching plugins.
2976               *
2977               * Covers the WHERE, GROUP BY, JOIN, ORDER BY, DISTINCT,
2978               * fields (SELECT), and LIMIT clauses.
2979               *
2980               * @since 3.1.0
2981               *
2982               * @param string[] $clauses {
2983               *     Associative array of the clauses for the query.
2984               *
2985               *     @type string $where    The WHERE clause of the query.
2986               *     @type string $groupby  The GROUP BY clause of the query.
2987               *     @type string $join     The JOIN clause of the query.
2988               *     @type string $orderby  The ORDER BY clause of the query.
2989               *     @type string $distinct The DISTINCT clause of the query.
2990               *     @type string $fields   The SELECT clause of the query.
2991               *     @type string $limits   The LIMIT clause of the query.
2992               * }
2993               * @param WP_Query $query  The WP_Query instance (passed by reference).
2994               */
2995              $clauses = (array) apply_filters_ref_array( 'posts_clauses_request', array( compact( $clauses ), &$this ) );
2996  
2997              $where    = isset( $clauses['where'] ) ? $clauses['where'] : '';
2998              $groupby  = isset( $clauses['groupby'] ) ? $clauses['groupby'] : '';
2999              $join     = isset( $clauses['join'] ) ? $clauses['join'] : '';
3000              $orderby  = isset( $clauses['orderby'] ) ? $clauses['orderby'] : '';
3001              $distinct = isset( $clauses['distinct'] ) ? $clauses['distinct'] : '';
3002              $fields   = isset( $clauses['fields'] ) ? $clauses['fields'] : '';
3003              $limits   = isset( $clauses['limits'] ) ? $clauses['limits'] : '';
3004          }
3005  
3006          if ( ! empty( $groupby ) ) {
3007              $groupby = 'GROUP BY ' . $groupby;
3008          }
3009          if ( ! empty( $orderby ) ) {
3010              $orderby = 'ORDER BY ' . $orderby;
3011          }
3012  
3013          $found_rows = '';
3014          if ( ! $q['no_found_rows'] && ! empty( $limits ) ) {
3015              $found_rows = 'SQL_CALC_FOUND_ROWS';
3016          }
3017  
3018          $old_request = "
3019              SELECT $found_rows $distinct $fields
3020              FROM {$wpdb->posts} $join
3021              WHERE 1=1 $where
3022              $groupby
3023              $orderby
3024              $limits
3025          ";
3026  
3027          $this->request = $old_request;
3028  
3029          if ( ! $q['suppress_filters'] ) {
3030              /**
3031               * Filters the completed SQL query before sending.
3032               *
3033               * @since 2.0.0
3034               *
3035               * @param string   $request The complete SQL query.
3036               * @param WP_Query $query   The WP_Query instance (passed by reference).
3037               */
3038              $this->request = apply_filters_ref_array( 'posts_request', array( $this->request, &$this ) );
3039          }
3040  
3041          /**
3042           * Filters the posts array before the query takes place.
3043           *
3044           * Return a non-null value to bypass WordPress' default post queries.
3045           *
3046           * Filtering functions that require pagination information are encouraged to set
3047           * the `found_posts` and `max_num_pages` properties of the WP_Query object,
3048           * passed to the filter by reference. If WP_Query does not perform a database
3049           * query, it will not have enough information to generate these values itself.
3050           *
3051           * @since 4.6.0
3052           *
3053           * @param WP_Post[]|int[]|null $posts Return an array of post data to short-circuit WP's query,
3054           *                                    or null to allow WP to run its normal queries.
3055           * @param WP_Query             $query The WP_Query instance (passed by reference).
3056           */
3057          $this->posts = apply_filters_ref_array( 'posts_pre_query', array( null, &$this ) );
3058  
3059          if ( 'ids' === $q['fields'] ) {
3060              if ( null === $this->posts ) {
3061                  $this->posts = $wpdb->get_col( $this->request );
3062              }
3063  
3064              /** @var int[] */
3065              $this->posts      = array_map( 'intval', $this->posts );
3066              $this->post_count = count( $this->posts );
3067              $this->set_found_posts( $q, $limits );
3068  
3069              return $this->posts;
3070          }
3071  
3072          if ( 'id=>parent' === $q['fields'] ) {
3073              if ( null === $this->posts ) {
3074                  $this->posts = $wpdb->get_results( $this->request );
3075              }
3076  
3077              $this->post_count = count( $this->posts );
3078              $this->set_found_posts( $q, $limits );
3079  
3080              /** @var int[] */
3081              $r = array();
3082              foreach ( $this->posts as $key => $post ) {
3083                  $this->posts[ $key ]->ID          = (int) $post->ID;
3084                  $this->posts[ $key ]->post_parent = (int) $post->post_parent;
3085  
3086                  $r[ (int) $post->ID ] = (int) $post->post_parent;
3087              }
3088  
3089              return $r;
3090          }
3091  
3092          if ( null === $this->posts ) {
3093              $split_the_query = ( $old_request == $this->request && "{$wpdb->posts}.*" === $fields && ! empty( $limits ) && $q['posts_per_page'] < 500 );
3094  
3095              /**
3096               * Filters whether to split the query.
3097               *
3098               * Splitting the query will cause it to fetch just the IDs of the found posts
3099               * (and then individually fetch each post by ID), rather than fetching every
3100               * complete row at once. One massive result vs. many small results.
3101               *
3102               * @since 3.4.0
3103               *
3104               * @param bool     $split_the_query Whether or not to split the query.
3105               * @param WP_Query $query           The WP_Query instance.
3106               */
3107              $split_the_query = apply_filters( 'split_the_query', $split_the_query, $this );
3108  
3109              if ( $split_the_query ) {
3110                  // First get the IDs and then fill in the objects.
3111  
3112                  $this->request = "
3113                      SELECT $found_rows $distinct {$wpdb->posts}.ID
3114                      FROM {$wpdb->posts} $join
3115                      WHERE 1=1 $where
3116                      $groupby
3117                      $orderby
3118                      $limits
3119                  ";
3120  
3121                  /**
3122                   * Filters the Post IDs SQL request before sending.
3123                   *
3124                   * @since 3.4.0
3125                   *
3126                   * @param string   $request The post ID request.
3127                   * @param WP_Query $query   The WP_Query instance.
3128                   */
3129                  $this->request = apply_filters( 'posts_request_ids', $this->request, $this );
3130  
3131                  $ids = $wpdb->get_col( $this->request );
3132  
3133                  if ( $ids ) {
3134                      $this->posts = $ids;
3135                      $this->set_found_posts( $q, $limits );
3136                      _prime_post_caches( $ids, $q['update_post_term_cache'], $q['update_post_meta_cache'] );
3137                  } else {
3138                      $this->posts = array();
3139                  }
3140              } else {
3141                  $this->posts = $wpdb->get_results( $this->request );
3142                  $this->set_found_posts( $q, $limits );
3143              }
3144          }
3145  
3146          // Convert to WP_Post objects.
3147          if ( $this->posts ) {
3148              /** @var WP_Post[] */
3149              $this->posts = array_map( 'get_post', $this->posts );
3150          }
3151  
3152          if ( ! $q['suppress_filters'] ) {
3153              /**
3154               * Filters the raw post results array, prior to status checks.
3155               *
3156               * @since 2.3.0
3157               *
3158               * @param WP_Post[] $posts Array of post objects.
3159               * @param WP_Query  $query The WP_Query instance (passed by reference).
3160               */
3161              $this->posts = apply_filters_ref_array( 'posts_results', array( $this->posts, &$this ) );
3162          }
3163  
3164          if ( ! empty( $this->posts ) && $this->is_comment_feed && $this->is_singular ) {
3165              /** This filter is documented in wp-includes/query.php */
3166              $cjoin = apply_filters_ref_array( 'comment_feed_join', array( '', &$this ) );
3167  
3168              /** This filter is documented in wp-includes/query.php */
3169              $cwhere = apply_filters_ref_array( 'comment_feed_where', array( "WHERE comment_post_ID = '{$this->posts[0]->ID}' AND comment_approved = '1'", &$this ) );
3170  
3171              /** This filter is documented in wp-includes/query.php */
3172              $cgroupby = apply_filters_ref_array( 'comment_feed_groupby', array( '', &$this ) );
3173              $cgroupby = ( ! empty( $cgroupby ) ) ? 'GROUP BY ' . $cgroupby : '';
3174  
3175              /** This filter is documented in wp-includes/query.php */
3176              $corderby = apply_filters_ref_array( 'comment_feed_orderby', array( 'comment_date_gmt DESC', &$this ) );
3177              $corderby = ( ! empty( $corderby ) ) ? 'ORDER BY ' . $corderby : '';
3178  
3179              /** This filter is documented in wp-includes/query.php */
3180              $climits = apply_filters_ref_array( 'comment_feed_limits', array( 'LIMIT ' . get_option( 'posts_per_rss' ), &$this ) );
3181  
3182              $comments_request = "SELECT {$wpdb->comments}.comment_ID FROM {$wpdb->comments} $cjoin $cwhere $cgroupby $corderby $climits";
3183  
3184              $key          = md5( $comments_request );
3185              $last_changed = wp_cache_get_last_changed( 'comment' );
3186  
3187              $cache_key   = "comment_feed:$key:$last_changed";
3188              $comment_ids = wp_cache_get( $cache_key, 'comment' );
3189              if ( false === $comment_ids ) {
3190                  $comment_ids = $wpdb->get_col( $comments_request );
3191                  wp_cache_add( $cache_key, $comment_ids, 'comment' );
3192              }
3193              _prime_comment_caches( $comment_ids, false );
3194  
3195              // Convert to WP_Comment.
3196              /** @var WP_Comment[] */
3197              $this->comments      = array_map( 'get_comment', $comment_ids );
3198              $this->comment_count = count( $this->comments );
3199          }
3200  
3201          // Check post status to determine if post should be displayed.
3202          if ( ! empty( $this->posts ) && ( $this->is_single || $this->is_page ) ) {
3203              $status = get_post_status( $this->posts[0] );
3204  
3205              if ( 'attachment' === $this->posts[0]->post_type && 0 === (int) $this->posts[0]->post_parent ) {
3206                  $this->is_page       = false;
3207                  $this->is_single     = true;
3208                  $this->is_attachment = true;
3209              }
3210  
3211              // If the post_status was specifically requested, let it pass through.
3212              if ( ! in_array( $status, $q_status, true ) ) {
3213                  $post_status_obj = get_post_status_object( $status );
3214  
3215                  if ( $post_status_obj && ! $post_status_obj->public ) {
3216                      if ( ! is_user_logged_in() ) {
3217                          // User must be logged in to view unpublished posts.
3218                          $this->posts = array();
3219                      } else {
3220                          if ( $post_status_obj->protected ) {
3221                              // User must have edit permissions on the draft to preview.
3222                              if ( ! current_user_can( $edit_cap, $this->posts[0]->ID ) ) {
3223                                  $this->posts = array();
3224                              } else {
3225                                  $this->is_preview = true;
3226                                  if ( 'future' !== $status ) {
3227                                      $this->posts[0]->post_date = current_time( 'mysql' );
3228                                  }
3229                              }
3230                          } elseif ( $post_status_obj->private ) {
3231                              if ( ! current_user_can( $read_cap, $this->posts[0]->ID ) ) {
3232                                  $this->posts = array();
3233                              }
3234                          } else {
3235                              $this->posts = array();
3236                          }
3237                      }
3238                  } elseif ( ! $post_status_obj ) {
3239                      // Post status is not registered, assume it's not public.
3240                      if ( ! current_user_can( $edit_cap, $this->posts[0]->ID ) ) {
3241                          $this->posts = array();
3242                      }
3243                  }
3244              }
3245  
3246              if ( $this->is_preview && $this->posts && current_user_can( $edit_cap, $this->posts[0]->ID ) ) {
3247                  /**
3248                   * Filters the single post for preview mode.
3249                   *
3250                   * @since 2.7.0
3251                   *
3252                   * @param WP_Post  $post_preview  The Post object.
3253                   * @param WP_Query $query         The WP_Query instance (passed by reference).
3254                   */
3255                  $this->posts[0] = get_post( apply_filters_ref_array( 'the_preview', array( $this->posts[0], &$this ) ) );
3256              }
3257          }
3258  
3259          // Put sticky posts at the top of the posts array.
3260          $sticky_posts = get_option( 'sticky_posts' );
3261          if ( $this->is_home && $page <= 1 && is_array( $sticky_posts ) && ! empty( $sticky_posts ) && ! $q['ignore_sticky_posts'] ) {
3262              $num_posts     = count( $this->posts );
3263              $sticky_offset = 0;
3264              // Loop over posts and relocate stickies to the front.
3265              for ( $i = 0; $i < $num_posts; $i++ ) {
3266                  if ( in_array( $this->posts[ $i ]->ID, $sticky_posts, true ) ) {
3267                      $sticky_post = $this->posts[ $i ];
3268                      // Remove sticky from current position.
3269                      array_splice( $this->posts, $i, 1 );
3270                      // Move to front, after other stickies.
3271                      array_splice( $this->posts, $sticky_offset, 0, array( $sticky_post ) );
3272                      // Increment the sticky offset. The next sticky will be placed at this offset.
3273                      $sticky_offset++;
3274                      // Remove post from sticky posts array.
3275                      $offset = array_search( $sticky_post->ID, $sticky_posts, true );
3276                      unset( $sticky_posts[ $offset ] );
3277                  }
3278              }
3279  
3280              // If any posts have been excluded specifically, Ignore those that are sticky.
3281              if ( ! empty( $sticky_posts ) && ! empty( $q['post__not_in'] ) ) {
3282                  $sticky_posts = array_diff( $sticky_posts, $q['post__not_in'] );
3283              }
3284  
3285              // Fetch sticky posts that weren't in the query results.
3286              if ( ! empty( $sticky_posts ) ) {
3287                  $stickies = get_posts(
3288                      array(
3289                          'post__in'               => $sticky_posts,
3290                          'post_type'              => $post_type,
3291                          'post_status'            => 'publish',
3292                          'posts_per_page'         => count( $sticky_posts ),
3293                          'suppress_filters'       => $q['suppress_filters'],
3294                          'cache_results'          => $q['cache_results'],
3295                          'update_post_meta_cache' => $q['update_post_meta_cache'],
3296                          'update_post_term_cache' => $q['update_post_term_cache'],
3297                          'lazy_load_term_meta'    => $q['lazy_load_term_meta'],
3298                      )
3299                  );
3300  
3301                  foreach ( $stickies as $sticky_post ) {
3302                      array_splice( $this->posts, $sticky_offset, 0, array( $sticky_post ) );
3303                      $sticky_offset++;
3304                  }
3305              }
3306          }
3307  
3308          // If comments have been fetched as part of the query, make sure comment meta lazy-loading is set up.
3309          if ( ! empty( $this->comments ) ) {
3310              wp_queue_comments_for_comment_meta_lazyload( $this->comments );
3311          }
3312  
3313          if ( ! $q['suppress_filters'] ) {
3314              /**
3315               * Filters the array of retrieved posts after they've been fetched and
3316               * internally processed.
3317               *
3318               * @since 1.5.0
3319               *
3320               * @param WP_Post[] $posts Array of post objects.
3321               * @param WP_Query  $query The WP_Query instance (passed by reference).
3322               */
3323              $this->posts = apply_filters_ref_array( 'the_posts', array( $this->posts, &$this ) );
3324          }
3325  
3326          // Ensure that any posts added/modified via one of the filters above are
3327          // of the type WP_Post and are filtered.
3328          if ( $this->posts ) {
3329              $this->post_count = count( $this->posts );
3330  
3331              /** @var WP_Post[] */
3332              $this->posts = array_map( 'get_post', $this->posts );
3333  
3334              if ( $q['cache_results'] ) {
3335                  update_post_caches( $this->posts, $post_type, $q['update_post_term_cache'], $q['update_post_meta_cache'] );
3336              }
3337  
3338              /** @var WP_Post */
3339              $this->post = reset( $this->posts );
3340          } else {
3341              $this->post_count = 0;
3342              $this->posts      = array();
3343          }
3344  
3345          if ( $q['lazy_load_term_meta'] ) {
3346              wp_queue_posts_for_term_meta_lazyload( $this->posts );
3347          }
3348  
3349          return $this->posts;
3350      }
3351  
3352      /**
3353       * Set up the amount of found posts and the number of pages (if limit clause was used)
3354       * for the current query.
3355       *
3356       * @since 3.5.0
3357       *
3358       * @global wpdb $wpdb WordPress database abstraction object.
3359       *
3360       * @param array  $q      Query variables.
3361       * @param string $limits LIMIT clauses of the query.
3362       */
3363  	private function set_found_posts( $q, $limits ) {
3364          global $wpdb;
3365  
3366          // Bail if posts is an empty array. Continue if posts is an empty string,
3367          // null, or false to accommodate caching plugins that fill posts later.
3368          if ( $q['no_found_rows'] || ( is_array( $this->posts ) && ! $this->posts ) ) {
3369              return;
3370          }
3371  
3372          if ( ! empty( $limits ) ) {
3373              /**
3374               * Filters the query to run for retrieving the found posts.
3375               *
3376               * @since 2.1.0
3377               *
3378               * @param string   $found_posts_query The query to run to find the found posts.
3379               * @param WP_Query $query             The WP_Query instance (passed by reference).
3380               */
3381              $found_posts_query = apply_filters_ref_array( 'found_posts_query', array( 'SELECT FOUND_ROWS()', &$this ) );
3382  
3383              $this->found_posts = (int) $wpdb->get_var( $found_posts_query );
3384          } else {
3385              if ( is_array( $this->posts ) ) {
3386                  $this->found_posts = count( $this->posts );
3387              } else {
3388                  if ( null === $this->posts ) {
3389                      $this->found_posts = 0;
3390                  } else {
3391                      $this->found_posts = 1;
3392                  }
3393              }
3394          }
3395  
3396          /**
3397           * Filters the number of found posts for the query.
3398           *
3399           * @since 2.1.0
3400           *
3401           * @param int      $found_posts The number of posts found.
3402           * @param WP_Query $query       The WP_Query instance (passed by reference).
3403           */
3404          $this->found_posts = (int) apply_filters_ref_array( 'found_posts', array( $this->found_posts, &$this ) );
3405  
3406          if ( ! empty( $limits ) ) {
3407              $this->max_num_pages = ceil( $this->found_posts / $q['posts_per_page'] );
3408          }
3409      }
3410  
3411      /**
3412       * Set up the next post and iterate current post index.
3413       *
3414       * @since 1.5.0
3415       *
3416       * @return WP_Post Next post.
3417       */
3418  	public function next_post() {
3419  
3420          $this->current_post++;
3421  
3422          /** @var WP_Post */
3423          $this->post = $this->posts[ $this->current_post ];
3424          return $this->post;
3425      }
3426  
3427      /**
3428       * Sets up the current post.
3429       *
3430       * Retrieves the next post, sets up the post, sets the 'in the loop'
3431       * property to true.
3432       *
3433       * @since 1.5.0
3434       *
3435       * @global WP_Post $post Global post object.
3436       */
3437  	public function the_post() {
3438          global $post;
3439          $this->in_the_loop = true;
3440  
3441          if ( -1 == $this->current_post ) { // Loop has just started.
3442              /**
3443               * Fires once the loop is started.
3444               *
3445               * @since 2.0.0
3446               *
3447               * @param WP_Query $query The WP_Query instance (passed by reference).
3448               */
3449              do_action_ref_array( 'loop_start', array( &$this ) );
3450          }
3451  
3452          $post = $this->next_post();
3453          $this->setup_postdata( $post );
3454      }
3455  
3456      /**
3457       * Determines whether there are more posts available in the loop.
3458       *
3459       * Calls the {@see 'loop_end'} action when the loop is complete.
3460       *
3461       * @since 1.5.0
3462       *
3463       * @return bool True if posts are available, false if end of the loop.
3464       */
3465  	public function have_posts() {
3466          if ( $this->current_post + 1 < $this->post_count ) {
3467              return true;
3468          } elseif ( $this->current_post + 1 == $this->post_count && $this->post_count > 0 ) {
3469              /**
3470               * Fires once the loop has ended.
3471               *
3472               * @since 2.0.0
3473               *
3474               * @param WP_Query $query The WP_Query instance (passed by reference).
3475               */
3476              do_action_ref_array( 'loop_end', array( &$this ) );
3477              // Do some cleaning up after the loop.
3478              $this->rewind_posts();
3479          } elseif ( 0 === $this->post_count ) {
3480              /**
3481               * Fires if no results are found in a post query.
3482               *
3483               * @since 4.9.0
3484               *
3485               * @param WP_Query $query The WP_Query instance.
3486               */
3487              do_action( 'loop_no_results', $this );
3488          }
3489  
3490          $this->in_the_loop = false;
3491          return false;
3492      }
3493  
3494      /**
3495       * Rewind the posts and reset post index.
3496       *
3497       * @since 1.5.0
3498       */
3499  	public function rewind_posts() {
3500          $this->current_post = -1;
3501          if ( $this->post_count > 0 ) {
3502              $this->post = $this->posts[0];
3503          }
3504      }
3505  
3506      /**
3507       * Iterate current comment index and return WP_Comment object.
3508       *
3509       * @since 2.2.0
3510       *
3511       * @return WP_Comment Comment object.
3512       */
3513  	public function next_comment() {
3514          $this->current_comment++;
3515  
3516          /** @var WP_Comment */
3517          $this->comment = $this->comments[ $this->current_comment ];
3518          return $this->comment;
3519      }
3520  
3521      /**
3522       * Sets up the current comment.
3523       *
3524       * @since 2.2.0
3525       *
3526       * @global WP_Comment $comment Global comment object.
3527       */
3528  	public function the_comment() {
3529          global $comment;
3530  
3531          $comment = $this->next_comment();
3532  
3533          if ( 0 == $this->current_comment ) {
3534              /**
3535               * Fires once the comment loop is started.
3536               *
3537               * @since 2.2.0
3538               */
3539              do_action( 'comment_loop_start' );
3540          }
3541      }
3542  
3543      /**
3544       * Whether there are more comments available.
3545       *
3546       * Automatically rewinds comments when finished.
3547       *
3548       * @since 2.2.0
3549       *
3550       * @return bool True if comments are available, false if no more comments.
3551       */
3552  	public function have_comments() {
3553          if ( $this->current_comment + 1 < $this->comment_count ) {
3554              return true;
3555          } elseif ( $this->current_comment + 1 == $this->comment_count ) {
3556              $this->rewind_comments();
3557          }
3558  
3559          return false;
3560      }
3561  
3562      /**
3563       * Rewind the comments, resets the comment index and comment to first.
3564       *
3565       * @since 2.2.0
3566       */
3567  	public function rewind_comments() {
3568          $this->current_comment = -1;
3569          if ( $this->comment_count > 0 ) {
3570              $this->comment = $this->comments[0];
3571          }
3572      }
3573  
3574      /**
3575       * Sets up the WordPress query by parsing query string.
3576       *
3577       * @since 1.5.0
3578       *
3579       * @see WP_Query::parse_query() for all available arguments.
3580       *
3581       * @param string|array $query URL query string or array of query arguments.
3582       * @return WP_Post[]|int[] Array of post objects or post IDs.
3583       */
3584  	public function query( $query ) {
3585          $this->init();
3586          $this->query      = wp_parse_args( $query );
3587          $this->query_vars = $this->query;
3588          return $this->get_posts();
3589      }
3590  
3591      /**
3592       * Retrieves the currently queried object.
3593       *
3594       * If queried object is not set, then the queried object will be set from
3595       * the category, tag, taxonomy, posts page, single post, page, or author
3596       * query variable. After it is set up, it will be returned.
3597       *
3598       * @since 1.5.0
3599       *
3600       * @return WP_Term|WP_Post_Type|WP_Post|WP_User|null The queried object.
3601       */
3602  	public function get_queried_object() {
3603          if ( isset( $this->queried_object ) ) {
3604              return $this->queried_object;
3605          }
3606  
3607          $this->queried_object    = null;
3608          $this->queried_object_id = null;
3609  
3610          if ( $this->is_category || $this->is_tag || $this->is_tax ) {
3611              if ( $this->is_category ) {
3612                  $cat           = $this->get( 'cat' );
3613                  $category_name = $this->get( 'category_name' );
3614  
3615                  if ( $cat ) {
3616                      $term = get_term( $cat, 'category' );
3617                  } elseif ( $category_name ) {
3618                      $term = get_term_by( 'slug', $category_name, 'category' );
3619                  }
3620              } elseif ( $this->is_tag ) {
3621                  $tag_id = $this->get( 'tag_id' );
3622                  $tag    = $this->get( 'tag' );
3623  
3624                  if ( $tag_id ) {
3625                      $term = get_term( $tag_id, 'post_tag' );
3626                  } elseif ( $tag ) {
3627                      $term = get_term_by( 'slug', $tag, 'post_tag' );
3628                  }
3629              } else {
3630                  // For other tax queries, grab the first term from the first clause.
3631                  if ( ! empty( $this->tax_query->queried_terms ) ) {
3632                      $queried_taxonomies = array_keys( $this->tax_query->queried_terms );
3633                      $matched_taxonomy   = reset( $queried_taxonomies );
3634                      $query              = $this->tax_query->queried_terms[ $matched_taxonomy ];
3635  
3636                      if ( ! empty( $query['terms'] ) ) {
3637                          if ( 'term_id' === $query['field'] ) {
3638                              $term = get_term( reset( $query['terms'] ), $matched_taxonomy );
3639                          } else {
3640                              $term = get_term_by( $query['field'], reset( $query['terms'] ), $matched_taxonomy );
3641                          }
3642                      }
3643                  }
3644              }
3645  
3646              if ( ! empty( $term ) && ! is_wp_error( $term ) ) {
3647                  $this->queried_object    = $term;
3648                  $this->queried_object_id = (int) $term->term_id;
3649  
3650                  if ( $this->is_category && 'category' === $this->queried_object->taxonomy ) {
3651                      _make_cat_compat( $this->queried_object );
3652                  }
3653              }
3654          } elseif ( $this->is_post_type_archive ) {
3655              $post_type = $this->get( 'post_type' );
3656  
3657              if ( is_array( $post_type ) ) {
3658                  $post_type = reset( $post_type );
3659              }
3660  
3661              $this->queried_object = get_post_type_object( $post_type );
3662          } elseif ( $this->is_posts_page ) {
3663              $page_for_posts = get_option( 'page_for_posts' );
3664  
3665              $this->queried_object    = get_post( $page_for_posts );
3666              $this->queried_object_id = (int) $this->queried_object->ID;
3667          } elseif ( $this->is_singular && ! empty( $this->post ) ) {
3668              $this->queried_object    = $this->post;
3669              $this->queried_object_id = (int) $this->post->ID;
3670          } elseif ( $this->is_author ) {
3671              $author      = (int) $this->get( 'author' );
3672              $author_name = $this->get( 'author_name' );
3673  
3674              if ( $author ) {
3675                  $this->queried_object_id = $author;
3676              } elseif ( $author_name ) {
3677                  $user = get_user_by( 'slug', $author_name );
3678  
3679                  if ( $user ) {
3680                      $this->queried_object_id = $user->ID;
3681                  }
3682              }
3683  
3684              $this->queried_object = get_userdata( $this->queried_object_id );
3685          }
3686  
3687          return $this->queried_object;
3688      }
3689  
3690      /**
3691       * Retrieves the ID of the currently queried object.
3692       *
3693       * @since 1.5.0
3694       *
3695       * @return int
3696       */
3697  	public function get_queried_object_id() {
3698          $this->get_queried_object();
3699  
3700          if ( isset( $this->queried_object_id ) ) {
3701              return $this->queried_object_id;
3702          }
3703  
3704          return 0;
3705      }
3706  
3707      /**
3708       * Constructor.
3709       *
3710       * Sets up the WordPress query, if parameter is not empty.
3711       *
3712       * @since 1.5.0
3713       *
3714       * @see WP_Query::parse_query() for all available arguments.
3715       *
3716       * @param string|array $query URL query string or array of vars.
3717       */
3718  	public function __construct( $query = '' ) {
3719          if ( ! empty( $query ) ) {
3720              $this->query( $query );
3721          }
3722      }
3723  
3724      /**
3725       * Make private properties readable for backward compatibility.
3726       *
3727       * @since 4.0.0
3728       *
3729       * @param string $name Property to get.
3730       * @return mixed Property.
3731       */
3732  	public function __get( $name ) {
3733          if ( in_array( $name, $this->compat_fields, true ) ) {
3734              return $this->$name;
3735          }
3736      }
3737  
3738      /**
3739       * Make private properties checkable for backward compatibility.
3740       *
3741       * @since 4.0.0
3742       *
3743       * @param string $name Property to check if set.
3744       * @return bool Whether the property is set.
3745       */
3746  	public function __isset( $name ) {
3747          if ( in_array( $name, $this->compat_fields, true ) ) {
3748              return isset( $this->$name );
3749          }
3750      }
3751  
3752      /**
3753       * Make private/protected methods readable for backward compatibility.
3754       *
3755       * @since 4.0.0
3756       *
3757       * @param string $name      Method to call.
3758       * @param array  $arguments Arguments to pass when calling.
3759       * @return mixed|false Return value of the callback, false otherwise.
3760       */
3761  	public function __call( $name, $arguments ) {
3762          if ( in_array( $name, $this->compat_methods, true ) ) {
3763              return $this->$name( ...$arguments );
3764          }
3765          return false;
3766      }
3767  
3768      /**
3769       * Is the query for an existing archive page?
3770       *
3771       * Archive pages include category, tag, author, date, custom post type,
3772       * and custom taxonomy based archives.
3773       *
3774       * @since 3.1.0
3775       *
3776       * @see WP_Query::is_category()
3777       * @see WP_Query::is_tag()
3778       * @see WP_Query::is_author()
3779       * @see WP_Query::is_date()
3780       * @see WP_Query::is_post_type_archive()
3781       * @see WP_Query::is_tax()
3782       *
3783       * @return bool Whether the query is for an existing archive page.
3784       */
3785  	public function is_archive() {
3786          return (bool) $this->is_archive;
3787      }
3788  
3789      /**
3790       * Is the query for an existing post type archive page?
3791       *
3792       * @since 3.1.0
3793       *
3794       * @param string|string[] $post_types Optional. Post type or array of posts types
3795       *                                    to check against. Default empty.
3796       * @return bool Whether the query is for an existing post type archive page.
3797       */
3798  	public function is_post_type_archive( $post_types = '' ) {
3799          if ( empty( $post_types ) || ! $this->is_post_type_archive ) {
3800              return (bool) $this->is_post_type_archive;
3801          }
3802  
3803          $post_type = $this->get( 'post_type' );
3804          if ( is_array( $post_type ) ) {
3805              $post_type = reset( $post_type );
3806          }
3807          $post_type_object = get_post_type_object( $post_type );
3808  
3809          return in_array( $post_type_object->name, (array) $post_types, true );
3810      }
3811  
3812      /**
3813       * Is the query for an existing attachment page?
3814       *
3815       * @since 3.1.0
3816       *
3817       * @param int|string|int[]|string[] $attachment Optional. Attachment ID, title, slug, or array of such
3818       *                                              to check against. Default empty.
3819       * @return bool Whether the query is for an existing attachment page.
3820       */
3821  	public function is_attachment( $attachment = '' ) {
3822          if ( ! $this->is_attachment ) {
3823              return false;
3824          }
3825  
3826          if ( empty( $attachment ) ) {
3827              return true;
3828          }
3829  
3830          $attachment = array_map( 'strval', (array) $attachment );
3831  
3832          $post_obj = $this->get_queried_object();
3833  
3834          if ( in_array( (string) $post_obj->ID, $attachment, true ) ) {
3835              return true;
3836          } elseif ( in_array( $post_obj->post_title, $attachment, true ) ) {
3837              return true;
3838          } elseif ( in_array( $post_obj->post_name, $attachment, true ) ) {
3839              return true;
3840          }
3841          return false;
3842      }
3843  
3844      /**
3845       * Is the query for an existing author archive page?
3846       *
3847       * If the $author parameter is specified, this function will additionally
3848       * check if the query is for one of the authors specified.
3849       *
3850       * @since 3.1.0
3851       *
3852       * @param int|string|int[]|string[] $author Optional. User ID, nickname, nicename, or array of such
3853       *                                          to check against. Default empty.
3854       * @return bool Whether the query is for an existing author archive page.
3855       */
3856  	public function is_author( $author = '' ) {
3857          if ( ! $this->is_author ) {
3858              return false;
3859          }
3860  
3861          if ( empty( $author ) ) {
3862              return true;
3863          }
3864  
3865          $author_obj = $this->get_queried_object();
3866  
3867          $author = array_map( 'strval', (array) $author );
3868  
3869          if ( in_array( (string) $author_obj->ID, $author, true ) ) {
3870              return true;
3871          } elseif ( in_array( $author_obj->nickname, $author, true ) ) {
3872              return true;
3873          } elseif ( in_array( $author_obj->user_nicename, $author, true ) ) {
3874              return true;
3875          }
3876  
3877          return false;
3878      }
3879  
3880      /**
3881       * Is the query for an existing category archive page?
3882       *
3883       * If the $category parameter is specified, this function will additionally
3884       * check if the query is for one of the categories specified.
3885       *
3886       * @since 3.1.0
3887       *
3888       * @param int|string|int[]|string[] $category Optional. Category ID, name, slug, or array of such
3889       *                                            to check against. Default empty.
3890       * @return bool Whether the query is for an existing category archive page.
3891       */
3892  	public function is_category( $category = '' ) {
3893          if ( ! $this->is_category ) {
3894              return false;
3895          }
3896  
3897          if ( empty( $category ) ) {
3898              return true;
3899          }
3900  
3901          $cat_obj = $this->get_queried_object();
3902  
3903          $category = array_map( 'strval', (array) $category );
3904  
3905          if ( in_array( (string) $cat_obj->term_id, $category, true ) ) {
3906              return true;
3907          } elseif ( in_array( $cat_obj->name, $category, true ) ) {
3908              return true;
3909          } elseif ( in_array( $cat_obj->slug, $category, true ) ) {
3910              return true;
3911          }
3912  
3913          return false;
3914      }
3915  
3916      /**
3917       * Is the query for an existing tag archive page?
3918       *
3919       * If the $tag parameter is specified, this function will additionally
3920       * check if the query is for one of the tags specified.
3921       *
3922       * @since 3.1.0
3923       *
3924       * @param int|string|int[]|string[] $tag Optional. Tag ID, name, slug, or array of such
3925       *                                       to check against. Default empty.
3926       * @return bool Whether the query is for an existing tag archive page.
3927       */
3928  	public function is_tag( $tag = '' ) {
3929          if ( ! $this->is_tag ) {
3930              return false;
3931          }
3932  
3933          if ( empty( $tag ) ) {
3934              return true;
3935          }
3936  
3937          $tag_obj = $this->get_queried_object();
3938  
3939          $tag = array_map( 'strval', (array) $tag );
3940  
3941          if ( in_array( (string) $tag_obj->term_id, $tag, true ) ) {
3942              return true;
3943          } elseif ( in_array( $tag_obj->name, $tag, true ) ) {
3944              return true;
3945          } elseif ( in_array( $tag_obj->slug, $tag, true ) ) {
3946              return true;
3947          }
3948  
3949          return false;
3950      }
3951  
3952      /**
3953       * Is the query for an existing custom taxonomy archive page?
3954       *
3955       * If the $taxonomy parameter is specified, this function will additionally
3956       * check if the query is for that specific $taxonomy.
3957       *
3958       * If the $term parameter is specified in addition to the $taxonomy parameter,
3959       * this function will additionally check if the query is for one of the terms
3960       * specified.
3961       *
3962       * @since 3.1.0
3963       *
3964       * @global WP_Taxonomy[] $wp_taxonomies Registered taxonomies.
3965       *
3966       * @param string|string[]           $taxonomy Optional. Taxonomy slug or slugs to check against.
3967       *                                            Default empty.
3968       * @param int|string|int[]|string[] $term     Optional. Term ID, name, slug, or array of such
3969       *                                            to check against. Default empty.
3970       * @return bool Whether the query is for an existing custom taxonomy archive page.
3971       *              True for custom taxonomy archive pages, false for built-in taxonomies
3972       *              (category and tag archives).
3973       */
3974  	public function is_tax( $taxonomy = '', $term = '' ) {
3975          global $wp_taxonomies;
3976  
3977          if ( ! $this->is_tax ) {
3978              return false;
3979          }
3980  
3981          if ( empty( $taxonomy ) ) {
3982              return true;
3983          }
3984  
3985          $queried_object = $this->get_queried_object();
3986          $tax_array      = array_intersect( array_keys( $wp_taxonomies ), (array) $taxonomy );
3987          $term_array     = (array) $term;
3988  
3989          // Check that the taxonomy matches.
3990          if ( ! ( isset( $queried_object->taxonomy ) && count( $tax_array ) && in_array( $queried_object->taxonomy, $tax_array, true ) ) ) {
3991              return false;
3992          }
3993  
3994          // Only a taxonomy provided.
3995          if ( empty( $term ) ) {
3996              return true;
3997          }
3998  
3999          return isset( $queried_object->term_id ) &&
4000              count(
4001                  array_intersect(
4002                      array( $queried_object->term_id, $queried_object->name, $queried_object->slug ),
4003                      $term_array
4004                  )
4005              );
4006      }
4007  
4008      /**
4009       * Whether the current URL is within the comments popup window.
4010       *
4011       * @since 3.1.0
4012       * @deprecated 4.5.0
4013       *
4014       * @return false Always returns false.
4015       */
4016  	public function is_comments_popup() {
4017          _deprecated_function( __FUNCTION__, '4.5.0' );
4018  
4019          return false;
4020      }
4021  
4022      /**
4023       * Is the query for an existing date archive?
4024       *
4025       * @since 3.1.0
4026       *
4027       * @return bool Whether the query is for an existing date archive.
4028       */
4029  	public function is_date() {
4030          return (bool) $this->is_date;
4031      }
4032  
4033      /**
4034       * Is the query for an existing day archive?
4035       *
4036       * @since 3.1.0
4037       *
4038       * @return bool Whether the query is for an existing day archive.
4039       */
4040  	public function is_day() {
4041          return (bool) $this->is_day;
4042      }
4043  
4044      /**
4045       * Is the query for a feed?
4046       *
4047       * @since 3.1.0
4048       *
4049       * @param string|string[] $feeds Optional. Feed type or array of feed types
4050       *                                         to check against. Default empty.
4051       * @return bool Whether the query is for a feed.
4052       */
4053  	public function is_feed( $feeds = '' ) {
4054          if ( empty( $feeds ) || ! $this->is_feed ) {
4055              return (bool) $this->is_feed;
4056          }
4057  
4058          $qv = $this->get( 'feed' );
4059          if ( 'feed' === $qv ) {
4060              $qv = get_default_feed();
4061          }
4062  
4063          return in_array( $qv, (array) $feeds, true );
4064      }
4065  
4066      /**
4067       * Is the query for a comments feed?
4068       *
4069       * @since 3.1.0
4070       *
4071       * @return bool Whether the query is for a comments feed.
4072       */
4073  	public function is_comment_feed() {
4074          return (bool) $this->is_comment_feed;
4075      }
4076  
4077      /**
4078       * Is the query for the front page of the site?
4079       *
4080       * This is for what is displayed at your site's main URL.
4081       *
4082       * Depends on the site's "Front page displays" Reading Settings 'show_on_front' and 'page_on_front'.
4083       *
4084       * If you set a static page for the front page of your site, this function will return
4085       * true when viewing that page.
4086       *
4087       * Otherwise the same as @see WP_Query::is_home()
4088       *
4089       * @since 3.1.0
4090       *
4091       * @return bool Whether the query is for the front page of the site.
4092       */
4093  	public function is_front_page() {
4094          // Most likely case.
4095          if ( 'posts' === get_option( 'show_on_front' ) && $this->is_home() ) {
4096              return true;
4097          } elseif ( 'page' === get_option( 'show_on_front' ) && get_option( 'page_on_front' )
4098              && $this->is_page( get_option( 'page_on_front' ) )
4099          ) {
4100              return true;
4101          } else {
4102              return false;
4103          }
4104      }
4105  
4106      /**
4107       * Is the query for the blog homepage?
4108       *
4109       * This is the page which shows the time based blog content of your site.
4110       *
4111       * Depends on the site's "Front page displays" Reading Settings 'show_on_front' and 'page_for_posts'.
4112       *
4113       * If you set a static page for the front page of your site, this function will return
4114       * true only on the page you set as the "Posts page".
4115       *
4116       * @since 3.1.0
4117       *
4118       * @see WP_Query::is_front_page()
4119       *
4120       * @return bool Whether the query is for the blog homepage.
4121       */
4122  	public function is_home() {
4123          return (bool) $this->is_home;
4124      }
4125  
4126      /**
4127       * Is the query for the Privacy Policy page?
4128       *
4129       * This is the page which shows the Privacy Policy content of your site.
4130       *
4131       * Depends on the site's "Change your Privacy Policy page" Privacy Settings 'wp_page_for_privacy_policy'.
4132       *
4133       * This function will return true only on the page you set as the "Privacy Policy page".
4134       *
4135       * @since 5.2.0
4136       *
4137       * @return bool Whether the query is for the Privacy Policy page.
4138       */
4139  	public function is_privacy_policy() {
4140          if ( get_option( 'wp_page_for_privacy_policy' )
4141              && $this->is_page( get_option( 'wp_page_for_privacy_policy' ) )
4142          ) {
4143              return true;
4144          } else {
4145              return false;
4146          }
4147      }
4148  
4149      /**
4150       * Is the query for an existing month archive?
4151       *
4152       * @since 3.1.0
4153       *
4154       * @return bool Whether the query is for an existing month archive.
4155       */
4156  	public function is_month() {
4157          return (bool) $this->is_month;
4158      }
4159  
4160      /**
4161       * Is the query for an existing single page?
4162       *
4163       * If the $page parameter is specified, this function will additionally
4164       * check if the query is for one of the pages specified.
4165       *
4166       * @since 3.1.0
4167       *
4168       * @see WP_Query::is_single()
4169       * @see WP_Query::is_singular()
4170       *
4171       * @param int|string|int[]|string[] $page Optional. Page ID, title, slug, path, or array of such
4172       *                                        to check against. Default empty.
4173       * @return bool Whether the query is for an existing single page.
4174       */
4175  	public function is_page( $page = '' ) {
4176          if ( ! $this->is_page ) {
4177              return false;
4178          }
4179  
4180          if ( empty( $page ) ) {
4181              return true;
4182          }
4183  
4184          $page_obj = $this->get_queried_object();
4185  
4186          $page = array_map( 'strval', (array) $page );
4187  
4188          if ( in_array( (string) $page_obj->ID, $page, true ) ) {
4189              return true;
4190          } elseif ( in_array( $page_obj->post_title, $page, true ) ) {
4191              return true;
4192          } elseif ( in_array( $page_obj->post_name, $page, true ) ) {
4193              return true;
4194          } else {
4195              foreach ( $page as $pagepath ) {
4196                  if ( ! strpos( $pagepath, '/' ) ) {
4197                      continue;
4198                  }
4199                  $pagepath_obj = get_page_by_path( $pagepath );
4200  
4201                  if ( $pagepath_obj && ( $pagepath_obj->ID == $page_obj->ID ) ) {
4202                      return true;
4203                  }
4204              }
4205          }
4206  
4207          return false;
4208      }
4209  
4210      /**
4211       * Is the query for a paged result and not for the first page?
4212       *
4213       * @since 3.1.0
4214       *
4215       * @return bool Whether the query is for a paged result.
4216       */
4217  	public function is_paged() {
4218          return (bool) $this->is_paged;
4219      }
4220  
4221      /**
4222       * Is the query for a post or page preview?
4223       *
4224       * @since 3.1.0
4225       *
4226       * @return bool Whether the query is for a post or page preview.
4227       */
4228  	public function is_preview() {
4229          return (bool) $this->is_preview;
4230      }
4231  
4232      /**
4233       * Is the query for the robots.txt file?
4234       *
4235       * @since 3.1.0
4236       *
4237       * @return bool Whether the query is for the robots.txt file.
4238       */
4239  	public function is_robots() {
4240          return (bool) $this->is_robots;
4241      }
4242  
4243      /**
4244       * Is the query for the favicon.ico file?
4245       *
4246       * @since 5.4.0
4247       *
4248       * @return bool Whether the query is for the favicon.ico file.
4249       */
4250  	public function is_favicon() {
4251          return (bool) $this->is_favicon;
4252      }
4253  
4254      /**
4255       * Is the query for a search?
4256       *
4257       * @since 3.1.0
4258       *
4259       * @return bool Whether the query is for a search.
4260       */
4261  	public function is_search() {
4262          return (bool) $this->is_search;
4263      }
4264  
4265      /**
4266       * Is the query for an existing single post?
4267       *
4268       * Works for any post type excluding pages.
4269       *
4270       * If the $post parameter is specified, this function will additionally
4271       * check if the query is for one of the Posts specified.
4272       *
4273       * @since 3.1.0
4274       *
4275       * @see WP_Query::is_page()
4276       * @see WP_Query::is_singular()
4277       *
4278       * @param int|string|int[]|string[] $post Optional. Post ID, title, slug, path, or array of such
4279       *                                        to check against. Default empty.
4280       * @return bool Whether the query is for an existing single post.
4281       */
4282  	public function is_single( $post = '' ) {
4283          if ( ! $this->is_single ) {
4284              return false;
4285          }
4286  
4287          if ( empty( $post ) ) {
4288              return true;
4289          }
4290  
4291          $post_obj = $this->get_queried_object();
4292  
4293          $post = array_map( 'strval', (array) $post );
4294  
4295          if ( in_array( (string) $post_obj->ID, $post, true ) ) {
4296              return true;
4297          } elseif ( in_array( $post_obj->post_title, $post, true ) ) {
4298              return true;
4299          } elseif ( in_array( $post_obj->post_name, $post, true ) ) {
4300              return true;
4301          } else {
4302              foreach ( $post as $postpath ) {
4303                  if ( ! strpos( $postpath, '/' ) ) {
4304                      continue;
4305                  }
4306                  $postpath_obj = get_page_by_path( $postpath, OBJECT, $post_obj->post_type );
4307  
4308                  if ( $postpath_obj && ( $postpath_obj->ID == $post_obj->ID ) ) {
4309                      return true;
4310                  }
4311              }
4312          }
4313          return false;
4314      }
4315  
4316      /**
4317       * Is the query for an existing single post of any post type (post, attachment, page,
4318       * custom post types)?
4319       *
4320       * If the $post_types parameter is specified, this function will additionally
4321       * check if the query is for one of the Posts Types specified.
4322       *
4323       * @since 3.1.0
4324       *
4325       * @see WP_Query::is_page()
4326       * @see WP_Query::is_single()
4327       *
4328       * @param string|string[] $post_types Optional. Post type or array of post types
4329       *                                    to check against. Default empty.
4330       * @return bool Whether the query is for an existing single post
4331       *              or any of the given post types.
4332       */
4333  	public function is_singular( $post_types = '' ) {
4334          if ( empty( $post_types ) || ! $this->is_singular ) {
4335              return (bool) $this->is_singular;
4336          }
4337  
4338          $post_obj = $this->get_queried_object();
4339  
4340          return in_array( $post_obj->post_type, (array) $post_types, true );
4341      }
4342  
4343      /**
4344       * Is the query for a specific time?
4345       *
4346       * @since 3.1.0
4347       *
4348       * @return bool Whether the query is for a specific time.
4349       */
4350  	public function is_time() {
4351          return (bool) $this->is_time;
4352      }
4353  
4354      /**
4355       * Is the query for a trackback endpoint call?
4356       *
4357       * @since 3.1.0
4358       *
4359       * @return bool Whether the query is for a trackback endpoint call.
4360       */
4361  	public function is_trackback() {
4362          return (bool) $this->is_trackback;
4363      }
4364  
4365      /**
4366       * Is the query for an existing year archive?
4367       *
4368       * @since 3.1.0
4369       *
4370       * @return bool Whether the query is for an existing year archive.
4371       */
4372  	public function is_year() {
4373          return (bool) $this->is_year;
4374      }
4375  
4376      /**
4377       * Is the query a 404 (returns no results)?
4378       *
4379       * @since 3.1.0
4380       *
4381       * @return bool Whether the query is a 404 error.
4382       */
4383  	public function is_404() {
4384          return (bool) $this->is_404;
4385      }
4386  
4387      /**
4388       * Is the query for an embedded post?
4389       *
4390       * @since 4.4.0
4391       *
4392       * @return bool Whether the query is for an embedded post.
4393       */
4394  	public function is_embed() {
4395          return (bool) $this->is_embed;
4396      }
4397  
4398      /**
4399       * Is the query the main query?
4400       *
4401       * @since 3.3.0
4402       *
4403       * @global WP_Query $wp_query WordPress Query object.
4404       *
4405       * @return bool Whether the query is the main query.
4406       */
4407  	public function is_main_query() {
4408          global $wp_the_query;
4409          return $wp_the_query === $this;
4410      }
4411  
4412      /**
4413       * Set up global post data.
4414       *
4415       * @since 4.1.0
4416       * @since 4.4.0 Added the ability to pass a post ID to `$post`.
4417       *
4418       * @global int     $id
4419       * @global WP_User $authordata
4420       * @global string  $currentday
4421       * @global string  $currentmonth
4422       * @global int     $page
4423       * @global array   $pages
4424       * @global int     $multipage
4425       * @global int     $more
4426       * @global int     $numpages
4427       *
4428       * @param WP_Post|object|int $post WP_Post instance or Post ID/object.
4429       * @return true True when finished.
4430       */
4431  	public function setup_postdata( $post ) {
4432          global $id, $authordata, $currentday, $currentmonth, $page, $pages, $multipage, $more, $numpages;
4433  
4434          if ( ! ( $post instanceof WP_Post ) ) {
4435              $post = get_post( $post );
4436          }
4437  
4438          if ( ! $post ) {
4439              return;
4440          }
4441  
4442          $elements = $this->generate_postdata( $post );
4443          if ( false === $elements ) {
4444              return;
4445          }
4446  
4447          $id           = $elements['id'];
4448          $authordata   = $elements['authordata'];
4449          $currentday   = $elements['currentday'];
4450          $currentmonth = $elements['currentmonth'];
4451          $page         = $elements['page'];
4452          $pages        = $elements['pages'];
4453          $multipage    = $elements['multipage'];
4454          $more         = $elements['more'];
4455          $numpages     = $elements['numpages'];
4456  
4457          /**
4458           * Fires once the post data has been set up.
4459           *
4460           * @since 2.8.0
4461           * @since 4.1.0 Introduced `$query` parameter.
4462           *
4463           * @param WP_Post  $post  The Post object (passed by reference).
4464           * @param WP_Query $query The current Query object (passed by reference).
4465           */
4466          do_action_ref_array( 'the_post', array( &$post, &$this ) );
4467  
4468          return true;
4469      }
4470  
4471      /**
4472       * Generate post data.
4473       *
4474       * @since 5.2.0
4475       *
4476       * @param WP_Post|object|int $post WP_Post instance or Post ID/object.
4477       * @return array|false Elements of post or false on failure.
4478       */
4479  	public function generate_postdata( $post ) {
4480  
4481          if ( ! ( $post instanceof WP_Post ) ) {
4482              $post = get_post( $post );
4483          }
4484  
4485          if ( ! $post ) {
4486              return false;
4487          }
4488  
4489          $id = (int) $post->ID;
4490  
4491          $authordata = get_userdata( $post->post_author );
4492  
4493          $currentday   = mysql2date( 'd.m.y', $post->post_date, false );
4494          $currentmonth = mysql2date( 'm', $post->post_date, false );
4495          $numpages     = 1;
4496          $multipage    = 0;
4497          $page         = $this->get( 'page' );
4498          if ( ! $page ) {
4499              $page = 1;
4500          }
4501  
4502          /*
4503           * Force full post content when viewing the permalink for the $post,
4504           * or when on an RSS feed. Otherwise respect the 'more' tag.
4505           */
4506          if ( get_queried_object_id() === $post->ID && ( $this->is_page() || $this->is_single() ) ) {
4507              $more = 1;
4508          } elseif ( $this->is_feed() ) {
4509              $more = 1;
4510          } else {
4511              $more = 0;
4512          }
4513  
4514          $content = $post->post_content;
4515          if ( false !== strpos( $content, '<!--nextpage-->' ) ) {
4516              $content = str_replace( "\n<!--nextpage-->\n", '<!--nextpage-->', $content );
4517              $content = str_replace( "\n<!--nextpage-->", '<!--nextpage-->', $content );
4518              $content = str_replace( "<!--nextpage-->\n", '<!--nextpage-->', $content );
4519  
4520              // Remove the nextpage block delimiters, to avoid invalid block structures in the split content.
4521              $content = str_replace( '<!-- wp:nextpage -->', '', $content );
4522              $content = str_replace( '<!-- /wp:nextpage -->', '', $content );
4523  
4524              // Ignore nextpage at the beginning of the content.
4525              if ( 0 === strpos( $content, '<!--nextpage-->' ) ) {
4526                  $content = substr( $content, 15 );
4527              }
4528  
4529              $pages = explode( '<!--nextpage-->', $content );
4530          } else {
4531              $pages = array( $post->post_content );
4532          }
4533  
4534          /**
4535           * Filters the "pages" derived from splitting the post content.
4536           *
4537           * "Pages" are determined by splitting the post content based on the presence
4538           * of `<!-- nextpage -->` tags.
4539           *
4540           * @since 4.4.0
4541           *
4542           * @param string[] $pages Array of "pages" from the post content split by `<!-- nextpage -->` tags.
4543           * @param WP_Post  $post  Current post object.
4544           */
4545          $pages = apply_filters( 'content_pagination', $pages, $post );
4546  
4547          $numpages = count( $pages );
4548  
4549          if ( $numpages > 1 ) {
4550              if ( $page > 1 ) {
4551                  $more = 1;
4552              }
4553              $multipage = 1;
4554          } else {
4555              $multipage = 0;
4556          }
4557  
4558          $elements = compact( 'id', 'authordata', 'currentday', 'currentmonth', 'page', 'pages', 'multipage', 'more', 'numpages' );
4559  
4560          return $elements;
4561      }
4562      /**
4563       * After looping through a nested query, this function
4564       * restores the $post global to the current post in this query.
4565       *
4566       * @since 3.7.0
4567       *
4568       * @global WP_Post $post Global post object.
4569       */
4570  	public function reset_postdata() {
4571          if ( ! empty( $this->post ) ) {
4572              $GLOBALS['post'] = $this->post;
4573              $this->setup_postdata( $this->post );
4574          }
4575      }
4576  
4577      /**
4578       * Lazyload term meta for posts in the loop.
4579       *
4580       * @since 4.4.0
4581       * @deprecated 4.5.0 See wp_queue_posts_for_term_meta_lazyload().
4582       *
4583       * @param mixed $check
4584       * @param int   $term_id
4585       * @return mixed
4586       */
4587  	public function lazyload_term_meta( $check, $term_id ) {
4588          _deprecated_function( __METHOD__, '4.5.0' );
4589          return $check;
4590      }
4591  
4592      /**
4593       * Lazyload comment meta for comments in the loop.
4594       *
4595       * @since 4.4.0
4596       * @deprecated 4.5.0 See wp_queue_comments_for_comment_meta_lazyload().
4597       *
4598       * @param mixed $check
4599       * @param int   $comment_id
4600       * @return mixed
4601       */
4602  	public function lazyload_comment_meta( $check, $comment_id ) {
4603          _deprecated_function( __METHOD__, '4.5.0' );
4604          return $check;
4605      }
4606  }


Generated: Tue Mar 19 01:00:02 2024 Cross-referenced by PHPXref 0.7.1