PageRenderTime 315ms CodeModel.GetById 161ms app.highlight 110ms RepoModel.GetById 11ms app.codeStats 2ms

/htdocs/wp-includes/query.php

https://bitbucket.org/dkrzos/phc
PHP | 3658 lines | 1837 code | 464 blank | 1357 comment | 537 complexity | 35b078a3bfe2e99adb91674477ab3c59 MD5 | raw file

Large files files are truncated, but you can click here to view the full file

   1<?php
   2/**
   3 * WordPress Query API
   4 *
   5 * The query API attempts to get which part of WordPress to the user is on. It
   6 * also provides functionality to getting URL query information.
   7 *
   8 * @link http://codex.wordpress.org/The_Loop More information on The Loop.
   9 *
  10 * @package WordPress
  11 * @subpackage Query
  12 */
  13
  14/**
  15 * Retrieve variable in the WP_Query class.
  16 *
  17 * @see WP_Query::get()
  18 * @since 1.5.0
  19 * @uses $wp_query
  20 *
  21 * @param string $var The variable key to retrieve.
  22 * @return mixed
  23 */
  24function get_query_var($var) {
  25	global $wp_query;
  26
  27	return $wp_query->get($var);
  28}
  29
  30/**
  31 * Retrieve the currently-queried object. Wrapper for $wp_query->get_queried_object()
  32 *
  33 * @uses WP_Query::get_queried_object
  34 *
  35 * @since 3.1.0
  36 * @access public
  37 *
  38 * @return object
  39 */
  40function get_queried_object() {
  41	global $wp_query;
  42	return $wp_query->get_queried_object();
  43}
  44
  45/**
  46 * Retrieve ID of the current queried object. Wrapper for $wp_query->get_queried_object_id()
  47 *
  48 * @uses WP_Query::get_queried_object_id()
  49 *
  50 * @since 3.1.0
  51 * @access public
  52 *
  53 * @return int
  54 */
  55function get_queried_object_id() {
  56	global $wp_query;
  57	return $wp_query->get_queried_object_id();
  58}
  59
  60/**
  61 * Set query variable.
  62 *
  63 * @see WP_Query::set()
  64 * @since 2.2.0
  65 * @uses $wp_query
  66 *
  67 * @param string $var Query variable key.
  68 * @param mixed $value
  69 * @return null
  70 */
  71function set_query_var($var, $value) {
  72	global $wp_query;
  73
  74	return $wp_query->set($var, $value);
  75}
  76
  77/**
  78 * Set up The Loop with query parameters.
  79 *
  80 * This will override the current WordPress Loop and shouldn't be used more than
  81 * once. This must not be used within the WordPress Loop.
  82 *
  83 * @since 1.5.0
  84 * @uses $wp_query
  85 *
  86 * @param string $query
  87 * @return array List of posts
  88 */
  89function query_posts($query) {
  90	$GLOBALS['wp_query'] = new WP_Query();
  91	return $GLOBALS['wp_query']->query($query);
  92}
  93
  94/**
  95 * Destroy the previous query and set up a new query.
  96 *
  97 * This should be used after {@link query_posts()} and before another {@link
  98 * query_posts()}. This will remove obscure bugs that occur when the previous
  99 * wp_query object is not destroyed properly before another is set up.
 100 *
 101 * @since 2.3.0
 102 * @uses $wp_query
 103 */
 104function wp_reset_query() {
 105	$GLOBALS['wp_query'] = $GLOBALS['wp_the_query'];
 106	wp_reset_postdata();
 107}
 108
 109/**
 110 * After looping through a separate query, this function restores
 111 * the $post global to the current post in the main query
 112 *
 113 * @since 3.0.0
 114 * @uses $wp_query
 115 */
 116function wp_reset_postdata() {
 117	global $wp_query;
 118	if ( !empty($wp_query->post) ) {
 119		$GLOBALS['post'] = $wp_query->post;
 120		setup_postdata($wp_query->post);
 121	}
 122}
 123
 124/*
 125 * Query type checks.
 126 */
 127
 128/**
 129 * Is the query for an existing archive page?
 130 *
 131 * Month, Year, Category, Author, Post Type archive...
 132 *
 133 * @see WP_Query::is_archive()
 134 * @since 1.5.0
 135 * @uses $wp_query
 136 *
 137 * @return bool
 138 */
 139function is_archive() {
 140	global $wp_query;
 141
 142	if ( ! isset( $wp_query ) ) {
 143		_doing_it_wrong( __FUNCTION__, __( 'Conditional query tags do not work before the query is run. Before then, they always return false.' ), '3.1' );
 144		return false;
 145	}
 146
 147	return $wp_query->is_archive();
 148}
 149
 150/**
 151 * Is the query for an existing post type archive page?
 152 *
 153 * @see WP_Query::is_post_type_archive()
 154 * @since 3.1.0
 155 * @uses $wp_query
 156 *
 157 * @param mixed $post_types Optional. Post type or array of posts types to check against.
 158 * @return bool
 159 */
 160function is_post_type_archive( $post_types = '' ) {
 161	global $wp_query;
 162
 163	if ( ! isset( $wp_query ) ) {
 164		_doing_it_wrong( __FUNCTION__, __( 'Conditional query tags do not work before the query is run. Before then, they always return false.' ), '3.1' );
 165		return false;
 166	}
 167
 168	return $wp_query->is_post_type_archive( $post_types );
 169}
 170
 171/**
 172 * Is the query for an existing attachment page?
 173 *
 174 * @see WP_Query::is_attachment()
 175 * @since 2.0.0
 176 * @uses $wp_query
 177 *
 178 * @return bool
 179 */
 180function is_attachment() {
 181	global $wp_query;
 182
 183	if ( ! isset( $wp_query ) ) {
 184		_doing_it_wrong( __FUNCTION__, __( 'Conditional query tags do not work before the query is run. Before then, they always return false.' ), '3.1' );
 185		return false;
 186	}
 187
 188	return $wp_query->is_attachment();
 189}
 190
 191/**
 192 * Is the query for an existing author archive page?
 193 *
 194 * If the $author parameter is specified, this function will additionally
 195 * check if the query is for one of the authors specified.
 196 *
 197 * @see WP_Query::is_author()
 198 * @since 1.5.0
 199 * @uses $wp_query
 200 *
 201 * @param mixed $author Optional. User ID, nickname, nicename, or array of User IDs, nicknames, and nicenames
 202 * @return bool
 203 */
 204function is_author( $author = '' ) {
 205	global $wp_query;
 206
 207	if ( ! isset( $wp_query ) ) {
 208		_doing_it_wrong( __FUNCTION__, __( 'Conditional query tags do not work before the query is run. Before then, they always return false.' ), '3.1' );
 209		return false;
 210	}
 211
 212	return $wp_query->is_author( $author );
 213}
 214
 215/**
 216 * Is the query for an existing category archive page?
 217 *
 218 * If the $category parameter is specified, this function will additionally
 219 * check if the query is for one of the categories specified.
 220 *
 221 * @see WP_Query::is_category()
 222 * @since 1.5.0
 223 * @uses $wp_query
 224 *
 225 * @param mixed $category Optional. Category ID, name, slug, or array of Category IDs, names, and slugs.
 226 * @return bool
 227 */
 228function is_category( $category = '' ) {
 229	global $wp_query;
 230
 231	if ( ! isset( $wp_query ) ) {
 232		_doing_it_wrong( __FUNCTION__, __( 'Conditional query tags do not work before the query is run. Before then, they always return false.' ), '3.1' );
 233		return false;
 234	}
 235
 236	return $wp_query->is_category( $category );
 237}
 238
 239/**
 240 * Is the query for an existing tag archive page?
 241 *
 242 * If the $tag parameter is specified, this function will additionally
 243 * check if the query is for one of the tags specified.
 244 *
 245 * @see WP_Query::is_tag()
 246 * @since 2.3.0
 247 * @uses $wp_query
 248 *
 249 * @param mixed $slug Optional. Tag slug or array of slugs.
 250 * @return bool
 251 */
 252function is_tag( $slug = '' ) {
 253	global $wp_query;
 254
 255	if ( ! isset( $wp_query ) ) {
 256		_doing_it_wrong( __FUNCTION__, __( 'Conditional query tags do not work before the query is run. Before then, they always return false.' ), '3.1' );
 257		return false;
 258	}
 259
 260	return $wp_query->is_tag( $slug );
 261}
 262
 263/**
 264 * Is the query for an existing taxonomy archive page?
 265 *
 266 * If the $taxonomy parameter is specified, this function will additionally
 267 * check if the query is for that specific $taxonomy.
 268 *
 269 * If the $term parameter is specified in addition to the $taxonomy parameter,
 270 * this function will additionally check if the query is for one of the terms
 271 * specified.
 272 *
 273 * @see WP_Query::is_tax()
 274 * @since 2.5.0
 275 * @uses $wp_query
 276 *
 277 * @param mixed $taxonomy Optional. Taxonomy slug or slugs.
 278 * @param mixed $term Optional. Term ID, name, slug or array of Term IDs, names, and slugs.
 279 * @return bool
 280 */
 281function is_tax( $taxonomy = '', $term = '' ) {
 282	global $wp_query;
 283
 284	if ( ! isset( $wp_query ) ) {
 285		_doing_it_wrong( __FUNCTION__, __( 'Conditional query tags do not work before the query is run. Before then, they always return false.' ), '3.1' );
 286		return false;
 287	}
 288
 289	return $wp_query->is_tax( $taxonomy, $term );
 290}
 291
 292/**
 293 * Whether the current URL is within the comments popup window.
 294 *
 295 * @see WP_Query::is_comments_popup()
 296 * @since 1.5.0
 297 * @uses $wp_query
 298 *
 299 * @return bool
 300 */
 301function is_comments_popup() {
 302	global $wp_query;
 303
 304	if ( ! isset( $wp_query ) ) {
 305		_doing_it_wrong( __FUNCTION__, __( 'Conditional query tags do not work before the query is run. Before then, they always return false.' ), '3.1' );
 306		return false;
 307	}
 308
 309	return $wp_query->is_comments_popup();
 310}
 311
 312/**
 313 * Is the query for an existing date archive?
 314 *
 315 * @see WP_Query::is_date()
 316 * @since 1.5.0
 317 * @uses $wp_query
 318 *
 319 * @return bool
 320 */
 321function is_date() {
 322	global $wp_query;
 323
 324	if ( ! isset( $wp_query ) ) {
 325		_doing_it_wrong( __FUNCTION__, __( 'Conditional query tags do not work before the query is run. Before then, they always return false.' ), '3.1' );
 326		return false;
 327	}
 328
 329	return $wp_query->is_date();
 330}
 331
 332/**
 333 * Is the query for an existing day archive?
 334 *
 335 * @see WP_Query::is_day()
 336 * @since 1.5.0
 337 * @uses $wp_query
 338 *
 339 * @return bool
 340 */
 341function is_day() {
 342	global $wp_query;
 343
 344	if ( ! isset( $wp_query ) ) {
 345		_doing_it_wrong( __FUNCTION__, __( 'Conditional query tags do not work before the query is run. Before then, they always return false.' ), '3.1' );
 346		return false;
 347	}
 348
 349	return $wp_query->is_day();
 350}
 351
 352/**
 353 * Is the query for a feed?
 354 *
 355 * @see WP_Query::is_feed()
 356 * @since 1.5.0
 357 * @uses $wp_query
 358 *
 359 * @param string|array $feeds Optional feed types to check.
 360 * @return bool
 361 */
 362function is_feed( $feeds = '' ) {
 363	global $wp_query;
 364
 365	if ( ! isset( $wp_query ) ) {
 366		_doing_it_wrong( __FUNCTION__, __( 'Conditional query tags do not work before the query is run. Before then, they always return false.' ), '3.1' );
 367		return false;
 368	}
 369
 370	return $wp_query->is_feed( $feeds );
 371}
 372
 373/**
 374 * Is the query for a comments feed?
 375 *
 376 * @see WP_Query::is_comments_feed()
 377 * @since 3.0.0
 378 * @uses $wp_query
 379 *
 380 * @return bool
 381 */
 382function is_comment_feed() {
 383	global $wp_query;
 384
 385	if ( ! isset( $wp_query ) ) {
 386		_doing_it_wrong( __FUNCTION__, __( 'Conditional query tags do not work before the query is run. Before then, they always return false.' ), '3.1' );
 387		return false;
 388	}
 389
 390	return $wp_query->is_comment_feed();
 391}
 392
 393/**
 394 * Is the query for the front page of the site?
 395 *
 396 * This is for what is displayed at your site's main URL.
 397 *
 398 * Depends on the site's "Front page displays" Reading Settings 'show_on_front' and 'page_on_front'.
 399 *
 400 * If you set a static page for the front page of your site, this function will return
 401 * true when viewing that page.
 402 *
 403 * Otherwise the same as @see is_home()
 404 *
 405 * @see WP_Query::is_front_page()
 406 * @since 2.5.0
 407 * @uses is_home()
 408 * @uses get_option()
 409 *
 410 * @return bool True, if front of site.
 411 */
 412function is_front_page() {
 413	global $wp_query;
 414
 415	if ( ! isset( $wp_query ) ) {
 416		_doing_it_wrong( __FUNCTION__, __( 'Conditional query tags do not work before the query is run. Before then, they always return false.' ), '3.1' );
 417		return false;
 418	}
 419
 420	return $wp_query->is_front_page();
 421}
 422
 423/**
 424 * Is the query for the blog homepage?
 425 *
 426 * This is the page which shows the time based blog content of your site.
 427 *
 428 * Depends on the site's "Front page displays" Reading Settings 'show_on_front' and 'page_for_posts'.
 429 *
 430 * If you set a static page for the front page of your site, this function will return
 431 * true only on the page you set as the "Posts page".
 432 *
 433 * @see is_front_page()
 434 *
 435 * @see WP_Query::is_home()
 436 * @since 1.5.0
 437 * @uses $wp_query
 438 *
 439 * @return bool True if blog view homepage.
 440 */
 441function is_home() {
 442	global $wp_query;
 443
 444	if ( ! isset( $wp_query ) ) {
 445		_doing_it_wrong( __FUNCTION__, __( 'Conditional query tags do not work before the query is run. Before then, they always return false.' ), '3.1' );
 446		return false;
 447	}
 448
 449	return $wp_query->is_home();
 450}
 451
 452/**
 453 * Is the query for an existing month archive?
 454 *
 455 * @see WP_Query::is_month()
 456 * @since 1.5.0
 457 * @uses $wp_query
 458 *
 459 * @return bool
 460 */
 461function is_month() {
 462	global $wp_query;
 463
 464	if ( ! isset( $wp_query ) ) {
 465		_doing_it_wrong( __FUNCTION__, __( 'Conditional query tags do not work before the query is run. Before then, they always return false.' ), '3.1' );
 466		return false;
 467	}
 468
 469	return $wp_query->is_month();
 470}
 471
 472/**
 473 * Is the query for an existing single page?
 474 *
 475 * If the $page parameter is specified, this function will additionally
 476 * check if the query is for one of the pages specified.
 477 *
 478 * @see is_single()
 479 * @see is_singular()
 480 *
 481 * @see WP_Query::is_page()
 482 * @since 1.5.0
 483 * @uses $wp_query
 484 *
 485 * @param mixed $page Page ID, title, slug, or array of such.
 486 * @return bool
 487 */
 488function is_page( $page = '' ) {
 489	global $wp_query;
 490
 491	if ( ! isset( $wp_query ) ) {
 492		_doing_it_wrong( __FUNCTION__, __( 'Conditional query tags do not work before the query is run. Before then, they always return false.' ), '3.1' );
 493		return false;
 494	}
 495
 496	return $wp_query->is_page( $page );
 497}
 498
 499/**
 500 * Is the query for paged result and not for the first page?
 501 *
 502 * @see WP_Query::is_paged()
 503 * @since 1.5.0
 504 * @uses $wp_query
 505 *
 506 * @return bool
 507 */
 508function is_paged() {
 509	global $wp_query;
 510
 511	if ( ! isset( $wp_query ) ) {
 512		_doing_it_wrong( __FUNCTION__, __( 'Conditional query tags do not work before the query is run. Before then, they always return false.' ), '3.1' );
 513		return false;
 514	}
 515
 516	return $wp_query->is_paged();
 517}
 518
 519/**
 520 * Is the query for a post or page preview?
 521 *
 522 * @see WP_Query::is_preview()
 523 * @since 2.0.0
 524 * @uses $wp_query
 525 *
 526 * @return bool
 527 */
 528function is_preview() {
 529	global $wp_query;
 530
 531	if ( ! isset( $wp_query ) ) {
 532		_doing_it_wrong( __FUNCTION__, __( 'Conditional query tags do not work before the query is run. Before then, they always return false.' ), '3.1' );
 533		return false;
 534	}
 535
 536	return $wp_query->is_preview();
 537}
 538
 539/**
 540 * Is the query for the robots file?
 541 *
 542 * @see WP_Query::is_robots()
 543 * @since 2.1.0
 544 * @uses $wp_query
 545 *
 546 * @return bool
 547 */
 548function is_robots() {
 549	global $wp_query;
 550
 551	if ( ! isset( $wp_query ) ) {
 552		_doing_it_wrong( __FUNCTION__, __( 'Conditional query tags do not work before the query is run. Before then, they always return false.' ), '3.1' );
 553		return false;
 554	}
 555
 556	return $wp_query->is_robots();
 557}
 558
 559/**
 560 * Is the query for a search?
 561 *
 562 * @see WP_Query::is_search()
 563 * @since 1.5.0
 564 * @uses $wp_query
 565 *
 566 * @return bool
 567 */
 568function is_search() {
 569	global $wp_query;
 570
 571	if ( ! isset( $wp_query ) ) {
 572		_doing_it_wrong( __FUNCTION__, __( 'Conditional query tags do not work before the query is run. Before then, they always return false.' ), '3.1' );
 573		return false;
 574	}
 575
 576	return $wp_query->is_search();
 577}
 578
 579/**
 580 * Is the query for an existing single post?
 581 *
 582 * Works for any post type, except attachments and pages
 583 *
 584 * If the $post parameter is specified, this function will additionally
 585 * check if the query is for one of the Posts specified.
 586 *
 587 * @see is_page()
 588 * @see is_singular()
 589 *
 590 * @see WP_Query::is_single()
 591 * @since 1.5.0
 592 * @uses $wp_query
 593 *
 594 * @param mixed $post Post ID, title, slug, or array of such.
 595 * @return bool
 596 */
 597function is_single( $post = '' ) {
 598	global $wp_query;
 599
 600	if ( ! isset( $wp_query ) ) {
 601		_doing_it_wrong( __FUNCTION__, __( 'Conditional query tags do not work before the query is run. Before then, they always return false.' ), '3.1' );
 602		return false;
 603	}
 604
 605	return $wp_query->is_single( $post );
 606}
 607
 608/**
 609 * Is the query for an existing single post of any post type (post, attachment, page, ... )?
 610 *
 611 * If the $post_types parameter is specified, this function will additionally
 612 * check if the query is for one of the Posts Types specified.
 613 *
 614 * @see is_page()
 615 * @see is_single()
 616 *
 617 * @see WP_Query::is_singular()
 618 * @since 1.5.0
 619 * @uses $wp_query
 620 *
 621 * @param mixed $post_types Optional. Post Type or array of Post Types
 622 * @return bool
 623 */
 624function is_singular( $post_types = '' ) {
 625	global $wp_query;
 626
 627	if ( ! isset( $wp_query ) ) {
 628		_doing_it_wrong( __FUNCTION__, __( 'Conditional query tags do not work before the query is run. Before then, they always return false.' ), '3.1' );
 629		return false;
 630	}
 631
 632	return $wp_query->is_singular( $post_types );
 633}
 634
 635/**
 636 * Is the query for a specific time?
 637 *
 638 * @see WP_Query::is_time()
 639 * @since 1.5.0
 640 * @uses $wp_query
 641 *
 642 * @return bool
 643 */
 644function is_time() {
 645	global $wp_query;
 646
 647	if ( ! isset( $wp_query ) ) {
 648		_doing_it_wrong( __FUNCTION__, __( 'Conditional query tags do not work before the query is run. Before then, they always return false.' ), '3.1' );
 649		return false;
 650	}
 651
 652	return $wp_query->is_time();
 653}
 654
 655/**
 656 * Is the query for a trackback endpoint call?
 657 *
 658 * @see WP_Query::is_trackback()
 659 * @since 1.5.0
 660 * @uses $wp_query
 661 *
 662 * @return bool
 663 */
 664function is_trackback() {
 665	global $wp_query;
 666
 667	if ( ! isset( $wp_query ) ) {
 668		_doing_it_wrong( __FUNCTION__, __( 'Conditional query tags do not work before the query is run. Before then, they always return false.' ), '3.1' );
 669		return false;
 670	}
 671
 672	return $wp_query->is_trackback();
 673}
 674
 675/**
 676 * Is the query for an existing year archive?
 677 *
 678 * @see WP_Query::is_year()
 679 * @since 1.5.0
 680 * @uses $wp_query
 681 *
 682 * @return bool
 683 */
 684function is_year() {
 685	global $wp_query;
 686
 687	if ( ! isset( $wp_query ) ) {
 688		_doing_it_wrong( __FUNCTION__, __( 'Conditional query tags do not work before the query is run. Before then, they always return false.' ), '3.1' );
 689		return false;
 690	}
 691
 692	return $wp_query->is_year();
 693}
 694
 695/**
 696 * Is the query a 404 (returns no results)?
 697 *
 698 * @see WP_Query::is_404()
 699 * @since 1.5.0
 700 * @uses $wp_query
 701 *
 702 * @return bool
 703 */
 704function is_404() {
 705	global $wp_query;
 706
 707	if ( ! isset( $wp_query ) ) {
 708		_doing_it_wrong( __FUNCTION__, __( 'Conditional query tags do not work before the query is run. Before then, they always return false.' ), '3.1' );
 709		return false;
 710	}
 711
 712	return $wp_query->is_404();
 713}
 714
 715/**
 716 * Is the query the main query?
 717 *
 718 * @since 3.3.0
 719 *
 720 * @return bool
 721 */
 722function is_main_query() {
 723	global $wp_query;
 724	return $wp_query->is_main_query();
 725}
 726
 727/*
 728 * The Loop. Post loop control.
 729 */
 730
 731/**
 732 * Whether current WordPress query has results to loop over.
 733 *
 734 * @see WP_Query::have_posts()
 735 * @since 1.5.0
 736 * @uses $wp_query
 737 *
 738 * @return bool
 739 */
 740function have_posts() {
 741	global $wp_query;
 742
 743	return $wp_query->have_posts();
 744}
 745
 746/**
 747 * Whether the caller is in the Loop.
 748 *
 749 * @since 2.0.0
 750 * @uses $wp_query
 751 *
 752 * @return bool True if caller is within loop, false if loop hasn't started or ended.
 753 */
 754function in_the_loop() {
 755	global $wp_query;
 756
 757	return $wp_query->in_the_loop;
 758}
 759
 760/**
 761 * Rewind the loop posts.
 762 *
 763 * @see WP_Query::rewind_posts()
 764 * @since 1.5.0
 765 * @uses $wp_query
 766 *
 767 * @return null
 768 */
 769function rewind_posts() {
 770	global $wp_query;
 771
 772	return $wp_query->rewind_posts();
 773}
 774
 775/**
 776 * Iterate the post index in the loop.
 777 *
 778 * @see WP_Query::the_post()
 779 * @since 1.5.0
 780 * @uses $wp_query
 781 */
 782function the_post() {
 783	global $wp_query;
 784
 785	$wp_query->the_post();
 786}
 787
 788/*
 789 * Comments loop.
 790 */
 791
 792/**
 793 * Whether there are comments to loop over.
 794 *
 795 * @see WP_Query::have_comments()
 796 * @since 2.2.0
 797 * @uses $wp_query
 798 *
 799 * @return bool
 800 */
 801function have_comments() {
 802	global $wp_query;
 803	return $wp_query->have_comments();
 804}
 805
 806/**
 807 * Iterate comment index in the comment loop.
 808 *
 809 * @see WP_Query::the_comment()
 810 * @since 2.2.0
 811 * @uses $wp_query
 812 *
 813 * @return object
 814 */
 815function the_comment() {
 816	global $wp_query;
 817	return $wp_query->the_comment();
 818}
 819
 820/*
 821 * WP_Query
 822 */
 823
 824/**
 825 * The WordPress Query class.
 826 *
 827 * @link http://codex.wordpress.org/Function_Reference/WP_Query Codex page.
 828 *
 829 * @since 1.5.0
 830 */
 831class WP_Query {
 832
 833	/**
 834	 * Query vars set by the user
 835	 *
 836	 * @since 1.5.0
 837	 * @access public
 838	 * @var array
 839	 */
 840	var $query;
 841
 842	/**
 843	 * Query vars, after parsing
 844	 *
 845	 * @since 1.5.0
 846	 * @access public
 847	 * @var array
 848	 */
 849	var $query_vars = array();
 850
 851	/**
 852	 * Taxonomy query, as passed to get_tax_sql()
 853	 *
 854	 * @since 3.1.0
 855	 * @access public
 856	 * @var object WP_Tax_Query
 857	 */
 858	var $tax_query;
 859
 860	/**
 861	 * Metadata query container
 862	 *
 863	 * @since 3.2.0
 864	 * @access public
 865	 * @var object WP_Meta_Query
 866	 */
 867	var $meta_query = false;
 868
 869	/**
 870	 * Holds the data for a single object that is queried.
 871	 *
 872	 * Holds the contents of a post, page, category, attachment.
 873	 *
 874	 * @since 1.5.0
 875	 * @access public
 876	 * @var object|array
 877	 */
 878	var $queried_object;
 879
 880	/**
 881	 * The ID of the queried object.
 882	 *
 883	 * @since 1.5.0
 884	 * @access public
 885	 * @var int
 886	 */
 887	var $queried_object_id;
 888
 889	/**
 890	 * Get post database query.
 891	 *
 892	 * @since 2.0.1
 893	 * @access public
 894	 * @var string
 895	 */
 896	var $request;
 897
 898	/**
 899	 * List of posts.
 900	 *
 901	 * @since 1.5.0
 902	 * @access public
 903	 * @var array
 904	 */
 905	var $posts;
 906
 907	/**
 908	 * The amount of posts for the current query.
 909	 *
 910	 * @since 1.5.0
 911	 * @access public
 912	 * @var int
 913	 */
 914	var $post_count = 0;
 915
 916	/**
 917	 * Index of the current item in the loop.
 918	 *
 919	 * @since 1.5.0
 920	 * @access public
 921	 * @var int
 922	 */
 923	var $current_post = -1;
 924
 925	/**
 926	 * Whether the loop has started and the caller is in the loop.
 927	 *
 928	 * @since 2.0.0
 929	 * @access public
 930	 * @var bool
 931	 */
 932	var $in_the_loop = false;
 933
 934	/**
 935	 * The current post ID.
 936	 *
 937	 * @since 1.5.0
 938	 * @access public
 939	 * @var object
 940	 */
 941	var $post;
 942
 943	/**
 944	 * The list of comments for current post.
 945	 *
 946	 * @since 2.2.0
 947	 * @access public
 948	 * @var array
 949	 */
 950	var $comments;
 951
 952	/**
 953	 * The amount of comments for the posts.
 954	 *
 955	 * @since 2.2.0
 956	 * @access public
 957	 * @var int
 958	 */
 959	var $comment_count = 0;
 960
 961	/**
 962	 * The index of the comment in the comment loop.
 963	 *
 964	 * @since 2.2.0
 965	 * @access public
 966	 * @var int
 967	 */
 968	var $current_comment = -1;
 969
 970	/**
 971	 * Current comment ID.
 972	 *
 973	 * @since 2.2.0
 974	 * @access public
 975	 * @var int
 976	 */
 977	var $comment;
 978
 979	/**
 980	 * The amount of found posts for the current query.
 981	 *
 982	 * If limit clause was not used, equals $post_count.
 983	 *
 984	 * @since 2.1.0
 985	 * @access public
 986	 * @var int
 987	 */
 988	var $found_posts = 0;
 989
 990	/**
 991	 * The amount of pages.
 992	 *
 993	 * @since 2.1.0
 994	 * @access public
 995	 * @var int
 996	 */
 997	var $max_num_pages = 0;
 998
 999	/**
1000	 * The amount of comment pages.
1001	 *
1002	 * @since 2.7.0
1003	 * @access public
1004	 * @var int
1005	 */
1006	var $max_num_comment_pages = 0;
1007
1008	/**
1009	 * Set if query is single post.
1010	 *
1011	 * @since 1.5.0
1012	 * @access public
1013	 * @var bool
1014	 */
1015	var $is_single = false;
1016
1017	/**
1018	 * Set if query is preview of blog.
1019	 *
1020	 * @since 2.0.0
1021	 * @access public
1022	 * @var bool
1023	 */
1024	var $is_preview = false;
1025
1026	/**
1027	 * Set if query returns a page.
1028	 *
1029	 * @since 1.5.0
1030	 * @access public
1031	 * @var bool
1032	 */
1033	var $is_page = false;
1034
1035	/**
1036	 * Set if query is an archive list.
1037	 *
1038	 * @since 1.5.0
1039	 * @access public
1040	 * @var bool
1041	 */
1042	var $is_archive = false;
1043
1044	/**
1045	 * Set if query is part of a date.
1046	 *
1047	 * @since 1.5.0
1048	 * @access public
1049	 * @var bool
1050	 */
1051	var $is_date = false;
1052
1053	/**
1054	 * Set if query contains a year.
1055	 *
1056	 * @since 1.5.0
1057	 * @access public
1058	 * @var bool
1059	 */
1060	var $is_year = false;
1061
1062	/**
1063	 * Set if query contains a month.
1064	 *
1065	 * @since 1.5.0
1066	 * @access public
1067	 * @var bool
1068	 */
1069	var $is_month = false;
1070
1071	/**
1072	 * Set if query contains a day.
1073	 *
1074	 * @since 1.5.0
1075	 * @access public
1076	 * @var bool
1077	 */
1078	var $is_day = false;
1079
1080	/**
1081	 * Set if query contains time.
1082	 *
1083	 * @since 1.5.0
1084	 * @access public
1085	 * @var bool
1086	 */
1087	var $is_time = false;
1088
1089	/**
1090	 * Set if query contains an author.
1091	 *
1092	 * @since 1.5.0
1093	 * @access public
1094	 * @var bool
1095	 */
1096	var $is_author = false;
1097
1098	/**
1099	 * Set if query contains category.
1100	 *
1101	 * @since 1.5.0
1102	 * @access public
1103	 * @var bool
1104	 */
1105	var $is_category = false;
1106
1107	/**
1108	 * Set if query contains tag.
1109	 *
1110	 * @since 2.3.0
1111	 * @access public
1112	 * @var bool
1113	 */
1114	var $is_tag = false;
1115
1116	/**
1117	 * Set if query contains taxonomy.
1118	 *
1119	 * @since 2.5.0
1120	 * @access public
1121	 * @var bool
1122	 */
1123	var $is_tax = false;
1124
1125	/**
1126	 * Set if query was part of a search result.
1127	 *
1128	 * @since 1.5.0
1129	 * @access public
1130	 * @var bool
1131	 */
1132	var $is_search = false;
1133
1134	/**
1135	 * Set if query is feed display.
1136	 *
1137	 * @since 1.5.0
1138	 * @access public
1139	 * @var bool
1140	 */
1141	var $is_feed = false;
1142
1143	/**
1144	 * Set if query is comment feed display.
1145	 *
1146	 * @since 2.2.0
1147	 * @access public
1148	 * @var bool
1149	 */
1150	var $is_comment_feed = false;
1151
1152	/**
1153	 * Set if query is trackback.
1154	 *
1155	 * @since 1.5.0
1156	 * @access public
1157	 * @var bool
1158	 */
1159	var $is_trackback = false;
1160
1161	/**
1162	 * Set if query is blog homepage.
1163	 *
1164	 * @since 1.5.0
1165	 * @access public
1166	 * @var bool
1167	 */
1168	var $is_home = false;
1169
1170	/**
1171	 * Set if query couldn't found anything.
1172	 *
1173	 * @since 1.5.0
1174	 * @access public
1175	 * @var bool
1176	 */
1177	var $is_404 = false;
1178
1179	/**
1180	 * Set if query is within comments popup window.
1181	 *
1182	 * @since 1.5.0
1183	 * @access public
1184	 * @var bool
1185	 */
1186	var $is_comments_popup = false;
1187
1188	/**
1189	 * Set if query is paged
1190	 *
1191	 * @since 1.5.0
1192	 * @access public
1193	 * @var bool
1194	 */
1195	var $is_paged = false;
1196
1197	/**
1198	 * Set if query is part of administration page.
1199	 *
1200	 * @since 1.5.0
1201	 * @access public
1202	 * @var bool
1203	 */
1204	var $is_admin = false;
1205
1206	/**
1207	 * Set if query is an attachment.
1208	 *
1209	 * @since 2.0.0
1210	 * @access public
1211	 * @var bool
1212	 */
1213	var $is_attachment = false;
1214
1215	/**
1216	 * Set if is single, is a page, or is an attachment.
1217	 *
1218	 * @since 2.1.0
1219	 * @access public
1220	 * @var bool
1221	 */
1222	var $is_singular = false;
1223
1224	/**
1225	 * Set if query is for robots.
1226	 *
1227	 * @since 2.1.0
1228	 * @access public
1229	 * @var bool
1230	 */
1231	var $is_robots = false;
1232
1233	/**
1234	 * Set if query contains posts.
1235	 *
1236	 * Basically, the homepage if the option isn't set for the static homepage.
1237	 *
1238	 * @since 2.1.0
1239	 * @access public
1240	 * @var bool
1241	 */
1242	var $is_posts_page = false;
1243
1244	/**
1245	 * Set if query is for a post type archive.
1246	 *
1247	 * @since 3.1.0
1248	 * @access public
1249	 * @var bool
1250	 */
1251	var $is_post_type_archive = false;
1252
1253	/**
1254	 * Stores the ->query_vars state like md5(serialize( $this->query_vars ) ) so we know
1255	 * whether we have to re-parse because something has changed
1256	 *
1257	 * @since 3.1.0
1258	 * @access private
1259	 */
1260	var $query_vars_hash = false;
1261
1262	/**
1263	 * Whether query vars have changed since the initial parse_query() call. Used to catch modifications to query vars made
1264	 * via pre_get_posts hooks.
1265	 *
1266	 * @since 3.1.1
1267	 * @access private
1268	 */
1269	var $query_vars_changed = true;
1270
1271	/**
1272	 * Set if post thumbnails are cached
1273	 *
1274	 * @since 3.2.0
1275	 * @access public
1276	 * @var bool
1277	 */
1278	 var $thumbnails_cached = false;
1279
1280	/**
1281	 * Resets query flags to false.
1282	 *
1283	 * The query flags are what page info WordPress was able to figure out.
1284	 *
1285	 * @since 2.0.0
1286	 * @access private
1287	 */
1288	function init_query_flags() {
1289		$this->is_single = false;
1290		$this->is_preview = false;
1291		$this->is_page = false;
1292		$this->is_archive = false;
1293		$this->is_date = false;
1294		$this->is_year = false;
1295		$this->is_month = false;
1296		$this->is_day = false;
1297		$this->is_time = false;
1298		$this->is_author = false;
1299		$this->is_category = false;
1300		$this->is_tag = false;
1301		$this->is_tax = false;
1302		$this->is_search = false;
1303		$this->is_feed = false;
1304		$this->is_comment_feed = false;
1305		$this->is_trackback = false;
1306		$this->is_home = false;
1307		$this->is_404 = false;
1308		$this->is_comments_popup = false;
1309		$this->is_paged = false;
1310		$this->is_admin = false;
1311		$this->is_attachment = false;
1312		$this->is_singular = false;
1313		$this->is_robots = false;
1314		$this->is_posts_page = false;
1315		$this->is_post_type_archive = false;
1316	}
1317
1318	/**
1319	 * Initiates object properties and sets default values.
1320	 *
1321	 * @since 1.5.0
1322	 * @access public
1323	 */
1324	function init() {
1325		unset($this->posts);
1326		unset($this->query);
1327		$this->query_vars = array();
1328		unset($this->queried_object);
1329		unset($this->queried_object_id);
1330		$this->post_count = 0;
1331		$this->current_post = -1;
1332		$this->in_the_loop = false;
1333		unset( $this->request );
1334		unset( $this->post );
1335		unset( $this->comments );
1336		unset( $this->comment );
1337		$this->comment_count = 0;
1338		$this->current_comment = -1;
1339		$this->found_posts = 0;
1340		$this->max_num_pages = 0;
1341		$this->max_num_comment_pages = 0;
1342
1343		$this->init_query_flags();
1344	}
1345
1346	/**
1347	 * Reparse the query vars.
1348	 *
1349	 * @since 1.5.0
1350	 * @access public
1351	 */
1352	function parse_query_vars() {
1353		$this->parse_query();
1354	}
1355
1356	/**
1357	 * Fills in the query variables, which do not exist within the parameter.
1358	 *
1359	 * @since 2.1.0
1360	 * @access public
1361	 *
1362	 * @param array $array Defined query variables.
1363	 * @return array Complete query variables with undefined ones filled in empty.
1364	 */
1365	function fill_query_vars($array) {
1366		$keys = array(
1367			'error'
1368			, 'm'
1369			, 'p'
1370			, 'post_parent'
1371			, 'subpost'
1372			, 'subpost_id'
1373			, 'attachment'
1374			, 'attachment_id'
1375			, 'name'
1376			, 'static'
1377			, 'pagename'
1378			, 'page_id'
1379			, 'second'
1380			, 'minute'
1381			, 'hour'
1382			, 'day'
1383			, 'monthnum'
1384			, 'year'
1385			, 'w'
1386			, 'category_name'
1387			, 'tag'
1388			, 'cat'
1389			, 'tag_id'
1390			, 'author_name'
1391			, 'feed'
1392			, 'tb'
1393			, 'paged'
1394			, 'comments_popup'
1395			, 'meta_key'
1396			, 'meta_value'
1397			, 'preview'
1398			, 's'
1399			, 'sentence'
1400			, 'fields'
1401			, 'menu_order'
1402		);
1403
1404		foreach ( $keys as $key ) {
1405			if ( !isset($array[$key]) )
1406				$array[$key] = '';
1407		}
1408
1409		$array_keys = array('category__in', 'category__not_in', 'category__and', 'post__in', 'post__not_in',
1410			'tag__in', 'tag__not_in', 'tag__and', 'tag_slug__in', 'tag_slug__and');
1411
1412		foreach ( $array_keys as $key ) {
1413			if ( !isset($array[$key]) )
1414				$array[$key] = array();
1415		}
1416		return $array;
1417	}
1418
1419	/**
1420	 * Parse a query string and set query type booleans.
1421	 *
1422	 * @since 1.5.0
1423	 * @access public
1424	 *
1425	 * @param string|array $query Optional query.
1426	 */
1427	function parse_query( $query =  '' ) {
1428		if ( ! empty( $query ) ) {
1429			$this->init();
1430			$this->query = $this->query_vars = wp_parse_args( $query );
1431		} elseif ( ! isset( $this->query ) ) {
1432			$this->query = $this->query_vars;
1433		}
1434
1435		$this->query_vars = $this->fill_query_vars($this->query_vars);
1436		$qv = &$this->query_vars;
1437		$this->query_vars_changed = true;
1438
1439		if ( ! empty($qv['robots']) )
1440			$this->is_robots = true;
1441
1442		$qv['p'] =  absint($qv['p']);
1443		$qv['page_id'] =  absint($qv['page_id']);
1444		$qv['year'] = absint($qv['year']);
1445		$qv['monthnum'] = absint($qv['monthnum']);
1446		$qv['day'] = absint($qv['day']);
1447		$qv['w'] = absint($qv['w']);
1448		$qv['m'] = absint($qv['m']);
1449		$qv['paged'] = absint($qv['paged']);
1450		$qv['cat'] = preg_replace( '|[^0-9,-]|', '', $qv['cat'] ); // comma separated list of positive or negative integers
1451		$qv['pagename'] = trim( $qv['pagename'] );
1452		$qv['name'] = trim( $qv['name'] );
1453		if ( '' !== $qv['hour'] ) $qv['hour'] = absint($qv['hour']);
1454		if ( '' !== $qv['minute'] ) $qv['minute'] = absint($qv['minute']);
1455		if ( '' !== $qv['second'] ) $qv['second'] = absint($qv['second']);
1456		if ( '' !== $qv['menu_order'] ) $qv['menu_order'] = absint($qv['menu_order']);
1457
1458		// Compat. Map subpost to attachment.
1459		if ( '' != $qv['subpost'] )
1460			$qv['attachment'] = $qv['subpost'];
1461		if ( '' != $qv['subpost_id'] )
1462			$qv['attachment_id'] = $qv['subpost_id'];
1463
1464		$qv['attachment_id'] = absint($qv['attachment_id']);
1465
1466		if ( ('' != $qv['attachment']) || !empty($qv['attachment_id']) ) {
1467			$this->is_single = true;
1468			$this->is_attachment = true;
1469		} elseif ( '' != $qv['name'] ) {
1470			$this->is_single = true;
1471		} elseif ( $qv['p'] ) {
1472			$this->is_single = true;
1473		} elseif ( ('' !== $qv['hour']) && ('' !== $qv['minute']) &&('' !== $qv['second']) && ('' != $qv['year']) && ('' != $qv['monthnum']) && ('' != $qv['day']) ) {
1474			// If year, month, day, hour, minute, and second are set, a single
1475			// post is being queried.
1476			$this->is_single = true;
1477		} elseif ( '' != $qv['static'] || '' != $qv['pagename'] || !empty($qv['page_id']) ) {
1478			$this->is_page = true;
1479			$this->is_single = false;
1480		} else {
1481		// Look for archive queries. Dates, categories, authors, search, post type archives.
1482
1483			if ( !empty($qv['s']) ) {
1484				$this->is_search = true;
1485			}
1486
1487			if ( '' !== $qv['second'] ) {
1488				$this->is_time = true;
1489				$this->is_date = true;
1490			}
1491
1492			if ( '' !== $qv['minute'] ) {
1493				$this->is_time = true;
1494				$this->is_date = true;
1495			}
1496
1497			if ( '' !== $qv['hour'] ) {
1498				$this->is_time = true;
1499				$this->is_date = true;
1500			}
1501
1502			if ( $qv['day'] ) {
1503				if ( ! $this->is_date ) {
1504					$this->is_day = true;
1505					$this->is_date = true;
1506				}
1507			}
1508
1509			if ( $qv['monthnum'] ) {
1510				if ( ! $this->is_date ) {
1511					$this->is_month = true;
1512					$this->is_date = true;
1513				}
1514			}
1515
1516			if ( $qv['year'] ) {
1517				if ( ! $this->is_date ) {
1518					$this->is_year = true;
1519					$this->is_date = true;
1520				}
1521			}
1522
1523			if ( $qv['m'] ) {
1524				$this->is_date = true;
1525				if ( strlen($qv['m']) > 9 ) {
1526					$this->is_time = true;
1527				} else if ( strlen($qv['m']) > 7 ) {
1528					$this->is_day = true;
1529				} else if ( strlen($qv['m']) > 5 ) {
1530					$this->is_month = true;
1531				} else {
1532					$this->is_year = true;
1533				}
1534			}
1535
1536			if ( '' != $qv['w'] ) {
1537				$this->is_date = true;
1538			}
1539
1540			$this->query_vars_hash = false;
1541			$this->parse_tax_query( $qv );
1542
1543			foreach ( $this->tax_query->queries as $tax_query ) {
1544				if ( 'NOT IN' != $tax_query['operator'] ) {
1545					switch ( $tax_query['taxonomy'] ) {
1546						case 'category':
1547							$this->is_category = true;
1548							break;
1549						case 'post_tag':
1550							$this->is_tag = true;
1551							break;
1552						default:
1553							$this->is_tax = true;
1554					}
1555				}
1556			}
1557			unset( $tax_query );
1558
1559			if ( empty($qv['author']) || ($qv['author'] == '0') ) {
1560				$this->is_author = false;
1561			} else {
1562				$this->is_author = true;
1563			}
1564
1565			if ( '' != $qv['author_name'] )
1566				$this->is_author = true;
1567
1568			if ( !empty( $qv['post_type'] ) && ! is_array( $qv['post_type'] ) ) {
1569				$post_type_obj = get_post_type_object( $qv['post_type'] );
1570				if ( ! empty( $post_type_obj->has_archive ) )
1571					$this->is_post_type_archive = true;
1572			}
1573
1574			if ( $this->is_post_type_archive || $this->is_date || $this->is_author || $this->is_category || $this->is_tag || $this->is_tax )
1575				$this->is_archive = true;
1576		}
1577
1578		if ( '' != $qv['feed'] )
1579			$this->is_feed = true;
1580
1581		if ( '' != $qv['tb'] )
1582			$this->is_trackback = true;
1583
1584		if ( '' != $qv['paged'] && ( intval($qv['paged']) > 1 ) )
1585			$this->is_paged = true;
1586
1587		if ( '' != $qv['comments_popup'] )
1588			$this->is_comments_popup = true;
1589
1590		// if we're previewing inside the write screen
1591		if ( '' != $qv['preview'] )
1592			$this->is_preview = true;
1593
1594		if ( is_admin() )
1595			$this->is_admin = true;
1596
1597		if ( false !== strpos($qv['feed'], 'comments-') ) {
1598			$qv['feed'] = str_replace('comments-', '', $qv['feed']);
1599			$qv['withcomments'] = 1;
1600		}
1601
1602		$this->is_singular = $this->is_single || $this->is_page || $this->is_attachment;
1603
1604		if ( $this->is_feed && ( !empty($qv['withcomments']) || ( empty($qv['withoutcomments']) && $this->is_singular ) ) )
1605			$this->is_comment_feed = true;
1606
1607		if ( !( $this->is_singular || $this->is_archive || $this->is_search || $this->is_feed || $this->is_trackback || $this->is_404 || $this->is_admin || $this->is_comments_popup || $this->is_robots ) )
1608			$this->is_home = true;
1609
1610		// Correct is_* for page_on_front and page_for_posts
1611		if ( $this->is_home && 'page' == get_option('show_on_front') && get_option('page_on_front') ) {
1612			$_query = wp_parse_args($this->query);
1613			// pagename can be set and empty depending on matched rewrite rules. Ignore an empty pagename.
1614			if ( isset($_query['pagename']) && '' == $_query['pagename'] )
1615				unset($_query['pagename']);
1616			if ( empty($_query) || !array_diff( array_keys($_query), array('preview', 'page', 'paged', 'cpage') ) ) {
1617				$this->is_page = true;
1618				$this->is_home = false;
1619				$qv['page_id'] = get_option('page_on_front');
1620				// Correct <!--nextpage--> for page_on_front
1621				if ( !empty($qv['paged']) ) {
1622					$qv['page'] = $qv['paged'];
1623					unset($qv['paged']);
1624				}
1625			}
1626		}
1627
1628		if ( '' != $qv['pagename'] ) {
1629			$this->queried_object = get_page_by_path($qv['pagename']);
1630			if ( !empty($this->queried_object) )
1631				$this->queried_object_id = (int) $this->queried_object->ID;
1632			else
1633				unset($this->queried_object);
1634
1635			if  ( 'page' == get_option('show_on_front') && isset($this->queried_object_id) && $this->queried_object_id == get_option('page_for_posts') ) {
1636				$this->is_page = false;
1637				$this->is_home = true;
1638				$this->is_posts_page = true;
1639			}
1640		}
1641
1642		if ( $qv['page_id'] ) {
1643			if  ( 'page' == get_option('show_on_front') && $qv['page_id'] == get_option('page_for_posts') ) {
1644				$this->is_page = false;
1645				$this->is_home = true;
1646				$this->is_posts_page = true;
1647			}
1648		}
1649
1650		if ( !empty($qv['post_type']) ) {
1651			if ( is_array($qv['post_type']) )
1652				$qv['post_type'] = array_map('sanitize_key', $qv['post_type']);
1653			else
1654				$qv['post_type'] = sanitize_key($qv['post_type']);
1655		}
1656
1657		if ( ! empty( $qv['post_status'] ) ) {
1658			if ( is_array( $qv['post_status'] ) )
1659				$qv['post_status'] = array_map('sanitize_key', $qv['post_status']);
1660			else
1661				$qv['post_status'] = preg_replace('|[^a-z0-9_,-]|', '', $qv['post_status']);
1662		}
1663
1664		if ( $this->is_posts_page && ( ! isset($qv['withcomments']) || ! $qv['withcomments'] ) )
1665			$this->is_comment_feed = false;
1666
1667		$this->is_singular = $this->is_single || $this->is_page || $this->is_attachment;
1668		// Done correcting is_* for page_on_front and page_for_posts
1669
1670		if ( '404' == $qv['error'] )
1671			$this->set_404();
1672
1673		$this->query_vars_hash = md5( serialize( $this->query_vars ) );
1674		$this->query_vars_changed = false;
1675
1676		do_action_ref_array('parse_query', array(&$this));
1677	}
1678
1679	/*
1680	 * Parses various taxonomy related query vars.
1681	 *
1682	 * @access protected
1683	 * @since 3.1.0
1684	 *
1685	 * @param array &$q The query variables
1686	 */
1687	function parse_tax_query( &$q ) {
1688		if ( ! empty( $q['tax_query'] ) && is_array( $q['tax_query'] ) ) {
1689			$tax_query = $q['tax_query'];
1690		} else {
1691			$tax_query = array();
1692		}
1693
1694		if ( !empty($q['taxonomy']) && !empty($q['term']) ) {
1695			$tax_query[] = array(
1696				'taxonomy' => $q['taxonomy'],
1697				'terms' => array( $q['term'] ),
1698				'field' => 'slug',
1699			);
1700		}
1701
1702		foreach ( $GLOBALS['wp_taxonomies'] as $taxonomy => $t ) {
1703			if ( 'post_tag' == $taxonomy )
1704				continue;	// Handled further down in the $q['tag'] block
1705
1706			if ( $t->query_var && !empty( $q[$t->query_var] ) ) {
1707				$tax_query_defaults = array(
1708					'taxonomy' => $taxonomy,
1709					'field' => 'slug',
1710				);
1711
1712 				if ( isset( $t->rewrite['hierarchical'] ) && $t->rewrite['hierarchical'] ) {
1713					$q[$t->query_var] = wp_basename( $q[$t->query_var] );
1714				}
1715
1716				$term = $q[$t->query_var];
1717
1718				if ( strpos($term, '+') !== false ) {
1719					$terms = preg_split( '/[+]+/', $term );
1720					foreach ( $terms as $term ) {
1721						$tax_query[] = array_merge( $tax_query_defaults, array(
1722							'terms' => array( $term )
1723						) );
1724					}
1725				} else {
1726					$tax_query[] = array_merge( $tax_query_defaults, array(
1727						'terms' => preg_split( '/[,]+/', $term )
1728					) );
1729				}
1730			}
1731		}
1732
1733		// Category stuff
1734		if ( !empty($q['cat']) && '0' != $q['cat'] && !$this->is_singular && $this->query_vars_changed ) {
1735			$q['cat'] = ''.urldecode($q['cat']).'';
1736			$q['cat'] = addslashes_gpc($q['cat']);
1737			$cat_array = preg_split('/[,\s]+/', $q['cat']);
1738			$q['cat'] = '';
1739			$req_cats = array();
1740			foreach ( (array) $cat_array as $cat ) {
1741				$cat = intval($cat);
1742				$req_cats[] = $cat;
1743				$in = ($cat > 0);
1744				$cat = abs($cat);
1745				if ( $in ) {
1746					$q['category__in'][] = $cat;
1747					$q['category__in'] = array_merge( $q['category__in'], get_term_children($cat, 'category') );
1748				} else {
1749					$q['category__not_in'][] = $cat;
1750					$q['category__not_in'] = array_merge( $q['category__not_in'], get_term_children($cat, 'category') );
1751				}
1752			}
1753			$q['cat'] = implode(',', $req_cats);
1754		}
1755
1756		if ( !empty($q['category__in']) ) {
1757			$q['category__in'] = array_map('absint', array_unique( (array) $q['category__in'] ) );
1758			$tax_query[] = array(
1759				'taxonomy' => 'category',
1760				'terms' => $q['category__in'],
1761				'field' => 'term_id',
1762				'include_children' => false
1763			);
1764		}
1765
1766		if ( !empty($q['category__not_in']) ) {
1767			$q['category__not_in'] = array_map('absint', array_unique( (array) $q['category__not_in'] ) );
1768			$tax_query[] = array(
1769				'taxonomy' => 'category',
1770				'terms' => $q['category__not_in'],
1771				'operator' => 'NOT IN',
1772				'include_children' => false
1773			);
1774		}
1775
1776		if ( !empty($q['category__and']) ) {
1777			$q['category__and'] = array_map('absint', array_unique( (array) $q['category__and'] ) );
1778			$tax_query[] = array(
1779				'taxonomy' => 'category',
1780				'terms' => $q['category__and'],
1781				'field' => 'term_id',
1782				'operator' => 'AND',
1783				'include_children' => false
1784			);
1785		}
1786
1787		// Tag stuff
1788		if ( '' != $q['tag'] && !$this->is_singular && $this->query_vars_changed ) {
1789			if ( strpos($q['tag'], ',') !== false ) {
1790				$tags = preg_split('/[,\r\n\t ]+/', $q['tag']);
1791				foreach ( (array) $tags as $tag ) {
1792					$tag = sanitize_term_field('slug', $tag, 0, 'post_tag', 'db');
1793					$q['tag_slug__in'][] = $tag;
1794				}
1795			} else if ( preg_match('/[+\r\n\t ]+/', $q['tag']) || !empty($q['cat']) ) {
1796				$tags = preg_split('/[+\r\n\t ]+/', $q['tag']);
1797				foreach ( (array) $tags as $tag ) {
1798					$tag = sanitize_term_field('slug', $tag, 0, 'post_tag', 'db');
1799					$q['tag_slug__and'][] = $tag;
1800				}
1801			} else {
1802				$q['tag'] = sanitize_term_field('slug', $q['tag'], 0, 'post_tag', 'db');
1803				$q['tag_slug__in'][] = $q['tag'];
1804			}
1805		}
1806
1807		if ( !empty($q['tag_id']) ) {
1808			$q['tag_id'] = absint( $q['tag_id'] );
1809			$tax_query[] = array(
1810				'taxonomy' => 'post_tag',
1811				'terms' => $q['tag_id']
1812			);
1813		}
1814
1815		if ( !empty($q['tag__in']) ) {
1816			$q['tag__in'] = array_map('absint', array_unique( (array) $q['tag__in'] ) );
1817			$tax_query[] = array(
1818				'taxonomy' => 'post_tag',
1819				'terms' => $q['tag__in']
1820			);
1821		}
1822
1823		if ( !empty($q['tag__not_in']) ) {
1824			$q['tag__not_in'] = array_map('absint', array_unique( (array) $q['tag__not_in'] ) );
1825			$tax_query[] = array(
1826				'taxonomy' => 'post_tag',
1827				'terms' => $q['tag__not_in'],
1828				'operator' => 'NOT IN'
1829			);
1830		}
1831
1832		if ( !empty($q['tag__and']) ) {
1833			$q['tag__and'] = array_map('absint', array_unique( (array) $q['tag__and'] ) );
1834			$tax_query[] = array(
1835				'taxonomy' => 'post_tag',
1836				'terms' => $q['tag__and'],
1837				'operator' => 'AND'
1838			);
1839		}
1840
1841		if ( !empty($q['tag_slug__in']) ) {
1842			$q['tag_slug__in'] = array_map('sanitize_title_for_query', array_unique( (array) $q['tag_slug__in'] ) );
1843			$tax_query[] = array(
1844				'taxonomy' => 'post_tag',
1845				'terms' => $q['tag_slug__in'],
1846				'field' => 'slug'
1847			);
1848		}
1849
1850		if ( !empty($q['tag_slug__and']) ) {
1851			$q['tag_slug__and'] = array_map('sanitize_title_for_query', array_unique( (array) $q['tag_slug__and'] ) );
1852			$tax_query[] = array(
1853				'taxonomy' => 'post_tag',
1854				'terms' => $q['tag_slug__and'],
1855				'field' => 'slug',
1856				'operator' => 'AND'
1857			);
1858		}
1859
1860		$this->tax_query = new WP_Tax_Query( $tax_query );
1861	}
1862
1863	/**
1864	 * Sets the 404 property and saves whether query is feed.
1865	 *
1866	 * @since 2.0.0
1867	 * @access public
1868	 */
1869	function set_404() {
1870		$is_feed = $this->is_feed;
1871
1872		$this->init_query_flags();
1873		$this->is_404 = true;
1874
1875		$this->is_feed = $is_feed;
1876	}
1877
1878	/**
1879	 * Retrieve query variable.
1880	 *
1881	 * @since 1.5.0
1882	 * @access public
1883	 *
1884	 * @param string $query_var Query variable key.
1885	 * @return mixed
1886	 */
1887	function get($query_var) {
1888		if ( isset($this->query_vars[$query_var]) )
1889			return $this->query_vars[$query_var];
1890
1891		return '';
1892	}
1893
1894	/**
1895	 * Set query variable.
1896	 *
1897	 * @since 1.5.0
1898	 * @access public
1899	 *
1900	 * @param string $query_var Query variable key.
1901	 * @param mixed $value Query variable value.
1902	 */
1903	function set($query_var, $value) {
1904		$this->query_vars[$query_var] = $value;
1905	}
1906
1907	/**
1908	 * Retrieve the posts based on query variables.
1909	 *
1910	 * There are a few filters and actions that can be used to modify the post
1911	 * database query.
1912	 *
1913	 * @since 1.5.0
1914	 * @access public
1915	 * @uses do_action_ref_array() Calls 'pre_get_posts' hook before retrieving posts.
1916	 *
1917	 * @return array List of posts.
1918	 */
1919	function get_posts() {
1920		global $wpdb, $user_ID, $_wp_using_ext_object_cache;
1921
1922		$this->parse_query();
1923
1924		do_action_ref_array('pre_get_posts', array(&$this));
1925
1926		// Shorthand.
1927		$q = &$this->query_vars;
1928
1929		// Fill again in case pre_get_posts unset some vars.
1930		$q = $this->fill_query_vars($q);
1931
1932		// Parse meta query
1933		$this->meta_query = new WP_Meta_Query();
1934		$this->meta_query->parse_query_vars( $q );
1935
1936		// Set a flag if a pre_get_posts hook changed the query vars.
1937		$hash = md5( serialize( $this->query_vars ) );
1938		if ( $hash != $this->query_vars_hash ) {
1939			$this->query_vars_changed = true;
1940			$this->query_vars_hash = $hash;
1941		}
1942		unset($hash);
1943
1944		// First let's clear some variables
1945		$distinct = '';
1946		$whichauthor = '';
1947		$whichmimetype = '';
1948		$where = '';
1949		$limits = '';
1950		$join = '';
1951		$search = '';
1952		$groupby = '';
1953		$fields = '';
1954		$post_status_join = false;
1955		$page = 1;
1956
1957		if ( isset( $q['caller_get_posts'] ) ) {
1958			_deprecated_argument( 'WP_Query', '3.1', __( '"caller_get_posts" is deprecated. Use "ignore_sticky_posts" instead.' ) );
1959			if ( !isset( $q['ignore_sticky_posts'] ) )
1960				$q['ignore_sticky_posts'] = $q['caller_get_posts'];
1961		}
1962
1963		if ( !isset( $q['ignore_sticky_posts'] ) )
1964			$q['ignore_sticky_posts'] = false;
1965
1966		if ( !isset($q['suppress_filters']) )
1967			$q['suppress_filters'] = false;
1968
1969		if ( !isset($q['cache_results']) ) {
1970			if ( $_wp_using_ext_object_cache )
1971				$q['cache_results'] = false;
1972			else
1973				$q['cache_results'] = true;
1974		}
1975
1976		if ( !isset($q['update_post_term_cache']) )
1977			$q['update_post_term_cache'] = true;
1978
1979		if ( !isset($q['update_post_meta_cache']) )
1980			$q['update_post_meta_cache'] = true;
1981
1982		if ( !isset($q['post_type']) ) {
1983			if ( $this->is_search )
1984				$q['post_type'] = 'any';
1985			else
1986				$q['post_type'] = '';
1987		}
1988		$post_type = $q['post_type'];
1989		if ( !isset($q['posts_per_page']) || $q['posts_per_page'] == 0 )
1990			$q['posts_per_page'] = get_option('posts_per_page');
1991		if ( isset($q['showposts']) && $q['showposts'] ) {
1992			$q['showposts'] = (int) $q['showposts'];
1993			$q['posts_per_page'] = $q['showposts'];
1994		}
1995		if ( (isset($q['posts_per_archive_page']) && $q['posts_per_archive_page'] != 0) && ($this->is_archive || $this->is_search) )
1996			$q['posts_per_page'] = $q['posts_per_archive_page'];
1997		if ( !isset($q['nopaging']) ) {
1998			if ( $q['posts_per_page'] == -1 ) {
1999				$q['nopaging'] = true;
2000			} else {
2001				$q['nopaging'] = false;
2002			}
2003		}
2004		if ( $this->is_feed ) {
2005			$q['posts_per_page'] = get_option('posts_per_rss');
2006			$q['nopaging'] = false;
2007		}
2008		$q['posts_per_page'] = (int) $q['posts_per_page'];
2009		if ( $q['posts_per_page'] < -1 )
2010			$q['posts_per_page'] = abs($q['posts_per_page']);
2011		else if ( $q['posts_per_page'] == 0 )
2012			$q['posts_per_page'] = 1;
2013
2014		if ( !isset($q['comments_per_page']) || $q['comments_per_page'] == 0 )
2015			$q['comments_per_page'] = get_option('comments_per_page');
2016
2017		if ( $this->is_home && (empty($this->query) || $q['preview'] == 'true') && ( 'page' == get_option('show_on_front') ) && get_option('page_on_front') ) {
2018			$this->is_page = true;
2019			$this->is_home = false;
2020			$q['page_id'] = get_option('page_on_front');
2021		}
2022
2023		if ( isset($q['page']) ) {
2024			$q['page'] = trim($q['page'], '/');
2025			$q['page'] = absint($q['page']);
2026		}
2027
2028		// If true, forcibly turns off SQL_CALC_FOUND_ROWS even when limits are present.
2029		if ( isset($q['no_found_rows']) )
2030			$q['no_found_rows'] = (bool) $q['no_found_rows'];
2031		else
2032			$q['no_found_rows'] = false;
2033
2034		switch ( $q['fields'] ) {
2035			case 'ids':
2036				$fields = "$wpdb->posts.ID";
2037				break;
2038			case 'id=>parent':
2039				$fields = "$wpdb->posts.ID, $wpdb->posts.post_parent";
2040				break;
2041			default:
2042				$fields = "$wpdb->posts.*";
2043		}
2044
2045		if ( '' !== $q['menu_order'] )
2046			$where .= " AND $wpdb->posts.menu_order = " . $q['menu_order'];
2047
2048		// If a month is specified in the querystring, load that month
2049		if ( $q['m'] ) {
2050			$q['m'] = '' . preg_replace('|[^0-9]|', '', $q['m']);
2051			$where .= " AND YEAR($wpdb->posts.post_date)=" . substr($q['m'], 0, 4);
2052			if ( strlen($q['m']) > 5 )
2053				$where .= " AND MONTH($wpdb->posts.post_date)=" . substr($q['m'], 4, 2);
2054			if ( strlen($q['m']) > 7 )
2055				$where .= " AND DAYOFMONTH($wpdb->posts.post_date)=" . substr($q['m'], 6, 2);
2056			if ( strlen($q['m']) > 9 )
2057				$where .= " AND HOUR($wpdb->posts.post_date)=" . substr($q['m'], 8, 2);
2058			if ( strlen($q['m']) > 11 )
2059				$where .= " AND MINUTE($wpdb->posts.post_date)=" . substr($q['m'], 10, 2);
2060			if ( strlen($q['m']) > 13 )
2061				$where .= " AND SECOND($wpdb->posts.post_date)=" . substr($q['m'], 12, 2);
2062		}
2063
2064		if ( '' !== $q['hour'] )
2065			$where .= " AND HOUR($wpdb->posts.post_date)='" . $q['hour'] . "'";
2066
2067		if ( '' !== $q['minute'] )
2068			$where .= " AND MINUTE($wpdb->posts.post_date)='" . $q['minute'] . "'";
2069
2070		if ( '' !== $q['second'] )
2071			$where .= " AND SECOND($wpdb->posts.post_date)='" . $q['second'] . "'";
2072
2073		if ( $q['year'] )
2074			$where .= " AND YEAR($wpdb->posts.post_date)='" . $q['year'] . "'";
2075
2076		if ( $q['monthnum'] )
2077			$where .= " AND MONTH($wpdb->posts.post_date)='" . $q['monthnum'] . "'";
2078
2079		if ( $q['day'] )
2080			$where .= " AND DAYOFMONTH($wpdb->posts.post_date)='" . $q['day'] . "'";
2081
2082		// If we've got a post_type AND its not "any" post_type.
2083		if ( !empty($q['post_type']) && 'any' != $q['post_type'] ) {
2084			foreach ( (array)$q['post_type'] as $_post_type ) {
2085				$ptype_obj = get_post_type_object($_post_type);
2086				if ( !$ptype_obj || !$ptype_obj->query_var || empty($q[ $ptype_obj->query_var ]) )
2087					continue;
2088
2089				if ( ! $ptype_obj->hierarchical || strpos($q[ $ptype_obj->query_var ], '/') === false ) {
2090					// Non-hierarchical post_types & parent-level-hierarchical post_types can directly use 'name'
2091					$q['name'] = $q[ $ptype_obj->query_var ];
2092				} else {
2093					// Hierarchical post_types will operate through the
2094					$q['pagename'] = $q[ $ptype_obj->query_var ];
2095					$q['name'] = '';
2096				}
2097
2098				// Only one request for a slug is possible, this is why name & pagename are overwritten above.
2099				break;
2100			} //end foreach
2101			unset($ptype_obj);
2102		}
2103
2104		if ( '' != $q['name'] ) {
2105			$q['name'] = sanitize_title_for_query( $q['name'] );
2106			$where .= " AND $wpdb->posts.post_name = '" . $q['name'] . "'";
2107		} elseif ( '' != $q['pagename'] ) {
2108			if ( isset($this->queried_object_id) ) {
2109				$reqpage = $this->queried_object_id;
2110			} else {
2111				if ( 'page' != $q['post_type'] ) {
2112					foreach ( (array)$q['post_type'] as $_post_type ) {
2113						$ptype_obj = get_post_type_object($_post_type);
2114						if ( !$ptype_obj || !$ptype_obj->hierarchical )
2115							continue;
2116
2117						$reqpage = get_page_by_path($q['pagename'], OBJECT, $_post_type);
2118						if ( $reqpage )
2119							break;
2120					}
2121					unset($ptype_obj);
2122				} else {
2123					$reqpage = get_page_by_path($q['pagename']);
2124				}
2125				if ( !empty($reqpage) )
2126					$reqpage = $reqpage->ID;
2127				else
2128					$reqpage = 0;
2129			}
2130
2131			$page_for_posts = get_option('page_for_posts');
2132			if  ( ('page' != get_option('show_on_front') ) || empty($page_for_posts) || ( $reqpage != $page_for_posts ) ) {
2133				$q['pagename'] = sanitize_title_for_query( wp_basename( $q['pagename'] ) );
2134				$q['name'] = $q['pagename'];
2135				$where .= " AND ($wpdb->posts.ID = '$reqpage')";
2136				$reqpage_obj = get_post( $reqpage );
2137				if ( is_object($reqpage_obj) && 'attachment' == $reqpage_obj->post_type ) {
2138					$this->is_attachment = true;
2139					$post_type = $q['post_type'] = 'attachment';
2140					$this->is_page = true;
2141					$q['attachment_id'] = $reqpage;
2142				}
2143			}
2144		} els…

Large files files are truncated, but you can click here to view the full file