filters.php 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270
  1. <?php
  2. /**
  3. * Test apply_filters() and related functions
  4. *
  5. * @group hooks
  6. */
  7. class Tests_Filters extends WP_UnitTestCase {
  8. function test_simple_filter() {
  9. $a = new MockAction();
  10. $tag = rand_str();
  11. $val = rand_str();
  12. add_filter($tag, array($a, 'filter'));
  13. $this->assertEquals($val, apply_filters($tag, $val));
  14. // only one event occurred for the hook, with empty args
  15. $this->assertEquals(1, $a->get_call_count());
  16. // only our hook was called
  17. $this->assertEquals(array($tag), $a->get_tags());
  18. $argsvar = $a->get_args();
  19. $args = array_pop( $argsvar );
  20. $this->assertEquals(array($val), $args);
  21. }
  22. function test_remove_filter() {
  23. $a = new MockAction();
  24. $tag = rand_str();
  25. $val = rand_str();
  26. add_filter($tag, array($a, 'filter'));
  27. $this->assertEquals($val, apply_filters($tag, $val));
  28. // make sure our hook was called correctly
  29. $this->assertEquals(1, $a->get_call_count());
  30. $this->assertEquals(array($tag), $a->get_tags());
  31. // now remove the filter, do it again, and make sure it's not called this time
  32. remove_filter($tag, array($a, 'filter'));
  33. $this->assertEquals($val, apply_filters($tag, $val));
  34. $this->assertEquals(1, $a->get_call_count());
  35. $this->assertEquals(array($tag), $a->get_tags());
  36. }
  37. function test_has_filter() {
  38. $tag = rand_str();
  39. $func = rand_str();
  40. $this->assertFalse( has_filter($tag, $func) );
  41. $this->assertFalse( has_filter($tag) );
  42. add_filter($tag, $func);
  43. $this->assertEquals( 10, has_filter($tag, $func) );
  44. $this->assertTrue( has_filter($tag) );
  45. remove_filter($tag, $func);
  46. $this->assertFalse( has_filter($tag, $func) );
  47. $this->assertFalse( has_filter($tag) );
  48. }
  49. // one tag with multiple filters
  50. function test_multiple_filters() {
  51. $a1 = new MockAction();
  52. $a2 = new MockAction();
  53. $tag = rand_str();
  54. $val = rand_str();
  55. // add both filters to the hook
  56. add_filter($tag, array($a1, 'filter'));
  57. add_filter($tag, array($a2, 'filter'));
  58. $this->assertEquals($val, apply_filters($tag, $val));
  59. // both filters called once each
  60. $this->assertEquals(1, $a1->get_call_count());
  61. $this->assertEquals(1, $a2->get_call_count());
  62. }
  63. function test_filter_args_1() {
  64. $a = new MockAction();
  65. $tag = rand_str();
  66. $val = rand_str();
  67. $arg1 = rand_str();
  68. add_filter($tag, array($a, 'filter'), 10, 2);
  69. // call the filter with a single argument
  70. $this->assertEquals($val, apply_filters($tag, $val, $arg1));
  71. $this->assertEquals(1, $a->get_call_count());
  72. $argsvar = $a->get_args();
  73. $this->assertEquals( array( $val, $arg1 ), array_pop( $argsvar ) );
  74. }
  75. function test_filter_args_2() {
  76. $a1 = new MockAction();
  77. $a2 = new MockAction();
  78. $tag = rand_str();
  79. $val = rand_str();
  80. $arg1 = rand_str();
  81. $arg2 = rand_str();
  82. // a1 accepts two arguments, a2 doesn't
  83. add_filter($tag, array($a1, 'filter'), 10, 3);
  84. add_filter($tag, array($a2, 'filter'));
  85. // call the filter with two arguments
  86. $this->assertEquals($val, apply_filters($tag, $val, $arg1, $arg2));
  87. // a1 should be called with both args
  88. $this->assertEquals(1, $a1->get_call_count());
  89. $argsvar1 = $a1->get_args();
  90. $this->assertEquals( array( $val, $arg1, $arg2 ), array_pop( $argsvar1 ) );
  91. // a2 should be called with one only
  92. $this->assertEquals(1, $a2->get_call_count());
  93. $argsvar2 = $a2->get_args();
  94. $this->assertEquals( array( $val ), array_pop( $argsvar2 ) );
  95. }
  96. function test_filter_priority() {
  97. $a = new MockAction();
  98. $tag = rand_str();
  99. $val = rand_str();
  100. // make two filters with different priorities
  101. add_filter($tag, array($a, 'filter'), 10);
  102. add_filter($tag, array($a, 'filter2'), 9);
  103. $this->assertEquals($val, apply_filters($tag, $val));
  104. // there should be two events, one per filter
  105. $this->assertEquals(2, $a->get_call_count());
  106. $expected = array (
  107. // filter2 is called first because it has priority 9
  108. array (
  109. 'filter' => 'filter2',
  110. 'tag' => $tag,
  111. 'args' => array($val)
  112. ),
  113. // filter 1 is called second
  114. array (
  115. 'filter' => 'filter',
  116. 'tag' => $tag,
  117. 'args' => array($val)
  118. ),
  119. );
  120. $this->assertEquals($expected, $a->get_events());
  121. }
  122. function test_all_filter() {
  123. $a = new MockAction();
  124. $tag1 = rand_str();
  125. $tag2 = rand_str();
  126. $val = rand_str();
  127. // add an 'all' filter
  128. add_filter('all', array($a, 'filterall'));
  129. // do some filters
  130. $this->assertEquals($val, apply_filters($tag1, $val));
  131. $this->assertEquals($val, apply_filters($tag2, $val));
  132. $this->assertEquals($val, apply_filters($tag1, $val));
  133. $this->assertEquals($val, apply_filters($tag1, $val));
  134. // our filter should have been called once for each apply_filters call
  135. $this->assertEquals(4, $a->get_call_count());
  136. // the right hooks should have been called in order
  137. $this->assertEquals(array($tag1, $tag2, $tag1, $tag1), $a->get_tags());
  138. remove_filter('all', array($a, 'filterall'));
  139. $this->assertFalse( has_filter('all', array($a, 'filterall')) );
  140. }
  141. function test_remove_all_filter() {
  142. $a = new MockAction();
  143. $tag = rand_str();
  144. $val = rand_str();
  145. add_filter('all', array($a, 'filterall'));
  146. $this->assertTrue( has_filter('all') );
  147. $this->assertEquals( 10, has_filter('all', array($a, 'filterall')) );
  148. $this->assertEquals($val, apply_filters($tag, $val));
  149. // make sure our hook was called correctly
  150. $this->assertEquals(1, $a->get_call_count());
  151. $this->assertEquals(array($tag), $a->get_tags());
  152. // now remove the filter, do it again, and make sure it's not called this time
  153. remove_filter('all', array($a, 'filterall'));
  154. $this->assertFalse( has_filter('all', array($a, 'filterall')) );
  155. $this->assertFalse( has_filter('all') );
  156. $this->assertEquals($val, apply_filters($tag, $val));
  157. // call cound should remain at 1
  158. $this->assertEquals(1, $a->get_call_count());
  159. $this->assertEquals(array($tag), $a->get_tags());
  160. }
  161. /**
  162. * @ticket 9886
  163. */
  164. function test_filter_ref_array() {
  165. $obj = new stdClass();
  166. $a = new MockAction();
  167. $tag = rand_str();
  168. add_action($tag, array($a, 'filter'));
  169. apply_filters_ref_array($tag, array(&$obj));
  170. $args = $a->get_args();
  171. $this->assertSame($args[0][0], $obj);
  172. // just in case we don't trust assertSame
  173. $obj->foo = true;
  174. $this->assertFalse( empty($args[0][0]->foo) );
  175. }
  176. /**
  177. * @ticket 12723
  178. */
  179. function test_filter_ref_array_result() {
  180. $obj = new stdClass();
  181. $a = new MockAction();
  182. $b = new MockAction();
  183. $tag = rand_str();
  184. add_action($tag, array($a, 'filter_append'), 10, 2);
  185. add_action($tag, array($b, 'filter_append'), 10, 2);
  186. $result = apply_filters_ref_array($tag, array('string', &$obj));
  187. $this->assertEquals($result, 'string_append_append');
  188. $args = $a->get_args();
  189. $this->assertSame($args[0][1], $obj);
  190. // just in case we don't trust assertSame
  191. $obj->foo = true;
  192. $this->assertFalse( empty($args[0][1]->foo) );
  193. $args = $b->get_args();
  194. $this->assertSame($args[0][1], $obj);
  195. // just in case we don't trust assertSame
  196. $obj->foo = true;
  197. $this->assertFalse( empty($args[0][1]->foo) );
  198. }
  199. function _self_removal($tag) {
  200. remove_action( $tag, array($this, '_self_removal'), 10, 1 );
  201. return $tag;
  202. }
  203. /**
  204. * @ticket 21169
  205. */
  206. function test_filter_removal_during_filter() {
  207. $tag = rand_str();
  208. $a = new MockAction();
  209. $b = new MockAction();
  210. add_action( $tag, array($a, 'filter_append'), 11, 1 );
  211. add_action( $tag, array($b, 'filter_append'), 12, 1 );
  212. add_action( $tag, array($this, '_self_removal'), 10, 1 );
  213. $result = apply_filters($tag, $tag);
  214. $this->assertEquals( 1, $a->get_call_count(), 'priority 11 filters should run after priority 10 empties itself' );
  215. $this->assertEquals( 1, $b->get_call_count(), 'priority 12 filters should run after priority 10 empties itself and priority 11 runs' );
  216. $this->assertEquals( $result, $tag . '_append_append', 'priority 11 and 12 filters should run after priority 10 empties itself' );
  217. }
  218. }