WordPress 4.7
[autoinstalls/wordpress.git] / wp-includes / template.php
1 <?php
2 /**
3  * Template loading functions.
4  *
5  * @package WordPress
6  * @subpackage Template
7  */
8
9 /**
10  * Retrieve path to a template
11  *
12  * Used to quickly retrieve the path of a template without including the file
13  * extension. It will also check the parent theme, if the file exists, with
14  * the use of locate_template(). Allows for more generic template location
15  * without the use of the other get_*_template() functions.
16  *
17  * @since 1.5.0
18  *
19  * @param string $type      Filename without extension.
20  * @param array  $templates An optional list of template candidates
21  * @return string Full path to template file.
22  */
23 function get_query_template( $type, $templates = array() ) {
24         $type = preg_replace( '|[^a-z0-9-]+|', '', $type );
25
26         if ( empty( $templates ) )
27                 $templates = array("{$type}.php");
28
29         /**
30          * Filters the list of template filenames that are searched for when retrieving a template to use.
31          *
32          * The last element in the array should always be the fallback template for this query type.
33          *
34          * Possible values for `$type` include: 'index', '404', 'archive', 'author', 'category', 'tag', 'taxonomy', 'date',
35          * 'embed', home', 'frontpage', 'page', 'paged', 'search', 'single', 'singular', and 'attachment'.
36          *
37          * @since 4.7.0
38          *
39          * @param array $templates A list of template candidates, in descending order of priority.
40          */
41         $templates = apply_filters( "{$type}_template_hierarchy", $templates );
42
43         $template = locate_template( $templates );
44
45         /**
46          * Filters the path of the queried template by type.
47          *
48          * The dynamic portion of the hook name, `$type`, refers to the filename -- minus the file
49          * extension and any non-alphanumeric characters delimiting words -- of the file to load.
50          * This hook also applies to various types of files loaded as part of the Template Hierarchy.
51          *
52          * Possible values for `$type` include: 'index', '404', 'archive', 'author', 'category', 'tag', 'taxonomy', 'date',
53          * 'embed', home', 'frontpage', 'page', 'paged', 'search', 'single', 'singular', and 'attachment'.
54          *
55          * @since 1.5.0
56          *
57          * @param string $template Path to the template. See locate_template().
58          */
59         return apply_filters( "{$type}_template", $template );
60 }
61
62 /**
63  * Retrieve path of index template in current or parent template.
64  *
65  * The template hierarchy is filterable via the {@see 'index_template_hierarchy'} hook.
66  * The template path is filterable via the {@see 'index_template'} hook.
67  *
68  * @since 3.0.0
69  *
70  * @see get_query_template()
71  *
72  * @return string Full path to index template file.
73  */
74 function get_index_template() {
75         return get_query_template('index');
76 }
77
78 /**
79  * Retrieve path of 404 template in current or parent template.
80  *
81  * The template hierarchy is filterable via the {@see '404_template_hierarchy'} hook.
82  * The template path is filterable via the {@see '404_template'} hook.
83  *
84  * @since 1.5.0
85  *
86  * @see get_query_template()
87  *
88  * @return string Full path to 404 template file.
89  */
90 function get_404_template() {
91         return get_query_template('404');
92 }
93
94 /**
95  * Retrieve path of archive template in current or parent template.
96  *
97  * The template hierarchy is filterable via the {@see 'archive_template_hierarchy'} hook.
98  * The template path is filterable via the {@see 'archive_template'} hook.
99  *
100  * @since 1.5.0
101  *
102  * @see get_query_template()
103  *
104  * @return string Full path to archive template file.
105  */
106 function get_archive_template() {
107         $post_types = array_filter( (array) get_query_var( 'post_type' ) );
108
109         $templates = array();
110
111         if ( count( $post_types ) == 1 ) {
112                 $post_type = reset( $post_types );
113                 $templates[] = "archive-{$post_type}.php";
114         }
115         $templates[] = 'archive.php';
116
117         return get_query_template( 'archive', $templates );
118 }
119
120 /**
121  * Retrieve path of post type archive template in current or parent template.
122  *
123  * The template hierarchy is filterable via the {@see 'archive_template_hierarchy'} hook.
124  * The template path is filterable via the {@see 'archive_template'} hook.
125  *
126  * @since 3.7.0
127  *
128  * @see get_archive_template()
129  *
130  * @return string Full path to archive template file.
131  */
132 function get_post_type_archive_template() {
133         $post_type = get_query_var( 'post_type' );
134         if ( is_array( $post_type ) )
135                 $post_type = reset( $post_type );
136
137         $obj = get_post_type_object( $post_type );
138         if ( ! $obj->has_archive )
139                 return '';
140
141         return get_archive_template();
142 }
143
144 /**
145  * Retrieve path of author template in current or parent template.
146  *
147  * The hierarchy for this template looks like:
148  *
149  * 1. author-{nicename}.php
150  * 2. author-{id}.php
151  * 3. author.php
152  *
153  * An example of this is:
154  *
155  * 1. author-john.php
156  * 2. author-1.php
157  * 3. author.php
158  *
159  * The template hierarchy is filterable via the {@see 'author_template_hierarchy'} hook.
160  * The template path is filterable via the {@see 'author_template'} hook.
161  *
162  * @since 1.5.0
163  *
164  * @see get_query_template()
165  *
166  * @return string Full path to author template file.
167  */
168 function get_author_template() {
169         $author = get_queried_object();
170
171         $templates = array();
172
173         if ( $author instanceof WP_User ) {
174                 $templates[] = "author-{$author->user_nicename}.php";
175                 $templates[] = "author-{$author->ID}.php";
176         }
177         $templates[] = 'author.php';
178
179         return get_query_template( 'author', $templates );
180 }
181
182 /**
183  * Retrieve path of category template in current or parent template.
184  *
185  * The hierarchy for this template looks like:
186  *
187  * 1. category-{slug}.php
188  * 2. category-{id}.php
189  * 3. category.php
190  *
191  * An example of this is:
192  *
193  * 1. category-news.php
194  * 2. category-2.php
195  * 3. category.php
196  *
197  * The template hierarchy is filterable via the {@see 'category_template_hierarchy'} hook.
198  * The template path is filterable via the {@see 'category_template'} hook.
199  *
200  * @since 1.5.0
201  * @since 4.7.0 The decoded form of `category-{slug}.php` was added to the top of the
202  *              template hierarchy when the category slug contains multibyte characters.
203  *
204  * @see get_query_template()
205  *
206  * @return string Full path to category template file.
207  */
208 function get_category_template() {
209         $category = get_queried_object();
210
211         $templates = array();
212
213         if ( ! empty( $category->slug ) ) {
214
215                 $slug_decoded = urldecode( $category->slug );
216                 if ( $slug_decoded !== $category->slug ) {
217                         $templates[] = "category-{$slug_decoded}.php";
218                 }
219
220                 $templates[] = "category-{$category->slug}.php";
221                 $templates[] = "category-{$category->term_id}.php";
222         }
223         $templates[] = 'category.php';
224
225         return get_query_template( 'category', $templates );
226 }
227
228 /**
229  * Retrieve path of tag template in current or parent template.
230  *
231  * The hierarchy for this template looks like:
232  *
233  * 1. tag-{slug}.php
234  * 2. tag-{id}.php
235  * 3. tag.php
236  *
237  * An example of this is:
238  *
239  * 1. tag-wordpress.php
240  * 2. tag-3.php
241  * 3. tag.php
242  *
243  * The template hierarchy is filterable via the {@see 'tag_template_hierarchy'} hook.
244  * The template path is filterable via the {@see 'tag_template'} hook.
245  *
246  * @since 2.3.0
247  * @since 4.7.0 The decoded form of `tag-{slug}.php` was added to the top of the
248  *              template hierarchy when the tag slug contains multibyte characters.
249  *
250  * @see get_query_template()
251  *
252  * @return string Full path to tag template file.
253  */
254 function get_tag_template() {
255         $tag = get_queried_object();
256
257         $templates = array();
258
259         if ( ! empty( $tag->slug ) ) {
260
261                 $slug_decoded = urldecode( $tag->slug );
262                 if ( $slug_decoded !== $tag->slug ) {
263                         $templates[] = "tag-{$slug_decoded}.php";
264                 }
265
266                 $templates[] = "tag-{$tag->slug}.php";
267                 $templates[] = "tag-{$tag->term_id}.php";
268         }
269         $templates[] = 'tag.php';
270
271         return get_query_template( 'tag', $templates );
272 }
273
274 /**
275  * Retrieve path of custom taxonomy term template in current or parent template.
276  *
277  * The hierarchy for this template looks like:
278  *
279  * 1. taxonomy-{taxonomy_slug}-{term_slug}.php
280  * 2. taxonomy-{taxonomy_slug}.php
281  * 3. taxonomy.php
282  *
283  * An example of this is:
284  *
285  * 1. taxonomy-location-texas.php
286  * 2. taxonomy-location.php
287  * 3. taxonomy.php
288  *
289  * The template hierarchy is filterable via the {@see 'taxonomy_template_hierarchy'} hook.
290  * The template path is filterable via the {@see 'taxonomy_template'} hook.
291  *
292  * @since 2.5.0
293  * @since 4.7.0 The decoded form of `taxonomy-{taxonomy_slug}-{term_slug}.php` was added to the top of the
294  *              template hierarchy when the term slug contains multibyte characters.
295  *
296  * @see get_query_template()
297  *
298  * @return string Full path to custom taxonomy term template file.
299  */
300 function get_taxonomy_template() {
301         $term = get_queried_object();
302
303         $templates = array();
304
305         if ( ! empty( $term->slug ) ) {
306                 $taxonomy = $term->taxonomy;
307
308                 $slug_decoded = urldecode( $term->slug );
309                 if ( $slug_decoded !== $term->slug ) {
310                         $templates[] = "taxonomy-$taxonomy-{$slug_decoded}.php";
311                 }
312
313                 $templates[] = "taxonomy-$taxonomy-{$term->slug}.php";
314                 $templates[] = "taxonomy-$taxonomy.php";
315         }
316         $templates[] = 'taxonomy.php';
317
318         return get_query_template( 'taxonomy', $templates );
319 }
320
321 /**
322  * Retrieve path of date template in current or parent template.
323  *
324  * The template hierarchy is filterable via the {@see 'date_template_hierarchy'} hook.
325  * The template path is filterable via the {@see 'date_template'} hook.
326  *
327  * @since 1.5.0
328  *
329  * @see get_query_template()
330  *
331  * @return string Full path to date template file.
332  */
333 function get_date_template() {
334         return get_query_template('date');
335 }
336
337 /**
338  * Retrieve path of home template in current or parent template.
339  *
340  * The template hierarchy is filterable via the {@see 'home_template_hierarchy'} hook.
341  * The template path is filterable via the {@see 'home_template'} hook.
342  *
343  * @since 1.5.0
344  *
345  * @see get_query_template()
346  *
347  * @return string Full path to home template file.
348  */
349 function get_home_template() {
350         $templates = array( 'home.php', 'index.php' );
351
352         return get_query_template( 'home', $templates );
353 }
354
355 /**
356  * Retrieve path of front page template in current or parent template.
357  *
358  * The template hierarchy is filterable via the {@see 'frontpage_template_hierarchy'} hook.
359  * The template path is filterable via the {@see 'frontpage_template'} hook.
360  *
361  * @since 3.0.0
362  *
363  * @see get_query_template()
364  *
365  * @return string Full path to front page template file.
366  */
367 function get_front_page_template() {
368         $templates = array('front-page.php');
369
370         return get_query_template( 'front_page', $templates );
371 }
372
373 /**
374  * Retrieve path of page template in current or parent template.
375  *
376  * The hierarchy for this template looks like:
377  *
378  * 1. {Page Template}.php
379  * 2. page-{page_name}.php
380  * 3. page-{id}.php
381  * 4. page.php
382  *
383  * An example of this is:
384  *
385  * 1. page-templates/full-width.php
386  * 2. page-about.php
387  * 3. page-4.php
388  * 4. page.php
389  *
390  * The template hierarchy is filterable via the {@see 'page_template_hierarchy'} hook.
391  * The template path is filterable via the {@see 'page_template'} hook.
392  *
393  * @since 1.5.0
394  * @since 4.7.0 The decoded form of `page-{page_name}.php` was added to the top of the
395  *              template hierarchy when the page name contains multibyte characters.
396  *
397  * @see get_query_template()
398  *
399  * @return string Full path to page template file.
400  */
401 function get_page_template() {
402         $id = get_queried_object_id();
403         $template = get_page_template_slug();
404         $pagename = get_query_var('pagename');
405
406         if ( ! $pagename && $id ) {
407                 // If a static page is set as the front page, $pagename will not be set. Retrieve it from the queried object
408                 $post = get_queried_object();
409                 if ( $post )
410                         $pagename = $post->post_name;
411         }
412
413         $templates = array();
414         if ( $template && 0 === validate_file( $template ) )
415                 $templates[] = $template;
416         if ( $pagename ) {
417                 $pagename_decoded = urldecode( $pagename );
418                 if ( $pagename_decoded !== $pagename ) {
419                         $templates[] = "page-{$pagename_decoded}.php";
420                 }
421                 $templates[] = "page-$pagename.php";
422         }
423         if ( $id )
424                 $templates[] = "page-$id.php";
425         $templates[] = 'page.php';
426
427         return get_query_template( 'page', $templates );
428 }
429
430 /**
431  * Retrieve path of search template in current or parent template.
432  *
433  * The template hierarchy is filterable via the {@see 'search_template_hierarchy'} hook.
434  * The template path is filterable via the {@see 'search_template'} hook.
435  *
436  * @since 1.5.0
437  *
438  * @see get_query_template()
439  *
440  * @return string Full path to search template file.
441  */
442 function get_search_template() {
443         return get_query_template('search');
444 }
445
446 /**
447  * Retrieve path of single template in current or parent template. Applies to single Posts,
448  * single Attachments, and single custom post types.
449  *
450  * The hierarchy for this template looks like:
451  *
452  * 1. {Post Type Template}.php
453  * 2. single-{post_type}-{post_name}.php
454  * 3. single-{post_type}.php
455  * 4. single.php
456  *
457  * An example of this is:
458  *
459  * 1. templates/full-width.php
460  * 2. single-post-hello-world.php
461  * 3. single-post.php
462  * 4. single.php
463  *
464  * The template hierarchy is filterable via the {@see 'single_template_hierarchy'} hook.
465  * The template path is filterable via the {@see 'single_template'} hook.
466  *
467  * @since 1.5.0
468  * @since 4.4.0 `single-{post_type}-{post_name}.php` was added to the top of the template hierarchy.
469  * @since 4.7.0 The decoded form of `single-{post_type}-{post_name}.php` was added to the top of the
470  *              template hierarchy when the post name contains multibyte characters.
471  * @since 4.7.0 {Post Type Template}.php was added to the top of the template hierarchy.
472  *
473  * @see get_query_template()
474  *
475  * @return string Full path to single template file.
476  */
477 function get_single_template() {
478         $object = get_queried_object();
479
480         $templates = array();
481
482         if ( ! empty( $object->post_type ) ) {
483                 $template = get_page_template_slug( $object );
484                 if ( $template && 0 === validate_file( $template ) ) {
485                         $templates[] = $template;
486                 }
487
488                 $name_decoded = urldecode( $object->post_name );
489                 if ( $name_decoded !== $object->post_name ) {
490                         $templates[] = "single-{$object->post_type}-{$name_decoded}.php";
491                 }
492
493                 $templates[] = "single-{$object->post_type}-{$object->post_name}.php";
494                 $templates[] = "single-{$object->post_type}.php";
495         }
496
497         $templates[] = "single.php";
498
499         return get_query_template( 'single', $templates );
500 }
501
502 /**
503  * Retrieves an embed template path in the current or parent template.
504  *
505  * The hierarchy for this template looks like:
506  *
507  * 1. embed-{post_type}-{post_format}.php
508  * 2. embed-{post_type}.php
509  * 3. embed.php
510  *
511  * An example of this is:
512  *
513  * 1. embed-post-audio.php
514  * 2. embed-post.php
515  * 3. embed.php
516  *
517  * The template hierarchy is filterable via the {@see 'embed_template_hierarchy'} hook.
518  * The template path is filterable via the {@see 'embed_template'} hook.
519  *
520  * @since 4.5.0
521  *
522  * @see get_query_template()
523  *
524  * @return string Full path to embed template file.
525  */
526 function get_embed_template() {
527         $object = get_queried_object();
528
529         $templates = array();
530
531         if ( ! empty( $object->post_type ) ) {
532                 $post_format = get_post_format( $object );
533                 if ( $post_format ) {
534                         $templates[] = "embed-{$object->post_type}-{$post_format}.php";
535                 }
536                 $templates[] = "embed-{$object->post_type}.php";
537         }
538
539         $templates[] = "embed.php";
540
541         return get_query_template( 'embed', $templates );
542 }
543
544 /**
545  * Retrieves the path of the singular template in current or parent template.
546  *
547  * The template hierarchy is filterable via the {@see 'singular_template_hierarchy'} hook.
548  * The template path is filterable via the {@see 'singular_template'} hook.
549  *
550  * @since 4.3.0
551  *
552  * @see get_query_template()
553  *
554  * @return string Full path to singular template file
555  */
556 function get_singular_template() {
557         return get_query_template( 'singular' );
558 }
559
560 /**
561  * Retrieve path of attachment template in current or parent template.
562  *
563  * The hierarchy for this template looks like:
564  *
565  * 1. {mime_type}-{sub_type}.php
566  * 2. {sub_type}.php
567  * 3. {mime_type}.php
568  * 4. attachment.php
569  *
570  * An example of this is:
571  *
572  * 1. image-jpeg.php
573  * 2. jpeg.php
574  * 3. image.php
575  * 4. attachment.php
576  *
577  * The template hierarchy is filterable via the {@see 'attachment_template_hierarchy'} hook.
578  * The template path is filterable via the {@see 'attachment_template'} hook.
579  *
580  * @since 2.0.0
581  * @since 4.3.0 The order of the mime type logic was reversed so the hierarchy is more logical.
582  *
583  * @see get_query_template()
584  *
585  * @global array $posts
586  *
587  * @return string Full path to attachment template file.
588  */
589 function get_attachment_template() {
590         $attachment = get_queried_object();
591
592         $templates = array();
593
594         if ( $attachment ) {
595                 if ( false !== strpos( $attachment->post_mime_type, '/' ) ) {
596                         list( $type, $subtype ) = explode( '/', $attachment->post_mime_type );
597                 } else {
598                         list( $type, $subtype ) = array( $attachment->post_mime_type, '' );
599                 }
600
601                 if ( ! empty( $subtype ) ) {
602                         $templates[] = "{$type}-{$subtype}.php";
603                         $templates[] = "{$subtype}.php";
604                 }
605                 $templates[] = "{$type}.php";
606         }
607         $templates[] = 'attachment.php';
608
609         return get_query_template( 'attachment', $templates );
610 }
611
612 /**
613  * Retrieve the name of the highest priority template file that exists.
614  *
615  * Searches in the STYLESHEETPATH before TEMPLATEPATH and wp-includes/theme-compat
616  * so that themes which inherit from a parent theme can just overload one file.
617  *
618  * @since 2.7.0
619  *
620  * @param string|array $template_names Template file(s) to search for, in order.
621  * @param bool         $load           If true the template file will be loaded if it is found.
622  * @param bool         $require_once   Whether to require_once or require. Default true. Has no effect if $load is false.
623  * @return string The template filename if one is located.
624  */
625 function locate_template($template_names, $load = false, $require_once = true ) {
626         $located = '';
627         foreach ( (array) $template_names as $template_name ) {
628                 if ( !$template_name )
629                         continue;
630                 if ( file_exists(STYLESHEETPATH . '/' . $template_name)) {
631                         $located = STYLESHEETPATH . '/' . $template_name;
632                         break;
633                 } elseif ( file_exists(TEMPLATEPATH . '/' . $template_name) ) {
634                         $located = TEMPLATEPATH . '/' . $template_name;
635                         break;
636                 } elseif ( file_exists( ABSPATH . WPINC . '/theme-compat/' . $template_name ) ) {
637                         $located = ABSPATH . WPINC . '/theme-compat/' . $template_name;
638                         break;
639                 }
640         }
641
642         if ( $load && '' != $located )
643                 load_template( $located, $require_once );
644
645         return $located;
646 }
647
648 /**
649  * Require the template file with WordPress environment.
650  *
651  * The globals are set up for the template file to ensure that the WordPress
652  * environment is available from within the function. The query variables are
653  * also available.
654  *
655  * @since 1.5.0
656  *
657  * @global array      $posts
658  * @global WP_Post    $post
659  * @global bool       $wp_did_header
660  * @global WP_Query   $wp_query
661  * @global WP_Rewrite $wp_rewrite
662  * @global wpdb       $wpdb
663  * @global string     $wp_version
664  * @global WP         $wp
665  * @global int        $id
666  * @global WP_Comment $comment
667  * @global int        $user_ID
668  *
669  * @param string $_template_file Path to template file.
670  * @param bool   $require_once   Whether to require_once or require. Default true.
671  */
672 function load_template( $_template_file, $require_once = true ) {
673         global $posts, $post, $wp_did_header, $wp_query, $wp_rewrite, $wpdb, $wp_version, $wp, $id, $comment, $user_ID;
674
675         if ( is_array( $wp_query->query_vars ) ) {
676                 extract( $wp_query->query_vars, EXTR_SKIP );
677         }
678
679         if ( isset( $s ) ) {
680                 $s = esc_attr( $s );
681         }
682
683         if ( $require_once ) {
684                 require_once( $_template_file );
685         } else {
686                 require( $_template_file );
687         }
688 }