taxonomy.php 28 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055
  1. <?php
  2. /**
  3. * @group taxonomy
  4. */
  5. class Tests_Taxonomy extends WP_UnitTestCase {
  6. function test_get_post_taxonomies() {
  7. $this->assertSame( array( 'category', 'post_tag', 'post_format' ), get_object_taxonomies( 'post' ) );
  8. }
  9. function test_get_link_taxonomies() {
  10. $this->assertSame( array( 'link_category' ), get_object_taxonomies( 'link' ) );
  11. }
  12. /**
  13. * @ticket 5417
  14. */
  15. function test_get_unknown_taxonomies() {
  16. // Taxonomies for an unknown object type.
  17. $this->assertSame( array(), get_object_taxonomies( rand_str() ) );
  18. $this->assertSame( array(), get_object_taxonomies( '' ) );
  19. $this->assertSame( array(), get_object_taxonomies( 0 ) );
  20. $this->assertSame( array(), get_object_taxonomies( null ) );
  21. }
  22. function test_get_post_taxonomy() {
  23. foreach ( get_object_taxonomies( 'post' ) as $taxonomy ) {
  24. $tax = get_taxonomy( $taxonomy );
  25. // Should return an object with the correct taxonomy object type.
  26. $this->assertTrue( is_object( $tax ) );
  27. $this->assertTrue( is_array( $tax->object_type ) );
  28. $this->assertSame( array( 'post' ), $tax->object_type );
  29. }
  30. }
  31. function test_get_the_taxonomies() {
  32. $post_id = self::factory()->post->create();
  33. $taxes = get_the_taxonomies( $post_id );
  34. $this->assertNotEmpty( $taxes );
  35. $this->assertSame( array( 'category' ), array_keys( $taxes ) );
  36. $id = self::factory()->tag->create();
  37. wp_set_post_tags( $post_id, array( $id ) );
  38. $taxes = get_the_taxonomies( $post_id );
  39. $this->assertNotEmpty( $taxes );
  40. $this->assertCount( 2, $taxes );
  41. $this->assertSame( array( 'category', 'post_tag' ), array_keys( $taxes ) );
  42. }
  43. /**
  44. * @ticket 27238
  45. */
  46. public function test_get_the_taxonomies_term_template() {
  47. $post_id = self::factory()->post->create();
  48. $taxes = get_the_taxonomies( $post_id, array( 'term_template' => '%2$s' ) );
  49. $this->assertSame( 'Categories: Uncategorized.', $taxes['category'] );
  50. $taxes = get_the_taxonomies( $post_id, array( 'term_template' => '<span class="foo"><a href="%1$s">%2$s</a></span>' ) );
  51. $link = get_category_link( 1 );
  52. $this->assertSame( 'Categories: <span class="foo"><a href="' . $link . '">Uncategorized</a></span>.', $taxes['category'] );
  53. }
  54. function test_the_taxonomies() {
  55. $post_id = self::factory()->post->create();
  56. $this->expectOutputString(
  57. sprintf(
  58. 'Categories: <a href="%s">Uncategorized</a>.',
  59. get_category_link( 1 )
  60. )
  61. );
  62. the_taxonomies( array( 'post' => $post_id ) );
  63. }
  64. /**
  65. * @ticket 27238
  66. */
  67. function test_the_taxonomies_term_template() {
  68. $post_id = self::factory()->post->create();
  69. $output = get_echo(
  70. 'the_taxonomies',
  71. array(
  72. array(
  73. 'post' => $post_id,
  74. 'term_template' => '%2$s',
  75. ),
  76. )
  77. );
  78. $this->assertSame( 'Categories: Uncategorized.', $output );
  79. $output = get_echo(
  80. 'the_taxonomies',
  81. array(
  82. array(
  83. 'post' => $post_id,
  84. 'term_template' => '<span class="foo"><a href="%1$s">%2$s</a></span>',
  85. ),
  86. )
  87. );
  88. $link = get_category_link( 1 );
  89. $this->assertSame( 'Categories: <span class="foo"><a href="' . $link . '">Uncategorized</a></span>.', $output );
  90. }
  91. function test_get_link_taxonomy() {
  92. foreach ( get_object_taxonomies( 'link' ) as $taxonomy ) {
  93. $tax = get_taxonomy( $taxonomy );
  94. // Should return an object with the correct taxonomy object type.
  95. $this->assertTrue( is_object( $tax ) );
  96. $this->assertTrue( is_array( $tax->object_type ) );
  97. $this->assertSame( array( 'link' ), $tax->object_type );
  98. }
  99. }
  100. function test_taxonomy_exists_known() {
  101. $this->assertTrue( taxonomy_exists( 'category' ) );
  102. $this->assertTrue( taxonomy_exists( 'post_tag' ) );
  103. $this->assertTrue( taxonomy_exists( 'link_category' ) );
  104. }
  105. function test_taxonomy_exists_unknown() {
  106. $this->assertFalse( taxonomy_exists( rand_str() ) );
  107. $this->assertFalse( taxonomy_exists( '' ) );
  108. $this->assertFalse( taxonomy_exists( 0 ) );
  109. $this->assertFalse( taxonomy_exists( null ) );
  110. }
  111. function test_is_taxonomy_hierarchical() {
  112. $this->assertTrue( is_taxonomy_hierarchical( 'category' ) );
  113. $this->assertFalse( is_taxonomy_hierarchical( 'post_tag' ) );
  114. $this->assertFalse( is_taxonomy_hierarchical( 'link_category' ) );
  115. }
  116. function test_is_taxonomy_hierarchical_unknown() {
  117. $this->assertFalse( is_taxonomy_hierarchical( rand_str() ) );
  118. $this->assertFalse( is_taxonomy_hierarchical( '' ) );
  119. $this->assertFalse( is_taxonomy_hierarchical( 0 ) );
  120. $this->assertFalse( is_taxonomy_hierarchical( null ) );
  121. }
  122. function test_register_taxonomy() {
  123. // Make up a new taxonomy name, and ensure it's unused.
  124. $tax = rand_str();
  125. $this->assertFalse( taxonomy_exists( $tax ) );
  126. register_taxonomy( $tax, 'post' );
  127. $this->assertTrue( taxonomy_exists( $tax ) );
  128. $this->assertFalse( is_taxonomy_hierarchical( $tax ) );
  129. // Clean up.
  130. unset( $GLOBALS['wp_taxonomies'][ $tax ] );
  131. }
  132. function test_register_hierarchical_taxonomy() {
  133. // Make up a new taxonomy name, and ensure it's unused.
  134. $tax = rand_str();
  135. $this->assertFalse( taxonomy_exists( $tax ) );
  136. register_taxonomy( $tax, 'post', array( 'hierarchical' => true ) );
  137. $this->assertTrue( taxonomy_exists( $tax ) );
  138. $this->assertTrue( is_taxonomy_hierarchical( $tax ) );
  139. // Clean up.
  140. unset( $GLOBALS['wp_taxonomies'][ $tax ] );
  141. }
  142. /**
  143. * @ticket 48558
  144. */
  145. function test_register_taxonomy_return_value() {
  146. $this->assertInstanceOf( 'WP_Taxonomy', register_taxonomy( 'foo', 'post' ) );
  147. }
  148. /**
  149. * @ticket 21593
  150. *
  151. * @expectedIncorrectUsage register_taxonomy
  152. */
  153. function test_register_taxonomy_with_too_long_name() {
  154. $this->assertInstanceOf( 'WP_Error', register_taxonomy( 'abcdefghijklmnopqrstuvwxyz0123456789', 'post', array() ) );
  155. }
  156. /**
  157. * @ticket 31135
  158. *
  159. * @expectedIncorrectUsage register_taxonomy
  160. */
  161. function test_register_taxonomy_with_empty_name() {
  162. $this->assertInstanceOf( 'WP_Error', register_taxonomy( '', 'post', array() ) );
  163. }
  164. /**
  165. * @ticket 26948
  166. */
  167. public function test_register_taxonomy_show_in_quick_edit_should_default_to_value_of_show_ui() {
  168. register_taxonomy(
  169. 'wptests_tax_1',
  170. 'post',
  171. array(
  172. 'show_ui' => true,
  173. )
  174. );
  175. register_taxonomy(
  176. 'wptests_tax_2',
  177. 'post',
  178. array(
  179. 'show_ui' => false,
  180. )
  181. );
  182. $tax_1 = get_taxonomy( 'wptests_tax_1' );
  183. $this->assertTrue( $tax_1->show_in_quick_edit );
  184. $tax_2 = get_taxonomy( 'wptests_tax_2' );
  185. $this->assertFalse( $tax_2->show_in_quick_edit );
  186. }
  187. /**
  188. * @ticket 11058
  189. */
  190. function test_registering_taxonomies_to_object_types() {
  191. // Create a taxonomy to test with.
  192. $tax = 'test_tax';
  193. $this->assertFalse( taxonomy_exists( $tax ) );
  194. register_taxonomy( $tax, 'post', array( 'hierarchical' => true ) );
  195. // Create a post type to test with.
  196. $post_type = 'test_cpt';
  197. $this->assertFalse( get_post_type( $post_type ) );
  198. $this->assertObjectHasAttribute( 'name', register_post_type( $post_type ) );
  199. // Core taxonomy, core post type.
  200. $this->assertTrue( unregister_taxonomy_for_object_type( 'category', 'post' ) );
  201. $this->assertFalse( unregister_taxonomy_for_object_type( 'category', 'post' ) );
  202. $this->assertTrue( register_taxonomy_for_object_type( 'category', 'post' ) );
  203. // Core taxonomy, non-core post type.
  204. $this->assertTrue( register_taxonomy_for_object_type( 'category', $post_type ) );
  205. $this->assertTrue( unregister_taxonomy_for_object_type( 'category', $post_type ) );
  206. $this->assertFalse( unregister_taxonomy_for_object_type( 'category', $post_type ) );
  207. $this->assertTrue( register_taxonomy_for_object_type( 'category', $post_type ) );
  208. // Core taxonomies, non-post object types.
  209. $this->assertFalse( register_taxonomy_for_object_type( 'category', 'user' ) );
  210. $this->assertFalse( unregister_taxonomy_for_object_type( 'category', 'user' ) );
  211. // Non-core taxonomy, core post type.
  212. $this->assertTrue( unregister_taxonomy_for_object_type( $tax, 'post' ) );
  213. $this->assertFalse( unregister_taxonomy_for_object_type( $tax, 'post' ) );
  214. $this->assertTrue( register_taxonomy_for_object_type( $tax, 'post' ) );
  215. // Non-core taxonomy, non-core post type.
  216. $this->assertTrue( register_taxonomy_for_object_type( $tax, $post_type ) );
  217. $this->assertTrue( unregister_taxonomy_for_object_type( $tax, $post_type ) );
  218. $this->assertFalse( unregister_taxonomy_for_object_type( $tax, $post_type ) );
  219. $this->assertTrue( register_taxonomy_for_object_type( $tax, $post_type ) );
  220. // Non-core taxonomies, non-post object types.
  221. $this->assertFalse( register_taxonomy_for_object_type( $tax, 'user' ) );
  222. $this->assertFalse( unregister_taxonomy_for_object_type( $tax, 'user' ) );
  223. unset( $GLOBALS['wp_taxonomies'][ $tax ] );
  224. _unregister_post_type( $post_type );
  225. }
  226. /**
  227. * @ticket 32590
  228. */
  229. public function test_register_taxonomy_for_post_type_for_taxonomy_with_no_object_type_should_filter_out_empty_object_types() {
  230. register_taxonomy( 'wptests_tax', '' );
  231. register_taxonomy_for_object_type( 'wptests_tax', 'post' );
  232. $tax = get_taxonomy( 'wptests_tax' );
  233. $expected = array( 'post' );
  234. $this->assertSameSets( $expected, $tax->object_type );
  235. }
  236. public function test_get_objects_in_term_should_return_invalid_taxonomy_error() {
  237. $terms = get_objects_in_term( 1, 'invalid_taxonomy' );
  238. $this->assertInstanceOf( 'WP_Error', $terms );
  239. $this->assertSame( 'invalid_taxonomy', $terms->get_error_code() );
  240. }
  241. public function test_get_objects_in_term_should_return_empty_array() {
  242. $this->assertSame( array(), get_objects_in_term( 1, 'post_tag' ) );
  243. }
  244. public function test_get_objects_in_term_should_return_objects_ids() {
  245. $tag_id = self::factory()->tag->create();
  246. $cat_id = self::factory()->category->create();
  247. $posts_with_tag = array();
  248. $posts_with_category = array();
  249. for ( $i = 0; $i < 3; $i++ ) {
  250. $post_id = self::factory()->post->create();
  251. wp_set_post_tags( $post_id, array( $tag_id ) );
  252. $posts_with_tag[] = $post_id;
  253. }
  254. for ( $i = 0; $i < 3; $i++ ) {
  255. $post_id = self::factory()->post->create();
  256. wp_set_post_categories( $post_id, array( $cat_id ) );
  257. $posts_with_category[] = $post_id;
  258. }
  259. for ( $i = 0; $i < 3; $i++ ) {
  260. self::factory()->post->create();
  261. }
  262. $posts_with_terms = array_merge( $posts_with_tag, $posts_with_category );
  263. $this->assertEquals( $posts_with_tag, get_objects_in_term( $tag_id, 'post_tag' ) );
  264. $this->assertEquals( $posts_with_category, get_objects_in_term( $cat_id, 'category' ) );
  265. $this->assertEquals( $posts_with_terms, get_objects_in_term( array( $tag_id, $cat_id ), array( 'post_tag', 'category' ) ) );
  266. $this->assertEquals( array_reverse( $posts_with_tag ), get_objects_in_term( $tag_id, 'post_tag', array( 'order' => 'desc' ) ) );
  267. }
  268. /**
  269. * @ticket 37094
  270. */
  271. public function test_term_assignment_should_invalidate_get_objects_in_term_cache() {
  272. register_taxonomy( 'wptests_tax', 'post' );
  273. $posts = self::factory()->post->create_many( 2 );
  274. $term_id = self::factory()->term->create(
  275. array(
  276. 'taxonomy' => 'wptests_tax',
  277. )
  278. );
  279. wp_set_object_terms( $posts[1], $term_id, 'wptests_tax' );
  280. // Prime cache.
  281. $before = get_objects_in_term( $term_id, 'wptests_tax' );
  282. $this->assertEqualSets( array( $posts[1] ), $before );
  283. wp_set_object_terms( $posts[1], array(), 'wptests_tax' );
  284. $after = get_objects_in_term( $term_id, 'wptests_tax' );
  285. $this->assertSame( array(), $after );
  286. }
  287. /**
  288. * @ticket 37094
  289. */
  290. public function test_term_deletion_should_invalidate_get_objects_in_term_cache() {
  291. register_taxonomy( 'wptests_tax', 'post' );
  292. $posts = self::factory()->post->create_many( 2 );
  293. $term_id = self::factory()->term->create(
  294. array(
  295. 'taxonomy' => 'wptests_tax',
  296. )
  297. );
  298. wp_set_object_terms( $posts[1], $term_id, 'wptests_tax' );
  299. // Prime cache.
  300. $before = get_objects_in_term( $term_id, 'wptests_tax' );
  301. $this->assertEqualSets( array( $posts[1] ), $before );
  302. wp_delete_term( $term_id, 'wptests_tax' );
  303. $after = get_objects_in_term( $term_id, 'wptests_tax' );
  304. $this->assertSame( array(), $after );
  305. }
  306. /**
  307. * @ticket 37094
  308. */
  309. public function test_post_deletion_should_invalidate_get_objects_in_term_cache() {
  310. register_taxonomy( 'wptests_tax', 'post' );
  311. $posts = self::factory()->post->create_many( 2 );
  312. $term_id = self::factory()->term->create(
  313. array(
  314. 'taxonomy' => 'wptests_tax',
  315. )
  316. );
  317. wp_set_object_terms( $posts[1], $term_id, 'wptests_tax' );
  318. // Prime cache.
  319. $before = get_objects_in_term( $term_id, 'wptests_tax' );
  320. $this->assertEqualSets( array( $posts[1] ), $before );
  321. wp_delete_post( $posts[1], true );
  322. $after = get_objects_in_term( $term_id, 'wptests_tax' );
  323. $this->assertSame( array(), $after );
  324. }
  325. /**
  326. * @ticket 25706
  327. */
  328. function test_in_category() {
  329. $post = self::factory()->post->create_and_get();
  330. // in_category() returns false when first parameter is empty().
  331. $this->assertFalse( in_category( '', $post ) );
  332. $this->assertFalse( in_category( false, $post ) );
  333. $this->assertFalse( in_category( null, $post ) );
  334. // Test expected behavior of in_category().
  335. $term = wp_insert_term( 'Test', 'category' );
  336. wp_set_object_terms( $post->ID, $term['term_id'], 'category' );
  337. $this->assertTrue( in_category( $term['term_id'], $post ) );
  338. }
  339. function test_insert_category_create() {
  340. $cat = array(
  341. 'cat_ID' => 0,
  342. 'taxonomy' => 'category',
  343. 'cat_name' => 'test1',
  344. );
  345. $this->assertTrue( is_numeric( wp_insert_category( $cat, true ) ) );
  346. }
  347. function test_insert_category_update() {
  348. $cat = array(
  349. 'cat_ID' => 1,
  350. 'taxonomy' => 'category',
  351. 'cat_name' => 'Updated Name',
  352. );
  353. $this->assertSame( 1, wp_insert_category( $cat ) );
  354. }
  355. function test_insert_category_force_error_handle() {
  356. $cat = array(
  357. 'cat_ID' => 0,
  358. 'taxonomy' => 'force_error',
  359. 'cat_name' => 'Error',
  360. );
  361. $this->assertTrue( is_a( wp_insert_category( $cat, true ), 'WP_Error' ) );
  362. }
  363. function test_insert_category_force_error_no_handle() {
  364. $cat = array(
  365. 'cat_ID' => 0,
  366. 'taxonomy' => 'force_error',
  367. 'cat_name' => 'Error',
  368. );
  369. $this->assertSame( 0, wp_insert_category( $cat, false ) );
  370. }
  371. public function test_get_ancestors_taxonomy_non_hierarchical() {
  372. register_taxonomy( 'wptests_tax', 'post' );
  373. $t = self::factory()->term->create(
  374. array(
  375. 'taxonomy' => 'wptests_tax',
  376. )
  377. );
  378. $this->assertSame( array(), get_ancestors( $t, 'wptests_tax' ) );
  379. _unregister_taxonomy( 'wptests_tax' );
  380. }
  381. public function test_get_ancestors_taxonomy() {
  382. register_taxonomy(
  383. 'wptests_tax',
  384. 'post',
  385. array(
  386. 'hierarchical' => true,
  387. )
  388. );
  389. $t1 = self::factory()->term->create(
  390. array(
  391. 'taxonomy' => 'wptests_tax',
  392. )
  393. );
  394. $t2 = self::factory()->term->create(
  395. array(
  396. 'taxonomy' => 'wptests_tax',
  397. 'parent' => $t1,
  398. )
  399. );
  400. $t3 = self::factory()->term->create(
  401. array(
  402. 'taxonomy' => 'wptests_tax',
  403. 'parent' => $t2,
  404. )
  405. );
  406. $t4 = self::factory()->term->create(
  407. array(
  408. 'taxonomy' => 'wptests_tax',
  409. 'parent' => $t1,
  410. )
  411. );
  412. $this->assertSameSets( array( $t2, $t1 ), get_ancestors( $t3, 'wptests_tax' ) );
  413. _unregister_taxonomy( 'wptests_tax' );
  414. }
  415. public function test_get_ancestors_post_type_non_hierarchical() {
  416. register_post_type( 'wptests_pt' );
  417. $p = self::factory()->post->create(
  418. array(
  419. 'taxonomy' => 'wptests_pt',
  420. )
  421. );
  422. $this->assertSameSets( array(), get_ancestors( $p, 'wptests_tax' ) );
  423. }
  424. public function test_get_ancestors_post_type() {
  425. register_post_type(
  426. 'wptests_pt',
  427. array(
  428. 'hierarchical' => true,
  429. )
  430. );
  431. $p1 = self::factory()->post->create(
  432. array(
  433. 'post_type' => 'wptests_pt',
  434. )
  435. );
  436. $p2 = self::factory()->post->create(
  437. array(
  438. 'post_type' => 'wptests_pt',
  439. 'post_parent' => $p1,
  440. )
  441. );
  442. $p3 = self::factory()->post->create(
  443. array(
  444. 'post_type' => 'wptests_pt',
  445. 'post_parent' => $p2,
  446. )
  447. );
  448. $p4 = self::factory()->post->create(
  449. array(
  450. 'post_type' => 'wptests_pt',
  451. 'post_parent' => $p1,
  452. )
  453. );
  454. $this->assertSameSets( array( $p2, $p1 ), get_ancestors( $p3, 'wptests_pt' ) );
  455. _unregister_post_type( 'wptests_pt' );
  456. }
  457. /**
  458. * @ticket 15029
  459. */
  460. public function test_get_ancestors_taxonomy_post_type_conflict_resource_type_taxonomy() {
  461. register_post_type(
  462. 'wptests_conflict',
  463. array(
  464. 'hierarchical' => true,
  465. )
  466. );
  467. $p1 = self::factory()->post->create(
  468. array(
  469. 'post_type' => 'wptests_conflict',
  470. )
  471. );
  472. $p2 = self::factory()->post->create(
  473. array(
  474. 'post_type' => 'wptests_conflict',
  475. 'post_parent' => $p1,
  476. )
  477. );
  478. register_taxonomy(
  479. 'wptests_conflict',
  480. 'post',
  481. array(
  482. 'hierarchical' => true,
  483. )
  484. );
  485. $t1 = self::factory()->term->create(
  486. array(
  487. 'taxonomy' => 'wptests_conflict',
  488. )
  489. );
  490. $t2 = self::factory()->term->create(
  491. array(
  492. 'taxonomy' => 'wptests_conflict',
  493. 'parent' => $t1,
  494. )
  495. );
  496. $this->assertSameSets( array( $p1 ), get_ancestors( $p2, 'wptests_conflict', 'post_type' ) );
  497. $this->assertSameSets( array( $t1 ), get_ancestors( $t2, 'wptests_conflict', 'taxonomy' ) );
  498. $this->assertSameSets( array( $t1 ), get_ancestors( $t2, 'wptests_conflict' ) );
  499. _unregister_post_type( 'wptests_pt' );
  500. }
  501. /**
  502. * @ticket 21949
  503. */
  504. public function test_nonpublicly_queryable_taxonomy_should_not_be_queryable_using_taxname_query_var() {
  505. register_taxonomy(
  506. 'wptests_tax',
  507. 'post',
  508. array(
  509. 'publicly_queryable' => false,
  510. )
  511. );
  512. $t = self::factory()->term->create_and_get(
  513. array(
  514. 'taxonomy' => 'wptests_tax',
  515. )
  516. );
  517. $p = self::factory()->post->create();
  518. wp_set_object_terms( $p, $t->slug, 'wptests_tax' );
  519. $this->go_to( '/?wptests_tax=' . $t->slug );
  520. $this->assertFalse( is_tax( 'wptests_tax' ) );
  521. }
  522. /**
  523. * @ticket 21949
  524. */
  525. public function test_it_should_be_possible_to_register_a_query_var_that_matches_the_name_of_a_nonpublicly_queryable_taxonomy() {
  526. global $wp;
  527. register_taxonomy(
  528. 'wptests_tax',
  529. 'post',
  530. array(
  531. 'publicly_queryable' => false,
  532. )
  533. );
  534. $t = $this->factory->term->create_and_get(
  535. array(
  536. 'taxonomy' => 'wptests_tax',
  537. )
  538. );
  539. $p = $this->factory->post->create();
  540. wp_set_object_terms( $p, $t->slug, 'wptests_tax' );
  541. add_filter( 'do_parse_request', array( $this, 'register_query_var' ) );
  542. $this->go_to( '/?wptests_tax=foo' );
  543. remove_filter( 'do_parse_request', array( $this, 'register_query_var' ) );
  544. // Not a taxonomy...
  545. $this->assertFalse( is_tax( 'wptests_tax' ) );
  546. // ...but query var works.
  547. $this->assertSame( 'foo', $wp->query_vars['wptests_tax'] );
  548. }
  549. public static function register_query_var( $r ) {
  550. global $wp;
  551. $wp->add_query_var( 'wptests_tax' );
  552. return $r;
  553. }
  554. /**
  555. * @ticket 21949
  556. */
  557. public function test_nonpublicly_queryable_taxonomy_should_not_be_queryable_using_taxonomy_and_term_vars() {
  558. register_taxonomy(
  559. 'wptests_tax',
  560. 'post',
  561. array(
  562. 'publicly_queryable' => false,
  563. )
  564. );
  565. $t = self::factory()->term->create_and_get(
  566. array(
  567. 'taxonomy' => 'wptests_tax',
  568. )
  569. );
  570. $p = self::factory()->post->create();
  571. wp_set_object_terms( $p, $t->slug, 'wptests_tax' );
  572. $this->go_to( '/?taxonomy=wptests_tax&term=' . $t->slug );
  573. $this->assertFalse( is_tax( 'wptests_tax' ) );
  574. }
  575. /**
  576. * @ticket 34491
  577. */
  578. public function test_public_taxonomy_should_be_publicly_queryable() {
  579. register_taxonomy(
  580. 'wptests_tax',
  581. 'post',
  582. array(
  583. 'public' => true,
  584. )
  585. );
  586. $this->assertContains( 'wptests_tax', get_taxonomies( array( 'publicly_queryable' => true ) ) );
  587. $t = self::factory()->term->create_and_get(
  588. array(
  589. 'taxonomy' => 'wptests_tax',
  590. )
  591. );
  592. $p = self::factory()->post->create();
  593. wp_set_object_terms( $p, $t->slug, 'wptests_tax' );
  594. $this->go_to( '/?wptests_tax=' . $t->slug );
  595. $this->assertTrue( is_tax( 'wptests_tax' ) );
  596. }
  597. /**
  598. * @ticket 34491
  599. */
  600. public function test_private_taxonomy_should_not_be_publicly_queryable() {
  601. register_taxonomy(
  602. 'wptests_tax',
  603. 'post',
  604. array(
  605. 'public' => false,
  606. )
  607. );
  608. $this->assertContains( 'wptests_tax', get_taxonomies( array( 'publicly_queryable' => false ) ) );
  609. $t = self::factory()->term->create_and_get(
  610. array(
  611. 'taxonomy' => 'wptests_tax',
  612. )
  613. );
  614. $p = self::factory()->post->create();
  615. wp_set_object_terms( $p, $t->slug, 'wptests_tax' );
  616. $this->go_to( '/?wptests_tax=' . $t->slug );
  617. $this->assertFalse( is_tax( 'wptests_tax' ) );
  618. }
  619. /**
  620. * @ticket 34491
  621. */
  622. public function test_private_taxonomy_should_be_overridden_by_publicly_queryable() {
  623. register_taxonomy(
  624. 'wptests_tax',
  625. 'post',
  626. array(
  627. 'public' => false,
  628. 'publicly_queryable' => true,
  629. )
  630. );
  631. $this->assertContains( 'wptests_tax', get_taxonomies( array( 'publicly_queryable' => true ) ) );
  632. $t = self::factory()->term->create_and_get(
  633. array(
  634. 'taxonomy' => 'wptests_tax',
  635. )
  636. );
  637. $p = self::factory()->post->create();
  638. wp_set_object_terms( $p, $t->slug, 'wptests_tax' );
  639. $this->go_to( '/?wptests_tax=' . $t->slug );
  640. $this->assertTrue( is_tax( 'wptests_tax' ) );
  641. }
  642. /**
  643. * @ticket 35089
  644. */
  645. public function test_query_var_should_be_forced_to_false_for_non_public_taxonomy() {
  646. register_taxonomy(
  647. 'wptests_tax',
  648. 'post',
  649. array(
  650. 'public' => false,
  651. 'query_var' => true,
  652. )
  653. );
  654. $tax = get_taxonomy( 'wptests_tax' );
  655. $this->assertFalse( $tax->query_var );
  656. }
  657. /**
  658. * @ticket 35227
  659. */
  660. public function test_unregister_taxonomy_unknown_taxonomy() {
  661. $this->assertWPError( unregister_taxonomy( 'foo' ) );
  662. }
  663. /**
  664. * @ticket 35227
  665. */
  666. public function test_unregister_taxonomy_twice() {
  667. register_taxonomy( 'foo', 'post' );
  668. $this->assertTrue( unregister_taxonomy( 'foo' ) );
  669. $this->assertWPError( unregister_taxonomy( 'foo' ) );
  670. }
  671. /**
  672. * @ticket 35227
  673. */
  674. public function test_unregister_taxonomy_disallow_builtin_taxonomy() {
  675. $this->assertWPError( unregister_taxonomy( 'post_tag' ) );
  676. $this->assertWPError( unregister_taxonomy( 'category' ) );
  677. }
  678. /**
  679. * @ticket 35227
  680. */
  681. public function test_unregister_taxonomy_removes_query_vars() {
  682. global $wp;
  683. register_taxonomy( 'foo', 'post', array( 'query_var' => 'bar' ) );
  684. $this->assertInternalType( 'int', array_search( 'bar', $wp->public_query_vars, true ) );
  685. $this->assertTrue( unregister_taxonomy( 'foo' ) );
  686. $this->assertFalse( array_search( 'bar', $wp->public_query_vars, true ) );
  687. }
  688. /**
  689. * @ticket 35227
  690. */
  691. public function test_unregister_taxonomy_removes_permastruct() {
  692. $this->set_permalink_structure( '/%postname%' );
  693. global $wp_rewrite;
  694. register_taxonomy(
  695. 'foo',
  696. 'post',
  697. array(
  698. 'query_var' => 'bar',
  699. 'rewrite' => true,
  700. )
  701. );
  702. $this->assertInternalType( 'array', $wp_rewrite->extra_permastructs['foo'] );
  703. $this->assertTrue( unregister_taxonomy( 'foo' ) );
  704. $this->assertFalse( isset( $wp_rewrite->extra_permastructs['foo'] ) );
  705. }
  706. /**
  707. * @ticket 35227
  708. */
  709. public function test_unregister_taxonomy_removes_rewrite_rules() {
  710. $this->set_permalink_structure( '/%postname%' );
  711. global $wp_rewrite;
  712. register_taxonomy( 'foo', 'post', array( 'query_var' => 'bar' ) );
  713. $count_before = count( $wp_rewrite->rewritereplace );
  714. $this->assertContains( '%foo%', $wp_rewrite->rewritecode );
  715. $this->assertContains( 'bar=', $wp_rewrite->queryreplace );
  716. $this->assertTrue( unregister_taxonomy( 'foo' ) );
  717. $this->assertNotContains( '%foo%', $wp_rewrite->rewritecode );
  718. $this->assertNotContains( 'bar=', $wp_rewrite->queryreplace );
  719. $this->assertSame( --$count_before, count( $wp_rewrite->rewritereplace ) ); // Array was reduced by one value.
  720. }
  721. /**
  722. * @ticket 35227
  723. */
  724. public function test_unregister_taxonomy_removes_taxonomy_from_global() {
  725. global $wp_taxonomies;
  726. register_taxonomy( 'foo', 'post' );
  727. $this->assertInternalType( 'object', $wp_taxonomies['foo'] );
  728. $this->assertInternalType( 'object', get_taxonomy( 'foo' ) );
  729. $this->assertTrue( unregister_taxonomy( 'foo' ) );
  730. $this->assertFalse( isset( $wp_taxonomies['foo'] ) );
  731. $this->assertFalse( get_taxonomy( 'foo' ) );
  732. }
  733. /**
  734. * @ticket 35227
  735. */
  736. public function test_unregister_taxonomy_removes_meta_box_callback() {
  737. global $wp_filter;
  738. register_taxonomy( 'foo', 'post' );
  739. $this->assertArrayHasKey( 'wp_ajax_add-foo', $wp_filter );
  740. $this->assertSame( 1, count( $wp_filter['wp_ajax_add-foo']->callbacks ) );
  741. $this->assertTrue( unregister_taxonomy( 'foo' ) );
  742. $this->assertArrayNotHasKey( 'wp_ajax_add-foo', $wp_filter );
  743. }
  744. /**
  745. * @ticket 35227
  746. */
  747. public function test_taxonomy_does_not_exist_after_unregister_taxonomy() {
  748. register_taxonomy( 'foo', 'post' );
  749. $this->assertTrue( taxonomy_exists( 'foo' ) );
  750. unregister_taxonomy( 'foo' );
  751. $this->assertFalse( taxonomy_exists( 'foo' ) );
  752. }
  753. /**
  754. * @ticket 39308
  755. */
  756. public function test_taxonomy_name_property_should_not_get_overridden_by_passed_args() {
  757. register_taxonomy( 'foo', 'post', array( 'name' => 'bar' ) );
  758. $taxonomy = get_taxonomy( 'foo' );
  759. unregister_taxonomy( 'foo' );
  760. $this->assertSame( 'foo', $taxonomy->name );
  761. }
  762. /**
  763. * @ticket 36514
  764. */
  765. public function test_edit_post_hierarchical_taxonomy() {
  766. $taxonomy_name = 'foo';
  767. $term_name = 'bar';
  768. register_taxonomy(
  769. $taxonomy_name,
  770. array( 'post' ),
  771. array(
  772. 'hierarchical' => false,
  773. 'meta_box_cb' => 'post_categories_meta_box',
  774. )
  775. );
  776. $post = self::factory()->post->create_and_get(
  777. array(
  778. 'post_type' => 'post',
  779. )
  780. );
  781. $term_id = self::factory()->term->create_object(
  782. array(
  783. 'name' => $term_name,
  784. 'taxonomy' => $taxonomy_name,
  785. )
  786. );
  787. wp_set_current_user( self::factory()->user->create( array( 'role' => 'editor' ) ) );
  788. $updated_post_id = edit_post(
  789. array(
  790. 'post_ID' => $post->ID,
  791. 'post_type' => 'post',
  792. 'tax_input' => array(
  793. $taxonomy_name => array(
  794. (string) $term_id, // Cast term_id as string to match what's sent in WP Admin.
  795. ),
  796. ),
  797. )
  798. );
  799. $terms_obj = get_the_terms( $updated_post_id, $taxonomy_name );
  800. $problematic_term = current( wp_list_pluck( $terms_obj, 'name' ) );
  801. $this->assertSame( $problematic_term, $term_name );
  802. }
  803. /**
  804. * Test default term for custom taxonomy.
  805. *
  806. * @ticket 43517
  807. */
  808. function test_default_term_for_custom_taxonomy() {
  809. wp_set_current_user( self::factory()->user->create( array( 'role' => 'editor' ) ) );
  810. $tax = 'custom-tax';
  811. // Create custom taxonomy to test with.
  812. register_taxonomy(
  813. $tax,
  814. 'post',
  815. array(
  816. 'hierarchical' => true,
  817. 'public' => true,
  818. 'default_term' => array(
  819. 'name' => 'Default category',
  820. 'slug' => 'default-category',
  821. ),
  822. )
  823. );
  824. // Add post.
  825. $post_id = self::factory()->post->create(
  826. array(
  827. 'post_title' => 'Foo',
  828. 'post_type' => 'post',
  829. )
  830. );
  831. // Test default term.
  832. $term = wp_get_post_terms( $post_id, $tax );
  833. $this->assertSame( get_option( 'default_term_' . $tax ), $term[0]->term_id );
  834. // Test default term deletion.
  835. $this->assertSame( wp_delete_term( $term[0]->term_id, $tax ), 0 );
  836. // Add custom post type.
  837. register_post_type(
  838. 'post-custom-tax',
  839. array(
  840. 'taxonomies' => array( $tax ),
  841. )
  842. );
  843. $post_id = self::factory()->post->create(
  844. array(
  845. 'post_title' => 'Foo',
  846. 'post_type' => 'post-custom-tax',
  847. )
  848. );
  849. // Test default term.
  850. $term = wp_get_post_terms( $post_id, $tax );
  851. $this->assertSame( get_option( 'default_term_' . $tax ), $term[0]->term_id );
  852. // wp_set_object_terms() should not assign default term.
  853. wp_set_object_terms( $post_id, array(), $tax );
  854. $term = wp_get_post_terms( $post_id, $tax );
  855. $this->assertSame( array(), $term );
  856. unregister_taxonomy( $tax );
  857. $this->assertSame( get_option( 'default_term_' . $tax ), false );
  858. }
  859. /**
  860. * @ticket 51320
  861. */
  862. function test_default_term_for_post_in_multiple_taxonomies() {
  863. $post_type = 'test_post_type';
  864. $tax1 = 'test_tax1';
  865. $tax2 = 'test_tax2';
  866. register_post_type( $post_type, array( 'taxonomies' => array( $tax1, $tax2 ) ) );
  867. register_taxonomy( $tax1, $post_type, array( 'default_term' => 'term_1' ) );
  868. register_taxonomy( $tax2, $post_type, array( 'default_term' => 'term_2' ) );
  869. $post_id = self::factory()->post->create( array( 'post_type' => $post_type ) );
  870. $taxonomies = get_post_taxonomies( $post_id );
  871. $this->assertContains( $tax1, $taxonomies );
  872. $this->assertContains( $tax2, $taxonomies );
  873. }
  874. }