template.php 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510
  1. <?php
  2. /**
  3. * test wp-includes/template.php
  4. *
  5. * @group themes
  6. */
  7. class Tests_Template extends WP_UnitTestCase {
  8. protected $hierarchy = array();
  9. protected static $page_on_front;
  10. protected static $page_for_posts;
  11. protected static $page;
  12. protected static $post;
  13. /**
  14. * Page For Privacy Policy.
  15. *
  16. * @since 5.2.0
  17. *
  18. * @var WP_Post $page_for_privacy_policy
  19. */
  20. protected static $page_for_privacy_policy;
  21. public static function wpSetUpBeforeClass( WP_UnitTest_Factory $factory ) {
  22. self::$page_on_front = $factory->post->create_and_get(
  23. array(
  24. 'post_type' => 'page',
  25. 'post_name' => 'page-on-front-😀',
  26. )
  27. );
  28. self::$page_for_posts = $factory->post->create_and_get(
  29. array(
  30. 'post_type' => 'page',
  31. 'post_name' => 'page-for-posts-😀',
  32. )
  33. );
  34. self::$page = $factory->post->create_and_get(
  35. array(
  36. 'post_type' => 'page',
  37. 'post_name' => 'page-name-😀',
  38. )
  39. );
  40. add_post_meta( self::$page->ID, '_wp_page_template', 'templates/page.php' );
  41. self::$post = $factory->post->create_and_get(
  42. array(
  43. 'post_type' => 'post',
  44. 'post_name' => 'post-name-😀',
  45. 'post_date' => '1984-02-25 12:34:56',
  46. )
  47. );
  48. set_post_format( self::$post, 'quote' );
  49. add_post_meta( self::$post->ID, '_wp_page_template', 'templates/post.php' );
  50. self::$page_for_privacy_policy = $factory->post->create_and_get(
  51. array(
  52. 'post_type' => 'page',
  53. 'post_title' => 'Privacy Policy',
  54. )
  55. );
  56. }
  57. public function setUp() {
  58. parent::setUp();
  59. register_post_type(
  60. 'cpt',
  61. array(
  62. 'public' => true,
  63. )
  64. );
  65. register_taxonomy(
  66. 'taxo',
  67. 'post',
  68. array(
  69. 'public' => true,
  70. 'hierarchical' => true,
  71. )
  72. );
  73. $this->set_permalink_structure( '/%year%/%monthnum%/%day%/%postname%/' );
  74. }
  75. public function tearDown() {
  76. unregister_post_type( 'cpt' );
  77. unregister_taxonomy( 'taxo' );
  78. $this->set_permalink_structure( '' );
  79. parent::tearDown();
  80. }
  81. public function test_404_template_hierarchy() {
  82. $url = add_query_arg(
  83. array(
  84. 'p' => '-1',
  85. ),
  86. home_url()
  87. );
  88. $this->assertTemplateHierarchy(
  89. $url,
  90. array(
  91. '404.php',
  92. )
  93. );
  94. }
  95. public function test_author_template_hierarchy() {
  96. $author = self::factory()->user->create_and_get(
  97. array(
  98. 'user_nicename' => 'foo',
  99. )
  100. );
  101. $this->assertTemplateHierarchy(
  102. get_author_posts_url( $author->ID ),
  103. array(
  104. 'author-foo.php',
  105. "author-{$author->ID}.php",
  106. 'author.php',
  107. 'archive.php',
  108. )
  109. );
  110. }
  111. public function test_category_template_hierarchy() {
  112. $term = self::factory()->term->create_and_get(
  113. array(
  114. 'taxonomy' => 'category',
  115. 'slug' => 'foo-😀',
  116. )
  117. );
  118. $this->assertTemplateHierarchy(
  119. get_term_link( $term ),
  120. array(
  121. 'category-foo-😀.php',
  122. 'category-foo-%f0%9f%98%80.php',
  123. "category-{$term->term_id}.php",
  124. 'category.php',
  125. 'archive.php',
  126. )
  127. );
  128. }
  129. public function test_tag_template_hierarchy() {
  130. $term = self::factory()->term->create_and_get(
  131. array(
  132. 'taxonomy' => 'post_tag',
  133. 'slug' => 'foo-😀',
  134. )
  135. );
  136. $this->assertTemplateHierarchy(
  137. get_term_link( $term ),
  138. array(
  139. 'tag-foo-😀.php',
  140. 'tag-foo-%f0%9f%98%80.php',
  141. "tag-{$term->term_id}.php",
  142. 'tag.php',
  143. 'archive.php',
  144. )
  145. );
  146. }
  147. public function test_taxonomy_template_hierarchy() {
  148. $term = self::factory()->term->create_and_get(
  149. array(
  150. 'taxonomy' => 'taxo',
  151. 'slug' => 'foo-😀',
  152. )
  153. );
  154. $this->assertTemplateHierarchy(
  155. get_term_link( $term ),
  156. array(
  157. 'taxonomy-taxo-foo-😀.php',
  158. 'taxonomy-taxo-foo-%f0%9f%98%80.php',
  159. 'taxonomy-taxo.php',
  160. 'taxonomy.php',
  161. 'archive.php',
  162. )
  163. );
  164. }
  165. public function test_date_template_hierarchy_for_year() {
  166. $this->assertTemplateHierarchy(
  167. get_year_link( 1984 ),
  168. array(
  169. 'date.php',
  170. 'archive.php',
  171. )
  172. );
  173. }
  174. public function test_date_template_hierarchy_for_month() {
  175. $this->assertTemplateHierarchy(
  176. get_month_link( 1984, 2 ),
  177. array(
  178. 'date.php',
  179. 'archive.php',
  180. )
  181. );
  182. }
  183. public function test_date_template_hierarchy_for_day() {
  184. $this->assertTemplateHierarchy(
  185. get_day_link( 1984, 2, 25 ),
  186. array(
  187. 'date.php',
  188. 'archive.php',
  189. )
  190. );
  191. }
  192. public function test_search_template_hierarchy() {
  193. $url = add_query_arg(
  194. array(
  195. 's' => 'foo',
  196. ),
  197. home_url()
  198. );
  199. $this->assertTemplateHierarchy(
  200. $url,
  201. array(
  202. 'search.php',
  203. )
  204. );
  205. }
  206. public function test_front_page_template_hierarchy_with_posts_on_front() {
  207. $this->assertSame( 'posts', get_option( 'show_on_front' ) );
  208. $this->assertTemplateHierarchy(
  209. home_url(),
  210. array(
  211. 'front-page.php',
  212. 'home.php',
  213. 'index.php',
  214. )
  215. );
  216. }
  217. public function test_front_page_template_hierarchy_with_page_on_front() {
  218. update_option( 'show_on_front', 'page' );
  219. update_option( 'page_on_front', self::$page_on_front->ID );
  220. update_option( 'page_for_posts', self::$page_for_posts->ID );
  221. $this->assertTemplateHierarchy(
  222. home_url(),
  223. array(
  224. 'front-page.php',
  225. 'page-page-on-front-😀.php',
  226. 'page-page-on-front-%f0%9f%98%80.php',
  227. 'page-' . self::$page_on_front->ID . '.php',
  228. 'page.php',
  229. 'singular.php',
  230. )
  231. );
  232. }
  233. public function test_home_template_hierarchy_with_page_on_front() {
  234. update_option( 'show_on_front', 'page' );
  235. update_option( 'page_on_front', self::$page_on_front->ID );
  236. update_option( 'page_for_posts', self::$page_for_posts->ID );
  237. $this->assertTemplateHierarchy(
  238. get_permalink( self::$page_for_posts ),
  239. array(
  240. 'home.php',
  241. 'index.php',
  242. )
  243. );
  244. }
  245. public function test_page_template_hierarchy() {
  246. $this->assertTemplateHierarchy(
  247. get_permalink( self::$page ),
  248. array(
  249. 'templates/page.php',
  250. 'page-page-name-😀.php',
  251. 'page-page-name-%f0%9f%98%80.php',
  252. 'page-' . self::$page->ID . '.php',
  253. 'page.php',
  254. 'singular.php',
  255. )
  256. );
  257. }
  258. /**
  259. * @ticket 44005
  260. * @group privacy
  261. */
  262. public function test_privacy_template_hierarchy() {
  263. update_option( 'wp_page_for_privacy_policy', self::$page_for_privacy_policy->ID );
  264. $this->assertTemplateHierarchy(
  265. get_permalink( self::$page_for_privacy_policy->ID ),
  266. array(
  267. 'privacy-policy.php',
  268. 'page-privacy-policy.php',
  269. 'page-' . self::$page_for_privacy_policy->ID . '.php',
  270. 'page.php',
  271. 'singular.php',
  272. )
  273. );
  274. }
  275. /**
  276. * @ticket 18375
  277. */
  278. public function test_single_template_hierarchy_for_post() {
  279. $this->assertTemplateHierarchy(
  280. get_permalink( self::$post ),
  281. array(
  282. 'templates/post.php',
  283. 'single-post-post-name-😀.php',
  284. 'single-post-post-name-%f0%9f%98%80.php',
  285. 'single-post.php',
  286. 'single.php',
  287. 'singular.php',
  288. )
  289. );
  290. }
  291. public function test_single_template_hierarchy_for_custom_post_type() {
  292. $cpt = self::factory()->post->create_and_get(
  293. array(
  294. 'post_type' => 'cpt',
  295. 'post_name' => 'cpt-name-😀',
  296. )
  297. );
  298. $this->assertTemplateHierarchy(
  299. get_permalink( $cpt ),
  300. array(
  301. 'single-cpt-cpt-name-😀.php',
  302. 'single-cpt-cpt-name-%f0%9f%98%80.php',
  303. 'single-cpt.php',
  304. 'single.php',
  305. 'singular.php',
  306. )
  307. );
  308. }
  309. /**
  310. * @ticket 18375
  311. */
  312. public function test_single_template_hierarchy_for_custom_post_type_with_template() {
  313. $cpt = self::factory()->post->create_and_get(
  314. array(
  315. 'post_type' => 'cpt',
  316. 'post_name' => 'cpt-name-😀',
  317. )
  318. );
  319. add_post_meta( $cpt->ID, '_wp_page_template', 'templates/cpt.php' );
  320. $this->assertTemplateHierarchy(
  321. get_permalink( $cpt ),
  322. array(
  323. 'templates/cpt.php',
  324. 'single-cpt-cpt-name-😀.php',
  325. 'single-cpt-cpt-name-%f0%9f%98%80.php',
  326. 'single-cpt.php',
  327. 'single.php',
  328. 'singular.php',
  329. )
  330. );
  331. }
  332. public function test_attachment_template_hierarchy() {
  333. $attachment = self::factory()->attachment->create_and_get(
  334. array(
  335. 'post_name' => 'attachment-name-😀',
  336. 'file' => 'image.jpg',
  337. 'post_mime_type' => 'image/jpeg',
  338. )
  339. );
  340. $this->assertTemplateHierarchy(
  341. get_permalink( $attachment ),
  342. array(
  343. 'image-jpeg.php',
  344. 'jpeg.php',
  345. 'image.php',
  346. 'attachment.php',
  347. 'single-attachment-attachment-name-😀.php',
  348. 'single-attachment-attachment-name-%f0%9f%98%80.php',
  349. 'single-attachment.php',
  350. 'single.php',
  351. 'singular.php',
  352. )
  353. );
  354. }
  355. /**
  356. * @ticket 18375
  357. */
  358. public function test_attachment_template_hierarchy_with_template() {
  359. $attachment = self::factory()->attachment->create_and_get(
  360. array(
  361. 'post_name' => 'attachment-name-😀',
  362. 'file' => 'image.jpg',
  363. 'post_mime_type' => 'image/jpeg',
  364. )
  365. );
  366. add_post_meta( $attachment, '_wp_page_template', 'templates/cpt.php' );
  367. $this->assertTemplateHierarchy(
  368. get_permalink( $attachment ),
  369. array(
  370. 'image-jpeg.php',
  371. 'jpeg.php',
  372. 'image.php',
  373. 'attachment.php',
  374. 'single-attachment-attachment-name-😀.php',
  375. 'single-attachment-attachment-name-%f0%9f%98%80.php',
  376. 'single-attachment.php',
  377. 'single.php',
  378. 'singular.php',
  379. )
  380. );
  381. }
  382. public function test_embed_template_hierarchy_for_post() {
  383. $this->assertTemplateHierarchy(
  384. get_post_embed_url( self::$post ),
  385. array(
  386. 'embed-post-quote.php',
  387. 'embed-post.php',
  388. 'embed.php',
  389. 'templates/post.php',
  390. 'single-post-post-name-😀.php',
  391. 'single-post-post-name-%f0%9f%98%80.php',
  392. 'single-post.php',
  393. 'single.php',
  394. 'singular.php',
  395. )
  396. );
  397. }
  398. public function test_embed_template_hierarchy_for_page() {
  399. $this->assertTemplateHierarchy(
  400. get_post_embed_url( self::$page ),
  401. array(
  402. 'embed-page.php',
  403. 'embed.php',
  404. 'templates/page.php',
  405. 'page-page-name-😀.php',
  406. 'page-page-name-%f0%9f%98%80.php',
  407. 'page-' . self::$page->ID . '.php',
  408. 'page.php',
  409. 'singular.php',
  410. )
  411. );
  412. }
  413. public function assertTemplateHierarchy( $url, array $expected, $message = '' ) {
  414. $this->go_to( $url );
  415. $hierarchy = $this->get_template_hierarchy();
  416. $this->assertSame( $expected, $hierarchy, $message );
  417. }
  418. protected static function get_query_template_conditions() {
  419. return array(
  420. 'embed' => 'is_embed',
  421. '404' => 'is_404',
  422. 'search' => 'is_search',
  423. 'front_page' => 'is_front_page',
  424. 'home' => 'is_home',
  425. 'privacy_policy' => 'is_privacy_policy',
  426. 'post_type_archive' => 'is_post_type_archive',
  427. 'taxonomy' => 'is_tax',
  428. 'attachment' => 'is_attachment',
  429. 'single' => 'is_single',
  430. 'page' => 'is_page',
  431. 'singular' => 'is_singular',
  432. 'category' => 'is_category',
  433. 'tag' => 'is_tag',
  434. 'author' => 'is_author',
  435. 'date' => 'is_date',
  436. 'archive' => 'is_archive',
  437. 'paged' => 'is_paged',
  438. );
  439. }
  440. protected function get_template_hierarchy() {
  441. foreach ( self::get_query_template_conditions() as $type => $condition ) {
  442. if ( call_user_func( $condition ) ) {
  443. $filter = str_replace( '_', '', $type );
  444. add_filter( "{$filter}_template_hierarchy", array( $this, 'log_template_hierarchy' ) );
  445. call_user_func( "get_{$type}_template" );
  446. remove_filter( "{$filter}_template_hierarchy", array( $this, 'log_template_hierarchy' ) );
  447. }
  448. }
  449. $hierarchy = $this->hierarchy;
  450. $this->hierarchy = array();
  451. return $hierarchy;
  452. }
  453. public function log_template_hierarchy( array $hierarchy ) {
  454. $this->hierarchy = array_merge( $this->hierarchy, $hierarchy );
  455. return $hierarchy;
  456. }
  457. }