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