/tests/phpunit/tests/term/wpSetObjectTerms.php

https://github.com/WordPress/wordpress-develop · PHP · 433 lines · 297 code · 84 blank · 52 comment · 3 complexity · 8915e19864e8ed329b07933bb209a0a5 MD5 · raw file

  1. <?php
  2. /**
  3. * @group taxonomy
  4. */
  5. class Tests_Term_WpSetObjectTerms extends WP_UnitTestCase {
  6. protected $taxonomy = 'category';
  7. protected static $post_ids = array();
  8. public static function wpSetUpBeforeClass( $factory ) {
  9. self::$post_ids = $factory->post->create_many( 5 );
  10. }
  11. /**
  12. * @ticket 26570
  13. */
  14. function test_set_object_terms() {
  15. $non_hier = rand_str( 10 );
  16. $hier = rand_str( 10 );
  17. // Register taxonomies.
  18. register_taxonomy( $non_hier, array() );
  19. register_taxonomy( $hier, array( 'hierarchical' => true ) );
  20. // Create a post.
  21. $post_id = self::$post_ids[0];
  22. /*
  23. * Set a single term (non-hierarchical) by ID.
  24. */
  25. $tag = wp_insert_term( 'Foo', $non_hier );
  26. $this->assertFalse( has_term( $tag['term_id'], $non_hier, $post_id ) );
  27. wp_set_object_terms( $post_id, $tag['term_id'], $non_hier );
  28. $this->assertTrue( has_term( $tag['term_id'], $non_hier, $post_id ) );
  29. /*
  30. * Set a single term (non-hierarchical) by slug.
  31. */
  32. $tag = wp_insert_term( 'Bar', $non_hier );
  33. $tag = get_term( $tag['term_id'], $non_hier );
  34. $this->assertFalse( has_term( $tag->slug, $non_hier, $post_id ) );
  35. wp_set_object_terms( $post_id, $tag->slug, $non_hier );
  36. $this->assertTrue( has_term( $tag->slug, $non_hier, $post_id ) );
  37. /*
  38. * Set a single term (hierarchical) by ID.
  39. */
  40. $cat = wp_insert_term( 'Baz', $hier );
  41. $this->assertFalse( has_term( $cat['term_id'], $hier, $post_id ) );
  42. wp_set_object_terms( $post_id, $cat['term_id'], $hier );
  43. $this->assertTrue( has_term( $cat['term_id'], $hier, $post_id ) );
  44. /*
  45. * Set a single term (hierarchical) by slug.
  46. */
  47. $cat = wp_insert_term( 'Qux', $hier );
  48. $cat = get_term( $cat['term_id'], $hier );
  49. $this->assertFalse( has_term( $cat->slug, $hier, $post_id ) );
  50. wp_set_object_terms( $post_id, $cat->slug, $hier );
  51. $this->assertTrue( has_term( $cat->slug, $hier, $post_id ) );
  52. /*
  53. * Set an array of term IDs (non-hierarchical) by ID.
  54. */
  55. $tag1 = wp_insert_term( '_tag1', $non_hier );
  56. $this->assertFalse( has_term( $tag1['term_id'], $non_hier, $post_id ) );
  57. $tag2 = wp_insert_term( '_tag2', $non_hier );
  58. $this->assertFalse( has_term( $tag2['term_id'], $non_hier, $post_id ) );
  59. $tag3 = wp_insert_term( '_tag3', $non_hier );
  60. $this->assertFalse( has_term( $tag3['term_id'], $non_hier, $post_id ) );
  61. wp_set_object_terms( $post_id, array( $tag1['term_id'], $tag2['term_id'], $tag3['term_id'] ), $non_hier );
  62. $this->assertTrue( has_term( array( $tag1['term_id'], $tag2['term_id'], $tag3['term_id'] ), $non_hier, $post_id ) );
  63. /*
  64. * Set an array of term slugs (hierarchical) by slug.
  65. */
  66. $cat1 = wp_insert_term( '_cat1', $hier );
  67. $cat1 = get_term( $cat1['term_id'], $hier );
  68. $this->assertFalse( has_term( $cat1->slug, $hier, $post_id ) );
  69. $cat2 = wp_insert_term( '_cat2', $hier );
  70. $cat2 = get_term( $cat2['term_id'], $hier );
  71. $this->assertFalse( has_term( $cat2->slug, $hier, $post_id ) );
  72. $cat3 = wp_insert_term( '_cat3', $hier );
  73. $cat3 = get_term( $cat3['term_id'], $hier );
  74. $this->assertFalse( has_term( $cat3->slug, $hier, $post_id ) );
  75. wp_set_object_terms( $post_id, array( $cat1->slug, $cat2->slug, $cat3->slug ), $hier );
  76. $this->assertTrue( has_term( array( $cat1->slug, $cat2->slug, $cat3->slug ), $hier, $post_id ) );
  77. }
  78. function test_set_object_terms_by_id() {
  79. $ids = self::$post_ids;
  80. $terms = array();
  81. for ( $i = 0; $i < 3; $i++ ) {
  82. $term = "term_{$i}";
  83. $result = wp_insert_term( $term, $this->taxonomy );
  84. $this->assertInternalType( 'array', $result );
  85. $term_id[ $term ] = $result['term_id'];
  86. }
  87. foreach ( $ids as $id ) {
  88. $tt = wp_set_object_terms( $id, array_values( $term_id ), $this->taxonomy );
  89. // Should return three term taxonomy IDs.
  90. $this->assertSame( 3, count( $tt ) );
  91. }
  92. // Each term should be associated with every post.
  93. foreach ( $term_id as $term => $id ) {
  94. $actual = get_objects_in_term( $id, $this->taxonomy );
  95. $this->assertSame( $ids, array_map( 'intval', $actual ) );
  96. }
  97. // Each term should have a count of 5.
  98. foreach ( array_keys( $term_id ) as $term ) {
  99. $t = get_term_by( 'name', $term, $this->taxonomy );
  100. $this->assertSame( 5, $t->count );
  101. }
  102. }
  103. function test_set_object_terms_by_name() {
  104. $ids = self::$post_ids;
  105. $terms = array(
  106. rand_str(),
  107. rand_str(),
  108. rand_str(),
  109. );
  110. foreach ( $ids as $id ) {
  111. $tt = wp_set_object_terms( $id, $terms, $this->taxonomy );
  112. // Should return three term taxonomy IDs.
  113. $this->assertSame( 3, count( $tt ) );
  114. // Remember which term has which term_id.
  115. for ( $i = 0; $i < 3; $i++ ) {
  116. $term = get_term_by( 'name', $terms[ $i ], $this->taxonomy );
  117. $term_id[ $terms[ $i ] ] = intval( $term->term_id );
  118. }
  119. }
  120. // Each term should be associated with every post.
  121. foreach ( $term_id as $term => $id ) {
  122. $actual = get_objects_in_term( $id, $this->taxonomy );
  123. $this->assertSame( $ids, array_map( 'intval', $actual ) );
  124. }
  125. // Each term should have a count of 5.
  126. foreach ( $terms as $term ) {
  127. $t = get_term_by( 'name', $term, $this->taxonomy );
  128. $this->assertSame( 5, $t->count );
  129. }
  130. }
  131. function test_set_object_terms_invalid() {
  132. // Bogus taxonomy.
  133. $result = wp_set_object_terms( self::$post_ids[0], array( rand_str() ), rand_str() );
  134. $this->assertWPError( $result );
  135. }
  136. public function test_wp_set_object_terms_append_true() {
  137. register_taxonomy( 'wptests_tax', 'post' );
  138. $p = self::$post_ids[0];
  139. $t1 = self::factory()->term->create(
  140. array(
  141. 'taxonomy' => 'wptests_tax',
  142. )
  143. );
  144. $t2 = self::factory()->term->create(
  145. array(
  146. 'taxonomy' => 'wptests_tax',
  147. )
  148. );
  149. $added1 = wp_set_object_terms( $p, array( $t1 ), 'wptests_tax' );
  150. $this->assertNotEmpty( $added1 );
  151. $this->assertSameSets( array( $t1 ), wp_get_object_terms( $p, 'wptests_tax', array( 'fields' => 'ids' ) ) );
  152. $added2 = wp_set_object_terms( $p, array( $t2 ), 'wptests_tax', true );
  153. $this->assertNotEmpty( $added2 );
  154. $this->assertSameSets( array( $t1, $t2 ), wp_get_object_terms( $p, 'wptests_tax', array( 'fields' => 'ids' ) ) );
  155. _unregister_taxonomy( 'wptests_tax' );
  156. }
  157. public function test_wp_set_object_terms_append_false() {
  158. register_taxonomy( 'wptests_tax', 'post' );
  159. $p = self::$post_ids[0];
  160. $t1 = self::factory()->term->create(
  161. array(
  162. 'taxonomy' => 'wptests_tax',
  163. )
  164. );
  165. $t2 = self::factory()->term->create(
  166. array(
  167. 'taxonomy' => 'wptests_tax',
  168. )
  169. );
  170. $added1 = wp_set_object_terms( $p, array( $t1 ), 'wptests_tax' );
  171. $this->assertNotEmpty( $added1 );
  172. $this->assertSameSets( array( $t1 ), wp_get_object_terms( $p, 'wptests_tax', array( 'fields' => 'ids' ) ) );
  173. $added2 = wp_set_object_terms( $p, array( $t2 ), 'wptests_tax', false );
  174. $this->assertNotEmpty( $added2 );
  175. $this->assertSameSets( array( $t2 ), wp_get_object_terms( $p, 'wptests_tax', array( 'fields' => 'ids' ) ) );
  176. _unregister_taxonomy( 'wptests_tax' );
  177. }
  178. public function test_wp_set_object_terms_append_default_to_false() {
  179. register_taxonomy( 'wptests_tax', 'post' );
  180. $p = self::$post_ids[0];
  181. $t1 = self::factory()->term->create(
  182. array(
  183. 'taxonomy' => 'wptests_tax',
  184. )
  185. );
  186. $t2 = self::factory()->term->create(
  187. array(
  188. 'taxonomy' => 'wptests_tax',
  189. )
  190. );
  191. $added1 = wp_set_object_terms( $p, array( $t1 ), 'wptests_tax' );
  192. $this->assertNotEmpty( $added1 );
  193. $this->assertSameSets( array( $t1 ), wp_get_object_terms( $p, 'wptests_tax', array( 'fields' => 'ids' ) ) );
  194. $added2 = wp_set_object_terms( $p, array( $t2 ), 'wptests_tax' );
  195. $this->assertNotEmpty( $added2 );
  196. $this->assertSameSets( array( $t2 ), wp_get_object_terms( $p, 'wptests_tax', array( 'fields' => 'ids' ) ) );
  197. _unregister_taxonomy( 'wptests_tax' );
  198. }
  199. /**
  200. * Set some terms on an object; then change them while leaving one intact.
  201. */
  202. function test_change_object_terms_by_id() {
  203. $post_id = self::$post_ids[0];
  204. // First set: 3 terms.
  205. $terms_1 = array();
  206. for ( $i = 0; $i < 3; $i++ ) {
  207. $term = "term_{$i}";
  208. $result = wp_insert_term( $term, $this->taxonomy );
  209. $this->assertInternalType( 'array', $result );
  210. $terms_1[ $i ] = $result['term_id'];
  211. }
  212. // Second set: one of the original terms, plus one new term.
  213. $terms_2 = array();
  214. $terms_2[0] = $terms_1[1];
  215. $term = 'term';
  216. $result = wp_insert_term( $term, $this->taxonomy );
  217. $terms_2[1] = $result['term_id'];
  218. // Set the initial terms.
  219. $tt_1 = wp_set_object_terms( $post_id, $terms_1, $this->taxonomy );
  220. $this->assertSame( 3, count( $tt_1 ) );
  221. // Make sure they're correct.
  222. $terms = wp_get_object_terms(
  223. $post_id,
  224. $this->taxonomy,
  225. array(
  226. 'fields' => 'ids',
  227. 'orderby' => 'term_id',
  228. )
  229. );
  230. $this->assertSame( $terms_1, $terms );
  231. // Change the terms.
  232. $tt_2 = wp_set_object_terms( $post_id, $terms_2, $this->taxonomy );
  233. $this->assertSame( 2, count( $tt_2 ) );
  234. // Make sure they're correct.
  235. $terms = wp_get_object_terms(
  236. $post_id,
  237. $this->taxonomy,
  238. array(
  239. 'fields' => 'ids',
  240. 'orderby' => 'term_id',
  241. )
  242. );
  243. $this->assertSame( $terms_2, $terms );
  244. // Make sure the term taxonomy ID for 'bar' matches.
  245. $this->assertSame( $tt_1[1], $tt_2[0] );
  246. }
  247. /**
  248. * Set some terms on an object; then change them while leaving one intact.
  249. */
  250. function test_change_object_terms_by_name() {
  251. $post_id = self::$post_ids[0];
  252. $terms_1 = array( 'foo', 'bar', 'baz' );
  253. $terms_2 = array( 'bar', 'bing' );
  254. // Set the initial terms.
  255. $tt_1 = wp_set_object_terms( $post_id, $terms_1, $this->taxonomy );
  256. $this->assertSame( 3, count( $tt_1 ) );
  257. // Make sure they're correct.
  258. $terms = wp_get_object_terms(
  259. $post_id,
  260. $this->taxonomy,
  261. array(
  262. 'fields' => 'names',
  263. 'orderby' => 'term_id',
  264. )
  265. );
  266. $this->assertSame( $terms_1, $terms );
  267. // Change the terms.
  268. $tt_2 = wp_set_object_terms( $post_id, $terms_2, $this->taxonomy );
  269. $this->assertSame( 2, count( $tt_2 ) );
  270. // Make sure they're correct.
  271. $terms = wp_get_object_terms(
  272. $post_id,
  273. $this->taxonomy,
  274. array(
  275. 'fields' => 'names',
  276. 'orderby' => 'term_id',
  277. )
  278. );
  279. $this->assertSame( $terms_2, $terms );
  280. // Make sure the term taxonomy ID for 'bar' matches.
  281. $this->assertEquals( $tt_1[1], $tt_2[0] );
  282. }
  283. public function test_should_create_term_that_does_not_exist() {
  284. register_taxonomy( 'wptests_tax', 'post' );
  285. $this->assertFalse( get_term_by( 'slug', 'foo', 'wptests_tax' ) );
  286. $tt_ids = wp_set_object_terms( self::$post_ids[0], 'foo', 'wptests_tax' );
  287. $this->assertNotEmpty( $tt_ids );
  288. $term = get_term_by( 'term_taxonomy_id', $tt_ids[0] );
  289. $this->assertInstanceOf( 'WP_Term', $term );
  290. $this->assertSame( 'foo', $term->slug );
  291. }
  292. public function test_should_find_existing_term_by_slug_match() {
  293. register_taxonomy( 'wptests_tax', 'post' );
  294. $t = self::factory()->term->create(
  295. array(
  296. 'taxonomy' => 'wptests_tax',
  297. 'slug' => 'foo',
  298. 'name' => 'Bar',
  299. )
  300. );
  301. $tt_ids = wp_set_object_terms( self::$post_ids[0], 'foo', 'wptests_tax' );
  302. $this->assertNotEmpty( $tt_ids );
  303. $term = get_term_by( 'term_taxonomy_id', $tt_ids[0] );
  304. $this->assertInstanceOf( 'WP_Term', $term );
  305. $this->assertSame( $t, $term->term_id );
  306. }
  307. public function test_should_find_existing_term_by_name_match() {
  308. register_taxonomy( 'wptests_tax', 'post' );
  309. $t = self::factory()->term->create(
  310. array(
  311. 'taxonomy' => 'wptests_tax',
  312. 'slug' => 'foo',
  313. 'name' => 'Bar',
  314. )
  315. );
  316. $tt_ids = wp_set_object_terms( self::$post_ids[0], 'Bar', 'wptests_tax' );
  317. $this->assertNotEmpty( $tt_ids );
  318. $term = get_term_by( 'term_taxonomy_id', $tt_ids[0] );
  319. $this->assertInstanceOf( 'WP_Term', $term );
  320. $this->assertSame( $t, $term->term_id );
  321. }
  322. public function test_should_give_precedence_to_slug_match_over_name_match() {
  323. register_taxonomy( 'wptests_tax', 'post' );
  324. $t1 = self::factory()->term->create(
  325. array(
  326. 'taxonomy' => 'wptests_tax',
  327. 'slug' => 'foo',
  328. 'name' => 'Bar',
  329. )
  330. );
  331. $t2 = self::factory()->term->create(
  332. array(
  333. 'taxonomy' => 'wptests_tax',
  334. 'slug' => 'bar',
  335. 'name' => 'Foo',
  336. )
  337. );
  338. $tt_ids = wp_set_object_terms( self::$post_ids[0], 'Bar', 'wptests_tax' );
  339. $this->assertNotEmpty( $tt_ids );
  340. $term = get_term_by( 'term_taxonomy_id', $tt_ids[0] );
  341. $this->assertInstanceOf( 'WP_Term', $term );
  342. $this->assertSame( $t2, $term->term_id );
  343. }
  344. public function test_non_existent_integers_should_be_ignored() {
  345. register_taxonomy( 'wptests_tax', 'post' );
  346. $tt_ids = wp_set_object_terms( self::$post_ids[0], 12345, 'wptests_tax' );
  347. $this->assertSame( array(), $tt_ids );
  348. }
  349. }