[ XREF Home ] [ Index ]

PHP Cross Reference of WordPress Trunk

Provided by Yoast

title

Body

[close]

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

   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   */
  24  function get_query_var($var) {
  25      global $wp_query;
  26  
  27      return $wp_query->get($var);
  28  }
  29  
  30  
  31  /**
  32   * Retrieve the currently-queried object.  Wrapper for $wp_query->get_queried_object()
  33   *
  34   * @uses WP_Query::get_queried_object
  35   *
  36   * @since 3.1.0
  37   * @access public
  38   *
  39   * @return object
  40   */
  41  function get_queried_object() {
  42      global $wp_query;
  43      return $wp_query->get_queried_object();
  44  }
  45  
  46  /**
  47   * Retrieve ID of the current queried object. Wrapper for $wp_query->get_queried_object_id()
  48   *
  49   * @uses WP_Query::get_queried_object_id()
  50   *
  51   * @since 3.1.0
  52   * @access public
  53   *
  54   * @return int
  55   */
  56  function get_queried_object_id() {
  57      global $wp_query;
  58      return $wp_query->get_queried_object_id();
  59  }
  60  
  61  /**
  62   * Set query variable.
  63   *
  64   * @see WP_Query::set()
  65   * @since 2.2.0
  66   * @uses $wp_query
  67   *
  68   * @param string $var Query variable key.
  69   * @param mixed $value
  70   * @return null
  71   */
  72  function set_query_var($var, $value) {
  73      global $wp_query;
  74  
  75      return $wp_query->set($var, $value);
  76  }
  77  
  78  /**
  79   * Set up The Loop with query parameters.
  80   *
  81   * This will override the current WordPress Loop and shouldn't be used more than
  82   * once. This must not be used within the WordPress Loop.
  83   *
  84   * @since 1.5.0
  85   * @uses $wp_query
  86   *
  87   * @param string $query
  88   * @return array List of posts
  89   */
  90  function &query_posts($query) {
  91      unset($GLOBALS['wp_query']);
  92      $GLOBALS['wp_query'] =& new WP_Query();
  93      return $GLOBALS['wp_query']->query($query);
  94  }
  95  
  96  /**
  97   * Destroy the previous query and set up a new query.
  98   *
  99   * This should be used after {@link query_posts()} and before another {@link
 100   * query_posts()}. This will remove obscure bugs that occur when the previous
 101   * wp_query object is not destroyed properly before another is set up.
 102   *
 103   * @since 2.3.0
 104   * @uses $wp_query
 105   */
 106  function wp_reset_query() {
 107      unset($GLOBALS['wp_query']);
 108      $GLOBALS['wp_query'] =& $GLOBALS['wp_the_query'];
 109      wp_reset_postdata();
 110  }
 111  
 112  /**
 113   * After looping through a separate query, this function restores
 114   * the $post global to the current post in the main query
 115   *
 116   * @since 3.0.0
 117   * @uses $wp_query
 118   */
 119  function wp_reset_postdata() {
 120      global $wp_query;
 121      if ( !empty($wp_query->post) ) {
 122          $GLOBALS['post'] = $wp_query->post;
 123          setup_postdata($wp_query->post);
 124      }
 125  }
 126  
 127  /*
 128   * Query type checks.
 129   */
 130  
 131  /**
 132   * Is the query for an archive page?
 133   *
 134   * Month, Year, Category, Author, Post Type archive...
 135   *
 136   * @see WP_Query::is_archive()
 137   * @since 1.5.0
 138   * @uses $wp_query
 139   *
 140   * @return bool
 141   */
 142  function is_archive() {
 143      global $wp_query;
 144  
 145      if ( ! isset( $wp_query ) ) {
 146          _doing_it_wrong( __FUNCTION__, __( 'Conditional query tags do not work before the query is run. Before then, they always return false.' ), '3.1' );
 147          return false;
 148      }
 149  
 150      return $wp_query->is_archive();
 151  }
 152  
 153  /**
 154   * Is the query for a post type archive page?
 155   *
 156   * @see WP_Query::is_post_type_archive()
 157   * @since 3.1.0
 158   * @uses $wp_query
 159   *
 160   * @param mixed $post_types Optional. Post type or array of posts types to check against.
 161   * @return bool
 162   */
 163  function is_post_type_archive( $post_types = '' ) {
 164      global $wp_query;
 165  
 166      if ( ! isset( $wp_query ) ) {
 167          _doing_it_wrong( __FUNCTION__, __( 'Conditional query tags do not work before the query is run. Before then, they always return false.' ), '3.1' );
 168          return false;
 169      }
 170  
 171      return $wp_query->is_post_type_archive( $post_types );
 172  }
 173  
 174  /**
 175   * Is the query for an attachment page?
 176   *
 177   * @see WP_Query::is_attachment()
 178   * @since 2.0.0
 179   * @uses $wp_query
 180   *
 181   * @return bool
 182   */
 183  function is_attachment() {
 184      global $wp_query;
 185  
 186      if ( ! isset( $wp_query ) ) {
 187          _doing_it_wrong( __FUNCTION__, __( 'Conditional query tags do not work before the query is run. Before then, they always return false.' ), '3.1' );
 188          return false;
 189      }
 190  
 191      return $wp_query->is_attachment();
 192  }
 193  
 194  /**
 195   * Is the query for an author archive page?
 196   *
 197   * If the $author parameter is specified, this function will additionally
 198   * check if the query is for one of the authors specified.
 199   *
 200   * @see WP_Query::is_author()
 201   * @since 1.5.0
 202   * @uses $wp_query
 203   *
 204   * @param mixed $author Optional. User ID, nickname, nicename, or array of User IDs, nicknames, and nicenames
 205   * @return bool
 206   */
 207  function is_author( $author = '' ) {
 208      global $wp_query;
 209  
 210      if ( ! isset( $wp_query ) ) {
 211          _doing_it_wrong( __FUNCTION__, __( 'Conditional query tags do not work before the query is run. Before then, they always return false.' ), '3.1' );
 212          return false;
 213      }
 214  
 215      return $wp_query->is_author( $author );
 216  }
 217  
 218  /**
 219   * Is the query for a category archive page?
 220   *
 221   * If the $category parameter is specified, this function will additionally
 222   * check if the query is for one of the categories specified.
 223   *
 224   * @see WP_Query::is_category()
 225   * @since 1.5.0
 226   * @uses $wp_query
 227   *
 228   * @param mixed $category Optional. Category ID, name, slug, or array of Category IDs, names, and slugs.
 229   * @return bool
 230   */
 231  function is_category( $category = '' ) {
 232      global $wp_query;
 233  
 234      if ( ! isset( $wp_query ) ) {
 235          _doing_it_wrong( __FUNCTION__, __( 'Conditional query tags do not work before the query is run. Before then, they always return false.' ), '3.1' );
 236          return false;
 237      }
 238  
 239      return $wp_query->is_category( $category );
 240  }
 241  
 242  /**
 243   * Is the query for a tag archive page?
 244   *
 245   * If the $tag parameter is specified, this function will additionally
 246   * check if the query is for one of the tags specified.
 247   *
 248   * @see WP_Query::is_tag()
 249   * @since 2.3.0
 250   * @uses $wp_query
 251   *
 252   * @param mixed $slug Optional. Tag slug or array of slugs.
 253   * @return bool
 254   */
 255  function is_tag( $slug = '' ) {
 256      global $wp_query;
 257  
 258      if ( ! isset( $wp_query ) ) {
 259          _doing_it_wrong( __FUNCTION__, __( 'Conditional query tags do not work before the query is run. Before then, they always return false.' ), '3.1' );
 260          return false;
 261      }
 262  
 263      return $wp_query->is_tag( $slug );
 264  }
 265  
 266  /**
 267   * Is the query for a taxonomy archive page?
 268   *
 269   * If the $taxonomy parameter is specified, this function will additionally
 270   * check if the query is for that specific $taxonomy.
 271   *
 272   * If the $term parameter is specified in addition to the $taxonomy parameter,
 273   * this function will additionally check if the query is for one of the terms
 274   * specified.
 275   *
 276   * @see WP_Query::is_tax()
 277   * @since 2.5.0
 278   * @uses $wp_query
 279   *
 280   * @param mixed $taxonomy Optional. Taxonomy slug or slugs.
 281   * @param mixed $term Optional. Term ID, name, slug or array of Term IDs, names, and slugs.
 282   * @return bool
 283   */
 284  function is_tax( $taxonomy = '', $term = '' ) {
 285      global $wp_query;
 286  
 287      if ( ! isset( $wp_query ) ) {
 288          _doing_it_wrong( __FUNCTION__, __( 'Conditional query tags do not work before the query is run. Before then, they always return false.' ), '3.1' );
 289          return false;
 290      }
 291  
 292      return $wp_query->is_tax( $taxonomy, $term );
 293  }
 294  
 295  /**
 296   * Whether the current URL is within the comments popup window.
 297   *
 298   * @see WP_Query::is_comments_popup()
 299   * @since 1.5.0
 300   * @uses $wp_query
 301   *
 302   * @return bool
 303   */
 304  function is_comments_popup() {
 305      global $wp_query;
 306  
 307      if ( ! isset( $wp_query ) ) {
 308          _doing_it_wrong( __FUNCTION__, __( 'Conditional query tags do not work before the query is run. Before then, they always return false.' ), '3.1' );
 309          return false;
 310      }
 311  
 312      return $wp_query->is_comments_popup();
 313  }
 314  
 315  /**
 316   * Is the query for a date archive?
 317   *
 318   * @see WP_Query::is_date()
 319   * @since 1.5.0
 320   * @uses $wp_query
 321   *
 322   * @return bool
 323   */
 324  function is_date() {
 325      global $wp_query;
 326  
 327      if ( ! isset( $wp_query ) ) {
 328          _doing_it_wrong( __FUNCTION__, __( 'Conditional query tags do not work before the query is run. Before then, they always return false.' ), '3.1' );
 329          return false;
 330      }
 331  
 332      return $wp_query->is_date();
 333  }
 334  
 335  /**
 336   * Is the query for a day archive?
 337   *
 338   * @see WP_Query::is_day()
 339   * @since 1.5.0
 340   * @uses $wp_query
 341   *
 342   * @return bool
 343   */
 344  function is_day() {
 345      global $wp_query;
 346  
 347      if ( ! isset( $wp_query ) ) {
 348          _doing_it_wrong( __FUNCTION__, __( 'Conditional query tags do not work before the query is run. Before then, they always return false.' ), '3.1' );
 349          return false;
 350      }
 351  
 352      return $wp_query->is_day();
 353  }
 354  
 355  /**
 356   * Is the query for a feed?
 357   *
 358   * @see WP_Query::is_feed()
 359   * @since 1.5.0
 360   * @uses $wp_query
 361   *
 362   * @param string|array $feeds Optional feed types to check.
 363   * @return bool
 364   */
 365  function is_feed( $feeds = '' ) {
 366      global $wp_query;
 367  
 368      if ( ! isset( $wp_query ) ) {
 369          _doing_it_wrong( __FUNCTION__, __( 'Conditional query tags do not work before the query is run. Before then, they always return false.' ), '3.1' );
 370          return false;
 371      }
 372  
 373      return $wp_query->is_feed( $feeds );
 374  }
 375  
 376  /**
 377   * Is the query for a comments feed?
 378   *
 379   * @see WP_Query::is_comments_feed()
 380   * @since 3.0.0
 381   * @uses $wp_query
 382   *
 383   * @return bool
 384   */
 385  function is_comment_feed() {
 386      global $wp_query;
 387  
 388      if ( ! isset( $wp_query ) ) {
 389          _doing_it_wrong( __FUNCTION__, __( 'Conditional query tags do not work before the query is run. Before then, they always return false.' ), '3.1' );
 390          return false;
 391      }
 392  
 393      return $wp_query->is_comment_feed();
 394  }
 395  
 396  /**
 397   * Is the query for the front page of the site?
 398   *
 399   * This is for what is displayed at your site's main URL.
 400   *
 401   * Depends on the site's "Front page displays" Reading Settings 'show_on_front' and 'page_on_front'.
 402   *
 403   * If you set a static page for the front page of your site, this function will return
 404   * true when viewing that page.
 405   *
 406   * Otherwise the same as @see is_home()
 407   *
 408   * @see WP_Query::is_front_page()
 409   * @since 2.5.0
 410   * @uses is_home()
 411   * @uses get_option()
 412   *
 413   * @return bool True, if front of site.
 414   */
 415  function is_front_page() {
 416      global $wp_query;
 417  
 418      if ( ! isset( $wp_query ) ) {
 419          _doing_it_wrong( __FUNCTION__, __( 'Conditional query tags do not work before the query is run. Before then, they always return false.' ), '3.1' );
 420          return false;
 421      }
 422  
 423      return $wp_query->is_front_page();
 424  }
 425  
 426  /**
 427   * Is the query for the blog homepage?
 428   *
 429   * This is the page which shows the time based blog content of your site.
 430   *
 431   * Depends on the site's "Front page displays" Reading Settings 'show_on_front' and 'page_for_posts'.
 432   *
 433   * If you set a static page for the front page of your site, this function will return
 434   * true only on the page you set as the "Posts page".
 435   *
 436   * @see is_front_page()
 437   *
 438   * @see WP_Query::is_home()
 439   * @since 1.5.0
 440   * @uses $wp_query
 441   *
 442   * @return bool True if blog view homepage.
 443   */
 444  function is_home() {
 445      global $wp_query;
 446  
 447      if ( ! isset( $wp_query ) ) {
 448          _doing_it_wrong( __FUNCTION__, __( 'Conditional query tags do not work before the query is run. Before then, they always return false.' ), '3.1' );
 449          return false;
 450      }
 451  
 452      return $wp_query->is_home();
 453  }
 454  
 455  /**
 456   * Is the query for a month archive?
 457   *
 458   * @see WP_Query::is_month()
 459   * @since 1.5.0
 460   * @uses $wp_query
 461   *
 462   * @return bool
 463   */
 464  function is_month() {
 465      global $wp_query;
 466  
 467      if ( ! isset( $wp_query ) ) {
 468          _doing_it_wrong( __FUNCTION__, __( 'Conditional query tags do not work before the query is run. Before then, they always return false.' ), '3.1' );
 469          return false;
 470      }
 471  
 472      return $wp_query->is_month();
 473  }
 474  
 475  /**
 476   * Is the query for a single page?
 477   *
 478   * If the $page parameter is specified, this function will additionally
 479   * check if the query is for one of the pages specified.
 480   *
 481   * @see is_single()
 482   * @see is_singular()
 483   *
 484   * @see WP_Query::is_page()
 485   * @since 1.5.0
 486   * @uses $wp_query
 487   *
 488   * @param mixed $page Page ID, title, slug, or array of such.
 489   * @return bool
 490   */
 491  function is_page( $page = '' ) {
 492      global $wp_query;
 493  
 494      if ( ! isset( $wp_query ) ) {
 495          _doing_it_wrong( __FUNCTION__, __( 'Conditional query tags do not work before the query is run. Before then, they always return false.' ), '3.1' );
 496          return false;
 497      }
 498  
 499      return $wp_query->is_page( $page );
 500  }
 501  
 502  /**
 503   * Is the query for paged result and not for the first page?
 504   *
 505   * @see WP_Query::is_paged()
 506   * @since 1.5.0
 507   * @uses $wp_query
 508   *
 509   * @return bool
 510   */
 511  function is_paged() {
 512      global $wp_query;
 513  
 514      if ( ! isset( $wp_query ) ) {
 515          _doing_it_wrong( __FUNCTION__, __( 'Conditional query tags do not work before the query is run. Before then, they always return false.' ), '3.1' );
 516          return false;
 517      }
 518  
 519      return $wp_query->is_paged();
 520  }
 521  
 522  /**
 523   * Is the query for a post or page preview?
 524   *
 525   * @see WP_Query::is_preview()
 526   * @since 2.0.0
 527   * @uses $wp_query
 528   *
 529   * @return bool
 530   */
 531  function is_preview() {
 532      global $wp_query;
 533  
 534      if ( ! isset( $wp_query ) ) {
 535          _doing_it_wrong( __FUNCTION__, __( 'Conditional query tags do not work before the query is run. Before then, they always return false.' ), '3.1' );
 536          return false;
 537      }
 538  
 539      return $wp_query->is_preview();
 540  }
 541  
 542  /**
 543   * Is the query for the robots file?
 544   *
 545   * @see WP_Query::is_robots()
 546   * @since 2.1.0
 547   * @uses $wp_query
 548   *
 549   * @return bool
 550   */
 551  function is_robots() {
 552      global $wp_query;
 553  
 554      if ( ! isset( $wp_query ) ) {
 555          _doing_it_wrong( __FUNCTION__, __( 'Conditional query tags do not work before the query is run. Before then, they always return false.' ), '3.1' );
 556          return false;
 557      }
 558  
 559      return $wp_query->is_robots();
 560  }
 561  
 562  /**
 563   * Is the query for a search?
 564   *
 565   * @see WP_Query::is_search()
 566   * @since 1.5.0
 567   * @uses $wp_query
 568   *
 569   * @return bool
 570   */
 571  function is_search() {
 572      global $wp_query;
 573  
 574      if ( ! isset( $wp_query ) ) {
 575          _doing_it_wrong( __FUNCTION__, __( 'Conditional query tags do not work before the query is run. Before then, they always return false.' ), '3.1' );
 576          return false;
 577      }
 578  
 579      return $wp_query->is_search();
 580  }
 581  
 582  /**
 583   * Is the query for a single post?
 584   *
 585   * Works for any post type, except attachments and pages
 586   *
 587   * If the $post parameter is specified, this function will additionally
 588   * check if the query is for one of the Posts specified.
 589   *
 590   * @see is_page()
 591   * @see is_singular()
 592   *
 593   * @see WP_Query::is_single()
 594   * @since 1.5.0
 595   * @uses $wp_query
 596   *
 597   * @param mixed $post Post ID, title, slug, or array of such.
 598   * @return bool
 599   */
 600  function is_single( $post = '' ) {
 601      global $wp_query;
 602  
 603      if ( ! isset( $wp_query ) ) {
 604          _doing_it_wrong( __FUNCTION__, __( 'Conditional query tags do not work before the query is run. Before then, they always return false.' ), '3.1' );
 605          return false;
 606      }
 607  
 608      return $wp_query->is_single( $post );
 609  }
 610  
 611  /**
 612   * Is the query for a single post of any post type (post, attachment, page, ... )?
 613   *
 614   * If the $post_types parameter is specified, this function will additionally
 615   * check if the query is for one of the Posts Types specified.
 616   *
 617   * @see is_page()
 618   * @see is_single()
 619   *
 620   * @see WP_Query::is_singular()
 621   * @since 1.5.0
 622   * @uses $wp_query
 623   *
 624   * @param mixed $post_types Optional. Post Type or array of Post Types
 625   * @return bool
 626   */
 627  function is_singular( $post_types = '' ) {
 628      global $wp_query;
 629  
 630      if ( ! isset( $wp_query ) ) {
 631          _doing_it_wrong( __FUNCTION__, __( 'Conditional query tags do not work before the query is run. Before then, they always return false.' ), '3.1' );
 632          return false;
 633      }
 634  
 635      return $wp_query->is_singular( $post_types );
 636  }
 637  
 638  /**
 639   * Is the query for a specific time?
 640   *
 641   * @see WP_Query::is_time()
 642   * @since 1.5.0
 643   * @uses $wp_query
 644   *
 645   * @return bool
 646   */
 647  function is_time() {
 648      global $wp_query;
 649  
 650      if ( ! isset( $wp_query ) ) {
 651          _doing_it_wrong( __FUNCTION__, __( 'Conditional query tags do not work before the query is run. Before then, they always return false.' ), '3.1' );
 652          return false;
 653      }
 654  
 655      return $wp_query->is_time();
 656  }
 657  
 658  /**
 659   * Is the query for a trackback endpoint call?
 660   *
 661   * @see WP_Query::is_trackback()
 662   * @since 1.5.0
 663   * @uses $wp_query
 664   *
 665   * @return bool
 666   */
 667  function is_trackback() {
 668      global $wp_query;
 669  
 670      if ( ! isset( $wp_query ) ) {
 671          _doing_it_wrong( __FUNCTION__, __( 'Conditional query tags do not work before the query is run. Before then, they always return false.' ), '3.1' );
 672          return false;
 673      }
 674  
 675      return $wp_query->is_trackback();
 676  }
 677  
 678  /**
 679   * Is the query for a specific year?
 680   *
 681   * @see WP_Query::is_year()
 682   * @since 1.5.0
 683   * @uses $wp_query
 684   *
 685   * @return bool
 686   */
 687  function is_year() {
 688      global $wp_query;
 689  
 690      if ( ! isset( $wp_query ) ) {
 691          _doing_it_wrong( __FUNCTION__, __( 'Conditional query tags do not work before the query is run. Before then, they always return false.' ), '3.1' );
 692          return false;
 693      }
 694  
 695      return $wp_query->is_year();
 696  }
 697  
 698  /**
 699   * Is the query a 404 (returns no results)?
 700   *
 701   * @see WP_Query::is_404()
 702   * @since 1.5.0
 703   * @uses $wp_query
 704   *
 705   * @return bool
 706   */
 707  function is_404() {
 708      global $wp_query;
 709  
 710      if ( ! isset( $wp_query ) ) {
 711          _doing_it_wrong( __FUNCTION__, __( 'Conditional query tags do not work before the query is run. Before then, they always return false.' ), '3.1' );
 712          return false;
 713      }
 714  
 715      return $wp_query->is_404();
 716  }
 717  
 718  /*
 719   * The Loop.  Post loop control.
 720   */
 721  
 722  /**
 723   * Whether current WordPress query has results to loop over.
 724   *
 725   * @see WP_Query::have_posts()
 726   * @since 1.5.0
 727   * @uses $wp_query
 728   *
 729   * @return bool
 730   */
 731  function have_posts() {
 732      global $wp_query;
 733  
 734      return $wp_query->have_posts();
 735  }
 736  
 737  /**
 738   * Whether the caller is in the Loop.
 739   *
 740   * @since 2.0.0
 741   * @uses $wp_query
 742   *
 743   * @return bool True if caller is within loop, false if loop hasn't started or ended.
 744   */
 745  function in_the_loop() {
 746      global $wp_query;
 747  
 748      return $wp_query->in_the_loop;
 749  }
 750  
 751  /**
 752   * Rewind the loop posts.
 753   *
 754   * @see WP_Query::rewind_posts()
 755   * @since 1.5.0
 756   * @uses $wp_query
 757   *
 758   * @return null
 759   */
 760  function rewind_posts() {
 761      global $wp_query;
 762  
 763      return $wp_query->rewind_posts();
 764  }
 765  
 766  /**
 767   * Iterate the post index in the loop.
 768   *
 769   * @see WP_Query::the_post()
 770   * @since 1.5.0
 771   * @uses $wp_query
 772   */
 773  function the_post() {
 774      global $wp_query;
 775  
 776      $wp_query->the_post();
 777  }
 778  
 779  /*
 780   * Comments loop.
 781   */
 782  
 783  /**
 784   * Whether there are comments to loop over.
 785   *
 786   * @see WP_Query::have_comments()
 787   * @since 2.2.0
 788   * @uses $wp_query
 789   *
 790   * @return bool
 791   */
 792  function have_comments() {
 793      global $wp_query;
 794      return $wp_query->have_comments();
 795  }
 796  
 797  /**
 798   * Iterate comment index in the comment loop.
 799   *
 800   * @see WP_Query::the_comment()
 801   * @since 2.2.0
 802   * @uses $wp_query
 803   *
 804   * @return object
 805   */
 806  function the_comment() {
 807      global $wp_query;
 808      return $wp_query->the_comment();
 809  }
 810  
 811  /*
 812   * WP_Query
 813   */
 814  
 815  /**
 816   * The WordPress Query class.
 817   *
 818   * @link http://codex.wordpress.org/Function_Reference/WP_Query Codex page.
 819   *
 820   * @since 1.5.0
 821   */
 822  class WP_Query {
 823  
 824      /**
 825       * Query vars set by the user
 826       *
 827       * @since 1.5.0
 828       * @access public
 829       * @var array
 830       */
 831      var $query;
 832  
 833      /**
 834       * Query vars, after parsing
 835       *
 836       * @since 1.5.0
 837       * @access public
 838       * @var array
 839       */
 840      var $query_vars = array();
 841  
 842      /**
 843       * Taxonomy query, as passed to get_tax_sql()
 844       *
 845       * @since 3.1.0
 846       * @access public
 847       * @var object WP_Tax_Query
 848       */
 849      var $tax_query;
 850  
 851      /**
 852       * Metadata query container
 853       *
 854       * @since 3.2
 855       * @access public
 856       * @var object WP_Meta_Query
 857       */
 858      var $meta_query = false;
 859  
 860      /**
 861       * Holds the data for a single object that is queried.
 862       *
 863       * Holds the contents of a post, page, category, attachment.
 864       *
 865       * @since 1.5.0
 866       * @access public
 867       * @var object|array
 868       */
 869      var $queried_object;
 870  
 871      /**
 872       * The ID of the queried object.
 873       *
 874       * @since 1.5.0
 875       * @access public
 876       * @var int
 877       */
 878      var $queried_object_id;
 879  
 880      /**
 881       * Get post database query.
 882       *
 883       * @since 2.0.1
 884       * @access public
 885       * @var string
 886       */
 887      var $request;
 888  
 889      /**
 890       * List of posts.
 891       *
 892       * @since 1.5.0
 893       * @access public
 894       * @var array
 895       */
 896      var $posts;
 897  
 898      /**
 899       * The amount of posts for the current query.
 900       *
 901       * @since 1.5.0
 902       * @access public
 903       * @var int
 904       */
 905      var $post_count = 0;
 906  
 907      /**
 908       * Index of the current item in the loop.
 909       *
 910       * @since 1.5.0
 911       * @access public
 912       * @var int
 913       */
 914      var $current_post = -1;
 915  
 916      /**
 917       * Whether the loop has started and the caller is in the loop.
 918       *
 919       * @since 2.0.0
 920       * @access public
 921       * @var bool
 922       */
 923      var $in_the_loop = false;
 924  
 925      /**
 926       * The current post ID.
 927       *
 928       * @since 1.5.0
 929       * @access public
 930       * @var object
 931       */
 932      var $post;
 933  
 934      /**
 935       * The list of comments for current post.
 936       *
 937       * @since 2.2.0
 938       * @access public
 939       * @var array
 940       */
 941      var $comments;
 942  
 943      /**
 944       * The amount of comments for the posts.
 945       *
 946       * @since 2.2.0
 947       * @access public
 948       * @var int
 949       */
 950      var $comment_count = 0;
 951  
 952      /**
 953       * The index of the comment in the comment loop.
 954       *
 955       * @since 2.2.0
 956       * @access public
 957       * @var int
 958       */
 959      var $current_comment = -1;
 960  
 961      /**
 962       * Current comment ID.
 963       *
 964       * @since 2.2.0
 965       * @access public
 966       * @var int
 967       */
 968      var $comment;
 969  
 970      /**
 971       * Amount of posts if limit clause was not used.
 972       *
 973       * @since 2.1.0
 974       * @access public
 975       * @var int
 976       */
 977      var $found_posts = 0;
 978  
 979      /**
 980       * The amount of pages.
 981       *
 982       * @since 2.1.0
 983       * @access public
 984       * @var int
 985       */
 986      var $max_num_pages = 0;
 987  
 988      /**
 989       * The amount of comment pages.
 990       *
 991       * @since 2.7.0
 992       * @access public
 993       * @var int
 994       */
 995      var $max_num_comment_pages = 0;
 996  
 997      /**
 998       * Set if query is single post.
 999       *
1000       * @since 1.5.0
1001       * @access public
1002       * @var bool
1003       */
1004      var $is_single = false;
1005  
1006      /**
1007       * Set if query is preview of blog.
1008       *
1009       * @since 2.0.0
1010       * @access public
1011       * @var bool
1012       */
1013      var $is_preview = false;
1014  
1015      /**
1016       * Set if query returns a page.
1017       *
1018       * @since 1.5.0
1019       * @access public
1020       * @var bool
1021       */
1022      var $is_page = false;
1023  
1024      /**
1025       * Set if query is an archive list.
1026       *
1027       * @since 1.5.0
1028       * @access public
1029       * @var bool
1030       */
1031      var $is_archive = false;
1032  
1033      /**
1034       * Set if query is part of a date.
1035       *
1036       * @since 1.5.0
1037       * @access public
1038       * @var bool
1039       */
1040      var $is_date = false;
1041  
1042      /**
1043       * Set if query contains a year.
1044       *
1045       * @since 1.5.0
1046       * @access public
1047       * @var bool
1048       */
1049      var $is_year = false;
1050  
1051      /**
1052       * Set if query contains a month.
1053       *
1054       * @since 1.5.0
1055       * @access public
1056       * @var bool
1057       */
1058      var $is_month = false;
1059  
1060      /**
1061       * Set if query contains a day.
1062       *
1063       * @since 1.5.0
1064       * @access public
1065       * @var bool
1066       */
1067      var $is_day = false;
1068  
1069      /**
1070       * Set if query contains time.
1071       *
1072       * @since 1.5.0
1073       * @access public
1074       * @var bool
1075       */
1076      var $is_time = false;
1077  
1078      /**
1079       * Set if query contains an author.
1080       *
1081       * @since 1.5.0
1082       * @access public
1083       * @var bool
1084       */
1085      var $is_author = false;
1086  
1087      /**
1088       * Set if query contains category.
1089       *
1090       * @since 1.5.0
1091       * @access public
1092       * @var bool
1093       */
1094      var $is_category = false;
1095  
1096      /**
1097       * Set if query contains tag.
1098       *
1099       * @since 2.3.0
1100       * @access public
1101       * @var bool
1102       */
1103      var $is_tag = false;
1104  
1105      /**
1106       * Set if query contains taxonomy.
1107       *
1108       * @since 2.5.0
1109       * @access public
1110       * @var bool
1111       */
1112      var $is_tax = false;
1113  
1114      /**
1115       * Set if query was part of a search result.
1116       *
1117       * @since 1.5.0
1118       * @access public
1119       * @var bool
1120       */
1121      var $is_search = false;
1122  
1123      /**
1124       * Set if query is feed display.
1125       *
1126       * @since 1.5.0
1127       * @access public
1128       * @var bool
1129       */
1130      var $is_feed = false;
1131  
1132      /**
1133       * Set if query is comment feed display.
1134       *
1135       * @since 2.2.0
1136       * @access public
1137       * @var bool
1138       */
1139      var $is_comment_feed = false;
1140  
1141      /**
1142       * Set if query is trackback.
1143       *
1144       * @since 1.5.0
1145       * @access public
1146       * @var bool
1147       */
1148      var $is_trackback = false;
1149  
1150      /**
1151       * Set if query is blog homepage.
1152       *
1153       * @since 1.5.0
1154       * @access public
1155       * @var bool
1156       */
1157      var $is_home = false;
1158  
1159      /**
1160       * Set if query couldn't found anything.
1161       *
1162       * @since 1.5.0
1163       * @access public
1164       * @var bool
1165       */
1166      var $is_404 = false;
1167  
1168      /**
1169       * Set if query is within comments popup window.
1170       *
1171       * @since 1.5.0
1172       * @access public
1173       * @var bool
1174       */
1175      var $is_comments_popup = false;
1176  
1177      /**
1178       * Set if query is paged
1179       *
1180       * @since 1.5.0
1181       * @access public
1182       * @var bool
1183       */
1184      var $is_paged = false;
1185  
1186      /**
1187       * Set if query is part of administration page.
1188       *
1189       * @since 1.5.0
1190       * @access public
1191       * @var bool
1192       */
1193      var $is_admin = false;
1194  
1195      /**
1196       * Set if query is an attachment.
1197       *
1198       * @since 2.0.0
1199       * @access public
1200       * @var bool
1201       */
1202      var $is_attachment = false;
1203  
1204      /**
1205       * Set if is single, is a page, or is an attachment.
1206       *
1207       * @since 2.1.0
1208       * @access public
1209       * @var bool
1210       */
1211      var $is_singular = false;
1212  
1213      /**
1214       * Set if query is for robots.
1215       *
1216       * @since 2.1.0
1217       * @access public
1218       * @var bool
1219       */
1220      var $is_robots = false;
1221  
1222      /**
1223       * Set if query contains posts.
1224       *
1225       * Basically, the homepage if the option isn't set for the static homepage.
1226       *
1227       * @since 2.1.0
1228       * @access public
1229       * @var bool
1230       */
1231      var $is_posts_page = false;
1232  
1233      /**
1234       * Set if query is for a post type archive.
1235       *
1236       * @since 3.1.0
1237       * @access public
1238       * @var bool
1239       */
1240      var $is_post_type_archive = false;
1241  
1242      /**
1243       * Stores the ->query_vars state like md5(serialize( $this->query_vars ) ) so we know
1244       * whether we have to re-parse because something has changed
1245       *
1246       * @since 3.1.0
1247       * @access private
1248       */
1249      var $query_vars_hash = false;
1250  
1251      /**
1252       * Whether query vars have changed since the initial parse_query() call.  Used to catch modifications to query vars made
1253       * via pre_get_posts hooks.
1254       *
1255       * @since 3.1.1
1256       * @access private
1257       */
1258      var $query_vars_changed = true;
1259  
1260      /**
1261       * Set if post thumbnails are cached
1262       *
1263       * @since 3.2
1264       * @access public
1265       * @var bool
1266       */
1267       var $thumbnails_cached = false;
1268  
1269      /**
1270       * Resets query flags to false.
1271       *
1272       * The query flags are what page info WordPress was able to figure out.
1273       *
1274       * @since 2.0.0
1275       * @access private
1276       */
1277  	function init_query_flags() {
1278          $this->is_single = false;
1279          $this->is_preview = false;
1280          $this->is_page = false;
1281          $this->is_archive = false;
1282          $this->is_date = false;
1283          $this->is_year = false;
1284          $this->is_month = false;
1285          $this->is_day = false;
1286          $this->is_time = false;
1287          $this->is_author = false;
1288          $this->is_category = false;
1289          $this->is_tag = false;
1290          $this->is_tax = false;
1291          $this->is_search = false;
1292          $this->is_feed = false;
1293          $this->is_comment_feed = false;
1294          $this->is_trackback = false;
1295          $this->is_home = false;
1296          $this->is_404 = false;
1297          $this->is_comments_popup = false;
1298          $this->is_paged = false;
1299          $this->is_admin = false;
1300          $this->is_attachment = false;
1301          $this->is_singular = false;
1302          $this->is_robots = false;
1303          $this->is_posts_page = false;
1304          $this->is_post_type_archive = false;
1305      }
1306  
1307      /**
1308       * Initiates object properties and sets default values.
1309       *
1310       * @since 1.5.0
1311       * @access public
1312       */
1313  	function init() {
1314          unset($this->posts);
1315          unset($this->query);
1316          $this->query_vars = array();
1317          unset($this->queried_object);
1318          unset($this->queried_object_id);
1319          $this->post_count = 0;
1320          $this->current_post = -1;
1321          $this->in_the_loop = false;
1322          unset( $this->request );
1323          unset( $this->post );
1324          unset( $this->comments );
1325          unset( $this->comment );
1326          $this->comment_count = 0;
1327          $this->current_comment = -1;
1328          $this->found_posts = 0;
1329          $this->max_num_pages = 0;
1330          $this->max_num_comment_pages = 0;
1331  
1332          $this->init_query_flags();
1333      }
1334  
1335      /**
1336       * Reparse the query vars.
1337       *
1338       * @since 1.5.0
1339       * @access public
1340       */
1341  	function parse_query_vars() {
1342          $this->parse_query();
1343      }
1344  
1345      /**
1346       * Fills in the query variables, which do not exist within the parameter.
1347       *
1348       * @since 2.1.0
1349       * @access public
1350       *
1351       * @param array $array Defined query variables.
1352       * @return array Complete query variables with undefined ones filled in empty.
1353       */
1354  	function fill_query_vars($array) {
1355          $keys = array(
1356              'error'
1357              , 'm'
1358              , 'p'
1359              , 'post_parent'
1360              , 'subpost'
1361              , 'subpost_id'
1362              , 'attachment'
1363              , 'attachment_id'
1364              , 'name'
1365              , 'static'
1366              , 'pagename'
1367              , 'page_id'
1368              , 'second'
1369              , 'minute'
1370              , 'hour'
1371              , 'day'
1372              , 'monthnum'
1373              , 'year'
1374              , 'w'
1375              , 'category_name'
1376              , 'tag'
1377              , 'cat'
1378              , 'tag_id'
1379              , 'author_name'
1380              , 'feed'
1381              , 'tb'
1382              , 'paged'
1383              , 'comments_popup'
1384              , 'meta_key'
1385              , 'meta_value'
1386              , 'preview'
1387              , 's'
1388              , 'sentence'
1389              , 'fields'
1390          );
1391  
1392          foreach ( $keys as $key ) {
1393              if ( !isset($array[$key]) )
1394                  $array[$key] = '';
1395          }
1396  
1397          $array_keys = array('category__in', 'category__not_in', 'category__and', 'post__in', 'post__not_in',
1398              'tag__in', 'tag__not_in', 'tag__and', 'tag_slug__in', 'tag_slug__and');
1399  
1400          foreach ( $array_keys as $key ) {
1401              if ( !isset($array[$key]) )
1402                  $array[$key] = array();
1403          }
1404          return $array;
1405      }
1406  
1407      /**
1408       * Parse a query string and set query type booleans.
1409       *
1410       * @since 1.5.0
1411       * @access public
1412       *
1413       * @param string|array $query Optional query.
1414       */
1415  	function parse_query( $query =  '' ) {
1416          if ( ! empty( $query ) ) {
1417              $this->init();
1418              $this->query = $this->query_vars = wp_parse_args( $query );
1419          } elseif ( ! isset( $this->query ) ) {
1420              $this->query = $this->query_vars;
1421          }
1422  
1423          $this->query_vars = $this->fill_query_vars($this->query_vars);
1424          $qv = &$this->query_vars;
1425          $this->query_vars_changed = true;
1426  
1427          if ( ! empty($qv['robots']) )
1428              $this->is_robots = true;
1429  
1430          $qv['p'] =  absint($qv['p']);
1431          $qv['page_id'] =  absint($qv['page_id']);
1432          $qv['year'] = absint($qv['year']);
1433          $qv['monthnum'] = absint($qv['monthnum']);
1434          $qv['day'] = absint($qv['day']);
1435          $qv['w'] = absint($qv['w']);
1436          $qv['m'] = absint($qv['m']);
1437          $qv['paged'] = absint($qv['paged']);
1438          $qv['cat'] = preg_replace( '|[^0-9,-]|', '', $qv['cat'] ); // comma separated list of positive or negative integers
1439          $qv['pagename'] = trim( $qv['pagename'] );
1440          $qv['name'] = trim( $qv['name'] );
1441          if ( '' !== $qv['hour'] ) $qv['hour'] = absint($qv['hour']);
1442          if ( '' !== $qv['minute'] ) $qv['minute'] = absint($qv['minute']);
1443          if ( '' !== $qv['second'] ) $qv['second'] = absint($qv['second']);
1444  
1445          // Compat.  Map subpost to attachment.
1446          if ( '' != $qv['subpost'] )
1447              $qv['attachment'] = $qv['subpost'];
1448          if ( '' != $qv['subpost_id'] )
1449              $qv['attachment_id'] = $qv['subpost_id'];
1450  
1451          $qv['attachment_id'] = absint($qv['attachment_id']);
1452  
1453          if ( ('' != $qv['attachment']) || !empty($qv['attachment_id']) ) {
1454              $this->is_single = true;
1455              $this->is_attachment = true;
1456          } elseif ( '' != $qv['name'] ) {
1457              $this->is_single = true;
1458          } elseif ( $qv['p'] ) {
1459              $this->is_single = true;
1460          } elseif ( ('' !== $qv['hour']) && ('' !== $qv['minute']) &&('' !== $qv['second']) && ('' != $qv['year']) && ('' != $qv['monthnum']) && ('' != $qv['day']) ) {
1461              // If year, month, day, hour, minute, and second are set, a single
1462              // post is being queried.
1463              $this->is_single = true;
1464          } elseif ( '' != $qv['static'] || '' != $qv['pagename'] || !empty($qv['page_id']) ) {
1465              $this->is_page = true;
1466              $this->is_single = false;
1467          } else {
1468          // Look for archive queries.  Dates, categories, authors, search, post type archives.
1469  
1470              if ( !empty($qv['s']) ) {
1471                  $this->is_search = true;
1472              }
1473  
1474              if ( '' !== $qv['second'] ) {
1475                  $this->is_time = true;
1476                  $this->is_date = true;
1477              }
1478  
1479              if ( '' !== $qv['minute'] ) {
1480                  $this->is_time = true;
1481                  $this->is_date = true;
1482              }
1483  
1484              if ( '' !== $qv['hour'] ) {
1485                  $this->is_time = true;
1486                  $this->is_date = true;
1487              }
1488  
1489              if ( $qv['day'] ) {
1490                  if ( ! $this->is_date ) {
1491                      $this->is_day = true;
1492                      $this->is_date = true;
1493                  }
1494              }
1495  
1496              if ( $qv['monthnum'] ) {
1497                  if ( ! $this->is_date ) {
1498                      $this->is_month = true;
1499                      $this->is_date = true;
1500                  }
1501              }
1502  
1503              if ( $qv['year'] ) {
1504                  if ( ! $this->is_date ) {
1505                      $this->is_year = true;
1506                      $this->is_date = true;
1507                  }
1508              }
1509  
1510              if ( $qv['m'] ) {
1511                  $this->is_date = true;
1512                  if ( strlen($qv['m']) > 9 ) {
1513                      $this->is_time = true;
1514                  } else if ( strlen($qv['m']) > 7 ) {
1515                      $this->is_day = true;
1516                  } else if ( strlen($qv['m']) > 5 ) {
1517                      $this->is_month = true;
1518                  } else {
1519                      $this->is_year = true;
1520                  }
1521              }
1522  
1523              if ( '' != $qv['w'] ) {
1524                  $this->is_date = true;
1525              }
1526  
1527              $this->query_vars_hash = false;
1528              $this->parse_tax_query( $qv );
1529  
1530              foreach ( $this->tax_query->queries as $tax_query ) {
1531                  if ( 'NOT IN' != $tax_query['operator'] ) {
1532                      switch ( $tax_query['taxonomy'] ) {
1533                          case 'category':
1534                              $this->is_category = true;
1535                              break;
1536                          case 'post_tag':
1537                              $this->is_tag = true;
1538                              break;
1539                          default:
1540                              $this->is_tax = true;
1541                      }
1542                  }
1543              }
1544              unset( $tax_query );
1545  
1546              if ( empty($qv['author']) || ($qv['author'] == '0') ) {
1547                  $this->is_author = false;
1548              } else {
1549                  $this->is_author = true;
1550              }
1551  
1552              if ( '' != $qv['author_name'] )
1553                  $this->is_author = true;
1554  
1555              if ( !empty( $qv['post_type'] ) && ! is_array( $qv['post_type'] ) ) {
1556                  $post_type_obj = get_post_type_object( $qv['post_type'] );
1557                  if ( ! empty( $post_type_obj->has_archive ) )
1558                      $this->is_post_type_archive = true;
1559              }
1560  
1561              if ( $this->is_post_type_archive || $this->is_date || $this->is_author || $this->is_category || $this->is_tag || $this->is_tax )
1562                  $this->is_archive = true;
1563          }
1564  
1565          if ( '' != $qv['feed'] )
1566              $this->is_feed = true;
1567  
1568          if ( '' != $qv['tb'] )
1569              $this->is_trackback = true;
1570  
1571          if ( '' != $qv['paged'] && ( intval($qv['paged']) > 1 ) )
1572              $this->is_paged = true;
1573  
1574          if ( '' != $qv['comments_popup'] )
1575              $this->is_comments_popup = true;
1576  
1577          // if we're previewing inside the write screen
1578          if ( '' != $qv['preview'] )
1579              $this->is_preview = true;
1580  
1581          if ( is_admin() )
1582              $this->is_admin = true;
1583  
1584          if ( false !== strpos($qv['feed'], 'comments-') ) {
1585              $qv['feed'] = str_replace('comments-', '', $qv['feed']);
1586              $qv['withcomments'] = 1;
1587          }
1588  
1589          $this->is_singular = $this->is_single || $this->is_page || $this->is_attachment;
1590  
1591          if ( $this->is_feed && ( !empty($qv['withcomments']) || ( empty($qv['withoutcomments']) && $this->is_singular ) ) )
1592              $this->is_comment_feed = true;
1593  
1594          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 ) )
1595              $this->is_home = true;
1596  
1597          // Correct is_* for page_on_front and page_for_posts
1598          if ( $this->is_home && 'page' == get_option('show_on_front') && get_option('page_on_front') ) {
1599              $_query = wp_parse_args($this->query);
1600              // pagename can be set and empty depending on matched rewrite rules. Ignore an empty pagename.
1601              if ( isset($_query['pagename']) && '' == $_query['pagename'] )
1602                  unset($_query['pagename']);
1603              if ( empty($_query) || !array_diff( array_keys($_query), array('preview', 'page', 'paged', 'cpage') ) ) {
1604                  $this->is_page = true;
1605                  $this->is_home = false;
1606                  $qv['page_id'] = get_option('page_on_front');
1607                  // Correct <!--nextpage--> for page_on_front
1608                  if ( !empty($qv['paged']) ) {
1609                      $qv['page'] = $qv['paged'];
1610                      unset($qv['paged']);
1611                  }
1612              }
1613          }
1614  
1615          if ( '' != $qv['pagename'] ) {
1616              $this->queried_object =& get_page_by_path($qv['pagename']);
1617              if ( !empty($this->queried_object) )
1618                  $this->queried_object_id = (int) $this->queried_object->ID;
1619              else
1620                  unset($this->queried_object);
1621  
1622              if  ( 'page' == get_option('show_on_front') && isset($this->queried_object_id) && $this->queried_object_id == get_option('page_for_posts') ) {
1623                  $this->is_page = false;
1624                  $this->is_home = true;
1625                  $this->is_posts_page = true;
1626              }
1627          }
1628  
1629          if ( $qv['page_id'] ) {
1630              if  ( 'page' == get_option('show_on_front') && $qv['page_id'] == get_option('page_for_posts') ) {
1631                  $this->is_page = false;
1632                  $this->is_home = true;
1633                  $this->is_posts_page = true;
1634              }
1635          }
1636  
1637          if ( !empty($qv['post_type']) ) {
1638              if ( is_array($qv['post_type']) )
1639                  $qv['post_type'] = array_map('sanitize_key', $qv['post_type']);
1640              else
1641                  $qv['post_type'] = sanitize_key($qv['post_type']);
1642          }
1643  
1644          if ( ! empty( $qv['post_status'] ) ) {
1645              if ( is_array( $qv['post_status'] ) )
1646                  $qv['post_status'] = array_map('sanitize_key', $qv['post_status']);
1647              else
1648                  $qv['post_status'] = preg_replace('|[^a-z0-9_,-]|', '', $qv['post_status']);
1649          }
1650  
1651          if ( $this->is_posts_page && ( ! isset($qv['withcomments']) || ! $qv['withcomments'] ) )
1652              $this->is_comment_feed = false;
1653  
1654          $this->is_singular = $this->is_single || $this->is_page || $this->is_attachment;
1655          // Done correcting is_* for page_on_front and page_for_posts
1656  
1657          if ( '404' == $qv['error'] )
1658              $this->set_404();
1659  
1660          $this->query_vars_hash = md5( serialize( $this->query_vars ) );
1661          $this->query_vars_changed = false;
1662  
1663          do_action_ref_array('parse_query', array(&$this));
1664      }
1665  
1666      /*
1667       * Parses various taxonomy related query vars.
1668       *
1669       * @access protected
1670       * @since 3.1.0
1671       *
1672       * @param array &$q The query variables
1673       */
1674  	function parse_tax_query( &$q ) {
1675          if ( ! empty( $q['tax_query'] ) && is_array( $q['tax_query'] ) ) {
1676              $tax_query = $q['tax_query'];
1677          } else {
1678              $tax_query = array();
1679          }
1680  
1681          if ( !empty($q['taxonomy']) && !empty($q['term']) ) {
1682              $tax_query[] = array(
1683                  'taxonomy' => $q['taxonomy'],
1684                  'terms' => array( $q['term'] ),
1685                  'field' => 'slug',
1686              );
1687          }
1688  
1689          foreach ( $GLOBALS['wp_taxonomies'] as $taxonomy => $t ) {
1690              if ( 'post_tag' == $taxonomy )
1691                  continue;    // Handled further down in the $q['tag'] block
1692  
1693              if ( $t->query_var && !empty( $q[$t->query_var] ) ) {
1694                  $tax_query_defaults = array(
1695                      'taxonomy' => $taxonomy,
1696                      'field' => 'slug',
1697                  );
1698  
1699                   if ( isset( $t->rewrite['hierarchical'] ) && $t->rewrite['hierarchical'] ) {
1700                      $q[$t->query_var] = wp_basename( $q[$t->query_var] );
1701                  }
1702  
1703                  $term = $q[$t->query_var];
1704  
1705                  if ( strpos($term, '+') !== false ) {
1706                      $terms = preg_split( '/[+]+/', $term );
1707                      foreach ( $terms as $term ) {
1708                          $tax_query[] = array_merge( $tax_query_defaults, array(
1709                              'terms' => array( $term )
1710                          ) );
1711                      }
1712                  } else {
1713                      $tax_query[] = array_merge( $tax_query_defaults, array(
1714                          'terms' => preg_split( '/[,]+/', $term )
1715                      ) );
1716                  }
1717              }
1718          }
1719  
1720          // Category stuff
1721          if ( !empty($q['cat']) && '0' != $q['cat'] && !$this->is_singular && $this->query_vars_changed ) {
1722              $q['cat'] = ''.urldecode($q['cat']).'';
1723              $q['cat'] = addslashes_gpc($q['cat']);
1724              $cat_array = preg_split('/[,\s]+/', $q['cat']);
1725              $q['cat'] = '';
1726              $req_cats = array();
1727              foreach ( (array) $cat_array as $cat ) {
1728                  $cat = intval($cat);
1729                  $req_cats[] = $cat;
1730                  $in = ($cat > 0);
1731                  $cat = abs($cat);
1732                  if ( $in ) {
1733                      $q['category__in'][] = $cat;
1734                      $q['category__in'] = array_merge( $q['category__in'], get_term_children($cat, 'category') );
1735                  } else {
1736                      $q['category__not_in'][] = $cat;
1737                      $q['category__not_in'] = array_merge( $q['category__not_in'], get_term_children($cat, 'category') );
1738                  }
1739              }
1740              $q['cat'] = implode(',', $req_cats);
1741          }
1742  
1743          if ( !empty($q['category__in']) ) {
1744              $q['category__in'] = array_map('absint', array_unique( (array) $q['category__in'] ) );
1745              $tax_query[] = array(
1746                  'taxonomy' => 'category',
1747                  'terms' => $q['category__in'],
1748                  'field' => 'term_id',
1749                  'include_children' => false
1750              );
1751          }
1752  
1753          if ( !empty($q['category__not_in']) ) {
1754              $q['category__not_in'] = array_map('absint', array_unique( (array) $q['category__not_in'] ) );
1755              $tax_query[] = array(
1756                  'taxonomy' => 'category',
1757                  'terms' => $q['category__not_in'],
1758                  'operator' => 'NOT IN',
1759                  'include_children' => false
1760              );
1761          }
1762  
1763          if ( !empty($q['category__and']) ) {
1764              $q['category__and'] = array_map('absint', array_unique( (array) $q['category__and'] ) );
1765              $tax_query[] = array(
1766                  'taxonomy' => 'category',
1767                  'terms' => $q['category__and'],
1768                  'field' => 'term_id',
1769                  'operator' => 'AND',
1770                  'include_children' => false
1771              );
1772          }
1773  
1774          // Tag stuff
1775          if ( '' != $q['tag'] && !$this->is_singular && $this->query_vars_changed ) {
1776              if ( strpos($q['tag'], ',') !== false ) {
1777                  $tags = preg_split('/[,\s]+/', $q['tag']);
1778                  foreach ( (array) $tags as $tag ) {
1779                      $tag = sanitize_term_field('slug', $tag, 0, 'post_tag', 'db');
1780                      $q['tag_slug__in'][] = $tag;
1781                  }
1782              } else if ( preg_match('/[+\s]+/', $q['tag']) || !empty($q['cat']) ) {
1783                  $tags = preg_split('/[+\s]+/', $q['tag']);
1784                  foreach ( (array) $tags as $tag ) {
1785                      $tag = sanitize_term_field('slug', $tag, 0, 'post_tag', 'db');
1786                      $q['tag_slug__and'][] = $tag;
1787                  }
1788              } else {
1789                  $q['tag'] = sanitize_term_field('slug', $q['tag'], 0, 'post_tag', 'db');
1790                  $q['tag_slug__in'][] = $q['tag'];
1791              }
1792          }
1793  
1794          if ( !empty($q['tag_id']) ) {
1795              $q['tag_id'] = absint( $q['tag_id'] );
1796              $tax_query[] = array(
1797                  'taxonomy' => 'post_tag',
1798                  'terms' => $q['tag_id']
1799              );
1800          }
1801  
1802          if ( !empty($q['tag__in']) ) {
1803              $q['tag__in'] = array_map('absint', array_unique( (array) $q['tag__in'] ) );
1804              $tax_query[] = array(
1805                  'taxonomy' => 'post_tag',
1806                  'terms' => $q['tag__in']
1807              );
1808          }
1809  
1810          if ( !empty($q['tag__not_in']) ) {
1811              $q['tag__not_in'] = array_map('absint', array_unique( (array) $q['tag__not_in'] ) );
1812              $tax_query[] = array(
1813                  'taxonomy' => 'post_tag',
1814                  'terms' => $q['tag__not_in'],
1815                  'operator' => 'NOT IN'
1816              );
1817          }
1818  
1819          if ( !empty($q['tag__and']) ) {
1820              $q['tag__and'] = array_map('absint', array_unique( (array) $q['tag__and'] ) );
1821              $tax_query[] = array(
1822                  'taxonomy' => 'post_tag',
1823                  'terms' => $q['tag__and'],
1824                  'operator' => 'AND'
1825              );
1826          }
1827  
1828          if ( !empty($q['tag_slug__in']) ) {
1829              $q['tag_slug__in'] = array_map('sanitize_title', array_unique( (array) $q['tag_slug__in'] ) );
1830              $tax_query[] = array(
1831                  'taxonomy' => 'post_tag',
1832                  'terms' => $q['tag_slug__in'],
1833                  'field' => 'slug'
1834              );
1835          }
1836  
1837          if ( !empty($q['tag_slug__and']) ) {
1838              $q['tag_slug__and'] = array_map('sanitize_title', array_unique( (array) $q['tag_slug__and'] ) );
1839              $tax_query[] = array(
1840                  'taxonomy' => 'post_tag',
1841                  'terms' => $q['tag_slug__and'],
1842                  'field' => 'slug',
1843                  'operator' => 'AND'
1844              );
1845          }
1846  
1847          $this->tax_query = new WP_Tax_Query( $tax_query );
1848      }
1849  
1850      /**
1851       * Sets the 404 property and saves whether query is feed.
1852       *
1853       * @since 2.0.0
1854       * @access public
1855       */
1856  	function set_404() {
1857          $is_feed = $this->is_feed;
1858  
1859          $this->init_query_flags();
1860          $this->is_404 = true;
1861  
1862          $this->is_feed = $is_feed;
1863      }
1864  
1865      /**
1866       * Retrieve query variable.
1867       *
1868       * @since 1.5.0
1869       * @access public
1870       *
1871       * @param string $query_var Query variable key.
1872       * @return mixed
1873       */
1874  	function get($query_var) {
1875          if ( isset($this->query_vars[$query_var]) )
1876              return $this->query_vars[$query_var];
1877  
1878          return '';
1879      }
1880  
1881      /**
1882       * Set query variable.
1883       *
1884       * @since 1.5.0
1885       * @access public
1886       *
1887       * @param string $query_var Query variable key.
1888       * @param mixed $value Query variable value.
1889       */
1890  	function set($query_var, $value) {
1891          $this->query_vars[$query_var] = $value;
1892      }
1893  
1894      /**
1895       * Retrieve the posts based on query variables.
1896       *
1897       * There are a few filters and actions that can be used to modify the post
1898       * database query.
1899       *
1900       * @since 1.5.0
1901       * @access public
1902       * @uses do_action_ref_array() Calls 'pre_get_posts' hook before retrieving posts.
1903       *
1904       * @return array List of posts.
1905       */
1906      function &get_posts() {
1907          global $wpdb, $user_ID, $_wp_using_ext_object_cache;
1908  
1909          $this->parse_query();
1910  
1911          do_action_ref_array('pre_get_posts', array(&$this));
1912  
1913          // Shorthand.
1914          $q = &$this->query_vars;
1915  
1916          // Fill again in case pre_get_posts unset some vars.
1917          $q = $this->fill_query_vars($q);
1918  
1919          // Parse meta query
1920          $this->meta_query = new WP_Meta_Query();
1921          $this->meta_query->parse_query_vars( $q );
1922  
1923          // Set a flag if a pre_get_posts hook changed the query vars.
1924          $hash = md5( serialize( $this->query_vars ) );
1925          if ( $hash != $this->query_vars_hash ) {
1926              $this->query_vars_changed = true;
1927              $this->query_vars_hash = $hash;
1928          }
1929          unset($hash);
1930  
1931          // First let's clear some variables
1932          $distinct = '';
1933          $whichauthor = '';
1934          $whichmimetype = '';
1935          $where = '';
1936          $limits = '';
1937          $join = '';
1938          $search = '';
1939          $groupby = '';
1940          $fields = '';
1941          $post_status_join = false;
1942          $page = 1;
1943  
1944          if ( isset( $q['caller_get_posts'] ) ) {
1945              _deprecated_argument( 'WP_Query', '3.1', __( '"caller_get_posts" is deprecated. Use "ignore_sticky_posts" instead.' ) );
1946              if ( !isset( $q['ignore_sticky_posts'] ) )
1947                  $q['ignore_sticky_posts'] = $q['caller_get_posts'];
1948          }
1949  
1950          if ( !isset( $q['ignore_sticky_posts'] ) )
1951              $q['ignore_sticky_posts'] = false;
1952  
1953          if ( !isset($q['suppress_filters']) )
1954              $q['suppress_filters'] = false;
1955  
1956          if ( !isset($q['cache_results']) ) {
1957              if ( $_wp_using_ext_object_cache )
1958                  $q['cache_results'] = false;
1959              else
1960                  $q['cache_results'] = true;
1961          }
1962  
1963          if ( !isset($q['update_post_term_cache']) )
1964              $q['update_post_term_cache'] = true;
1965  
1966          if ( !isset($q['update_post_meta_cache']) )
1967              $q['update_post_meta_cache'] = true;
1968  
1969          if ( !isset($q['post_type']) ) {
1970              if ( $this->is_search )
1971                  $q['post_type'] = 'any';
1972              else
1973                  $q['post_type'] = '';
1974          }
1975          $post_type = $q['post_type'];
1976          if ( !isset($q['posts_per_page']) || $q['posts_per_page'] == 0 )
1977              $q['posts_per_page'] = get_option('posts_per_page');
1978          if ( isset($q['showposts']) && $q['showposts'] ) {
1979              $q['showposts'] = (int) $q['showposts'];
1980              $q['posts_per_page'] = $q['showposts'];
1981          }
1982          if ( (isset($q['posts_per_archive_page']) && $q['posts_per_archive_page'] != 0) && ($this->is_archive || $this->is_search) )
1983              $q['posts_per_page'] = $q['posts_per_archive_page'];
1984          if ( !isset($q['nopaging']) ) {
1985              if ( $q['posts_per_page'] == -1 ) {
1986                  $q['nopaging'] = true;
1987              } else {
1988                  $q['nopaging'] = false;
1989              }
1990          }
1991          if ( $this->is_feed ) {
1992              $q['posts_per_page'] = get_option('posts_per_rss');
1993              $q['nopaging'] = false;
1994          }
1995          $q['posts_per_page'] = (int) $q['posts_per_page'];
1996          if ( $q['posts_per_page'] < -1 )
1997              $q['posts_per_page'] = abs($q['posts_per_page']);
1998          else if ( $q['posts_per_page'] == 0 )
1999              $q['posts_per_page'] = 1;
2000  
2001          if ( !isset($q['comments_per_page']) || $q['comments_per_page'] == 0 )
2002              $q['comments_per_page'] = get_option('comments_per_page');
2003  
2004          if ( $this->is_home && (empty($this->query) || $q['preview'] == 'true') && ( 'page' == get_option('show_on_front') ) && get_option('page_on_front') ) {
2005              $this->is_page = true;
2006              $this->is_home = false;
2007              $q['page_id'] = get_option('page_on_front');
2008          }
2009  
2010          if ( isset($q['page']) ) {
2011              $q['page'] = trim($q['page'], '/');
2012              $q['page'] = absint($q['page']);
2013          }
2014  
2015          // If true, forcibly turns off SQL_CALC_FOUND_ROWS even when limits are present.
2016          if ( isset($q['no_found_rows']) )
2017              $q['no_found_rows'] = (bool) $q['no_found_rows'];
2018          else
2019              $q['no_found_rows'] = false;
2020  
2021          switch ( $q['fields'] ) {
2022              case 'ids':
2023                  $fields = "$wpdb->posts.ID";
2024                  break;
2025              case 'id=>parent':
2026                  $fields = "$wpdb->posts.ID, $wpdb->posts.post_parent";
2027                  break;
2028              default:
2029                  $fields = "$wpdb->posts.*";
2030          }
2031  
2032          // If a month is specified in the querystring, load that month
2033          if ( $q['m'] ) {
2034              $q['m'] = '' . preg_replace('|[^0-9]|', '', $q['m']);
2035              $where .= " AND YEAR($wpdb->posts.post_date)=" . substr($q['m'], 0, 4);
2036              if ( strlen($q['m']) > 5 )
2037                  $where .= " AND MONTH($wpdb->posts.post_date)=" . substr($q['m'], 4, 2);
2038              if ( strlen($q['m']) > 7 )
2039                  $where .= " AND DAYOFMONTH($wpdb->posts.post_date)=" . substr($q['m'], 6, 2);
2040              if ( strlen($q['m']) > 9 )
2041                  $where .= " AND HOUR($wpdb->posts.post_date)=" . substr($q['m'], 8, 2);
2042              if ( strlen($q['m']) > 11 )
2043                  $where .= " AND MINUTE($wpdb->posts.post_date)=" . substr($q['m'], 10, 2);
2044              if ( strlen($q['m']) > 13 )
2045                  $where .= " AND SECOND($wpdb->posts.post_date)=" . substr($q['m'], 12, 2);
2046          }
2047  
2048          if ( '' !== $q['hour'] )
2049              $where .= " AND HOUR($wpdb->posts.post_date)='" . $q['hour'] . "'";
2050  
2051          if ( '' !== $q['minute'] )
2052              $where .= " AND MINUTE($wpdb->posts.post_date)='" . $q['minute'] . "'";
2053  
2054          if ( '' !== $q['second'] )
2055              $where .= " AND SECOND($wpdb->posts.post_date)='" . $q['second'] . "'";
2056  
2057          if ( $q['year'] )
2058              $where .= " AND YEAR($wpdb->posts.post_date)='" . $q['year'] . "'";
2059  
2060          if ( $q['monthnum'] )
2061              $where .= " AND MONTH($wpdb->posts.post_date)='" . $q['monthnum'] . "'";
2062  
2063          if ( $q['day'] )
2064              $where .= " AND DAYOFMONTH($wpdb->posts.post_date)='" . $q['day'] . "'";
2065  
2066          // If we've got a post_type AND its not "any" post_type.
2067          if ( !empty($q['post_type']) && 'any' != $q['post_type'] ) {
2068              foreach ( (array)$q['post_type'] as $_post_type ) {
2069                  $ptype_obj = get_post_type_object($_post_type);
2070                  if ( !$ptype_obj || !$ptype_obj->query_var || empty($q[ $ptype_obj->query_var ]) )
2071                      continue;
2072  
2073                  if ( ! $ptype_obj->hierarchical || strpos($q[ $ptype_obj->query_var ], '/') === false ) {
2074                      // Non-hierarchical post_types & parent-level-hierarchical post_types can directly use 'name'
2075                      $q['name'] = $q[ $ptype_obj->query_var ];
2076                  } else {
2077                      // Hierarchical post_types will operate through the
2078                      $q['pagename'] = $q[ $ptype_obj->query_var ];
2079                      $q['name'] = '';
2080                  }
2081  
2082                  // Only one request for a slug is possible, this is why name & pagename are overwritten above.
2083                  break;
2084              } //end foreach
2085              unset($ptype_obj);
2086          }
2087  
2088          if ( '' != $q['name'] ) {
2089              $q['name'] = sanitize_title_for_query( $q['name'] );
2090              $where .= " AND $wpdb->posts.post_name = '" . $q['name'] . "'";
2091          } elseif ( '' != $q['pagename'] ) {
2092              if ( isset($this->queried_object_id) ) {
2093                  $reqpage = $this->queried_object_id;
2094              } else {
2095                  if ( 'page' != $q['post_type'] ) {
2096                      foreach ( (array)$q['post_type'] as $_post_type ) {
2097                          $ptype_obj = get_post_type_object($_post_type);
2098                          if ( !$ptype_obj || !$ptype_obj->hierarchical )
2099                              continue;
2100  
2101                          $reqpage = get_page_by_path($q['pagename'], OBJECT, $_post_type);
2102                          if ( $reqpage )
2103                              break;
2104                      }
2105                      unset($ptype_obj);
2106                  } else {
2107                      $reqpage = get_page_by_path($q['pagename']);
2108                  }
2109                  if ( !empty($reqpage) )
2110                      $reqpage = $reqpage->ID;
2111                  else
2112                      $reqpage = 0;
2113              }
2114  
2115              $page_for_posts = get_option('page_for_posts');
2116              if  ( ('page' != get_option('show_on_front') ) || empty($page_for_posts) || ( $reqpage != $page_for_posts ) ) {
2117                  $q['pagename'] = sanitize_title_for_query( wp_basename( $q['pagename'] ) );
2118                  $q['name'] = $q['pagename'];
2119                  $where .= " AND ($wpdb->posts.ID = '$reqpage')";
2120                  $reqpage_obj = get_page($reqpage);
2121                  if ( is_object($reqpage_obj) && 'attachment' == $reqpage_obj->post_type ) {
2122                      $this->is_attachment = true;
2123                      $post_type = $q['post_type'] = 'attachment';
2124                      $this->is_page = true;
2125                      $q['attachment_id'] = $reqpage;
2126                  }
2127              }
2128          } elseif ( '' != $q['attachment'] ) {
2129              $q['attachment'] = sanitize_title_for_query( wp_basename( $q['attachment'] ) );
2130              $q['name'] = $q['attachment'];
2131              $where .= " AND $wpdb->posts.post_name = '" . $q['attachment'] . "'";
2132          }
2133  
2134          if ( $q['w'] )
2135              $where .= ' AND ' . _wp_mysql_week( "`$wpdb->posts`.`post_date`" ) . " = '" . $q['w'] . "'";
2136  
2137          if ( intval($q['comments_popup']) )
2138              $q['p'] = absint($q['comments_popup']);
2139  
2140          // If an attachment is requested by number, let it supercede any post number.
2141          if ( $q['attachment_id'] )
2142              $q['p'] = absint($q['attachment_id']);
2143  
2144          // If a post number is specified, load that post
2145          if ( $q['p'] ) {
2146              $where .= " AND {$wpdb->posts}.ID = " . $q['p'];
2147          } elseif ( $q['post__in'] ) {
2148              $post__in = implode(',', array_map( 'absint', $q['post__in'] ));
2149              $where .= " AND {$wpdb->posts}.ID IN ($post__in)";
2150          } elseif ( $q['post__not_in'] ) {
2151              $post__not_in = implode(',',  array_map( 'absint', $q['post__not_in'] ));
2152              $where .= " AND {$wpdb->posts}.ID NOT IN ($post__not_in)";
2153          }
2154  
2155          if ( is_numeric($q['post_parent']) )
2156              $where .= $wpdb->prepare( " AND $wpdb->posts.post_parent = %d ", $q['post_parent'] );
2157  
2158          if ( $q['page_id'] ) {
2159              if  ( ('page' != get_option('show_on_front') ) || ( $q['page_id'] != get_option('page_for_posts') ) ) {
2160                  $q['p'] = $q['page_id'];
2161                  $where = " AND {$wpdb->posts}.ID = " . $q['page_id'];
2162              }
2163          }
2164  
2165          // If a search pattern is specified, load the posts that match
2166          if ( !empty($q['s']) ) {
2167              // added slashes screw with quote grouping when done early, so done later
2168              $q['s'] = stripslashes($q['s']);
2169              if ( !empty($q['sentence']) ) {
2170                  $q['search_terms'] = array($q['s']);
2171              } else {
2172                  preg_match_all('/".*?("|$)|((?<=[\\s",+])|^)[^\\s",+]+/', $q['s'], $matches);
2173                  $q['search_terms'] = array_map('_search_terms_tidy', $matches[0]);
2174              }
2175              $n = !empty($q['exact']) ? '' : '%';
2176              $searchand = '';
2177              foreach( (array) $q['search_terms'] as $term ) {
2178                  $term = esc_sql( like_escape( $term ) );
2179                  $search .= "{$searchand}(($wpdb->posts.post_title LIKE '{$n}{$term}{$n}') OR ($wpdb->posts.post_content LIKE '{$n}{$term}{$n}'))";
2180                  $searchand = ' AND ';
2181              }
2182  
2183              if ( !empty($search) ) {
2184                  $search = " AND ({$search}) ";
2185                  if ( !is_user_logged_in() )
2186                      $search .= " AND ($wpdb->posts.post_password = '') ";
2187              }
2188          }
2189  
2190          // Allow plugins to contextually add/remove/modify the search section of the database query
2191          $search = apply_filters_ref_array('posts_search', array( $search, &$this ) );
2192  
2193          // Taxonomies
2194          if ( !$this->is_singular ) {
2195              $this->parse_tax_query( $q );
2196  
2197              $clauses = $this->tax_query->get_sql( $wpdb->posts, 'ID' );
2198  
2199              $join .= $clauses['join'];
2200              $where .= $clauses['where'];
2201          }
2202  
2203          if ( $this->is_tax ) {
2204              if ( empty($post_type) ) {
2205                  $post_type = 'any';
2206                  $post_status_join = true;
2207              } elseif ( in_array('attachment', (array) $post_type) ) {
2208                  $post_status_join = true;
2209              }
2210          }
2211  
2212          // Back-compat
2213          if ( !empty($this->tax_query->queries) ) {
2214              $tax_query_in_and = wp_list_filter( $this->tax_query->queries, array( 'operator' => 'NOT IN' ), 'NOT' );
2215              if ( !empty( $tax_query_in_and ) ) {
2216                  if ( !isset( $q['taxonomy'] ) ) {
2217                      foreach ( $tax_query_in_and as $a_tax_query ) {
2218                          if ( !in_array( $a_tax_query['taxonomy'], array( 'category', 'post_tag' ) ) ) {
2219                              $q['taxonomy'] = $a_tax_query['taxonomy'];
2220                              if ( 'slug' == $a_tax_query['field'] )
2221                                  $q['term'] = $a_tax_query['terms'][0];
2222                              else
2223                                  $q['term_id'] = $a_tax_query['terms'][0];
2224  
2225                              break;
2226                          }
2227                      }
2228                  }
2229  
2230                  $cat_query = wp_list_filter( $tax_query_in_and, array( 'taxonomy' => 'category' ) );
2231                  if ( !empty( $cat_query ) ) {
2232                      $cat_query = reset( $cat_query );
2233                      $the_cat = get_term_by( $cat_query['field'], $cat_query['terms'][0], 'category' );
2234                      if ( $the_cat ) {
2235                          $this->set( 'cat', $the_cat->term_id );
2236                          $this->set( 'category_name', $the_cat->slug );
2237                      }
2238                      unset( $the_cat );
2239                  }
2240                  unset( $cat_query );
2241  
2242                  $tag_query = wp_list_filter( $tax_query_in_and, array( 'taxonomy' => 'post_tag' ) );
2243                  if ( !empty( $tag_query ) ) {
2244                      $tag_query = reset( $tag_query );
2245                      $the_tag = get_term_by( $tag_query['field'], $tag_query['terms'][0], 'post_tag' );
2246                      if ( $the_tag ) {
2247                          $this->set( 'tag_id', $the_tag->term_id );
2248                      }
2249                      unset( $the_tag );
2250                  }
2251                  unset( $tag_query );
2252              }
2253          }
2254  
2255          if ( !empty( $this->tax_query->queries ) || !empty( $this->meta_query->queries ) ) {
2256              $groupby = "{$wpdb->posts}.ID";
2257          }
2258  
2259          // Author/user stuff
2260  
2261          if ( empty($q['author']) || ($q['author'] == '0') ) {
2262              $whichauthor = '';
2263          } else {
2264              $q['author'] = (string)urldecode($q['author']);
2265              $q['author'] = addslashes_gpc($q['author']);
2266              if ( strpos($q['author'], '-') !== false ) {
2267                  $eq = '!=';
2268                  $andor = 'AND';
2269                  $q['author'] = explode('-', $q['author']);
2270                  $q['author'] = (string)absint($q['author'][1]);
2271              } else {
2272                  $eq = '=';
2273                  $andor = 'OR';
2274              }
2275              $author_array = preg_split('/[,\s]+/', $q['author']);
2276              $_author_array = array();
2277              foreach ( $author_array as $key => $_author )
2278                  $_author_array[] = "$wpdb->posts.post_author " . $eq . ' ' . absint($_author);
2279              $whichauthor .= ' AND (' . implode(" $andor ", $_author_array) . ')';
2280              unset($author_array, $_author_array);
2281          }
2282  
2283          // Author stuff for nice URLs
2284  
2285          if ( '' != $q['author_name'] ) {
2286              if ( strpos($q['author_name'], '/') !== false ) {
2287                  $q['author_name'] = explode('/', $q['author_name']);
2288                  if ( $q['author_name'][ count($q['author_name'])-1 ] ) {
2289                      $q['author_name'] = $q['author_name'][count($q['author_name'])-1]; // no trailing slash
2290                  } else {
2291                      $q['author_name'] = $q['author_name'][count($q['author_name'])-2]; // there was a trailling slash
2292                  }
2293              }
2294              $q['author_name'] = sanitize_title_for_query( $q['author_name'] );
2295              $q['author'] = get_user_by('slug', $q['author_name']);
2296              if ( $q['author'] )
2297                  $q['author'] = $q['author']->ID;
2298              $whichauthor .= " AND ($wpdb->posts.post_author = " . absint($q['author']) . ')';
2299          }
2300  
2301          // MIME-Type stuff for attachment browsing
2302  
2303          if ( isset($q['post_mime_type']) && '' != $q['post_mime_type'] ) {
2304              $table_alias = $post_status_join ? $wpdb->posts : '';
2305              $whichmimetype = wp_post_mime_type_where($q['post_mime_type'], $table_alias);
2306          }
2307  
2308          $where .= $search . $whichauthor . $whichmimetype;
2309  
2310          if ( empty($q['order']) || ((strtoupper($q['order']) != 'ASC') && (strtoupper($q['order']) != 'DESC')) )
2311              $q['order'] = 'DESC';
2312  
2313          // Order by
2314          if ( empty($q['orderby']) ) {
2315              $orderby = "$wpdb->posts.post_date " . $q['order'];
2316          } elseif ( 'none' == $q['orderby'] ) {
2317              $orderby = '';
2318          } else {
2319              // Used to filter values
2320              $allowed_keys = array('author', 'date', 'title', 'modified', 'menu_order', 'parent', 'ID', 'rand', 'comment_count');
2321              if ( !empty($q['meta_key']) ) {
2322                  $allowed_keys[] = $q['meta_key'];
2323                  $allowed_keys[] = 'meta_value';
2324                  $allowed_keys[] = 'meta_value_num';
2325              }
2326              $q['orderby'] = urldecode($q['orderby']);
2327              $q['orderby'] = addslashes_gpc($q['orderby']);
2328  
2329              $orderby_array = array();
2330              foreach ( explode( ' ', $q['orderby'] ) as $i => $orderby ) {
2331                  // Only allow certain values for safety
2332                  if ( ! in_array($orderby, $allowed_keys) )
2333                      continue;
2334  
2335                  switch ( $orderby ) {
2336                      case 'menu_order':
2337                          break;
2338                      case 'ID':
2339                          $orderby = "$wpdb->posts.ID";
2340                          break;
2341                      case 'rand':
2342                          $orderby = 'RAND()';
2343                          break;
2344                      case $q['meta_key']:
2345                      case 'meta_value':
2346                          $orderby = "$wpdb->postmeta.meta_value";
2347                          break;
2348                      case 'meta_value_num':
2349                          $orderby = "$wpdb->postmeta.meta_value+0";
2350                          break;
2351                      case 'comment_count':
2352                          $orderby = "$wpdb->posts.comment_count";
2353                          break;
2354                      default:
2355                          $orderby = "$wpdb->posts.post_" . $orderby;
2356                  }
2357  
2358                  $orderby_array[] = $orderby;
2359              }
2360              $orderby = implode( ',', $orderby_array );
2361  
2362              if ( empty( $orderby ) )
2363                  $orderby = "$wpdb->posts.post_date ".$q['order'];
2364              else
2365                  $orderby .= " {$q['order']}";
2366          }
2367  
2368          if ( is_array( $post_type ) ) {
2369              $post_type_cap = 'multiple_post_type';
2370          } else {
2371              $post_type_object = get_post_type_object( $post_type );
2372              if ( empty( $post_type_object ) )
2373                  $post_type_cap = $post_type;
2374          }
2375  
2376          $exclude_post_types = '';
2377          $in_search_post_types = get_post_types( array('exclude_from_search' => false) );
2378          if ( ! empty( $in_search_post_types ) )
2379              $exclude_post_types .= $wpdb->prepare(" AND $wpdb->posts.post_type IN ('" . join("', '", $in_search_post_types ) . "')");
2380  
2381          if ( 'any' == $post_type ) {
2382              $where .= $exclude_post_types;
2383          } elseif ( !empty( $post_type ) && is_array( $post_type ) ) {
2384              $where .= " AND $wpdb->posts.post_type IN ('" . join("', '", $post_type) . "')";
2385          } elseif ( ! empty( $post_type ) ) {
2386              $where .= " AND $wpdb->posts.post_type = '$post_type'";
2387              $post_type_object = get_post_type_object ( $post_type );
2388          } elseif ( $this->is_attachment ) {
2389              $where .= " AND $wpdb->posts.post_type = 'attachment'";
2390              $post_type_object = get_post_type_object ( 'attachment' );
2391          } elseif ( $this->is_page ) {
2392              $where .= " AND $wpdb->posts.post_type = 'page'";
2393              $post_type_object = get_post_type_object ( 'page' );
2394          } else {
2395              $where .= " AND $wpdb->posts.post_type = 'post'";
2396              $post_type_object = get_post_type_object ( 'post' );
2397          }
2398  
2399          if ( ! empty( $post_type_object ) ) {
2400              $edit_cap = $post_type_object->cap->edit_post;
2401              $read_cap = $post_type_object->cap->read_post;
2402              $edit_others_cap = $post_type_object->cap->edit_others_posts;
2403              $read_private_cap = $post_type_object->cap->read_private_posts;
2404          } else {
2405              $edit_cap = 'edit_' . $post_type_cap;
2406              $read_cap = 'read_' . $post_type_cap;
2407              $edit_others_cap = 'edit_others_' . $post_type_cap . 's';
2408              $read_private_cap = 'read_private_' . $post_type_cap . 's';
2409          }
2410  
2411          if ( ! empty( $q['post_status'] ) ) {
2412              $statuswheres = array();
2413              $q_status = $q['post_status'];
2414              if ( ! is_array( $q_status ) )
2415                  $q_status = explode(',', $q_status);
2416              $r_status = array();
2417              $p_status = array();
2418              $e_status = array();
2419              if ( in_array('any', $q_status) ) {
2420                  foreach ( get_post_stati( array('exclude_from_search' => true) ) as $status )
2421                      $e_status[] = "$wpdb->posts.post_status <> '$status'";
2422              } else {
2423                  foreach ( get_post_stati() as $status ) {
2424                      if ( in_array( $status, $q_status ) ) {
2425                          if ( 'private' == $status )
2426                              $p_status[] = "$wpdb->posts.post_status = '$status'";
2427                          else
2428                              $r_status[] = "$wpdb->posts.post_status = '$status'";
2429                      }
2430                  }
2431              }
2432  
2433              if ( empty($q['perm'] ) || 'readable' != $q['perm'] ) {
2434                  $r_status = array_merge($r_status, $p_status);
2435                  unset($p_status);
2436              }
2437  
2438              if ( !empty($e_status) ) {
2439                  $statuswheres[] = "(" . join( ' AND ', $e_status ) . ")";
2440              }
2441              if ( !empty($r_status) ) {
2442                  if ( !empty($q['perm'] ) && 'editable' == $q['perm'] && !current_user_can($edit_others_cap) )
2443                      $statuswheres[] = "($wpdb->posts.post_author = $user_ID " .  "AND (" . join( ' OR ', $r_status ) . "))";
2444                  else
2445                      $statuswheres[] = "(" . join( ' OR ', $r_status ) . ")";
2446              }
2447              if ( !empty($p_status) ) {
2448                  if ( !empty($q['perm'] ) && 'readable' == $q['perm'] && !current_user_can($read_private_cap) )
2449                      $statuswheres[] = "($wpdb->posts.post_author = $user_ID " .  "AND (" . join( ' OR ', $p_status ) . "))";
2450                  else
2451                      $statuswheres[] = "(" . join( ' OR ', $p_status ) . ")";
2452              }
2453              if ( $post_status_join ) {
2454                  $join .= " LEFT JOIN $wpdb->posts AS p2 ON ($wpdb->posts.post_parent = p2.ID) ";
2455                  foreach ( $statuswheres as $index => $statuswhere )
2456                      $statuswheres[$index] = "($statuswhere OR ($wpdb->posts.post_status = 'inherit' AND " . str_replace($wpdb->posts, 'p2', $statuswhere) . "))";
2457              }
2458              foreach ( $statuswheres as $statuswhere )
2459                  $where .= " AND $statuswhere";
2460          } elseif ( !$this->is_singular ) {
2461              $where .= " AND ($wpdb->posts.post_status = 'publish'";
2462  
2463              // Add public states.
2464              $public_states = get_post_stati( array('public' => true) );
2465              foreach ( (array) $public_states as $state ) {
2466                  if ( 'publish' == $state ) // Publish is hard-coded above.
2467                      continue;
2468                  $where .= " OR $wpdb->posts.post_status = '$state'";
2469              }
2470  
2471              if ( is_admin() ) {
2472                  // Add protected states that should show in the admin all list.
2473                  $admin_all_states = get_post_stati( array('protected' => true, 'show_in_admin_all_list' => true) );
2474                  foreach ( (array) $admin_all_states as $state )
2475                      $where .= " OR $wpdb->posts.post_status = '$state'";
2476              }
2477  
2478              if ( is_user_logged_in() ) {
2479                  // Add private states that are limited to viewing by the author of a post or someone who has caps to read private states.
2480                  $private_states = get_post_stati( array('private' => true) );
2481                  foreach ( (array) $private_states as $state )
2482                      $where .= current_user_can( $read_private_cap ) ? " OR $wpdb->posts.post_status = '$state'" : " OR $wpdb->posts.post_author = $user_ID AND $wpdb->posts.post_status = '$state'";
2483              }
2484  
2485              $where .= ')';
2486          }
2487  
2488          if ( !empty( $this->meta_query->queries ) ) {
2489              $clauses = $this->meta_query->get_sql( 'post', $wpdb->posts, 'ID', $this );
2490              $join .= $clauses['join'];
2491              $where .= $clauses['where'];
2492          }
2493  
2494          // Apply filters on where and join prior to paging so that any
2495          // manipulations to them are reflected in the paging by day queries.
2496          if ( !$q['suppress_filters'] ) {
2497              $where = apply_filters_ref_array('posts_where', array( $where, &$this ) );
2498              $join = apply_filters_ref_array('posts_join', array( $join, &$this ) );
2499          }
2500  
2501          // Paging
2502          if ( empty($q['nopaging']) && !$this->is_singular ) {
2503              $page = absint($q['paged']);
2504              if ( empty($page) )
2505                  $page = 1;
2506  
2507              if ( empty($q['offset']) ) {
2508                  $pgstrt = '';
2509                  $pgstrt = ($page - 1) * $q['posts_per_page'] . ', ';
2510                  $limits = 'LIMIT ' . $pgstrt . $q['posts_per_page'];
2511              } else { // we're ignoring $page and using 'offset'
2512                  $q['offset'] = absint($q['offset']);
2513                  $pgstrt = $q['offset'] . ', ';
2514                  $limits = 'LIMIT ' . $pgstrt . $q['posts_per_page'];
2515              }
2516          }
2517  
2518          // Comments feeds
2519          if ( $this->is_comment_feed && ( $this->is_archive || $this->is_search || !$this->is_singular ) ) {
2520              if ( $this->is_archive || $this->is_search ) {
2521                  $cjoin = "JOIN $wpdb->posts ON ($wpdb->comments.comment_post_ID = $wpdb->posts.ID) $join ";
2522                  $cwhere = "WHERE comment_approved = '1' $where";
2523                  $cgroupby = "$wpdb->comments.comment_id";
2524              } else { // Other non singular e.g. front
2525                  $cjoin = "JOIN $wpdb->posts ON ( $wpdb->comments.comment_post_ID = $wpdb->posts.ID )";
2526                  $cwhere = "WHERE post_status = 'publish' AND comment_approved = '1'";
2527                  $cgroupby = '';
2528              }
2529  
2530              if ( !$q['suppress_filters'] ) {
2531                  $cjoin = apply_filters_ref_array('comment_feed_join', array( $cjoin, &$this ) );
2532                  $cwhere = apply_filters_ref_array('comment_feed_where', array( $cwhere, &$this ) );
2533                  $cgroupby = apply_filters_ref_array('comment_feed_groupby', array( $cgroupby, &$this ) );
2534                  $corderby = apply_filters_ref_array('comment_feed_orderby', array( 'comment_date_gmt DESC', &$this ) );
2535                  $climits = apply_filters_ref_array('comment_feed_limits', array( 'LIMIT ' . get_option('posts_per_rss'), &$this ) );
2536              }
2537              $cgroupby = ( ! empty( $cgroupby ) ) ? 'GROUP BY ' . $cgroupby : '';
2538              $corderby = ( ! empty( $corderby ) ) ? 'ORDER BY ' . $corderby : '';
2539  
2540              $this->comments = (array) $wpdb->get_results("SELECT $distinct $wpdb->comments.* FROM $wpdb->comments $cjoin $cwhere $cgroupby $corderby $climits");
2541              $this->comment_count = count($this->comments);
2542  
2543              $post_ids = array();
2544  
2545              foreach ( $this->comments as $comment )
2546                  $post_ids[] = (int) $comment->comment_post_ID;
2547  
2548              $post_ids = join(',', $post_ids);
2549              $join = '';
2550              if ( $post_ids )
2551                  $where = "AND $wpdb->posts.ID IN ($post_ids) ";
2552              else
2553                  $where = "AND 0";
2554          }
2555  
2556          $pieces = array( 'where', 'groupby', 'join', 'orderby', 'distinct', 'fields', 'limits' );
2557  
2558          // Apply post-paging filters on where and join.  Only plugins that
2559          // manipulate paging queries should use these hooks.
2560          if ( !$q['suppress_filters'] ) {
2561              $where        = apply_filters_ref_array( 'posts_where_paged',    array( $where, &$this ) );
2562              $groupby    = apply_filters_ref_array( 'posts_groupby',        array( $groupby, &$this ) );
2563              $join        = apply_filters_ref_array( 'posts_join_paged',    array( $join, &$this ) );
2564              $orderby    = apply_filters_ref_array( 'posts_orderby',        array( $orderby, &$this ) );
2565              $distinct    = apply_filters_ref_array( 'posts_distinct',    array( $distinct, &$this ) );
2566              $limits        = apply_filters_ref_array( 'post_limits',        array( $limits, &$this ) );
2567              $fields        = apply_filters_ref_array( 'posts_fields',        array( $fields, &$this ) );
2568  
2569              // Filter all clauses at once, for convenience
2570              $clauses = (array) apply_filters_ref_array( 'posts_clauses', array( compact( $pieces ), &$this ) );
2571              foreach ( $pieces as $piece )
2572                  $$piece = isset( $clauses[ $piece ] ) ? $clauses[ $piece ] : '';
2573          }
2574  
2575          // Announce current selection parameters.  For use by caching plugins.
2576          do_action( 'posts_selection', $where . $groupby . $orderby . $limits . $join );
2577  
2578          // Filter again for the benefit of caching plugins.  Regular plugins should use the hooks above.
2579          if ( !$q['suppress_filters'] ) {
2580              $where        = apply_filters_ref_array( 'posts_where_request',        array( $where, &$this ) );
2581              $groupby    = apply_filters_ref_array( 'posts_groupby_request',        array( $groupby, &$this ) );
2582              $join        = apply_filters_ref_array( 'posts_join_request',        array( $join, &$this ) );
2583              $orderby    = apply_filters_ref_array( 'posts_orderby_request',        array( $orderby, &$this ) );
2584              $distinct    = apply_filters_ref_array( 'posts_distinct_request',    array( $distinct, &$this ) );
2585              $fields        = apply_filters_ref_array( 'posts_fields_request',        array( $fields, &$this ) );
2586              $limits        = apply_filters_ref_array( 'post_limits_request',        array( $limits, &$this ) );
2587  
2588              // Filter all clauses at once, for convenience
2589              $clauses = (array) apply_filters_ref_array( 'posts_clauses_request', array( compact( $pieces ), &$this ) );
2590              foreach ( $pieces as $piece )
2591                  $$piece = isset( $clauses[ $piece ] ) ? $clauses[ $piece ] : '';
2592          }
2593  
2594          if ( ! empty($groupby) )
2595              $groupby = 'GROUP BY ' . $groupby;
2596          if ( !empty( $orderby ) )
2597              $orderby = 'ORDER BY ' . $orderby;
2598  
2599          $found_rows = '';
2600          if ( !$q['no_found_rows'] && !empty($limits) )
2601              $found_rows = 'SQL_CALC_FOUND_ROWS';
2602  
2603          $this->request = " SELECT $found_rows $distinct $fields FROM $wpdb->posts $join WHERE 1=1 $where $groupby $orderby $limits";
2604          if ( !$q['suppress_filters'] )
2605              $this->request = apply_filters_ref_array('posts_request', array( $this->request, &$this ) );
2606  
2607          if ( 'ids' == $q['fields'] ) {
2608              $this->posts = $wpdb->get_col($this->request);
2609  
2610              return $this->posts;
2611          }
2612  
2613          if ( 'id=>parent' == $q['fields'] ) {
2614              $this->posts = $wpdb->get_results($this->request);
2615  
2616              $r = array();
2617              foreach ( $this->posts as $post )
2618                  $r[ $post->ID ] = $post->post_parent;
2619  
2620              return $r;
2621          }
2622  
2623          $this->posts = $wpdb->get_results($this->request);
2624  
2625          // Raw results filter.  Prior to status checks.
2626          if ( !$q['suppress_filters'] )
2627              $this->posts = apply_filters_ref_array('posts_results', array( $this->posts, &$this ) );
2628  
2629          if ( !empty($this->posts) && $this->is_comment_feed && $this->is_singular ) {
2630              $cjoin = apply_filters_ref_array('comment_feed_join', array( '', &$this ) );
2631              $cwhere = apply_filters_ref_array('comment_feed_where', array( "WHERE comment_post_ID = '{$this->posts[0]->ID}' AND comment_approved = '1'", &$this ) );
2632              $cgroupby = apply_filters_ref_array('comment_feed_groupby', array( '', &$this ) );
2633              $cgroupby = ( ! empty( $cgroupby ) ) ? 'GROUP BY ' . $cgroupby : '';
2634              $corderby = apply_filters_ref_array('comment_feed_orderby', array( 'comment_date_gmt DESC', &$this ) );
2635              $corderby = ( ! empty( $corderby ) ) ? 'ORDER BY ' . $corderby : '';
2636              $climits = apply_filters_ref_array('comment_feed_limits', array( 'LIMIT ' . get_option('posts_per_rss'), &$this ) );
2637              $comments_request = "SELECT $wpdb->comments.* FROM $wpdb->comments $cjoin $cwhere $cgroupby $corderby $climits";
2638              $this->comments = $wpdb->get_results($comments_request);
2639              $this->comment_count = count($this->comments);
2640          }
2641  
2642          if ( !$q['no_found_rows'] && !empty($limits) ) {
2643              $found_posts_query = apply_filters_ref_array( 'found_posts_query', array( 'SELECT FOUND_ROWS()', &$this ) );
2644              $this->found_posts = $wpdb->get_var( $found_posts_query );
2645              $this->found_posts = apply_filters_ref_array( 'found_posts', array( $this->found_posts, &$this ) );
2646              $this->max_num_pages = ceil($this->found_posts / $q['posts_per_page']);
2647          }
2648  
2649          // Check post status to determine if post should be displayed.
2650          if ( !empty($this->posts) && ($this->is_single || $this->is_page) ) {
2651              $status = get_post_status($this->posts[0]);
2652              $post_status_obj = get_post_status_object($status);
2653              //$type = get_post_type($this->posts[0]);
2654              if ( !$post_status_obj->public ) {
2655                  if ( ! is_user_logged_in() ) {
2656                      // User must be logged in to view unpublished posts.
2657                      $this->posts = array();
2658                  } else {
2659                      if  ( $post_status_obj->protected ) {
2660                          // User must have edit permissions on the draft to preview.
2661                          if ( ! current_user_can($edit_cap, $this->posts[0]->ID) ) {
2662                              $this->posts = array();
2663                          } else {
2664                              $this->is_preview = true;
2665                              if ( 'future' != $status )
2666                                  $this->posts[0]->post_date = current_time('mysql');
2667                          }
2668                      } elseif ( $post_status_obj->private ) {
2669                          if ( ! current_user_can($read_cap, $this->posts[0]->ID) )
2670                              $this->posts = array();
2671                      } else {
2672                          $this->posts = array();
2673                      }
2674                  }
2675              }
2676  
2677              if ( $this->is_preview && current_user_can( $edit_cap, $this->posts[0]->ID ) )
2678                  $this->posts[0] = apply_filters_ref_array('the_preview', array( $this->posts[0], &$this ));
2679          }
2680  
2681          // Put sticky posts at the top of the posts array
2682          $sticky_posts = get_option('sticky_posts');
2683          if ( $this->is_home && $page <= 1 && is_array($sticky_posts) && !empty($sticky_posts) && !$q['ignore_sticky_posts'] ) {
2684              $num_posts = count($this->posts);
2685              $sticky_offset = 0;
2686              // Loop over posts and relocate stickies to the front.
2687              for ( $i = 0; $i < $num_posts; $i++ ) {
2688                  if ( in_array($this->posts[$i]->ID, $sticky_posts) ) {
2689                      $sticky_post = $this->posts[$i];
2690                      // Remove sticky from current position
2691                      array_splice($this->posts, $i, 1);
2692                      // Move to front, after other stickies
2693                      array_splice($this->posts, $sticky_offset, 0, array($sticky_post));
2694                      // Increment the sticky offset.  The next sticky will be placed at this offset.
2695                      $sticky_offset++;
2696                      // Remove post from sticky posts array
2697                      $offset = array_search($sticky_post->ID, $sticky_posts);
2698                      unset( $sticky_posts[$offset] );
2699                  }
2700              }
2701  
2702              // If any posts have been excluded specifically, Ignore those that are sticky.
2703              if ( !empty($sticky_posts) && !empty($q['post__not_in']) )
2704                  $sticky_posts = array_diff($sticky_posts, $q['post__not_in']);
2705  
2706              // Fetch sticky posts that weren't in the query results
2707              if ( !empty($sticky_posts) ) {
2708                  $stickies__in = implode(',', array_map( 'absint', $sticky_posts ));
2709                  // honor post type(s) if not set to any
2710                  $stickies_where = '';
2711                  if ( 'any' != $post_type && '' != $post_type ) {
2712                      if ( is_array( $post_type ) ) {
2713                          $post_types = join( "', '", $post_type );
2714                      } else {
2715                          $post_types = $post_type;
2716                      }
2717                      $stickies_where = "AND $wpdb->posts.post_type IN ('" . $post_types . "')";
2718                  }
2719  
2720                  $stickies = $wpdb->get_results( "SELECT * FROM $wpdb->posts WHERE $wpdb->posts.ID IN ($stickies__in) $stickies_where" );
2721                  foreach ( $stickies as $sticky_post ) {
2722                      // Ignore sticky posts the current user cannot read or are not published.
2723                      if ( 'publish' != $sticky_post->post_status )
2724                          continue;
2725                      array_splice($this->posts, $sticky_offset, 0, array($sticky_post));
2726                      $sticky_offset++;
2727                  }
2728              }
2729          }
2730  
2731          if ( !$q['suppress_filters'] )
2732              $this->posts = apply_filters_ref_array('the_posts', array( $this->posts, &$this ) );
2733  
2734          $this->post_count = count($this->posts);
2735  
2736          // Sanitize before caching so it'll only get done once
2737          for ( $i = 0; $i < $this->post_count; $i++ ) {
2738              $this->posts[$i] = sanitize_post($this->posts[$i], 'raw');
2739          }
2740  
2741          if ( $q['cache_results'] )
2742              update_post_caches($this->posts, $post_type, $q['update_post_term_cache'], $q['update_post_meta_cache']);
2743  
2744          if ( $this->post_count > 0 ) {
2745              $this->post = $this->posts[0];
2746          }
2747  
2748          return $this->posts;
2749      }
2750  
2751      /**
2752       * Set up the next post and iterate current post index.
2753       *
2754       * @since 1.5.0
2755       * @access public
2756       *
2757       * @return object Next post.
2758       */
2759  	function next_post() {
2760  
2761          $this->current_post++;
2762  
2763          $this->post = $this->posts[$this->current_post];
2764          return $this->post;
2765      }
2766  
2767      /**
2768       * Sets up the current post.
2769       *
2770       * Retrieves the next post, sets up the post, sets the 'in the loop'
2771       * property to true.
2772       *
2773       * @since 1.5.0
2774       * @access public
2775       * @uses $post
2776       * @uses do_action_ref_array() Calls 'loop_start' if loop has just started
2777       */
2778  	function the_post() {
2779          global $post;
2780          $this->in_the_loop = true;
2781  
2782          if ( $this->current_post == -1 ) // loop has just started
2783              do_action_ref_array('loop_start', array(&$this));
2784  
2785          $post = $this->next_post();
2786          setup_postdata($post);
2787      }
2788  
2789      /**
2790       * Whether there are more posts available in the loop.
2791       *
2792       * Calls action 'loop_end', when the loop is complete.
2793       *
2794       * @since 1.5.0
2795       * @access public
2796       * @uses do_action_ref_array() Calls 'loop_end' if loop is ended
2797       *
2798       * @return bool True if posts are available, false if end of loop.
2799       */
2800  	function have_posts() {
2801          if ( $this->current_post + 1 < $this->post_count ) {
2802              return true;
2803          } elseif ( $this->current_post + 1 == $this->post_count && $this->post_count > 0 ) {
2804              do_action_ref_array('loop_end', array(&$this));
2805              // Do some cleaning up after the loop
2806              $this->rewind_posts();
2807          }
2808  
2809          $this->in_the_loop = false;
2810          return false;
2811      }
2812  
2813      /**
2814       * Rewind the posts and reset post index.
2815       *
2816       * @since 1.5.0
2817       * @access public
2818       */
2819  	function rewind_posts() {
2820          $this->current_post = -1;
2821          if ( $this->post_count > 0 ) {
2822              $this->post = $this->posts[0];
2823          }
2824      }
2825  
2826      /**
2827       * Iterate current comment index and return comment object.
2828       *
2829       * @since 2.2.0
2830       * @access public
2831       *
2832       * @return object Comment object.
2833       */
2834  	function next_comment() {
2835          $this->current_comment++;
2836  
2837          $this->comment = $this->comments[$this->current_comment];
2838          return $this->comment;
2839      }
2840  
2841      /**
2842       * Sets up the current comment.
2843       *
2844       * @since 2.2.0
2845       * @access public
2846       * @global object $comment Current comment.
2847       * @uses do_action() Calls 'comment_loop_start' hook when first comment is processed.
2848       */
2849  	function the_comment() {
2850          global $comment;
2851  
2852          $comment = $this->next_comment();
2853  
2854          if ( $this->current_comment == 0 ) {
2855              do_action('comment_loop_start');
2856          }
2857      }
2858  
2859      /**
2860       * Whether there are more comments available.
2861       *
2862       * Automatically rewinds comments when finished.
2863       *
2864       * @since 2.2.0
2865       * @access public
2866       *
2867       * @return bool True, if more comments. False, if no more posts.
2868       */
2869  	function have_comments() {
2870          if ( $this->current_comment + 1 < $this->comment_count ) {
2871              return true;
2872          } elseif ( $this->current_comment + 1 == $this->comment_count ) {
2873              $this->rewind_comments();
2874          }
2875  
2876          return false;
2877      }
2878  
2879      /**
2880       * Rewind the comments, resets the comment index and comment to first.
2881       *
2882       * @since 2.2.0
2883       * @access public
2884       */
2885  	function rewind_comments() {
2886          $this->current_comment = -1;
2887          if ( $this->comment_count > 0 ) {
2888              $this->comment = $this->comments[0];
2889          }
2890      }
2891  
2892      /**
2893       * Sets up the WordPress query by parsing query string.
2894       *
2895       * @since 1.5.0
2896       * @access public
2897       *
2898       * @param string $query URL query string.
2899       * @return array List of posts.
2900       */
2901      function &query( $query ) {
2902          $this->init();
2903          $this->query = $this->query_vars = wp_parse_args( $query );
2904          return $this->get_posts();
2905      }
2906  
2907      /**
2908       * Retrieve queried object.
2909       *
2910       * If queried object is not set, then the queried object will be set from
2911       * the category, tag, taxonomy, posts page, single post, page, or author
2912       * query variable. After it is set up, it will be returned.
2913       *
2914       * @since 1.5.0
2915       * @access public
2916       *
2917       * @return object
2918       */
2919  	function get_queried_object() {
2920          if ( isset($this->queried_object) )
2921              return $this->queried_object;
2922  
2923          $this->queried_object = NULL;
2924          $this->queried_object_id = 0;
2925  
2926          if ( $this->is_category || $this->is_tag || $this->is_tax ) {
2927              $tax_query_in_and = wp_list_filter( $this->tax_query->queries, array( 'operator' => 'NOT IN' ), 'NOT' );
2928  
2929              $query = reset( $tax_query_in_and );
2930  
2931              if ( 'term_id' == $query['field'] )
2932                  $term = get_term( reset( $query['terms'] ), $query['taxonomy'] );
2933              else
2934                  $term = get_term_by( $query['field'], reset( $query['terms'] ), $query['taxonomy'] );
2935  
2936              if ( $term && ! is_wp_error($term) )  {
2937                  $this->queried_object = $term;
2938                  $this->queried_object_id = (int) $term->term_id;
2939  
2940                  if ( $this->is_category )
2941                      _make_cat_compat( $this->queried_object );
2942              }
2943          } elseif ( $this->is_post_type_archive ) {
2944              $this->queried_object = get_post_type_object( $this->get('post_type') );
2945          } elseif ( $this->is_posts_page ) {
2946              $page_for_posts = get_option('page_for_posts');
2947              $this->queried_object = & get_page( $page_for_posts );
2948              $this->queried_object_id = (int) $this->queried_object->ID;
2949          } elseif ( $this->is_singular && !is_null($this->post) ) {
2950              $this->queried_object = $this->post;
2951              $this->queried_object_id = (int) $this->post->ID;
2952          } elseif ( $this->is_author ) {
2953              $this->queried_object_id = (int) $this->get('author');
2954              $this->queried_object = get_userdata( $this->queried_object_id );
2955          }
2956  
2957          return $this->queried_object;
2958      }
2959  
2960      /**
2961       * Retrieve ID of the current queried object.
2962       *
2963       * @since 1.5.0
2964       * @access public
2965       *
2966       * @return int
2967       */
2968  	function get_queried_object_id() {
2969          $this->get_queried_object();
2970  
2971          if ( isset($this->queried_object_id) ) {
2972              return $this->queried_object_id;
2973          }
2974  
2975          return 0;
2976      }
2977  
2978      /**
2979       * Constructor.
2980       *
2981       * Sets up the WordPress query, if parameter is not empty.
2982       *
2983       * @since 1.5.0
2984       * @access public
2985       *
2986       * @param string $query URL query string.
2987       * @return WP_Query
2988       */
2989  	function __construct($query = '') {
2990          if ( ! empty($query) ) {
2991              $this->query($query);
2992          }
2993      }
2994  
2995      /**
2996        * Is the query for an archive page?
2997        *
2998        * Month, Year, Category, Author, Post Type archive...
2999       *
3000        * @since 3.1.0
3001        *
3002        * @return bool
3003        */
3004  	function is_archive() {
3005          return (bool) $this->is_archive;
3006      }
3007  
3008      /**
3009       * Is the query for a post type archive page?
3010       *
3011       * @since 3.1.0
3012       *
3013       * @param mixed $post_types Optional. Post type or array of posts types to check against.
3014       * @return bool
3015       */
3016  	function is_post_type_archive( $post_types = '' ) {
3017          if ( empty( $post_types ) || !$this->is_post_type_archive )
3018              return (bool) $this->is_post_type_archive;
3019  
3020          $post_type_object = $this->get_queried_object();
3021  
3022          return in_array( $post_type_object->name, (array) $post_types );
3023      }
3024  
3025      /**
3026       * Is the query for an attachment page?
3027       *
3028       * @since 3.1.0
3029       *
3030       * @return bool
3031       */
3032  	function is_attachment() {
3033          return (bool) $this->is_attachment;
3034      }
3035  
3036      /**
3037       * Is the query for an author archive page?
3038       *
3039       * If the $author parameter is specified, this function will additionally
3040       * check if the query is for one of the authors specified.
3041       *
3042       * @since 3.1.0
3043       *
3044       * @param mixed $author Optional. User ID, nickname, nicename, or array of User IDs, nicknames, and nicenames
3045       * @return bool
3046       */
3047  	function is_author( $author = '' ) {
3048          if ( !$this->is_author )
3049              return false;
3050  
3051          if ( empty($author) )
3052              return true;
3053  
3054          $author_obj = $this->get_queried_object();
3055  
3056          $author = (array) $author;
3057  
3058          if ( in_array( $author_obj->ID, $author ) )
3059              return true;
3060          elseif ( in_array( $author_obj->nickname, $author ) )
3061              return true;
3062          elseif ( in_array( $author_obj->user_nicename, $author ) )
3063              return true;
3064  
3065          return false;
3066      }
3067  
3068      /**
3069       * Is the query for a category archive page?
3070       *
3071       * If the $category parameter is specified, this function will additionally
3072       * check if the query is for one of the categories specified.
3073       *
3074       * @since 3.1.0
3075       *
3076       * @param mixed $category Optional. Category ID, name, slug, or array of Category IDs, names, and slugs.
3077       * @return bool
3078       */
3079  	function is_category( $category = '' ) {
3080          if ( !$this->is_category )
3081              return false;
3082  
3083          if ( empty($category) )
3084              return true;
3085  
3086          $cat_obj = $this->get_queried_object();
3087  
3088          $category = (array) $category;
3089  
3090          if ( in_array( $cat_obj->term_id, $category ) )
3091              return true;
3092          elseif ( in_array( $cat_obj->name, $category ) )
3093              return true;
3094          elseif ( in_array( $cat_obj->slug, $category ) )
3095              return true;
3096  
3097          return false;
3098      }
3099  
3100      /**
3101       * Is the query for a tag archive page?
3102       *
3103       * If the $tag parameter is specified, this function will additionally
3104       * check if the query is for one of the tags specified.
3105       *
3106       * @since 3.1.0
3107       *
3108       * @param mixed $slug Optional. Tag slug or array of slugs.
3109       * @return bool
3110       */
3111  	function is_tag( $slug = '' ) {
3112          if ( !$this->is_tag )
3113              return false;
3114  
3115          if ( empty( $slug ) )
3116              return true;
3117  
3118          $tag_obj = $this->get_queried_object();
3119  
3120          $slug = (array) $slug;
3121  
3122          if ( in_array( $tag_obj->slug, $slug ) )
3123              return true;
3124  
3125          return false;
3126      }
3127  
3128      /**
3129       * Is the query for a taxonomy archive page?
3130       *
3131       * If the $taxonomy parameter is specified, this function will additionally
3132       * check if the query is for that specific $taxonomy.
3133       *
3134       * If the $term parameter is specified in addition to the $taxonomy parameter,
3135       * this function will additionally check if the query is for one of the terms
3136       * specified.
3137       *
3138       * @since 3.1.0
3139       *
3140       * @param mixed $taxonomy Optional. Taxonomy slug or slugs.
3141       * @param mixed $term. Optional. Term ID, name, slug or array of Term IDs, names, and slugs.
3142       * @return bool
3143       */
3144  	function is_tax( $taxonomy = '', $term = '' ) {
3145          global $wp_taxonomies;
3146  
3147          if ( !$this->is_tax )
3148              return false;
3149  
3150          if ( empty( $taxonomy ) )
3151              return true;
3152  
3153          $queried_object = $this->get_queried_object();
3154          $tax_array = array_intersect( array_keys( $wp_taxonomies ), (array) $taxonomy );
3155          $term_array = (array) $term;
3156  
3157          if ( empty( $term ) ) // Only a Taxonomy provided
3158              return isset( $queried_object->taxonomy ) && count( $tax_array ) && in_array( $queried_object->taxonomy, $tax_array );
3159  
3160          return isset( $queried_object->term_id ) &&
3161              count( array_intersect(
3162                  array( $queried_object->term_id, $queried_object->name, $queried_object->slug ),
3163                  $term_array
3164              ) );
3165      }
3166  
3167      /**
3168       * Whether the current URL is within the comments popup window.
3169       *
3170       * @since 3.1.0
3171       *
3172       * @return bool
3173       */
3174  	function is_comments_popup() {
3175          return (bool) $this->is_comments_popup;
3176      }
3177  
3178      /**
3179       * Is the query for a date archive?
3180       *
3181       * @since 3.1.0
3182       *
3183       * @return bool
3184       */
3185  	function is_date() {
3186          return (bool) $this->is_date;
3187      }
3188  
3189  
3190      /**
3191       * Is the query for a day archive?
3192       *
3193       * @since 3.1.0
3194       *
3195       * @return bool
3196       */
3197  	function is_day() {
3198          return (bool) $this->is_day;
3199      }
3200  
3201      /**
3202       * Is the query for a feed?
3203       *
3204       * @since 3.1.0
3205       *
3206       * @param string|array $feeds Optional feed types to check.
3207       * @return bool
3208       */
3209  	function is_feed( $feeds = '' ) {
3210          if ( empty( $feeds ) || ! $this->is_feed )
3211              return (bool) $this->is_feed;
3212          $qv = $this->get( 'feed' );
3213          if ( 'feed' == $qv )
3214              $qv = get_default_feed();
3215          return in_array( $qv, (array) $feeds );
3216      }
3217  
3218      /**
3219       * Is the query for a comments feed?
3220       *
3221       * @since 3.1.0
3222       *
3223       * @return bool
3224       */
3225  	function is_comment_feed() {
3226          return (bool) $this->is_comment_feed;
3227      }
3228  
3229      /**
3230       * Is the query for the front page of the site?
3231       *
3232       * This is for what is displayed at your site's main URL.
3233       *
3234       * Depends on the site's "Front page displays" Reading Settings 'show_on_front' and 'page_on_front'.
3235       *
3236       * If you set a static page for the front page of your site, this function will return
3237       * true when viewing that page.
3238       *
3239       * Otherwise the same as @see WP_Query::is_home()
3240       *
3241       * @since 3.1.0
3242       * @uses is_home()
3243       * @uses get_option()
3244       *
3245       * @return bool True, if front of site.
3246       */
3247  	function is_front_page() {
3248          // most likely case
3249          if ( 'posts' == get_option( 'show_on_front') && $this->is_home() )
3250              return true;
3251          elseif ( 'page' == get_option( 'show_on_front') && get_option( 'page_on_front' ) && $this->is_page( get_option( 'page_on_front' ) ) )
3252              return true;
3253          else
3254              return false;
3255      }
3256  
3257      /**
3258       * Is the query for the blog homepage?
3259       *
3260       * This is the page which shows the time based blog content of your site.
3261       *
3262       * Depends on the site's "Front page displays" Reading Settings 'show_on_front' and 'page_for_posts'.
3263       *
3264       * If you set a static page for the front page of your site, this function will return
3265       * true only on the page you set as the "Posts page".
3266       *
3267       * @see WP_Query::is_front_page()
3268       *
3269       * @since 3.1.0
3270       *
3271       * @return bool True if blog view homepage.
3272       */
3273  	function is_home() {
3274          return (bool) $this->is_home;
3275      }
3276  
3277      /**
3278       * Is the query for a month archive?
3279       *
3280       * @since 3.1.0
3281       *
3282       * @return bool
3283       */
3284  	function is_month() {
3285          return (bool) $this->is_month;
3286      }
3287  
3288      /**
3289       * Is the query for a single page?
3290       *
3291       * If the $page parameter is specified, this function will additionally
3292       * check if the query is for one of the pages specified.
3293       *
3294       * @see WP_Query::is_single()
3295       * @see WP_Query::is_singular()
3296       *
3297       * @since 3.1.0
3298       *
3299       * @param mixed $page Page ID, title, slug, or array of such.
3300       * @return bool
3301       */
3302  	function is_page( $page = '' ) {
3303          if ( !$this->is_page )
3304              return false;
3305  
3306          if ( empty( $page ) )
3307              return true;
3308  
3309          $page_obj = $this->get_queried_object();
3310  
3311          $page = (array) $page;
3312  
3313          if ( in_array( $page_obj->ID, $page ) )
3314              return true;
3315          elseif ( in_array( $page_obj->post_title, $page ) )
3316              return true;
3317          else if ( in_array( $page_obj->post_name, $page ) )
3318              return true;
3319  
3320          return false;
3321      }
3322  
3323      /**
3324       * Is the query for paged result and not for the first page?
3325       *
3326       * @since 3.1.0
3327       *
3328       * @return bool
3329       */
3330  	function is_paged() {
3331          return (bool) $this->is_paged;
3332      }
3333  
3334      /**
3335       * Is the query for a post or page preview?
3336       *
3337       * @since 3.1.0
3338       *
3339       * @return bool
3340       */
3341  	function is_preview() {
3342          return (bool) $this->is_preview;
3343      }
3344  
3345      /**
3346       * Is the query for the robots file?
3347       *
3348       * @since 3.1.0
3349       *
3350       * @return bool
3351       */
3352  	function is_robots() {
3353          return (bool) $this->is_robots;
3354      }
3355  
3356      /**
3357       * Is the query for a search?
3358       *
3359       * @since 3.1.0
3360       *
3361       * @return bool
3362       */
3363  	function is_search() {
3364          return (bool) $this->is_search;
3365      }
3366  
3367      /**
3368       * Is the query for a single post?
3369       *
3370       * Works for any post type, except attachments and pages
3371       *
3372       * If the $post parameter is specified, this function will additionally
3373       * check if the query is for one of the Posts specified.
3374       *
3375       * @see WP_Query::is_page()
3376       * @see WP_Query::is_singular()
3377       *
3378       * @since 3.1.0
3379       *
3380       * @param mixed $post Post ID, title, slug, or array of such.
3381       * @return bool
3382       */
3383  	function is_single( $post = '' ) {
3384          if ( !$this->is_single )
3385              return false;
3386  
3387          if ( empty($post) )
3388              return true;
3389  
3390          $post_obj = $this->get_queried_object();
3391  
3392          $post = (array) $post;
3393  
3394          if ( in_array( $post_obj->ID, $post ) )
3395              return true;
3396          elseif ( in_array( $post_obj->post_title, $post ) )
3397              return true;
3398          elseif ( in_array( $post_obj->post_name, $post ) )
3399              return true;
3400  
3401          return false;
3402      }
3403  
3404      /**
3405       * Is the query for a single post of any post type (post, attachment, page, ... )?
3406       *
3407       * If the $post_types parameter is specified, this function will additionally
3408       * check if the query is for one of the Posts Types specified.
3409       *
3410       * @see WP_Query::is_page()
3411       * @see WP_Query::is_single()
3412       *
3413       * @since 3.1.0
3414       *
3415       * @param mixed $post_types Optional. Post Type or array of Post Types
3416       * @return bool
3417       */
3418  	function is_singular( $post_types = '' ) {
3419          if ( empty( $post_types ) || !$this->is_singular )
3420              return (bool) $this->is_singular;
3421  
3422          $post_obj = $this->get_queried_object();
3423  
3424          return in_array( $post_obj->post_type, (array) $post_types );
3425      }
3426  
3427      /**
3428       * Is the query for a specific time?
3429       *
3430       * @since 3.1.0
3431       *
3432       * @return bool
3433       */
3434  	function is_time() {
3435          return (bool) $this->is_time;
3436      }
3437  
3438      /**
3439       * Is the query for a trackback endpoint call?
3440       *
3441       * @since 3.1.0
3442       *
3443       * @return bool
3444       */
3445  	function is_trackback() {
3446          return (bool) $this->is_trackback;
3447      }
3448  
3449      /**
3450       * Is the query for a specific year?
3451       *
3452       * @since 3.1.0
3453       *
3454       * @return bool
3455       */
3456  	function is_year() {
3457          return (bool) $this->is_year;
3458      }
3459  
3460      /**
3461       * Is the query a 404 (returns no results)?
3462       *
3463       * @since 3.1.0
3464       *
3465       * @return bool
3466       */
3467  	function is_404() {
3468          return (bool) $this->is_404;
3469      }
3470  }
3471  
3472  /**
3473   * Redirect old slugs to the correct permalink.
3474   *
3475   * Attempts to find the current slug from the past slugs.
3476   *
3477   * @since 2.1.0
3478   * @uses $wp_query
3479   * @uses $wpdb
3480   *
3481   * @return null If no link is found, null is returned.
3482   */
3483  function wp_old_slug_redirect() {
3484      global $wp_query;
3485      if ( is_404() && '' != $wp_query->query_vars['name'] ) :
3486          global $wpdb;
3487  
3488          // Guess the current post_type based on the query vars.
3489          if ( get_query_var('post_type') )
3490              $post_type = get_query_var('post_type');
3491          elseif ( !empty($wp_query->query_vars['pagename']) )
3492              $post_type = 'page';
3493          else
3494              $post_type = 'post';
3495  
3496          // Do not attempt redirect for hierarchical post types
3497          if ( is_post_type_hierarchical( $post_type ) )
3498              return;
3499  
3500          $query = $wpdb->prepare("SELECT post_id FROM $wpdb->postmeta, $wpdb->posts WHERE ID = post_id AND post_type = %s AND meta_key = '_wp_old_slug' AND meta_value = %s", $post_type, $wp_query->query_vars['name']);
3501  
3502          // if year, monthnum, or day have been specified, make our query more precise
3503          // just in case there are multiple identical _wp_old_slug values
3504          if ( '' != $wp_query->query_vars['year'] )
3505              $query .= $wpdb->prepare(" AND YEAR(post_date) = %d", $wp_query->query_vars['year']);
3506          if ( '' != $wp_query->query_vars['monthnum'] )
3507              $query .= $wpdb->prepare(" AND MONTH(post_date) = %d", $wp_query->query_vars['monthnum']);
3508          if ( '' != $wp_query->query_vars['day'] )
3509              $query .= $wpdb->prepare(" AND DAYOFMONTH(post_date) = %d", $wp_query->query_vars['day']);
3510  
3511          $id = (int) $wpdb->get_var($query);
3512  
3513          if ( ! $id )
3514              return;
3515  
3516          $link = get_permalink($id);
3517  
3518          if ( !$link )
3519              return;
3520  
3521          wp_redirect( $link, 301 ); // Permanent redirect
3522          exit;
3523      endif;
3524  }
3525  
3526  /**
3527   * Set up global post data.
3528   *
3529   * @since 1.5.0
3530   *
3531   * @param object $post Post data.
3532   * @uses do_action_ref_array() Calls 'the_post'
3533   * @return bool True when finished.
3534   */
3535  function setup_postdata($post) {
3536      global $id, $authordata, $currentday, $currentmonth, $page, $pages, $multipage, $more, $numpages;
3537  
3538      $id = (int) $post->ID;
3539  
3540      $authordata = get_userdata($post->post_author);
3541  
3542      $currentday = mysql2date('d.m.y', $post->post_date, false);
3543      $currentmonth = mysql2date('m', $post->post_date, false);
3544      $numpages = 1;
3545      $page = get_query_var('page');
3546      if ( !$page )
3547          $page = 1;
3548      if ( is_single() || is_page() || is_feed() )
3549          $more = 1;
3550      $content = $post->post_content;
3551      if ( strpos( $content, '<!--nextpage-->' ) ) {
3552          if ( $page > 1 )
3553              $more = 1;
3554          $multipage = 1;
3555          $content = str_replace("\n<!--nextpage-->\n", '<!--nextpage-->', $content);
3556          $content = str_replace("\n<!--nextpage-->", '<!--nextpage-->', $content);
3557          $content = str_replace("<!--nextpage-->\n", '<!--nextpage-->', $content);
3558          $pages = explode('<!--nextpage-->', $content);
3559          $numpages = count($pages);
3560      } else {
3561          $pages = array( $post->post_content );
3562          $multipage = 0;
3563      }
3564  
3565      do_action_ref_array('the_post', array(&$post));
3566  
3567      return true;
3568  }
3569  ?>


Generated: Wed Jun 1 08:30:02 2011 Cross-referenced by PHPXref 0.7
Provided by Yoast and awesome WordPress Hosting