Ticket #34913: 0001-Fix-issue-34913.2.patch
File 0001-Fix-issue-34913.2.patch, 9.2 KB (added by , 9 years ago) |
---|
-
src/wp-includes/cron.php
From 4d310cae7f1a664bd86b580074e9edb98cf6b5ae Mon Sep 17 00:00:00 2001 From: jrfnl <github_nospam@adviesenzo.nl> Date: Tue, 8 Dec 2015 15:01:10 +0100 Subject: [PATCH] Fix issue #34913 "Unscheduling cron jobs fails when original arguments were not an array." --- src/wp-includes/cron.php | 76 ++++++++++++++++++++++------------- tests/phpunit/tests/cron.php | 95 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 144 insertions(+), 27 deletions(-) diff --git a/src/wp-includes/cron.php b/src/wp-includes/cron.php index 60492c5..8dbc2b1 100644
a b function wp_schedule_single_event( $timestamp, $hook, $args = array()) { 47 47 if ( ! $event ) 48 48 return false; 49 49 50 $event->args = _cron_cast_to_array_helper( $event->args ); 50 51 $key = md5(serialize($event->args)); 51 52 52 53 $crons[$event->timestamp][$event->hook][$key] = array( 'schedule' => $event->schedule, 'args' => $event->args ); … … function wp_schedule_event( $timestamp, $recurrence, $hook, $args = array()) { 94 95 if ( ! $event ) 95 96 return false; 96 97 98 $event->args = _cron_cast_to_array_helper( $event->args ); 97 99 $key = md5(serialize($event->args)); 98 100 99 101 $crons[$event->timestamp][$event->hook][$key] = array( 'schedule' => $event->schedule, 'args' => $event->args, 'interval' => $event->interval ); … … function wp_reschedule_event( $timestamp, $recurrence, $hook, $args = array() ) 120 122 121 123 $crons = _get_cron_array(); 122 124 $schedules = wp_get_schedules(); 123 $key = md5( serialize( $args ) );124 125 $interval = 0; 125 126 126 127 // First we try to get it from the schedule … … function wp_reschedule_event( $timestamp, $recurrence, $hook, $args = array() ) 129 130 } 130 131 // Now we try to get it from the saved interval in case the schedule disappears 131 132 if ( 0 == $interval ) { 133 $key = md5( serialize( _cron_cast_to_array_helper( $args ) ) ); 132 134 $interval = $crons[ $timestamp ][ $hook ][ $key ]['interval']; 133 135 } 134 136 // Now we assume something is wrong and fail to schedule … … function wp_unschedule_event( $timestamp, $hook, $args = array() ) { 170 172 } 171 173 172 174 $crons = _get_cron_array(); 173 $key = md5(serialize($args)); 174 unset( $crons[$timestamp][$hook][$key] ); 175 if ( empty($crons[$timestamp][$hook]) ) 176 unset( $crons[$timestamp][$hook] ); 177 if ( empty($crons[$timestamp]) ) 178 unset( $crons[$timestamp] ); 175 $key = md5( serialize( _cron_cast_to_array_helper( $args ) ) ); 176 unset( $crons[ $timestamp ][ $hook ][ $key ] ); 177 if ( empty( $crons[ $timestamp ][ $hook ] ) ) { 178 unset( $crons[ $timestamp ][ $hook ] ); 179 } 180 if ( empty( $crons[ $timestamp ] ) ) { 181 unset( $crons[ $timestamp ] ); 182 } 179 183 _set_cron_array( $crons ); 180 184 } 181 185 … … function wp_clear_scheduled_hook( $hook, $args = array() ) { 221 225 */ 222 226 function wp_next_scheduled( $hook, $args = array() ) { 223 227 $crons = _get_cron_array(); 224 $key = md5(serialize($args)); 225 if ( empty($crons) ) 228 if ( empty( $crons ) ) { 226 229 return false; 230 } 231 232 $key = md5( serialize( _cron_cast_to_array_helper( $args ) ) ); 227 233 foreach ( $crons as $timestamp => $cron ) { 228 if ( isset( $cron[ $hook][$key] ) )234 if ( isset( $cron[ $hook ][ $key ] ) ) { 229 235 return $timestamp; 236 } 230 237 } 231 238 return false; 232 239 } … … function wp_get_schedules() { 412 419 */ 413 420 function wp_get_schedule($hook, $args = array()) { 414 421 $crons = _get_cron_array(); 415 $key = md5(serialize($args)); 416 if ( empty($crons) ) 422 if ( empty( $crons ) ) { 417 423 return false; 424 } 425 426 $key = md5( serialize( _cron_cast_to_array_helper( $args ) ) ); 418 427 foreach ( $crons as $timestamp => $cron ) { 419 if ( isset( $cron[$hook][$key] ) ) 420 return $cron[$hook][$key]['schedule']; 428 if ( isset( $cron[ $hook ][ $key ] ) ) { 429 return $cron[ $hook ][ $key ]['schedule']; 430 } 421 431 } 422 432 return false; 423 433 } … … function wp_get_schedule($hook, $args = array()) { 435 445 * @return false|array CRON info array. 436 446 */ 437 447 function _get_cron_array() { 438 $cron = get_option( 'cron');439 if ( ! is_array( $cron) )448 $cron = get_option( 'cron' ); 449 if ( ! is_array( $cron ) ) { 440 450 return false; 451 } 441 452 442 if ( !isset($cron['version']) ) 443 $cron = _upgrade_cron_array($cron); 453 if ( ! isset( $cron['version'] ) || 3 > $cron['version'] ) { 454 $cron = _upgrade_cron_array( $cron ); 455 } 444 456 445 unset( $cron['version']);457 unset( $cron['version'] ); 446 458 447 459 return $cron; 448 460 } … … function _get_cron_array() { 456 468 * @param array $cron Cron info array from {@link _get_cron_array()}. 457 469 */ 458 470 function _set_cron_array($cron) { 459 $cron['version'] = 2;471 $cron['version'] = 3; 460 472 update_option( 'cron', $cron ); 461 473 } 462 474 463 475 /** 464 476 * Upgrade a Cron info array. 465 477 * 466 * This function upgrades the Cron info array to version 2.478 * This function upgrades the Cron info array to version 3. 467 479 * 468 480 * @since 2.1.0 469 481 * @access private … … function _set_cron_array($cron) { 472 484 * @return array An upgraded Cron info array. 473 485 */ 474 486 function _upgrade_cron_array($cron) { 475 if ( isset( $cron['version']) && 2 == $cron['version'])487 if ( isset( $cron['version'] ) && 3 === $cron['version'] ) { 476 488 return $cron; 489 } 477 490 478 491 $new_cron = array(); 479 492 480 foreach ( (array) $cron as $timestamp => $hooks) { 481 foreach ( (array) $hooks as $hook => $args ) { 482 $key = md5(serialize($args['args'])); 483 $new_cron[$timestamp][$hook][$key] = $args; 493 foreach ( (array) $cron as $timestamp => $hooks ) { 494 foreach ( (array) $hooks as $hook => $event ) { 495 foreach( (array) $event as $args ) { 496 $key = md5( serialize( _cron_cast_to_array_helper( $args['args'] ) ) ); 497 $new_cron[ $timestamp ][ $hook ][ $key ] = $args; 498 } 484 499 } 485 500 } 486 501 487 $new_cron['version'] = 2;502 $new_cron['version'] = 3; 488 503 update_option( 'cron', $new_cron ); 489 504 return $new_cron; 490 505 } 506 507 function _cron_cast_to_array_helper( $args ) { 508 if ( is_object( $args ) ) { 509 return array( $args ); 510 } 511 return (array) $args; 512 } 513 No newline at end of file -
tests/phpunit/tests/cron.php
diff --git a/tests/phpunit/tests/cron.php b/tests/phpunit/tests/cron.php index b411a5b..560182c 100644
a b class Tests_Cron extends WP_UnitTestCase { 189 189 190 190 } 191 191 192 193 /** 194 * @ticket 34913 195 * 196 * @expectedDeprecated wp_clear_scheduled_hook 197 */ 198 function test_clear_schedule_non_array_args() { 199 $hook = rand_str(); 200 $bool_arg = true; 201 $int_arg = mt_rand(); 202 $float_arg = mt_rand() / mt_getrandmax(); 203 $string_arg = rand_str(); 204 $obj_arg = new cronTestClass(); 205 206 // Schedule several events with non-array arguments. 207 wp_schedule_single_event( strtotime('+1 hour'), $hook, $bool_arg ); 208 wp_schedule_single_event( strtotime('+2 hour'), $hook, $int_arg ); 209 wp_schedule_single_event( strtotime('+3 hour'), $hook, $float_arg ); 210 wp_schedule_single_event( strtotime('+4 hour'), $hook, $string_arg ); 211 wp_schedule_single_event( strtotime('+5 hour'), $hook, $obj_arg ); 212 213 // Make sure they're returned by wp_next_scheduled(). 214 $this->assertTrue( wp_next_scheduled($hook, $bool_arg) > 0 ); 215 $this->assertTrue( wp_next_scheduled($hook, $int_arg) > 0 ); 216 $this->assertTrue( wp_next_scheduled($hook, $float_arg) > 0 ); 217 $this->assertTrue( wp_next_scheduled($hook, $string_arg) > 0 ); 218 $this->assertTrue( wp_next_scheduled($hook, $obj_arg) > 0 ); 219 220 // Clear the schedule for the bool_arg event and make sure it's gone. 221 wp_clear_scheduled_hook($hook, $bool_arg ); 222 $this->assertFalse( wp_next_scheduled($hook, $bool_arg) ); 223 224 // Clear the schedule for the int_arg event and make sure it's gone. 225 wp_clear_scheduled_hook($hook, $int_arg ); 226 $this->assertFalse( wp_next_scheduled($hook, $int_arg) ); 227 228 // Clear the schedule for the float_arg event and make sure it's gone. 229 wp_clear_scheduled_hook($hook, $float_arg ); 230 $this->assertFalse( wp_next_scheduled($hook, $float_arg) ); 231 232 // Clear the schedule for the string_arg event and make sure it's gone. 233 wp_clear_scheduled_hook($hook, $string_arg ); 234 $this->assertFalse( wp_next_scheduled($hook, $string_arg) ); 235 236 // Clear the schedule for the object_arg event and make sure it's gone. 237 wp_clear_scheduled_hook($hook, $obj_arg ); 238 $this->assertFalse( wp_next_scheduled($hook, $obj_arg) ); 239 240 } 241 242 /** 243 * @ticket 34913 244 * 245 * @internal Separate test for resources as this one can easily fail and we don't want to skip the 246 * complete group of tests if it does. 247 * 248 * @expectedDeprecated wp_clear_scheduled_hook 249 */ 250 function test_clear_schedule_resource_arg() { 251 $hook = rand_str(); 252 $arg = tmpfile(); 253 254 if ( $arg === false ) { 255 $this->markTestSkipped( 'Could not create resource.' ); 256 return; 257 } 258 259 // Schedule event with resource argument. 260 wp_schedule_single_event( strtotime('+1 hour'), $hook, $arg ); 261 262 // Make sure they're returned by wp_next_scheduled(). 263 $this->assertTrue( wp_next_scheduled($hook, $arg) > 0 ); 264 265 // Clear the schedule for the event and make sure it's gone. 266 wp_clear_scheduled_hook($hook, $arg ); 267 $this->assertFalse( wp_next_scheduled($hook, $arg) ); 268 269 fclose( $arg ); 270 271 } 272 273 192 274 /** 193 275 * @ticket 6966 194 276 */ … … class WPTestCronRunning extends _WPEmptyBlog { 327 409 } 328 410 } 329 411 */ 412 413 /** 414 * Test class belonging to the `test_clear_schedule_non_array_arg()` test. 415 */ 416 class cronTestClass { 417 public $property_a = 'something'; 418 public $property_b = 123; 419 private $property_c = false; 420 421 public function some_function() { 422 return true; 423 } 424 }