/wp-includes/template.php

https://gitlab.com/WPonEB/WPonEB · PHP · 692 lines · 212 code · 71 blank · 409 comment · 40 complexity · 0523871c22646012db8ff498c4bf3194 MD5 · raw file

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