rewrite.php 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488
  1. <?php
  2. /**
  3. * A set of unit tests for functions in wp-includes/rewrite.php
  4. *
  5. * @group rewrite
  6. */
  7. class Tests_Rewrite extends WP_UnitTestCase {
  8. private $home_url;
  9. function setUp() {
  10. parent::setUp();
  11. $this->set_permalink_structure( '/%year%/%monthnum%/%day%/%postname%/' );
  12. create_initial_taxonomies();
  13. $this->home_url = get_option( 'home' );
  14. }
  15. function tearDown() {
  16. global $wp_rewrite;
  17. $wp_rewrite->init();
  18. update_option( 'home', $this->home_url );
  19. parent::tearDown();
  20. }
  21. /**
  22. * @ticket 16840
  23. */
  24. public function test_add_rule() {
  25. global $wp_rewrite;
  26. $pattern = 'path/to/rewrite/([^/]+)/?$';
  27. $redirect = 'index.php?test_var1=$matches[1]&test_var2=1';
  28. $wp_rewrite->add_rule( $pattern, $redirect );
  29. $wp_rewrite->flush_rules();
  30. $rewrite_rules = $wp_rewrite->rewrite_rules();
  31. $this->assertSame( $redirect, $rewrite_rules[ $pattern ] );
  32. }
  33. /**
  34. * @ticket 16840
  35. */
  36. public function test_add_rule_redirect_array() {
  37. global $wp_rewrite;
  38. $pattern = 'path/to/rewrite/([^/]+)/?$';
  39. $redirect = 'index.php?test_var1=$matches[1]&test_var2=1';
  40. $wp_rewrite->add_rule(
  41. $pattern,
  42. array(
  43. 'test_var1' => '$matches[1]',
  44. 'test_var2' => '1',
  45. )
  46. );
  47. $wp_rewrite->flush_rules();
  48. $rewrite_rules = $wp_rewrite->rewrite_rules();
  49. $this->assertSame( $redirect, $rewrite_rules[ $pattern ] );
  50. }
  51. /**
  52. * @ticket 16840
  53. */
  54. public function test_add_rule_top() {
  55. global $wp_rewrite;
  56. $pattern = 'path/to/rewrite/([^/]+)/?$';
  57. $redirect = 'index.php?test_var1=$matches[1]&test_var2=1';
  58. $wp_rewrite->add_rule( $pattern, $redirect, 'top' );
  59. $wp_rewrite->flush_rules();
  60. $extra_rules_top = $wp_rewrite->extra_rules_top;
  61. $this->assertContains( $redirect, $extra_rules_top[ $pattern ] );
  62. }
  63. function test_url_to_postid() {
  64. $id = self::factory()->post->create();
  65. $this->assertSame( $id, url_to_postid( get_permalink( $id ) ) );
  66. $id = self::factory()->post->create( array( 'post_type' => 'page' ) );
  67. $this->assertSame( $id, url_to_postid( get_permalink( $id ) ) );
  68. }
  69. function test_url_to_postid_set_url_scheme_https_to_http() {
  70. $post_id = self::factory()->post->create();
  71. $permalink = get_permalink( $post_id );
  72. $this->assertSame( $post_id, url_to_postid( set_url_scheme( $permalink, 'https' ) ) );
  73. $post_id = self::factory()->post->create( array( 'post_type' => 'page' ) );
  74. $permalink = get_permalink( $post_id );
  75. $this->assertSame( $post_id, url_to_postid( set_url_scheme( $permalink, 'https' ) ) );
  76. }
  77. function test_url_to_postid_set_url_scheme_http_to_https() {
  78. $_SERVER['HTTPS'] = 'on';
  79. $post_id = self::factory()->post->create();
  80. $post_permalink = get_permalink( $post_id );
  81. $post_url_to_id = url_to_postid( set_url_scheme( $post_permalink, 'http' ) );
  82. $page_id = self::factory()->post->create( array( 'post_type' => 'page' ) );
  83. $page_permalink = get_permalink( $page_id );
  84. $page_url_to_id = url_to_postid( set_url_scheme( $page_permalink, 'http' ) );
  85. $this->assertSame( $post_id, $post_url_to_id );
  86. $this->assertSame( $page_id, $page_url_to_id );
  87. }
  88. /**
  89. * @ticket 35531
  90. * @group multisite
  91. * @group ms-required
  92. */
  93. function test_url_to_postid_of_http_site_when_current_site_uses_https() {
  94. $_SERVER['HTTPS'] = 'on';
  95. $network_home = home_url();
  96. $this->blog_id_35531 = self::factory()->blog->create();
  97. add_filter( 'home_url', array( $this, '_filter_http_home_url' ), 10, 4 );
  98. switch_to_blog( $this->blog_id_35531 );
  99. $post_id = self::factory()->post->create();
  100. $permalink = get_permalink( $post_id );
  101. $url_to_postid = url_to_postid( $permalink );
  102. restore_current_blog();
  103. // Cleanup.
  104. remove_filter( 'home_url', array( $this, '_filter_http_home_url' ), 10 );
  105. // Test the tests.
  106. $this->assertSame( 'http', parse_url( $permalink, PHP_URL_SCHEME ) );
  107. $this->assertSame( 'https', parse_url( $network_home, PHP_URL_SCHEME ) );
  108. // Test that the url_to_postid() call matched.
  109. $this->assertSame( $post_id, $url_to_postid );
  110. }
  111. /**
  112. * Enforce an `http` scheme for our target site.
  113. *
  114. * @param string $url The complete home URL including scheme and path.
  115. * @param string $path Path relative to the home URL. Blank string if no path is specified.
  116. * @param string|null $orig_scheme Scheme to give the home URL context.
  117. * @param int|null $blog_id Site ID, or null for the current site.
  118. * @return string The complete home URL including scheme and path.
  119. */
  120. function _filter_http_home_url( $url, $path, $orig_scheme, $_blog_id ) {
  121. global $blog_id;
  122. if ( $this->blog_id_35531 === $blog_id ) {
  123. return set_url_scheme( $url, 'http' );
  124. }
  125. return $url;
  126. }
  127. function test_url_to_postid_custom_post_type() {
  128. delete_option( 'rewrite_rules' );
  129. $post_type = rand_str( 12 );
  130. register_post_type( $post_type, array( 'public' => true ) );
  131. $id = self::factory()->post->create( array( 'post_type' => $post_type ) );
  132. $this->assertSame( $id, url_to_postid( get_permalink( $id ) ) );
  133. _unregister_post_type( $post_type );
  134. }
  135. function test_url_to_postid_hierarchical() {
  136. $parent_id = self::factory()->post->create(
  137. array(
  138. 'post_title' => 'Parent',
  139. 'post_type' => 'page',
  140. )
  141. );
  142. $child_id = self::factory()->post->create(
  143. array(
  144. 'post_title' => 'Child',
  145. 'post_type' => 'page',
  146. 'post_parent' => $parent_id,
  147. )
  148. );
  149. $this->assertSame( $parent_id, url_to_postid( get_permalink( $parent_id ) ) );
  150. $this->assertSame( $child_id, url_to_postid( get_permalink( $child_id ) ) );
  151. }
  152. function test_url_to_postid_hierarchical_with_matching_leaves() {
  153. $parent_id = self::factory()->post->create(
  154. array(
  155. 'post_name' => 'parent',
  156. 'post_type' => 'page',
  157. )
  158. );
  159. $child_id_1 = self::factory()->post->create(
  160. array(
  161. 'post_name' => 'child1',
  162. 'post_type' => 'page',
  163. 'post_parent' => $parent_id,
  164. )
  165. );
  166. $child_id_2 = self::factory()->post->create(
  167. array(
  168. 'post_name' => 'child2',
  169. 'post_type' => 'page',
  170. 'post_parent' => $parent_id,
  171. )
  172. );
  173. $grandchild_id_1 = self::factory()->post->create(
  174. array(
  175. 'post_name' => 'grandchild',
  176. 'post_type' => 'page',
  177. 'post_parent' => $child_id_1,
  178. )
  179. );
  180. $grandchild_id_2 = self::factory()->post->create(
  181. array(
  182. 'post_name' => 'grandchild',
  183. 'post_type' => 'page',
  184. 'post_parent' => $child_id_2,
  185. )
  186. );
  187. $this->assertSame( home_url( 'parent/child1/grandchild/' ), get_permalink( $grandchild_id_1 ) );
  188. $this->assertSame( home_url( 'parent/child2/grandchild/' ), get_permalink( $grandchild_id_2 ) );
  189. $this->assertSame( $grandchild_id_1, url_to_postid( get_permalink( $grandchild_id_1 ) ) );
  190. $this->assertSame( $grandchild_id_2, url_to_postid( get_permalink( $grandchild_id_2 ) ) );
  191. }
  192. function test_url_to_postid_home_has_path() {
  193. update_option( 'home', home_url( '/example/' ) );
  194. $id = self::factory()->post->create(
  195. array(
  196. 'post_title' => 'Hi',
  197. 'post_type' => 'page',
  198. 'post_name' => 'examp',
  199. )
  200. );
  201. $this->assertSame( $id, url_to_postid( get_permalink( $id ) ) );
  202. $this->assertSame( $id, url_to_postid( site_url( '/example/examp' ) ) );
  203. $this->assertSame( $id, url_to_postid( '/example/examp/' ) );
  204. $this->assertSame( $id, url_to_postid( '/example/examp' ) );
  205. $this->assertSame( 0, url_to_postid( site_url( '/example/ex' ) ) );
  206. $this->assertSame( 0, url_to_postid( '/example/ex' ) );
  207. $this->assertSame( 0, url_to_postid( '/example/ex/' ) );
  208. $this->assertSame( 0, url_to_postid( '/example-page/example/' ) );
  209. $this->assertSame( 0, url_to_postid( '/example-page/ex/' ) );
  210. }
  211. /**
  212. * @ticket 30438
  213. */
  214. function test_parse_request_home_path() {
  215. $home_url = home_url( '/path/' );
  216. update_option( 'home', $home_url );
  217. $this->go_to( $home_url );
  218. $this->assertSame( array(), $GLOBALS['wp']->query_vars );
  219. $this->go_to( $home_url . 'page' );
  220. $this->assertSame(
  221. array(
  222. 'page' => '',
  223. 'pagename' => 'page',
  224. ),
  225. $GLOBALS['wp']->query_vars
  226. );
  227. }
  228. /**
  229. * @ticket 30438
  230. */
  231. function test_parse_request_home_path_with_regex_character() {
  232. $home_url = home_url( '/ma.ch/' );
  233. $not_a_home_url = home_url( '/match/' );
  234. update_option( 'home', $home_url );
  235. $this->go_to( $home_url );
  236. $this->assertSame( array(), $GLOBALS['wp']->query_vars );
  237. $this->go_to( $home_url . 'page' );
  238. $this->assertSame(
  239. array(
  240. 'page' => '',
  241. 'pagename' => 'page',
  242. ),
  243. $GLOBALS['wp']->query_vars
  244. );
  245. $this->go_to( $not_a_home_url . 'page' );
  246. $this->assertNotEquals(
  247. array(
  248. 'page' => '',
  249. 'pagename' => 'page',
  250. ),
  251. $GLOBALS['wp']->query_vars
  252. );
  253. $this->assertSame(
  254. array(
  255. 'page' => '',
  256. 'pagename' => 'match/page',
  257. ),
  258. $GLOBALS['wp']->query_vars
  259. );
  260. }
  261. /**
  262. * @ticket 30018
  263. */
  264. function test_parse_request_home_path_non_public_type() {
  265. register_post_type( 'foo', array( 'public' => false ) );
  266. $url = add_query_arg( 'foo', '1', home_url() );
  267. $this->go_to( $url );
  268. _unregister_post_type( 'foo' );
  269. $this->assertSame( array(), $GLOBALS['wp']->query_vars );
  270. }
  271. function test_url_to_postid_dupe_path() {
  272. update_option( 'home', home_url( '/example/' ) );
  273. $id = self::factory()->post->create(
  274. array(
  275. 'post_title' => 'Hi',
  276. 'post_type' => 'page',
  277. 'post_name' => 'example',
  278. )
  279. );
  280. $this->assertSame( $id, url_to_postid( get_permalink( $id ) ) );
  281. $this->assertSame( $id, url_to_postid( site_url( '/example/example/' ) ) );
  282. $this->assertSame( $id, url_to_postid( '/example/example/' ) );
  283. $this->assertSame( $id, url_to_postid( '/example/example' ) );
  284. }
  285. /**
  286. * Reveals bug introduced in WP 3.0
  287. */
  288. function test_url_to_postid_home_url_collision() {
  289. update_option( 'home', home_url( '/example' ) );
  290. self::factory()->post->create(
  291. array(
  292. 'post_title' => 'Collision',
  293. 'post_type' => 'page',
  294. 'post_name' => 'collision',
  295. )
  296. );
  297. // This url should NOT return a post ID.
  298. $badurl = site_url( '/example-collision' );
  299. $this->assertSame( 0, url_to_postid( $badurl ) );
  300. }
  301. /**
  302. * Reveals bug introduced in WP 3.0
  303. *
  304. * @group ms-required
  305. */
  306. function test_url_to_postid_ms_home_url_collision() {
  307. $blog_id = self::factory()->blog->create( array( 'path' => '/example' ) );
  308. switch_to_blog( $blog_id );
  309. self::factory()->post->create(
  310. array(
  311. 'post_title' => 'Collision ',
  312. 'post_type' => 'page',
  313. )
  314. );
  315. // This url should NOT return a post ID.
  316. $badurl = network_home_url( '/example-collision' );
  317. $this->assertSame( 0, url_to_postid( $badurl ) );
  318. restore_current_blog();
  319. }
  320. /**
  321. * @ticket 21970
  322. */
  323. function test_url_to_postid_with_post_slug_that_clashes_with_a_trashed_page() {
  324. $this->set_permalink_structure( '/%postname%/' );
  325. $page_id = self::factory()->post->create(
  326. array(
  327. 'post_type' => 'page',
  328. 'post_status' => 'trash',
  329. )
  330. );
  331. $post_id = self::factory()->post->create( array( 'post_title' => get_post( $page_id )->post_title ) );
  332. $this->assertSame( $post_id, url_to_postid( get_permalink( $post_id ) ) );
  333. }
  334. /**
  335. * @ticket 34971
  336. */
  337. function test_url_to_postid_static_front_page() {
  338. $post_id = self::factory()->post->create( array( 'post_type' => 'page' ) );
  339. $this->assertSame( 0, url_to_postid( home_url() ) );
  340. update_option( 'show_on_front', 'page' );
  341. update_option( 'page_on_front', $post_id );
  342. $this->assertSame( $post_id, url_to_postid( set_url_scheme( home_url(), 'http' ) ) );
  343. $this->assertSame( $post_id, url_to_postid( set_url_scheme( home_url(), 'https' ) ) );
  344. $this->assertSame( $post_id, url_to_postid( str_replace( array( 'http://', 'https://' ), 'http://www.', home_url() ) ) );
  345. $this->assertSame( $post_id, url_to_postid( home_url() . '#random' ) );
  346. $this->assertSame( $post_id, url_to_postid( home_url() . '?random' ) );
  347. update_option( 'show_on_front', 'posts' );
  348. }
  349. /**
  350. * @ticket 39373
  351. */
  352. public function test_url_to_postid_should_bail_when_host_does_not_match() {
  353. $this->set_permalink_structure( '/%postname%/' );
  354. $post_id = self::factory()->post->create( array( 'post_name' => 'foo-bar-baz' ) );
  355. $permalink = get_permalink( $post_id );
  356. $url = str_replace( home_url(), 'http://some-other-domain.com', get_permalink( $post_id ) );
  357. $this->assertSame( $post_id, url_to_postid( $permalink ) );
  358. $this->assertSame( 0, url_to_postid( $url ) );
  359. }
  360. /**
  361. * @ticket 21970
  362. */
  363. function test_parse_request_with_post_slug_that_clashes_with_a_trashed_page() {
  364. $this->set_permalink_structure( '/%postname%/' );
  365. $page_id = self::factory()->post->create(
  366. array(
  367. 'post_type' => 'page',
  368. 'post_status' => 'trash',
  369. )
  370. );
  371. $post_id = self::factory()->post->create( array( 'post_title' => get_post( $page_id )->post_title ) );
  372. $this->go_to( get_permalink( $post_id ) );
  373. $this->assertTrue( is_single() );
  374. $this->assertFalse( is_404() );
  375. }
  376. /**
  377. * @ticket 29107
  378. */
  379. public function test_flush_rules_does_not_delete_option() {
  380. $this->set_permalink_structure( '' );
  381. $rewrite_rules = get_option( 'rewrite_rules' );
  382. $this->assertSame( '', $rewrite_rules );
  383. $this->set_permalink_structure( '/%year%/%monthnum%/%day%/%postname%/' );
  384. $rewrite_rules = get_option( 'rewrite_rules' );
  385. $this->assertInternalType( 'array', $rewrite_rules );
  386. $this->assertNotEmpty( $rewrite_rules );
  387. }
  388. }