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