Ticket #17817: 17817.21.diff
File 17817.21.diff, 21.2 KB (added by , 8 years ago) |
---|
-
src/wp-includes/plugin.php
22 22 */ 23 23 24 24 // Initialize the filter globals. 25 global $wp_filter, $wp_actions, $merged_filters, $wp_current_filter;25 require( ABSPATH . WPINC . '/class-wp-hook.php' ); 26 26 27 if ( ! isset( $wp_filter ) ) 27 /** @var WP_Hook[] $wp_filter */ 28 global $wp_filter, $wp_actions, $wp_current_filter; 29 30 if ( $wp_filter ) { 31 $wp_filter = WP_Hook::build_preinitialized_hooks( $wp_filter ); 32 } else { 28 33 $wp_filter = array(); 34 } 29 35 30 36 if ( ! isset( $wp_actions ) ) 31 37 $wp_actions = array(); 32 38 33 if ( ! isset( $merged_filters ) )34 $merged_filters = array();35 36 39 if ( ! isset( $wp_current_filter ) ) 37 40 $wp_current_filter = array(); 38 41 … … 89 92 * @since 0.71 90 93 * 91 94 * @global array $wp_filter A multidimensional array of all hooks and the callbacks hooked to them. 92 * @global array $merged_filters Tracks the tags that need to be merged for later. If the hook is added,93 * it doesn't need to run through that process.94 95 * 95 96 * @param string $tag The name of the filter to hook the $function_to_add callback to. 96 97 * @param callable $function_to_add The callback to be run when the filter is applied. … … 103 104 * @return true 104 105 */ 105 106 function add_filter( $tag, $function_to_add, $priority = 10, $accepted_args = 1 ) { 106 global $wp_filter , $merged_filters;107 108 $idx = _wp_filter_build_unique_id($tag, $function_to_add, $priority);109 $wp_filter[$tag][$priority][$idx] = array('function' => $function_to_add, 'accepted_args' => $accepted_args);110 unset( $merged_filters[ $tag ]);107 global $wp_filter; 108 if ( ! isset( $wp_filter[ $tag ] ) ) { 109 $wp_filter[ $tag ] = new WP_Hook(); 110 } 111 $wp_filter[ $tag ]->add_filter( $tag, $function_to_add, $priority, $accepted_args ); 111 112 return true; 112 113 } 113 114 … … 128 129 * return value. 129 130 */ 130 131 function has_filter($tag, $function_to_check = false) { 131 // Don't reset the internal array pointer 132 $wp_filter = $GLOBALS['wp_filter']; 133 134 $has = ! empty( $wp_filter[ $tag ] ); 135 136 // Make sure at least one priority has a filter callback 137 if ( $has ) { 138 $exists = false; 139 foreach ( $wp_filter[ $tag ] as $callbacks ) { 140 if ( ! empty( $callbacks ) ) { 141 $exists = true; 142 break; 143 } 144 } 145 146 if ( ! $exists ) { 147 $has = false; 148 } 149 } 150 151 if ( false === $function_to_check || false === $has ) 152 return $has; 132 global $wp_filter; 153 133 154 if ( ! $idx = _wp_filter_build_unique_id($tag, $function_to_check, false) )134 if ( ! isset( $wp_filter[ $tag ] ) ) { 155 135 return false; 156 157 foreach ( (array) array_keys($wp_filter[$tag]) as $priority ) {158 if ( isset($wp_filter[$tag][$priority][$idx]) )159 return $priority;160 136 } 161 137 162 return false;138 return $wp_filter[ $tag ]->has_filter( $tag, $function_to_check ); 163 139 } 164 140 165 141 /** … … 190 166 * @since 0.71 191 167 * 192 168 * @global array $wp_filter Stores all of the filters. 193 * @global array $merged_filters Merges the filter hooks using this function.194 169 * @global array $wp_current_filter Stores the list of current filters with the current one last. 195 170 * 196 171 * @param string $tag The name of the filter hook. … … 199 174 * @return mixed The filtered value after all hooked functions are applied to it. 200 175 */ 201 176 function apply_filters( $tag, $value ) { 202 global $wp_filter, $ merged_filters, $wp_current_filter;177 global $wp_filter, $wp_current_filter; 203 178 204 179 $args = array(); 205 180 … … 219 194 if ( !isset($wp_filter['all']) ) 220 195 $wp_current_filter[] = $tag; 221 196 222 // Sort.223 if ( !isset( $merged_filters[ $tag ] ) ) {224 ksort($wp_filter[$tag]);225 $merged_filters[ $tag ] = true;226 }227 228 reset( $wp_filter[ $tag ] );229 230 197 if ( empty($args) ) 231 198 $args = func_get_args(); 232 199 233 do { 234 foreach ( (array) current($wp_filter[$tag]) as $the_ ) 235 if ( !is_null($the_['function']) ){ 236 $args[1] = $value; 237 $value = call_user_func_array($the_['function'], array_slice($args, 1, (int) $the_['accepted_args'])); 238 } 200 // don't pass the tag name to WP_Hook 201 array_shift( $args ); 239 202 240 } while ( next($wp_filter[$tag]) !== false);203 $filtered = $wp_filter[ $tag ]->apply_filters( $value, $args ); 241 204 242 205 array_pop( $wp_current_filter ); 243 206 244 return $ value;207 return $filtered; 245 208 } 246 209 247 210 /** … … 253 216 * functions hooked to `$tag` are supplied using an array. 254 217 * 255 218 * @global array $wp_filter Stores all of the filters 256 * @global array $merged_filters Merges the filter hooks using this function.257 219 * @global array $wp_current_filter Stores the list of current filters with the current one last 258 220 * 259 221 * @param string $tag The name of the filter hook. … … 261 223 * @return mixed The filtered value after all hooked functions are applied to it. 262 224 */ 263 225 function apply_filters_ref_array($tag, $args) { 264 global $wp_filter, $ merged_filters, $wp_current_filter;226 global $wp_filter, $wp_current_filter; 265 227 266 228 // Do 'all' actions first 267 229 if ( isset($wp_filter['all']) ) { … … 279 241 if ( !isset($wp_filter['all']) ) 280 242 $wp_current_filter[] = $tag; 281 243 282 // Sort 283 if ( !isset( $merged_filters[ $tag ] ) ) { 284 ksort($wp_filter[$tag]); 285 $merged_filters[ $tag ] = true; 286 } 287 288 reset( $wp_filter[ $tag ] ); 289 290 do { 291 foreach ( (array) current($wp_filter[$tag]) as $the_ ) 292 if ( !is_null($the_['function']) ) 293 $args[0] = call_user_func_array($the_['function'], array_slice($args, 0, (int) $the_['accepted_args'])); 294 295 } while ( next($wp_filter[$tag]) !== false ); 244 $filtered = $wp_filter[ $tag ]->apply_filters( $args[0], $args ); 296 245 297 246 array_pop( $wp_current_filter ); 298 247 299 return $ args[0];248 return $filtered; 300 249 } 301 250 302 251 /** … … 313 262 * @since 1.2.0 314 263 * 315 264 * @global array $wp_filter Stores all of the filters 316 * @global array $merged_filters Merges the filter hooks using this function.317 265 * 318 266 * @param string $tag The filter hook to which the function to be removed is hooked. 319 267 * @param callable $function_to_remove The name of the function which should be removed. … … 321 269 * @return bool Whether the function existed before it was removed. 322 270 */ 323 271 function remove_filter( $tag, $function_to_remove, $priority = 10 ) { 324 $function_to_remove = _wp_filter_build_unique_id( $tag, $function_to_remove, $priority ); 325 326 $r = isset( $GLOBALS['wp_filter'][ $tag ][ $priority ][ $function_to_remove ] ); 272 global $wp_filter; 327 273 328 if ( true === $r ) { 329 unset( $GLOBALS['wp_filter'][ $tag ][ $priority ][ $function_to_remove ] ); 330 if ( empty( $GLOBALS['wp_filter'][ $tag ][ $priority ] ) ) { 331 unset( $GLOBALS['wp_filter'][ $tag ][ $priority ] ); 274 $r = false; 275 if ( isset( $wp_filter[ $tag ] ) ) { 276 $r = $wp_filter[ $tag ]->remove_filter( $tag, $function_to_remove, $priority ); 277 if ( ! $wp_filter[ $tag ]->callbacks ) { 278 unset( $wp_filter[ $tag ] ); 332 279 } 333 if ( empty( $GLOBALS['wp_filter'][ $tag ] ) ) {334 $GLOBALS['wp_filter'][ $tag ] = array();335 }336 unset( $GLOBALS['merged_filters'][ $tag ] );337 280 } 338 281 339 282 return $r; … … 344 287 * 345 288 * @since 2.7.0 346 289 * 347 * @global array $wp_filter Stores all of the filters 348 * @global array $merged_filters Merges the filter hooks using this function. 290 * @global array $wp_filter Stores all of the filters 349 291 * 350 292 * @param string $tag The filter to remove hooks from. 351 293 * @param int|bool $priority Optional. The priority number to remove. Default false. 352 294 * @return true True when finished. 353 295 */ 354 296 function remove_all_filters( $tag, $priority = false ) { 355 global $wp_filter , $merged_filters;297 global $wp_filter; 356 298 357 299 if ( isset( $wp_filter[ $tag ]) ) { 358 if ( false === $priority ) { 359 $wp_filter[ $tag ] = array(); 360 } elseif ( isset( $wp_filter[ $tag ][ $priority ] ) ) { 361 $wp_filter[ $tag ][ $priority ] = array(); 300 $wp_filter[ $tag ]->remove_all_filters( $priority ); 301 if ( ! $wp_filter[ $tag ]->has_filters() ) { 302 unset( $wp_filter[ $tag ] ); 362 303 } 363 304 } 364 305 365 unset( $merged_filters[ $tag ] );366 367 306 return true; 368 307 } 369 308 … … 473 412 * 474 413 * @global array $wp_filter Stores all of the filters 475 414 * @global array $wp_actions Increments the amount of times action was triggered. 476 * @global array $merged_filters Merges the filter hooks using this function.477 415 * @global array $wp_current_filter Stores the list of current filters with the current one last 478 416 * 479 417 * @param string $tag The name of the action to be executed. … … 481 419 * functions hooked to the action. Default empty. 482 420 */ 483 421 function do_action($tag, $arg = '') { 484 global $wp_filter, $wp_actions, $ merged_filters, $wp_current_filter;422 global $wp_filter, $wp_actions, $wp_current_filter; 485 423 486 424 if ( ! isset($wp_actions[$tag]) ) 487 425 $wp_actions[$tag] = 1; … … 512 450 for ( $a = 2, $num = func_num_args(); $a < $num; $a++ ) 513 451 $args[] = func_get_arg($a); 514 452 515 // Sort 516 if ( !isset( $merged_filters[ $tag ] ) ) { 517 ksort($wp_filter[$tag]); 518 $merged_filters[ $tag ] = true; 519 } 520 521 reset( $wp_filter[ $tag ] ); 522 523 do { 524 foreach ( (array) current($wp_filter[$tag]) as $the_ ) 525 if ( !is_null($the_['function']) ) 526 call_user_func_array($the_['function'], array_slice($args, 0, (int) $the_['accepted_args'])); 527 528 } while ( next($wp_filter[$tag]) !== false ); 453 $wp_filter[ $tag ]->do_action( $args ); 529 454 530 455 array_pop($wp_current_filter); 531 456 } … … 558 483 * functions hooked to $tag< are supplied using an array. 559 484 * @global array $wp_filter Stores all of the filters 560 485 * @global array $wp_actions Increments the amount of times action was triggered. 561 * @global array $merged_filters Merges the filter hooks using this function.562 486 * @global array $wp_current_filter Stores the list of current filters with the current one last 563 487 * 564 488 * @param string $tag The name of the action to be executed. 565 489 * @param array $args The arguments supplied to the functions hooked to `$tag`. 566 490 */ 567 491 function do_action_ref_array($tag, $args) { 568 global $wp_filter, $wp_actions, $ merged_filters, $wp_current_filter;492 global $wp_filter, $wp_actions, $wp_current_filter; 569 493 570 494 if ( ! isset($wp_actions[$tag]) ) 571 495 $wp_actions[$tag] = 1; … … 588 512 if ( !isset($wp_filter['all']) ) 589 513 $wp_current_filter[] = $tag; 590 514 591 // Sort 592 if ( !isset( $merged_filters[ $tag ] ) ) { 593 ksort($wp_filter[$tag]); 594 $merged_filters[ $tag ] = true; 595 } 596 597 reset( $wp_filter[ $tag ] ); 598 599 do { 600 foreach ( (array) current($wp_filter[$tag]) as $the_ ) 601 if ( !is_null($the_['function']) ) 602 call_user_func_array($the_['function'], array_slice($args, 0, (int) $the_['accepted_args'])); 603 604 } while ( next($wp_filter[$tag]) !== false ); 515 $wp_filter[ $tag ]->do_action( $args ); 605 516 606 517 array_pop($wp_current_filter); 607 518 } … … 923 834 function _wp_call_all_hook($args) { 924 835 global $wp_filter; 925 836 926 reset( $wp_filter['all'] ); 927 do { 928 foreach ( (array) current($wp_filter['all']) as $the_ ) 929 if ( !is_null($the_['function']) ) 930 call_user_func_array($the_['function'], $args); 931 932 } while ( next($wp_filter['all']) !== false ); 837 $wp_filter['all']->do_all_hook( $args ); 933 838 } 934 839 935 840 /** -
tests/phpunit/includes/functions.php
21 21 22 22 // For adding hooks before loading WP 23 23 function tests_add_filter($tag, $function_to_add, $priority = 10, $accepted_args = 1) { 24 global $wp_filter , $merged_filters;24 global $wp_filter; 25 25 26 26 $idx = _test_filter_build_unique_id($tag, $function_to_add, $priority); 27 27 $wp_filter[$tag][$priority][$idx] = array('function' => $function_to_add, 'accepted_args' => $accepted_args); 28 unset( $merged_filters[ $tag ] );29 28 return true; 30 29 } 31 30 32 31 function _test_filter_build_unique_id($tag, $function, $priority) { 33 global $wp_filter;34 static $filter_id_count = 0;35 36 32 if ( is_string($function) ) 37 33 return $function; 38 34 -
tests/phpunit/includes/testcase.php
223 223 * @return void 224 224 */ 225 225 protected function _backup_hooks() { 226 $globals = array( ' merged_filters', 'wp_actions', 'wp_current_filter', 'wp_filter' );226 $globals = array( 'wp_actions', 'wp_current_filter' ); 227 227 foreach ( $globals as $key ) { 228 228 self::$hooks_saved[ $key ] = $GLOBALS[ $key ]; 229 229 } 230 self::$hooks_saved['wp_filter'] = array(); 231 foreach ( $GLOBALS['wp_filter'] as $hook_name => $hook_object ) { 232 self::$hooks_saved['wp_filter'][ $hook_name ] = clone $hook_object; 233 } 230 234 } 231 235 232 236 /** … … 240 244 * @return void 241 245 */ 242 246 protected function _restore_hooks() { 243 $globals = array( ' merged_filters', 'wp_actions', 'wp_current_filter', 'wp_filter' );247 $globals = array( 'wp_actions', 'wp_current_filter' ); 244 248 foreach ( $globals as $key ) { 245 249 if ( isset( self::$hooks_saved[ $key ] ) ) { 246 250 $GLOBALS[ $key ] = self::$hooks_saved[ $key ]; 247 251 } 248 252 } 253 if ( isset( self::$hooks_saved['wp_filter'] ) ) { 254 $GLOBALS['wp_filter'] = array(); 255 foreach ( self::$hooks_saved['wp_filter'] as $hook_name => $hook_object ) { 256 $GLOBALS['wp_filter'][ $hook_name ] = clone $hook_object; 257 } 258 } 249 259 } 250 260 251 261 static function flush_cache() { -
tests/phpunit/tests/actions.php
114 114 $this->assertEquals( array( $val1 ), array_pop( $argsvar2 ) ); 115 115 } 116 116 117 /** 118 * Test that multiple callbacks receive the correct number of args even when the number 119 * is less than, or greater than previous hooks. 120 * 121 * @see https://core.trac.wordpress.org/ticket/17817#comment:72 122 * @ticket 17817 123 */ 124 function test_action_args_3() { 125 $a1 = new MockAction(); 126 $a2 = new MockAction(); 127 $a3 = new MockAction(); 128 $tag = rand_str(); 129 $val1 = rand_str(); 130 $val2 = rand_str(); 131 132 // a1 accepts two arguments, a2 doesn't, a3 accepts two arguments 133 add_action( $tag, array( &$a1, 'action' ), 10, 2 ); 134 add_action( $tag, array( &$a2, 'action' ) ); 135 add_action( $tag, array( &$a3, 'action' ), 10, 2 ); 136 // call the action with two arguments 137 do_action( $tag, $val1, $val2 ); 138 139 $call_count = $a1->get_call_count(); 140 // a1 should be called with both args 141 $this->assertEquals( 1, $call_count ); 142 $argsvar1 = $a1->get_args(); 143 $this->assertEquals( array( $val1, $val2 ), array_pop( $argsvar1 ) ); 144 145 // a2 should be called with one only 146 $this->assertEquals( 1, $a2->get_call_count() ); 147 $argsvar2 = $a2->get_args(); 148 $this->assertEquals( array( $val1 ), array_pop( $argsvar2 ) ); 149 150 // a3 should be called with both args 151 $this->assertEquals( 1, $a3->get_call_count() ); 152 $argsvar3 = $a3->get_args(); 153 $this->assertEquals( array( $val1, $val2 ), array_pop( $argsvar3 ) ); 154 } 155 117 156 function test_action_priority() { 118 157 $a = new MockAction(); 119 158 $tag = rand_str(); … … 258 297 } 259 298 260 299 /** 300 * @ticket 17817 301 */ 302 function test_action_recursion() { 303 $tag = rand_str(); 304 $a = new MockAction(); 305 $b = new MockAction(); 306 307 add_action( $tag, array( $a, 'action' ), 11, 1 ); 308 add_action( $tag, array( $b, 'action' ), 13, 1 ); 309 add_action( $tag, array( $this, 'action_that_causes_recursion' ), 12, 1 ); 310 do_action( $tag, $tag ); 311 312 $this->assertEquals( 2, $a->get_call_count(), 'recursive actions should call all callbacks with earlier priority' ); 313 $this->assertEquals( 2, $b->get_call_count(), 'recursive actions should call callbacks with later priority' ); 314 } 315 316 function action_that_causes_recursion( $tag ) { 317 static $recursing = false; 318 if ( ! $recursing ) { 319 $recursing = true; 320 do_action( $tag, $tag ); 321 } 322 $recursing = false; 323 } 324 325 /** 326 * @ticket 9968 327 * @ticket 17817 328 */ 329 function test_action_callback_manipulation_while_running() { 330 $tag = rand_str(); 331 $a = new MockAction(); 332 $b = new MockAction(); 333 $c = new MockAction(); 334 $d = new MockAction(); 335 $e = new MockAction(); 336 337 add_action( $tag, array( $a, 'action' ), 11, 2 ); 338 add_action( $tag, array( $this, 'action_that_manipulates_a_running_hook' ), 12, 2 ); 339 add_action( $tag, array( $b, 'action' ), 12, 2 ); 340 341 do_action( $tag, $tag, array( $a, $b, $c, $d, $e ) ); 342 do_action( $tag, $tag, array( $a, $b, $c, $d, $e ) ); 343 344 $this->assertEquals( 2, $a->get_call_count(), 'callbacks should run unless otherwise instructed' ); 345 $this->assertEquals( 1, $b->get_call_count(), 'callback removed by same priority callback should still get called' ); 346 $this->assertEquals( 1, $c->get_call_count(), 'callback added by same priority callback should not get called' ); 347 $this->assertEquals( 2, $d->get_call_count(), 'callback added by earlier priority callback should get called' ); 348 $this->assertEquals( 1, $e->get_call_count(), 'callback added by later priority callback should not get called' ); 349 } 350 351 function action_that_manipulates_a_running_hook( $tag, $mocks ) { 352 remove_action( $tag, array( $mocks[ 1 ], 'action' ), 12, 2 ); 353 add_action( $tag, array( $mocks[ 2 ], 'action' ), 12, 2 ); 354 add_action( $tag, array( $mocks[ 3 ], 'action' ), 13, 2 ); 355 add_action( $tag, array( $mocks[ 4 ], 'action' ), 10, 2 ); 356 } 357 358 /** 359 * @ticket 17817 360 * 361 * This specificaly addresses the concern raised at 362 * https://core.trac.wordpress.org/ticket/17817#comment:52 363 */ 364 function test_remove_anonymous_callback() { 365 $tag = rand_str(); 366 $a = new MockAction(); 367 add_action( $tag, array( $a, 'action' ), 12, 1 ); 368 $this->assertTrue( has_action( $tag ) ); 369 370 $hook = $GLOBALS['wp_filter'][ $tag ]; 371 372 // From http://wordpress.stackexchange.com/a/57088/6445 373 foreach ( $hook as $priority => $filter ) { 374 foreach ( $filter as $identifier => $function ) { 375 if ( is_array( $function ) 376 && is_a( $function['function'][ 0 ], 'MockAction' ) 377 && 'action' === $function['function'][ 1 ] 378 ) { 379 remove_filter( 380 $tag, 381 array( $function['function'][ 0 ], 'action' ), 382 $priority 383 ); 384 } 385 } 386 } 387 388 $this->assertFalse( has_action( $tag ) ); 389 } 390 391 392 /** 393 * Test the ArrayAccess methods of WP_Hook 394 * 395 * @ticket 17817 396 */ 397 function test_array_access_of_wp_filter_global() { 398 global $wp_filter; 399 $tag = rand_str(); 400 401 add_action( $tag, '__return_null', 11, 1 ); 402 403 $this->assertTrue( isset( $wp_filter[ $tag ][ 11 ] ) ); 404 $this->assertArrayHasKey( '__return_null', $wp_filter[ $tag ][ 11 ] ); 405 406 unset( $wp_filter[ $tag ][ 11 ] ); 407 $this->assertFalse( has_action( $tag, '__return_null' ) ); 408 409 $wp_filter[ $tag ][ 11 ] = array( '__return_null' => array( 'function' => '__return_null', 'accepted_args' => 1 ) ); 410 $this->assertEquals( 11, has_action( $tag, '__return_null' ) ); 411 } 412 413 /** 261 414 * Make sure current_action() behaves as current_filter() 262 415 * 263 416 * @ticket 14994 -
tests/phpunit/tests/filters.php
296 296 } 297 297 298 298 /** 299 * @ticket 29070300 */301 function test_has_filter_doesnt_reset_wp_filter() {302 add_action( 'action_test_has_filter_doesnt_reset_wp_filter', '__return_null', 1 );303 add_action( 'action_test_has_filter_doesnt_reset_wp_filter', '__return_null', 2 );304 add_action( 'action_test_has_filter_doesnt_reset_wp_filter', '__return_null', 3 );305 add_action( 'action_test_has_filter_doesnt_reset_wp_filter', array( $this, '_action_test_has_filter_doesnt_reset_wp_filter' ), 4 );306 307 do_action( 'action_test_has_filter_doesnt_reset_wp_filter' );308 }309 function _action_test_has_filter_doesnt_reset_wp_filter() {310 global $wp_filter;311 312 has_action( 'action_test_has_filter_doesnt_reset_wp_filter', '_function_that_doesnt_exist' );313 314 $filters = current( $wp_filter['action_test_has_filter_doesnt_reset_wp_filter'] );315 $the_ = current( $filters );316 $this->assertEquals( $the_['function'], array( $this, '_action_test_has_filter_doesnt_reset_wp_filter' ) );317 }318 319 /**320 299 * @ticket 10441 321 300 * @expectedDeprecated tests_apply_filters_deprecated 322 301 */ -
tests/phpunit/tests/post/types.php
446 446 447 447 $this->assertSame( 1, count( $wp_filter['future_foo'] ) ); 448 448 $this->assertTrue( unregister_post_type( 'foo' ) ); 449 $this->assert Same( array(), $wp_filter['future_foo']);449 $this->assertArrayNotHasKey( 'future_foo', $wp_filter ); 450 450 } 451 451 452 452 /** … … 462 462 463 463 $this->assertSame( 1, count( $wp_filter['add_meta_boxes_foo'] ) ); 464 464 $this->assertTrue( unregister_post_type( 'foo' ) ); 465 $this->assert Same( array(), $wp_filter['add_meta_boxes_foo']);465 $this->assertArrayNotHasKey( 'add_meta_boxes_foo', $wp_filter ); 466 466 } 467 467 468 468 /** -
tests/phpunit/tests/taxonomy.php
697 697 698 698 $this->assertSame( 1, count( $wp_filter['wp_ajax_add-foo'] ) ); 699 699 $this->assertTrue( unregister_taxonomy( 'foo' ) ); 700 $this->assert Same( array(), $wp_filter['wp_ajax_add-foo']);700 $this->assertArrayNotHasKey( 'wp_ajax_add-foo', $wp_filter ); 701 701 } 702 702 703 703 /**