WordPress 4.7
[autoinstalls/wordpress.git] / wp-includes / query.php
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 https://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  * @since 1.5.0
18  * @since 3.9.0 The `$default` argument was introduced.
19  *
20  * @global WP_Query $wp_query Global WP_Query instance.
21  *
22  * @param string $var       The variable key to retrieve.
23  * @param mixed  $default   Optional. Value to return if the query variable is not set. Default empty.
24  * @return mixed Contents of the query variable.
25  */
26 function get_query_var( $var, $default = '' ) {
27         global $wp_query;
28         return $wp_query->get( $var, $default );
29 }
30
31 /**
32  * Retrieve the currently-queried object.
33  *
34  * Wrapper for WP_Query::get_queried_object().
35  *
36  * @since 3.1.0
37  * @access public
38  *
39  * @global WP_Query $wp_query Global WP_Query instance.
40  *
41  * @return object Queried object.
42  */
43 function get_queried_object() {
44         global $wp_query;
45         return $wp_query->get_queried_object();
46 }
47
48 /**
49  * Retrieve ID of the current queried object.
50  *
51  * Wrapper for WP_Query::get_queried_object_id().
52  *
53  * @since 3.1.0
54  *
55  * @global WP_Query $wp_query Global WP_Query instance.
56  *
57  * @return int ID of the queried object.
58  */
59 function get_queried_object_id() {
60         global $wp_query;
61         return $wp_query->get_queried_object_id();
62 }
63
64 /**
65  * Set query variable.
66  *
67  * @since 2.2.0
68  *
69  * @global WP_Query $wp_query Global WP_Query instance.
70  *
71  * @param string $var   Query variable key.
72  * @param mixed  $value Query variable value.
73  */
74 function set_query_var( $var, $value ) {
75         global $wp_query;
76         $wp_query->set( $var, $value );
77 }
78
79 /**
80  * Sets up The Loop with query parameters.
81  *
82  * Note: This function will completely override the main query and isn't intended for use
83  * by plugins or themes. Its overly-simplistic approach to modifying the main query can be
84  * problematic and should be avoided wherever possible. In most cases, there are better,
85  * more performant options for modifying the main query such as via the {@see 'pre_get_posts'}
86  * action within WP_Query.
87  *
88  * This must not be used within the WordPress Loop.
89  *
90  * @since 1.5.0
91  *
92  * @global WP_Query $wp_query Global WP_Query instance.
93  *
94  * @param array|string $query Array or string of WP_Query arguments.
95  * @return array List of post objects.
96  */
97 function query_posts($query) {
98         $GLOBALS['wp_query'] = new WP_Query();
99         return $GLOBALS['wp_query']->query($query);
100 }
101
102 /**
103  * Destroys the previous query and sets up a new query.
104  *
105  * This should be used after query_posts() and before another query_posts().
106  * This will remove obscure bugs that occur when the previous WP_Query object
107  * is not destroyed properly before another is set up.
108  *
109  * @since 2.3.0
110  *
111  * @global WP_Query $wp_query     Global WP_Query instance.
112  * @global WP_Query $wp_the_query Copy of the global WP_Query instance created during wp_reset_query().
113  */
114 function wp_reset_query() {
115         $GLOBALS['wp_query'] = $GLOBALS['wp_the_query'];
116         wp_reset_postdata();
117 }
118
119 /**
120  * After looping through a separate query, this function restores
121  * the $post global to the current post in the main query.
122  *
123  * @since 3.0.0
124  *
125  * @global WP_Query $wp_query Global WP_Query instance.
126  */
127 function wp_reset_postdata() {
128         global $wp_query;
129
130         if ( isset( $wp_query ) ) {
131                 $wp_query->reset_postdata();
132         }
133 }
134
135 /*
136  * Query type checks.
137  */
138
139 /**
140  * Is the query for an existing archive page?
141  *
142  * Month, Year, Category, Author, Post Type archive...
143  *
144  * @since 1.5.0
145  *
146  * @global WP_Query $wp_query Global WP_Query instance.
147  *
148  * @return bool
149  */
150 function is_archive() {
151         global $wp_query;
152
153         if ( ! isset( $wp_query ) ) {
154                 _doing_it_wrong( __FUNCTION__, __( 'Conditional query tags do not work before the query is run. Before then, they always return false.' ), '3.1.0' );
155                 return false;
156         }
157
158         return $wp_query->is_archive();
159 }
160
161 /**
162  * Is the query for an existing post type archive page?
163  *
164  * @since 3.1.0
165  *
166  * @global WP_Query $wp_query Global WP_Query instance.
167  *
168  * @param string|array $post_types Optional. Post type or array of posts types to check against.
169  * @return bool
170  */
171 function is_post_type_archive( $post_types = '' ) {
172         global $wp_query;
173
174         if ( ! isset( $wp_query ) ) {
175                 _doing_it_wrong( __FUNCTION__, __( 'Conditional query tags do not work before the query is run. Before then, they always return false.' ), '3.1.0' );
176                 return false;
177         }
178
179         return $wp_query->is_post_type_archive( $post_types );
180 }
181
182 /**
183  * Is the query for an existing attachment page?
184  *
185  * @since 2.0.0
186  *
187  * @global WP_Query $wp_query Global WP_Query instance.
188  *
189  * @param int|string|array|object $attachment Attachment ID, title, slug, or array of such.
190  * @return bool
191  */
192 function is_attachment( $attachment = '' ) {
193         global $wp_query;
194
195         if ( ! isset( $wp_query ) ) {
196                 _doing_it_wrong( __FUNCTION__, __( 'Conditional query tags do not work before the query is run. Before then, they always return false.' ), '3.1.0' );
197                 return false;
198         }
199
200         return $wp_query->is_attachment( $attachment );
201 }
202
203 /**
204  * Is the query for an existing author archive page?
205  *
206  * If the $author parameter is specified, this function will additionally
207  * check if the query is for one of the authors specified.
208  *
209  * @since 1.5.0
210  *
211  * @global WP_Query $wp_query Global WP_Query instance.
212  *
213  * @param mixed $author Optional. User ID, nickname, nicename, or array of User IDs, nicknames, and nicenames
214  * @return bool
215  */
216 function is_author( $author = '' ) {
217         global $wp_query;
218
219         if ( ! isset( $wp_query ) ) {
220                 _doing_it_wrong( __FUNCTION__, __( 'Conditional query tags do not work before the query is run. Before then, they always return false.' ), '3.1.0' );
221                 return false;
222         }
223
224         return $wp_query->is_author( $author );
225 }
226
227 /**
228  * Is the query for an existing category archive page?
229  *
230  * If the $category parameter is specified, this function will additionally
231  * check if the query is for one of the categories specified.
232  *
233  * @since 1.5.0
234  *
235  * @global WP_Query $wp_query Global WP_Query instance.
236  *
237  * @param mixed $category Optional. Category ID, name, slug, or array of Category IDs, names, and slugs.
238  * @return bool
239  */
240 function is_category( $category = '' ) {
241         global $wp_query;
242
243         if ( ! isset( $wp_query ) ) {
244                 _doing_it_wrong( __FUNCTION__, __( 'Conditional query tags do not work before the query is run. Before then, they always return false.' ), '3.1.0' );
245                 return false;
246         }
247
248         return $wp_query->is_category( $category );
249 }
250
251 /**
252  * Is the query for an existing tag archive page?
253  *
254  * If the $tag parameter is specified, this function will additionally
255  * check if the query is for one of the tags specified.
256  *
257  * @since 2.3.0
258  *
259  * @global WP_Query $wp_query Global WP_Query instance.
260  *
261  * @param mixed $tag Optional. Tag ID, name, slug, or array of Tag IDs, names, and slugs.
262  * @return bool
263  */
264 function is_tag( $tag = '' ) {
265         global $wp_query;
266
267         if ( ! isset( $wp_query ) ) {
268                 _doing_it_wrong( __FUNCTION__, __( 'Conditional query tags do not work before the query is run. Before then, they always return false.' ), '3.1.0' );
269                 return false;
270         }
271
272         return $wp_query->is_tag( $tag );
273 }
274
275 /**
276  * Is the query for an existing custom taxonomy archive page?
277  *
278  * If the $taxonomy parameter is specified, this function will additionally
279  * check if the query is for that specific $taxonomy.
280  *
281  * If the $term parameter is specified in addition to the $taxonomy parameter,
282  * this function will additionally check if the query is for one of the terms
283  * specified.
284  *
285  * @since 2.5.0
286  *
287  * @global WP_Query $wp_query Global WP_Query instance.
288  *
289  * @param string|array     $taxonomy Optional. Taxonomy slug or slugs.
290  * @param int|string|array $term     Optional. Term ID, name, slug or array of Term IDs, names, and slugs.
291  * @return bool True for custom taxonomy archive pages, false for built-in taxonomies (category and tag archives).
292  */
293 function is_tax( $taxonomy = '', $term = '' ) {
294         global $wp_query;
295
296         if ( ! isset( $wp_query ) ) {
297                 _doing_it_wrong( __FUNCTION__, __( 'Conditional query tags do not work before the query is run. Before then, they always return false.' ), '3.1.0' );
298                 return false;
299         }
300
301         return $wp_query->is_tax( $taxonomy, $term );
302 }
303
304 /**
305  * Is the query for an existing date archive?
306  *
307  * @since 1.5.0
308  *
309  * @global WP_Query $wp_query Global WP_Query instance.
310  *
311  * @return bool
312  */
313 function is_date() {
314         global $wp_query;
315
316         if ( ! isset( $wp_query ) ) {
317                 _doing_it_wrong( __FUNCTION__, __( 'Conditional query tags do not work before the query is run. Before then, they always return false.' ), '3.1.0' );
318                 return false;
319         }
320
321         return $wp_query->is_date();
322 }
323
324 /**
325  * Is the query for an existing day archive?
326  *
327  * @since 1.5.0
328  *
329  * @global WP_Query $wp_query Global WP_Query instance.
330  *
331  * @return bool
332  */
333 function is_day() {
334         global $wp_query;
335
336         if ( ! isset( $wp_query ) ) {
337                 _doing_it_wrong( __FUNCTION__, __( 'Conditional query tags do not work before the query is run. Before then, they always return false.' ), '3.1.0' );
338                 return false;
339         }
340
341         return $wp_query->is_day();
342 }
343
344 /**
345  * Is the query for a feed?
346  *
347  * @since 1.5.0
348  *
349  * @global WP_Query $wp_query Global WP_Query instance.
350  *
351  * @param string|array $feeds Optional feed types to check.
352  * @return bool
353  */
354 function is_feed( $feeds = '' ) {
355         global $wp_query;
356
357         if ( ! isset( $wp_query ) ) {
358                 _doing_it_wrong( __FUNCTION__, __( 'Conditional query tags do not work before the query is run. Before then, they always return false.' ), '3.1.0' );
359                 return false;
360         }
361
362         return $wp_query->is_feed( $feeds );
363 }
364
365 /**
366  * Is the query for a comments feed?
367  *
368  * @since 3.0.0
369  *
370  * @global WP_Query $wp_query Global WP_Query instance.
371  *
372  * @return bool
373  */
374 function is_comment_feed() {
375         global $wp_query;
376
377         if ( ! isset( $wp_query ) ) {
378                 _doing_it_wrong( __FUNCTION__, __( 'Conditional query tags do not work before the query is run. Before then, they always return false.' ), '3.1.0' );
379                 return false;
380         }
381
382         return $wp_query->is_comment_feed();
383 }
384
385 /**
386  * Is the query for the front page of the site?
387  *
388  * This is for what is displayed at your site's main URL.
389  *
390  * Depends on the site's "Front page displays" Reading Settings 'show_on_front' and 'page_on_front'.
391  *
392  * If you set a static page for the front page of your site, this function will return
393  * true when viewing that page.
394  *
395  * Otherwise the same as @see is_home()
396  *
397  * @since 2.5.0
398  *
399  * @global WP_Query $wp_query Global WP_Query instance.
400  *
401  * @return bool True, if front of site.
402  */
403 function is_front_page() {
404         global $wp_query;
405
406         if ( ! isset( $wp_query ) ) {
407                 _doing_it_wrong( __FUNCTION__, __( 'Conditional query tags do not work before the query is run. Before then, they always return false.' ), '3.1.0' );
408                 return false;
409         }
410
411         return $wp_query->is_front_page();
412 }
413
414 /**
415  * Determines if the query is for the blog homepage.
416  *
417  * The blog homepage is the page that shows the time-based blog content of the site.
418  *
419  * is_home() is dependent on the site's "Front page displays" Reading Settings 'show_on_front'
420  * and 'page_for_posts'.
421  *
422  * If a static page is set for the front page of the site, this function will return true only
423  * on the page you set as the "Posts page".
424  *
425  * @since 1.5.0
426  *
427  * @see is_front_page()
428  * @global WP_Query $wp_query Global WP_Query instance.
429  *
430  * @return bool True if blog view homepage, otherwise false.
431  */
432 function is_home() {
433         global $wp_query;
434
435         if ( ! isset( $wp_query ) ) {
436                 _doing_it_wrong( __FUNCTION__, __( 'Conditional query tags do not work before the query is run. Before then, they always return false.' ), '3.1.0' );
437                 return false;
438         }
439
440         return $wp_query->is_home();
441 }
442
443 /**
444  * Is the query for an existing month archive?
445  *
446  * @since 1.5.0
447  *
448  * @global WP_Query $wp_query Global WP_Query instance.
449  *
450  * @return bool
451  */
452 function is_month() {
453         global $wp_query;
454
455         if ( ! isset( $wp_query ) ) {
456                 _doing_it_wrong( __FUNCTION__, __( 'Conditional query tags do not work before the query is run. Before then, they always return false.' ), '3.1.0' );
457                 return false;
458         }
459
460         return $wp_query->is_month();
461 }
462
463 /**
464  * Is the query for an existing single page?
465  *
466  * If the $page parameter is specified, this function will additionally
467  * check if the query is for one of the pages specified.
468  *
469  * @see is_single()
470  * @see is_singular()
471  *
472  * @since 1.5.0
473  *
474  * @global WP_Query $wp_query Global WP_Query instance.
475  *
476  * @param int|string|array $page Optional. Page ID, title, slug, or array of such. Default empty.
477  * @return bool Whether the query is for an existing single page.
478  */
479 function is_page( $page = '' ) {
480         global $wp_query;
481
482         if ( ! isset( $wp_query ) ) {
483                 _doing_it_wrong( __FUNCTION__, __( 'Conditional query tags do not work before the query is run. Before then, they always return false.' ), '3.1.0' );
484                 return false;
485         }
486
487         return $wp_query->is_page( $page );
488 }
489
490 /**
491  * Is the query for paged result and not for the first page?
492  *
493  * @since 1.5.0
494  *
495  * @global WP_Query $wp_query Global WP_Query instance.
496  *
497  * @return bool
498  */
499 function is_paged() {
500         global $wp_query;
501
502         if ( ! isset( $wp_query ) ) {
503                 _doing_it_wrong( __FUNCTION__, __( 'Conditional query tags do not work before the query is run. Before then, they always return false.' ), '3.1.0' );
504                 return false;
505         }
506
507         return $wp_query->is_paged();
508 }
509
510 /**
511  * Is the query for a post or page preview?
512  *
513  * @since 2.0.0
514  *
515  * @global WP_Query $wp_query Global WP_Query instance.
516  *
517  * @return bool
518  */
519 function is_preview() {
520         global $wp_query;
521
522         if ( ! isset( $wp_query ) ) {
523                 _doing_it_wrong( __FUNCTION__, __( 'Conditional query tags do not work before the query is run. Before then, they always return false.' ), '3.1.0' );
524                 return false;
525         }
526
527         return $wp_query->is_preview();
528 }
529
530 /**
531  * Is the query for the robots file?
532  *
533  * @since 2.1.0
534  *
535  * @global WP_Query $wp_query Global WP_Query instance.
536  *
537  * @return bool
538  */
539 function is_robots() {
540         global $wp_query;
541
542         if ( ! isset( $wp_query ) ) {
543                 _doing_it_wrong( __FUNCTION__, __( 'Conditional query tags do not work before the query is run. Before then, they always return false.' ), '3.1.0' );
544                 return false;
545         }
546
547         return $wp_query->is_robots();
548 }
549
550 /**
551  * Is the query for a search?
552  *
553  * @since 1.5.0
554  *
555  * @global WP_Query $wp_query Global WP_Query instance.
556  *
557  * @return bool
558  */
559 function is_search() {
560         global $wp_query;
561
562         if ( ! isset( $wp_query ) ) {
563                 _doing_it_wrong( __FUNCTION__, __( 'Conditional query tags do not work before the query is run. Before then, they always return false.' ), '3.1.0' );
564                 return false;
565         }
566
567         return $wp_query->is_search();
568 }
569
570 /**
571  * Is the query for an existing single post?
572  *
573  * Works for any post type, except attachments and pages
574  *
575  * If the $post parameter is specified, this function will additionally
576  * check if the query is for one of the Posts specified.
577  *
578  * @see is_page()
579  * @see is_singular()
580  *
581  * @since 1.5.0
582  *
583  * @global WP_Query $wp_query Global WP_Query instance.
584  *
585  * @param int|string|array $post Optional. Post ID, title, slug, or array of such. Default empty.
586  * @return bool Whether the query is for an existing single post.
587  */
588 function is_single( $post = '' ) {
589         global $wp_query;
590
591         if ( ! isset( $wp_query ) ) {
592                 _doing_it_wrong( __FUNCTION__, __( 'Conditional query tags do not work before the query is run. Before then, they always return false.' ), '3.1.0' );
593                 return false;
594         }
595
596         return $wp_query->is_single( $post );
597 }
598
599 /**
600  * Is the query for an existing single post of any post type (post, attachment, page, ... )?
601  *
602  * If the $post_types parameter is specified, this function will additionally
603  * check if the query is for one of the Posts Types specified.
604  *
605  * @see is_page()
606  * @see is_single()
607  *
608  * @since 1.5.0
609  *
610  * @global WP_Query $wp_query Global WP_Query instance.
611  *
612  * @param string|array $post_types Optional. Post type or array of post types. Default empty.
613  * @return bool Whether the query is for an existing single post of any of the given post types.
614  */
615 function is_singular( $post_types = '' ) {
616         global $wp_query;
617
618         if ( ! isset( $wp_query ) ) {
619                 _doing_it_wrong( __FUNCTION__, __( 'Conditional query tags do not work before the query is run. Before then, they always return false.' ), '3.1.0' );
620                 return false;
621         }
622
623         return $wp_query->is_singular( $post_types );
624 }
625
626 /**
627  * Is the query for a specific time?
628  *
629  * @since 1.5.0
630  *
631  * @global WP_Query $wp_query Global WP_Query instance.
632  *
633  * @return bool
634  */
635 function is_time() {
636         global $wp_query;
637
638         if ( ! isset( $wp_query ) ) {
639                 _doing_it_wrong( __FUNCTION__, __( 'Conditional query tags do not work before the query is run. Before then, they always return false.' ), '3.1.0' );
640                 return false;
641         }
642
643         return $wp_query->is_time();
644 }
645
646 /**
647  * Is the query for a trackback endpoint call?
648  *
649  * @since 1.5.0
650  *
651  * @global WP_Query $wp_query Global WP_Query instance.
652  *
653  * @return bool
654  */
655 function is_trackback() {
656         global $wp_query;
657
658         if ( ! isset( $wp_query ) ) {
659                 _doing_it_wrong( __FUNCTION__, __( 'Conditional query tags do not work before the query is run. Before then, they always return false.' ), '3.1.0' );
660                 return false;
661         }
662
663         return $wp_query->is_trackback();
664 }
665
666 /**
667  * Is the query for an existing year archive?
668  *
669  * @since 1.5.0
670  *
671  * @global WP_Query $wp_query Global WP_Query instance.
672  *
673  * @return bool
674  */
675 function is_year() {
676         global $wp_query;
677
678         if ( ! isset( $wp_query ) ) {
679                 _doing_it_wrong( __FUNCTION__, __( 'Conditional query tags do not work before the query is run. Before then, they always return false.' ), '3.1.0' );
680                 return false;
681         }
682
683         return $wp_query->is_year();
684 }
685
686 /**
687  * Is the query a 404 (returns no results)?
688  *
689  * @since 1.5.0
690  *
691  * @global WP_Query $wp_query Global WP_Query instance.
692  *
693  * @return bool
694  */
695 function is_404() {
696         global $wp_query;
697
698         if ( ! isset( $wp_query ) ) {
699                 _doing_it_wrong( __FUNCTION__, __( 'Conditional query tags do not work before the query is run. Before then, they always return false.' ), '3.1.0' );
700                 return false;
701         }
702
703         return $wp_query->is_404();
704 }
705
706 /**
707  * Is the query for an embedded post?
708  *
709  * @since 4.4.0
710  *
711  * @global WP_Query $wp_query Global WP_Query instance.
712  *
713  * @return bool Whether we're in an embedded post or not.
714  */
715 function is_embed() {
716         global $wp_query;
717
718         if ( ! isset( $wp_query ) ) {
719                 _doing_it_wrong( __FUNCTION__, __( 'Conditional query tags do not work before the query is run. Before then, they always return false.' ), '3.1.0' );
720                 return false;
721         }
722
723         return $wp_query->is_embed();
724 }
725
726 /**
727  * Is the query the main query?
728  *
729  * @since 3.3.0
730  *
731  * @global WP_Query $wp_query Global WP_Query instance.
732  *
733  * @return bool
734  */
735 function is_main_query() {
736         if ( 'pre_get_posts' === current_filter() ) {
737                 $message = sprintf(
738                         /* translators: 1: pre_get_posts 2: WP_Query->is_main_query() 3: is_main_query() 4: link to codex is_main_query() page. */
739                         __( 'In %1$s, use the %2$s method, not the %3$s function. See %4$s.' ),
740                         '<code>pre_get_posts</code>',
741                         '<code>WP_Query->is_main_query()</code>',
742                         '<code>is_main_query()</code>',
743                         __( 'https://codex.wordpress.org/Function_Reference/is_main_query' )
744                 );
745                 _doing_it_wrong( __FUNCTION__, $message, '3.7.0' );
746         }
747
748         global $wp_query;
749         return $wp_query->is_main_query();
750 }
751
752 /*
753  * The Loop. Post loop control.
754  */
755
756 /**
757  * Whether current WordPress query has results to loop over.
758  *
759  * @since 1.5.0
760  *
761  * @global WP_Query $wp_query Global WP_Query instance.
762  *
763  * @return bool
764  */
765 function have_posts() {
766         global $wp_query;
767         return $wp_query->have_posts();
768 }
769
770 /**
771  * Whether the caller is in the Loop.
772  *
773  * @since 2.0.0
774  *
775  * @global WP_Query $wp_query Global WP_Query instance.
776  *
777  * @return bool True if caller is within loop, false if loop hasn't started or ended.
778  */
779 function in_the_loop() {
780         global $wp_query;
781         return $wp_query->in_the_loop;
782 }
783
784 /**
785  * Rewind the loop posts.
786  *
787  * @since 1.5.0
788  *
789  * @global WP_Query $wp_query Global WP_Query instance.
790  */
791 function rewind_posts() {
792         global $wp_query;
793         $wp_query->rewind_posts();
794 }
795
796 /**
797  * Iterate the post index in the loop.
798  *
799  * @since 1.5.0
800  *
801  * @global WP_Query $wp_query Global WP_Query instance.
802  */
803 function the_post() {
804         global $wp_query;
805         $wp_query->the_post();
806 }
807
808 /*
809  * Comments loop.
810  */
811
812 /**
813  * Whether there are comments to loop over.
814  *
815  * @since 2.2.0
816  *
817  * @global WP_Query $wp_query Global WP_Query instance.
818  *
819  * @return bool
820  */
821 function have_comments() {
822         global $wp_query;
823         return $wp_query->have_comments();
824 }
825
826 /**
827  * Iterate comment index in the comment loop.
828  *
829  * @since 2.2.0
830  *
831  * @global WP_Query $wp_query Global WP_Query instance.
832  *
833  * @return object
834  */
835 function the_comment() {
836         global $wp_query;
837         return $wp_query->the_comment();
838 }
839
840 /**
841  * Redirect old slugs to the correct permalink.
842  *
843  * Attempts to find the current slug from the past slugs.
844  *
845  * @since 2.1.0
846  *
847  * @global wpdb $wpdb WordPress database abstraction object.
848  */
849 function wp_old_slug_redirect() {
850         if ( is_404() && '' !== get_query_var( 'name' ) ) {
851                 global $wpdb;
852
853                 // Guess the current post_type based on the query vars.
854                 if ( get_query_var( 'post_type' ) ) {
855                         $post_type = get_query_var( 'post_type' );
856                 } elseif ( get_query_var( 'attachment' ) ) {
857                         $post_type = 'attachment';
858                 } elseif ( get_query_var( 'pagename' ) ) {
859                         $post_type = 'page';
860                 } else {
861                         $post_type = 'post';
862                 }
863
864                 if ( is_array( $post_type ) ) {
865                         if ( count( $post_type ) > 1 ) {
866                                 return;
867                         }
868                         $post_type = reset( $post_type );
869                 }
870
871                 // Do not attempt redirect for hierarchical post types
872                 if ( is_post_type_hierarchical( $post_type ) ) {
873                         return;
874                 }
875
876                 $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, get_query_var( 'name' ) );
877
878                 // if year, monthnum, or day have been specified, make our query more precise
879                 // just in case there are multiple identical _wp_old_slug values
880                 if ( get_query_var( 'year' ) ) {
881                         $query .= $wpdb->prepare(" AND YEAR(post_date) = %d", get_query_var( 'year' ) );
882                 }
883                 if ( get_query_var( 'monthnum' ) ) {
884                         $query .= $wpdb->prepare(" AND MONTH(post_date) = %d", get_query_var( 'monthnum' ) );
885                 }
886                 if ( get_query_var( 'day' ) ) {
887                         $query .= $wpdb->prepare(" AND DAYOFMONTH(post_date) = %d", get_query_var( 'day' ) );
888                 }
889
890                 $id = (int) $wpdb->get_var( $query );
891
892                 if ( ! $id ) {
893                         return;
894                 }
895
896                 $link = get_permalink( $id );
897
898                 if ( get_query_var( 'paged' ) > 1 ) {
899                         $link = user_trailingslashit( trailingslashit( $link ) . 'page/' . get_query_var( 'paged' ) );
900                 } elseif( is_embed() ) {
901                         $link = user_trailingslashit( trailingslashit( $link ) . 'embed' );
902                 }
903
904                 /**
905                  * Filters the old slug redirect URL.
906                  *
907                  * @since 4.4.0
908                  *
909                  * @param string $link The redirect URL.
910                  */
911                 $link = apply_filters( 'old_slug_redirect_url', $link );
912
913                 if ( ! $link ) {
914                         return;
915                 }
916
917                 wp_redirect( $link, 301 ); // Permanent redirect
918                 exit;
919         }
920 }
921
922 /**
923  * Set up global post data.
924  *
925  * @since 1.5.0
926  * @since 4.4.0 Added the ability to pass a post ID to `$post`.
927  *
928  * @global WP_Query $wp_query Global WP_Query instance.
929  *
930  * @param WP_Post|object|int $post WP_Post instance or Post ID/object.
931  * @return bool True when finished.
932  */
933 function setup_postdata( $post ) {
934         global $wp_query;
935
936         if ( ! empty( $wp_query ) && $wp_query instanceof WP_Query ) {
937                 return $wp_query->setup_postdata( $post );
938         }
939
940         return false;
941 }