template.php 23 KB

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