| [ XREF Home ] [ Index ] |
PHP Cross Reference of WordPress TrunkProvided by Yoast |
[Summary view] [Print] [Text view]
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 ?>
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
| Generated: Wed Jun 1 08:30:02 2011 |
Cross-referenced by PHPXref 0.7 Provided by Yoast and awesome WordPress Hosting |