Ticket #32656: 32656.4.diff
File 32656.4.diff, 22.1 KB (added by , 5 years ago) |
---|
-
src/wp-includes/cron.php
diff --git src/wp-includes/cron.php src/wp-includes/cron.php index fbf5a629af..7a147433dd 100644
26 26 * @param int $timestamp Unix timestamp (UTC) for when to next run the event. 27 27 * @param string $hook Action hook to execute when the event is run. 28 28 * @param array $args Optional. Array containing each separate argument to pass to the hook's callback function. 29 * @return false|void False if the event did not getscheduled.29 * @return bool Whether or not the requested event has been scheduled. 30 30 */ 31 31 function wp_schedule_single_event( $timestamp, $hook, $args = array() ) { 32 32 // Make sure timestamp is a positive integer … … function wp_schedule_single_event( $timestamp, $hook, $args = array() ) { 34 34 return false; 35 35 } 36 36 37 // Don't schedule a duplicate if there's already an identical event due within 10 minutes of it38 $next = wp_next_scheduled( $hook, $args );39 if ( $next && abs( $next - $timestamp ) <= 10 * MINUTE_IN_SECONDS ) {40 return false;41 }42 43 $crons = _get_cron_array();44 37 $event = (object) array( 45 38 'hook' => $hook, 46 39 'timestamp' => $timestamp, … … function wp_schedule_single_event( $timestamp, $hook, $args = array() ) { 48 41 'args' => $args, 49 42 ); 50 43 44 /** 45 * Filter to preflight or hijack scheduling an event. 46 * 47 * Passing a non-null value will short-circuit adding the event to the cron 48 * array, returning the passed value instead. 49 * 50 * Both single events and recurring events are passed through this filter; 51 * single events have `$event->schedule` as false, whereas recurring events 52 * have this set to a recurrence from {@see wp_get_schedules}. Recurring 53 * events also have the integer recurrence interval set as `$event->interval`. 54 * 55 * Before scheduling, it is recommended you check for an identical event 56 * within ten minutes and apply the {@see schedule_event} filter to check 57 * if another plugin has disallowed the event. 58 * 59 * Pass true if the event was successfully scheduled, false if not. 60 * 61 * @param null|bool $pre Value to return instead. Default null to continue adding the event. 62 * @param stdClass $event { 63 * An object containing an event's data. 64 * 65 * @type string $hook Action hook to execute when the event is run. 66 * @type int $timestamp Unix timestamp (UTC) for when to next run the event. 67 * @type string|false $schedule How often the event should subsequently recur. 68 * @type array $args Array containing each separate argument to pass to the hook's callback function. 69 * @type int $interval The interval time in seconds for the schedule. Only present for recurring events. 70 * } 71 */ 72 $pre = apply_filters( 'pre_schedule_event', null, $event ); 73 if ( null !== $pre ) { 74 return $pre; 75 } 76 77 // Don't schedule a duplicate if there's already an identical event due within 10 minutes of it 78 $next = wp_next_scheduled( $hook, $args ); 79 if ( $next && abs( $next - $timestamp ) <= 10 * MINUTE_IN_SECONDS ) { 80 return false; 81 } 82 51 83 /** 52 84 * Filters a single event before it is scheduled. 53 85 * … … function wp_schedule_single_event( $timestamp, $hook, $args = array() ) { 72 104 73 105 $key = md5( serialize( $event->args ) ); 74 106 107 $crons = _get_cron_array(); 75 108 $crons[ $event->timestamp ][ $event->hook ][ $key ] = array( 76 109 'schedule' => $event->schedule, 77 110 'args' => $event->args, 78 111 ); 79 112 uksort( $crons, 'strnatcasecmp' ); 80 _set_cron_array( $crons );113 return _set_cron_array( $crons ); 81 114 } 82 115 83 116 /** … … function wp_schedule_single_event( $timestamp, $hook, $args = array() ) { 105 138 * @param string $recurrence How often the event should subsequently recur. See wp_get_schedules() for accepted values. 106 139 * @param string $hook Action hook to execute when the event is run. 107 140 * @param array $args Optional. Array containing each separate argument to pass to the hook's callback function. 108 * @return false|void False if the event did not getscheduled.141 * @return bool Whether or not the requested event has been scheduled. 109 142 */ 110 143 function wp_schedule_event( $timestamp, $recurrence, $hook, $args = array() ) { 111 144 // Make sure timestamp is a positive integer … … function wp_schedule_event( $timestamp, $recurrence, $hook, $args = array() ) { 113 146 return false; 114 147 } 115 148 116 $crons = _get_cron_array();117 149 $schedules = wp_get_schedules(); 118 150 119 151 if ( ! isset( $schedules[ $recurrence ] ) ) { … … function wp_schedule_event( $timestamp, $recurrence, $hook, $args = array() ) { 127 159 'args' => $args, 128 160 'interval' => $schedules[ $recurrence ]['interval'], 129 161 ); 162 163 /** This filter is documented in wp-includes/cron.php */ 164 $pre = apply_filters( 'pre_schedule_event', null, $event ); 165 if ( null !== $pre ) { 166 return $pre; 167 } 168 130 169 /** This filter is documented in wp-includes/cron.php */ 131 170 $event = apply_filters( 'schedule_event', $event ); 132 171 … … function wp_schedule_event( $timestamp, $recurrence, $hook, $args = array() ) { 137 176 138 177 $key = md5( serialize( $event->args ) ); 139 178 179 $crons = _get_cron_array(); 140 180 $crons[ $event->timestamp ][ $event->hook ][ $key ] = array( 141 181 'schedule' => $event->schedule, 142 182 'args' => $event->args, 143 183 'interval' => $event->interval, 144 184 ); 145 185 uksort( $crons, 'strnatcasecmp' ); 146 _set_cron_array( $crons );186 return _set_cron_array( $crons ); 147 187 } 148 188 149 189 /** … … function wp_schedule_event( $timestamp, $recurrence, $hook, $args = array() ) { 155 195 * @param string $recurrence How often the event should subsequently recur. See wp_get_schedules() for accepted values. 156 196 * @param string $hook Action hook to execute when the event is run. 157 197 * @param array $args Optional. Array containing each separate argument to pass to the hook's callback function. 158 * @return false|void False if the event did not getrescheduled.198 * @return bool Whether or not the requested event has been rescheduled. 159 199 */ 160 200 function wp_reschedule_event( $timestamp, $recurrence, $hook, $args = array() ) { 161 201 // Make sure timestamp is a positive integer … … function wp_reschedule_event( $timestamp, $recurrence, $hook, $args = array() ) 163 203 return false; 164 204 } 165 205 166 $crons = _get_cron_array();167 206 $schedules = wp_get_schedules(); 168 $key = md5( serialize( $args ) );169 207 $interval = 0; 170 208 171 // First we try to get it from the schedule209 // First we try to get the interval from the schedule. 172 210 if ( isset( $schedules[ $recurrence ] ) ) { 173 211 $interval = $schedules[ $recurrence ]['interval']; 174 212 } 175 // Now we try to get it from the saved interval in case the schedule disappears 176 if ( 0 == $interval ) { 177 $interval = $crons[ $timestamp ][ $hook ][ $key ]['interval']; 213 214 // Now we try to get it from the saved interval in case the schedule disappears. 215 if ( 0 === $interval ) { 216 $scheduled_event = wp_get_scheduled_event( $hook, $args, $timestamp ); 217 if ( $scheduled_event && isset( $scheduled_event->interval ) ) { 218 $interval = $scheduled_event->interval; 219 } 178 220 } 221 222 $event = (object) array( 223 'hook' => $hook, 224 'timestamp' => $timestamp, 225 'schedule' => $recurrence, 226 'args' => $args, 227 'interval' => $interval, 228 ); 229 230 /** 231 * Filter to preflight or hijack rescheduling of events. 232 * 233 * Passing a non-null value will short-circuit the normal rescheduling 234 * process, returning the passed value instead. 235 * 236 * Pass true if the event was successfully scheduled, false if not. 237 * 238 * @param null|bool $pre Value to return instead. Default null to continue adding the event. 239 * @param stdClass $event { 240 * An object containing an event's data. 241 * 242 * @type string $hook Action hook to execute when the event is run. 243 * @type int $timestamp Unix timestamp (UTC) for when to next run the event. 244 * @type string|false $schedule How often the event should subsequently recur. 245 * @type array $args Array containing each separate argument to pass to the hook's callback function. 246 * @type int $interval The interval time in seconds for the schedule. Only present for recurring events. 247 * } 248 */ 249 $pre = apply_filters( 'pre_reschedule_event', null, $event ); 250 if ( null !== $pre ) { 251 return $pre; 252 } 253 179 254 // Now we assume something is wrong and fail to schedule 180 255 if ( 0 == $interval ) { 181 256 return false; … … function wp_reschedule_event( $timestamp, $recurrence, $hook, $args = array() ) 189 264 $timestamp = $now + ( $interval - ( ( $now - $timestamp ) % $interval ) ); 190 265 } 191 266 192 wp_schedule_event( $timestamp, $recurrence, $hook, $args );267 return wp_schedule_event( $timestamp, $recurrence, $hook, $args ); 193 268 } 194 269 195 270 /** … … function wp_reschedule_event( $timestamp, $recurrence, $hook, $args = array() ) 205 280 * @param array $args Optional. Array containing each separate argument to pass to the hook's callback function. 206 281 * Although not passed to a callback, these arguments are used to uniquely identify the 207 282 * event, so they should be the same as those used when originally scheduling the event. 208 * @return false|void False if the event did not getunscheduled.283 * @return bool Whether or not the requested event has been unscheduled. 209 284 */ 210 285 function wp_unschedule_event( $timestamp, $hook, $args = array() ) { 211 286 // Make sure timestamp is a positive integer … … function wp_unschedule_event( $timestamp, $hook, $args = array() ) { 213 288 return false; 214 289 } 215 290 291 /** 292 * Filter to preflight or hijack unscheduling of events. 293 * 294 * Passing a non-null value will short-circuit the normal unscheduling 295 * process, returning the passed value instead. 296 * 297 * Pass true if the event was successfully unscheduled, false if not. 298 * 299 * @param null|bool $pre Value to return instead. Default null to continue unscheduling the event. 300 * @param int $timestamp Timestamp for when to run the event. 301 * @param string $hook Action hook, the execution of which will be unscheduled. 302 * @param array $args Arguments to pass to the hook's callback function. 303 */ 304 $pre = apply_filters( 'pre_unschedule_event', null, $timestamp, $hook, $args ); 305 if ( null !== $pre ) { 306 return $pre; 307 } 308 216 309 $crons = _get_cron_array(); 217 310 $key = md5( serialize( $args ) ); 218 311 unset( $crons[ $timestamp ][ $hook ][ $key ] ); … … function wp_unschedule_event( $timestamp, $hook, $args = array() ) { 222 315 if ( empty( $crons[ $timestamp ] ) ) { 223 316 unset( $crons[ $timestamp ] ); 224 317 } 225 _set_cron_array( $crons );318 return _set_cron_array( $crons ); 226 319 } 227 320 228 321 /** … … function wp_unschedule_event( $timestamp, $hook, $args = array() ) { 232 325 * 233 326 * @param string $hook Action hook, the execution of which will be unscheduled. 234 327 * @param array $args Optional. Arguments that were to be passed to the hook's callback function. 328 * @return array Boolean values, indicating the result of attempting to unschedule each indicated event, with timestamps as keys. 235 329 */ 236 330 function wp_clear_scheduled_hook( $hook, $args = array() ) { 237 331 // Backward compatibility … … function wp_clear_scheduled_hook( $hook, $args = array() ) { 241 335 $args = array_slice( func_get_args(), 1 ); 242 336 } 243 337 338 /** 339 * Filter to preflight or hijack clearing a scheduled hook. 340 * 341 * Passing a non-null value will short-circuit the normal unscheduling 342 * process, returning the passed value instead. 343 * 344 * Pass an empty array if no events are unscheduled, an array of boolean 345 * values if events are unscheduled see {@see wp_clear_scheduled_hook}. 346 * 347 * @param null|array $pre Value to return instead. Default null to continue unscheduling the event. 348 * @param string $hook Action hook, the execution of which will be unscheduled. 349 * @param array $args Arguments to pass to the hook's callback function. 350 */ 351 $pre = apply_filters( 'pre_clear_scheduled_hook', null, $hook, $args ); 352 if ( null !== $pre ) { 353 return $pre; 354 } 355 244 356 // This logic duplicates wp_next_scheduled() 245 357 // It's required due to a scenario where wp_unschedule_event() fails due to update_option() failing, 246 358 // and, wp_next_scheduled() returns the same schedule in an infinite loop. 247 359 $crons = _get_cron_array(); 248 360 if ( empty( $crons ) ) { 249 return ;361 return array(); 250 362 } 251 363 252 $key = md5( serialize( $args ) ); 364 $results = array(); 365 $key = md5( serialize( $args ) ); 253 366 foreach ( $crons as $timestamp => $cron ) { 254 367 if ( isset( $cron[ $hook ][ $key ] ) ) { 255 wp_unschedule_event( $timestamp, $hook, $args );368 $results[ $timestamp ] = wp_unschedule_event( $timestamp, $hook, $args ); 256 369 } 257 370 } 371 return $results; 258 372 } 259 373 260 374 /** … … function wp_clear_scheduled_hook( $hook, $args = array() ) { 265 379 * @since 4.9.0 266 380 * 267 381 * @param string $hook Action hook, the execution of which will be unscheduled. 382 * @return bool Whether or not the requested events have been unscheduled. 268 383 */ 269 384 function wp_unschedule_hook( $hook ) { 385 /** 386 * Filter to preflight or hijack clearing all events attached to the hook. 387 * 388 * Passing a non-null value will short-circuit the normal unscheduling 389 * process, returning the passed value instead. 390 * 391 * Pass true if events are cleared, false if not. 392 * 393 * @param null|array $pre Value to return instead. Default null to continue unscheduling the hook. 394 * @param string $hook Action hook, the execution of which will be unscheduled. 395 */ 396 $pre = apply_filters( 'pre_unschedule_hook', null, $hook ); 397 if ( null !== $pre ) { 398 return $pre; 399 } 400 270 401 $crons = _get_cron_array(); 271 402 272 403 foreach ( $crons as $timestamp => $args ) { … … function wp_unschedule_hook( $hook ) { 277 408 } 278 409 } 279 410 280 _set_cron_array( $crons ); 411 return _set_cron_array( $crons ); 412 } 413 414 /** 415 * Retrieve a scheduled event. 416 * 417 * Retrieve the full event object for a given event. 418 * 419 * @param string $hook Action hook of the event. 420 * @param array $args Optional. Array containing each separate argument to pass to the hook's callback function. 421 * Although not passed to a callback, these arguments are used to uniquely identify the 422 * event, so they should be the same as those used when originally scheduling the event. 423 * @param int|null $timestamp Optional. Unix timestamp (UTC) of the event. If not specified, the next scheduled event is returned. 424 * @return bool|object The event object. False if the event does not exist. 425 */ 426 function wp_get_scheduled_event( $hook, $args = array(), $timestamp = null ) { 427 if ( ! $timestamp ) { 428 // Get the next scheduled event. 429 $timestamp = wp_next_scheduled( $hook, $args ); 430 } 431 432 /** 433 * Filter to preflight or hijack retrieving a scheduled event. 434 * 435 * Passing a non-null value will short-circuit the normal 436 * process, returning the passed value instead. 437 * 438 * Pass false if the event does not exist, otherwise an event object 439 * should be returned. 440 * 441 * @param null|bool $pre Value to return instead. Default null to continue retrieving the event. 442 * @param string $hook Action hook of the event. 443 * @param array $args Array containing each separate argument to pass to the hook's callback function. 444 * Although not passed to a callback, these arguments are used to uniquely identify the 445 * event. 446 * @param int $timestamp Unix timestamp (UTC) of the event. 447 */ 448 $pre = apply_filters( 'pre_get_scheduled_event', null, $hook, $args, $timestamp ); 449 if ( null !== $pre ) { 450 return $pre; 451 } 452 453 $crons = _get_cron_array(); 454 $key = md5( serialize( $args ) ); 455 456 if ( ! $timestamp || ! isset( $crons[ $timestamp ] ) ) { 457 // No such event. 458 return false; 459 } 460 461 if ( ! isset( $crons[ $timestamp ][ $hook ] ) || ! isset( $crons[ $timestamp ][ $hook ][ $key ] ) ) { 462 return false; 463 } 464 465 $event = (object) array( 466 'hook' => $hook, 467 'timestamp' => $timestamp, 468 'schedule' => $crons[ $timestamp ][ $hook ][ $key ]['schedule'], 469 'args' => $args, 470 ); 471 472 if ( isset( $crons[ $timestamp ][ $hook ][ $key ]['interval'] ) ) { 473 $event->interval = $crons[ $timestamp ][ $hook ][ $key ]['interval']; 474 } 475 476 return $event; 281 477 } 282 478 283 479 /** … … function wp_unschedule_hook( $hook ) { 292 488 * @return false|int The Unix timestamp of the next time the event will occur. False if the event doesn't exist. 293 489 */ 294 490 function wp_next_scheduled( $hook, $args = array() ) { 491 /** 492 * Filter to preflight or hijack retrieving the next scheduled event timestamp. 493 * 494 * Passing a non-null value will short-circuit the normal retrieval 495 * process, returning the passed value instead. 496 * 497 * Pass the timestamp of the next event if it exists, false if not. 498 * 499 * @param null|bool $pre Value to return instead. Default null to continue unscheduling the event. 500 * @param string $hook Action hook of the event. 501 * @param array $args Arguments to pass to the hook's callback function. 502 */ 503 $pre = apply_filters( 'pre_next_scheduled', null, $hook, $args ); 504 if ( null !== $pre ) { 505 return $pre; 506 } 507 295 508 $crons = _get_cron_array(); 296 509 $key = md5( serialize( $args ) ); 297 if ( empty( $crons ) ) { 298 return false; 299 } 300 foreach ( $crons as $timestamp => $cron ) { 301 if ( isset( $cron[ $hook ][ $key ] ) ) { 302 return $timestamp; 510 $next = false; 511 512 if ( ! empty( $crons ) ) { 513 foreach ( $crons as $timestamp => $cron ) { 514 if ( isset( $cron[ $hook ][ $key ] ) ) { 515 $next = $timestamp; 516 break; 517 } 303 518 } 304 519 } 305 return false; 520 521 /** 522 * Filter the next scheduled event timestamp. 523 * 524 * @param int|bool $next The UNIX timestamp when the scheduled event will next occur, or false if not found. 525 * @param string $hook Action hook to execute when cron is run. 526 * @param array $args Arguments to be passed to the callback function. Used for deduplicating events. 527 */ 528 return apply_filters( 'next_scheduled', $next, $hook, $args ); 306 529 } 307 530 308 531 /** … … function wp_next_scheduled( $hook, $args = array() ) { 311 534 * @since 2.1.0 312 535 * 313 536 * @param int $gmt_time Optional. Unix timestamp (UTC). Default 0 (current time is used). 537 * @return null|WP_Error|array Null when cron could not be spawned, because it is not needed to run. 538 * When cron runs, return the result of {@see wp_remote_post} 314 539 */ 315 540 function spawn_cron( $gmt_time = 0 ) { 316 541 if ( ! $gmt_time ) { … … function spawn_cron( $gmt_time = 0 ) { 318 543 } 319 544 320 545 if ( defined( 'DOING_CRON' ) || isset( $_GET['doing_wp_cron'] ) ) { 321 return ;546 return null; 322 547 } 323 548 324 549 /* … … function spawn_cron( $gmt_time = 0 ) { 336 561 337 562 // don't run if another process is currently running it or more than once every 60 sec. 338 563 if ( $lock + WP_CRON_LOCK_TIMEOUT > $gmt_time ) { 339 return ;564 return null; 340 565 } 341 566 342 567 //sanity check 343 568 $crons = _get_cron_array(); 344 569 if ( ! is_array( $crons ) ) { 345 return ;570 return null; 346 571 } 347 572 348 573 $keys = array_keys( $crons ); 349 574 if ( isset( $keys[0] ) && $keys[0] > $gmt_time ) { 350 return ;575 return null; 351 576 } 352 577 353 578 if ( defined( 'ALTERNATE_WP_CRON' ) && ALTERNATE_WP_CRON ) { 354 579 if ( 'GET' !== $_SERVER['REQUEST_METHOD'] || defined( 'DOING_AJAX' ) || defined( 'XMLRPC_REQUEST' ) ) { 355 return ;580 return null; 356 581 } 357 582 358 583 $doing_wp_cron = sprintf( '%.22F', $gmt_time ); … … function spawn_cron( $gmt_time = 0 ) { 368 593 flush(); 369 594 370 595 WP_DEBUG ? include_once( ABSPATH . 'wp-cron.php' ) : @include_once( ABSPATH . 'wp-cron.php' ); 371 return ;596 return null; 372 597 } 373 598 374 599 // Set the cron lock with the current unix timestamp, when the cron is being spawned. … … function spawn_cron( $gmt_time = 0 ) { 409 634 ), $doing_wp_cron 410 635 ); 411 636 412 wp_remote_post( $cron_request['url'], $cron_request['args'] );637 return wp_remote_post( $cron_request['url'], $cron_request['args'] ); 413 638 } 414 639 415 640 /** 416 641 * Run scheduled callbacks or spawn cron for all scheduled events. 417 642 * 418 643 * @since 2.1.0 644 * 645 * @return array Array of spawn_cron() results for any cron jobs that were run, with cron timestamps as keys. 419 646 */ 420 647 function wp_cron() { 421 648 // Prevent infinite loops caused by lack of wp-cron.php 422 649 if ( strpos( $_SERVER['REQUEST_URI'], '/wp-cron.php' ) !== false || ( defined( 'DISABLE_WP_CRON' ) && DISABLE_WP_CRON ) ) { 423 return ;650 return array(); 424 651 } 425 652 426 if ( false === $crons = _get_cron_array() ) { 427 return; 653 $crons = _get_cron_array(); 654 if ( false === $crons ) { 655 return array(); 428 656 } 429 657 430 658 $gmt_time = microtime( true ); 431 659 $keys = array_keys( $crons ); 432 660 if ( isset( $keys[0] ) && $keys[0] > $gmt_time ) { 433 return ;661 return array(); 434 662 } 435 663 664 $results = array(); 436 665 $schedules = wp_get_schedules(); 437 666 foreach ( $crons as $timestamp => $cronhooks ) { 438 667 if ( $timestamp > $gmt_time ) { … … function wp_cron() { 442 671 if ( isset( $schedules[ $hook ]['callback'] ) && ! call_user_func( $schedules[ $hook ]['callback'] ) ) { 443 672 continue; 444 673 } 445 spawn_cron( $gmt_time );674 $results[ $timestamp ] = spawn_cron( $gmt_time ); 446 675 break 2; 447 676 } 448 677 } 678 679 return $results; 449 680 } 450 681 451 682 /** … … function wp_get_schedules() { 514 745 * @return string|false False, if no schedule. Schedule name on success. 515 746 */ 516 747 function wp_get_schedule( $hook, $args = array() ) { 517 $crons = _get_cron_array(); 518 $key = md5( serialize( $args ) ); 519 if ( empty( $crons ) ) { 520 return false; 521 } 522 foreach ( $crons as $timestamp => $cron ) { 523 if ( isset( $cron[ $hook ][ $key ] ) ) { 524 return $cron[ $hook ][ $key ]['schedule']; 525 } 748 $schedule = false; 749 $event = wp_get_scheduled_event( $hook, $args ); 750 751 if ( $event ) { 752 $schedule = $event->schedule; 526 753 } 527 return false; 754 755 /** 756 * Filter the schedule for a hook. 757 * 758 * @param string|bool $schedule Schedule for the hook. False if not found. 759 * @param string $hook Action hook to execute when cron is run. 760 * @param array $args Optional. Arguments to pass to the hook's callback function. 761 */ 762 return apply_filters( 'get_schedule', $schedule, $hook, $args ); 528 763 } 529 764 530 765 // … … function _get_cron_array() { 561 796 * @access private 562 797 * 563 798 * @param array $cron Cron info array from _get_cron_array(). 799 * @return bool Whether the update of the cron option succeeded (according to {@see update_option}) 564 800 */ 565 801 function _set_cron_array( $cron ) { 566 802 $cron['version'] = 2; 567 update_option( 'cron', $cron );803 return update_option( 'cron', $cron ); 568 804 } 569 805 570 806 /**