You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

689 lines
19 KiB

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