WordPress.org

Make WordPress Core

Ticket #28635: 28635.diff

File 28635.diff, 6.3 KB (added by westonruter, 5 years ago)

Echo status codes from wp-cron.php. Use _ajax_wp_die_handler for DOING_CRON too. Introduce filterable wp_cron_exit_handler with HTTP status codes. Add hooks for cron loops. Commits:https://github.com/x-team/wordpress-develop/compare/master...d6450f9 PR: https://github.com/x-team/wordpress-develop/pull/21

  • src/wp-cron.php

    diff --git src/wp-cron.php src/wp-cron.php
    index 2b965dd..3df77b5 100644
     
    99 * @package WordPress
    1010 */
    1111
    12 ignore_user_abort(true);
    13 
    14 if ( !empty($_POST) || defined('DOING_AJAX') || defined('DOING_CRON') )
    15         die();
     12ignore_user_abort( true );
    1613
    1714/**
    1815 * Tell WordPress we are doing the CRON task.
    1916 *
    2017 * @var bool
    2118 */
    22 define('DOING_CRON', true);
     19define( 'DOING_CRON', true );
    2320
    24 if ( !defined('ABSPATH') ) {
     21if ( ! defined( 'ABSPATH' ) ) {
    2522        /** Set up WordPress environment */
    2623        require_once( dirname( __FILE__ ) . '/wp-load.php' );
    2724}
    2825
     26/**
     27 * Default handler for a WP Cron exit
     28 *
     29 * @param string $code
     30 */
     31function wp_cron_default_exit_handler( $code ) {
     32        do_action( 'wp_cron_response_close', $code );
     33        if ( 'bad_post_request_or_doing_ajax_or_doing_cron' === $code ) {
     34                $response = 400;
     35        } elseif ( 'empty_cron_array' === $code ) {
     36                $response = 204;
     37        } elseif ( 'no_scheduled_actions_due' === $code ) {
     38                $response = 204;
     39        } elseif ( 'cron_locked' === $code ) {
     40                $response = 403;
     41        } elseif ( 'cron_lock_check_fail' === $code ) {
     42                $response = 400;
     43        } elseif ( 'ok_exit_prematurely' === $code ) {
     44                $response = 200;
     45        } elseif ( 'ok' === $code ) {
     46                $response = 200;
     47        } else {
     48                $response = 500;
     49        }
     50        if ( ! headers_sent() ) {
     51                header( 'Content-Type: text/plain' );
     52                status_header( $response );
     53        }
     54        wp_die( $code, '', compact( $response ) );
     55}
     56
     57/**
     58 * @var string $wp_cron_exit_handler
     59 * @todo docs
     60 */
     61$wp_cron_exit_handler = apply_filters( 'wp_cron_exit_handler', 'wp_cron_default_exit_handler' );
     62
     63if ( ! empty( $_POST ) || defined( 'DOING_AJAX' ) || defined( 'DOING_CRON' ) ) {
     64        $wp_cron_exit_handler( 'bad_post_request_or_doing_ajax_or_doing_cron' );
     65}
     66
    2967// Uncached doing_cron transient fetch
    3068function _get_cron_lock() {
    3169        global $wpdb;
    function _get_cron_lock() { 
    3977                $value = wp_cache_get( 'doing_cron', 'transient', true );
    4078        } else {
    4179                $row = $wpdb->get_row( $wpdb->prepare( "SELECT option_value FROM $wpdb->options WHERE option_name = %s LIMIT 1", '_transient_doing_cron' ) );
    42                 if ( is_object( $row ) )
     80                if ( is_object( $row ) ) {
    4381                        $value = $row->option_value;
     82                }
    4483        }
    4584
    4685        return $value;
    4786}
    4887
    49 if ( false === $crons = _get_cron_array() )
    50         die();
     88if ( false === $crons = _get_cron_array() ) {
     89        $wp_cron_exit_handler( 'empty_cron_array' );
     90}
    5191
    5292$keys = array_keys( $crons );
    5393$gmt_time = microtime( true );
    5494
    55 if ( isset($keys[0]) && $keys[0] > $gmt_time )
    56         die();
     95if ( isset( $keys[0] ) && $keys[0] > $gmt_time ) {
     96        $wp_cron_exit_handler( 'no_scheduled_actions_due' );
     97}
    5798
    58 $doing_cron_transient = get_transient( 'doing_cron');
     99$doing_cron_transient = get_transient( 'doing_cron' );
    59100
    60101// Use global $doing_wp_cron lock otherwise use the GET lock. If no lock, trying grabbing a new lock.
    61102if ( empty( $doing_wp_cron ) ) {
    62         if ( empty( $_GET[ 'doing_wp_cron' ] ) ) {
     103        if ( empty( $_GET['doing_wp_cron'] ) ) {
    63104                // Called from external script/job. Try setting a lock.
    64                 if ( $doing_cron_transient && ( $doing_cron_transient + WP_CRON_LOCK_TIMEOUT > $gmt_time ) )
    65                         return;
     105                if ( $doing_cron_transient && ( $doing_cron_transient + WP_CRON_LOCK_TIMEOUT > $gmt_time ) ) {
     106                        $wp_cron_exit_handler( 'cron_locked' );
     107                }
    66108                $doing_cron_transient = $doing_wp_cron = sprintf( '%.22F', microtime( true ) );
    67109                set_transient( 'doing_cron', $doing_wp_cron );
    68110        } else {
    69                 $doing_wp_cron = $_GET[ 'doing_wp_cron' ];
     111                $doing_wp_cron = $_GET['doing_wp_cron'];
    70112        }
    71113}
    72114
    73115// Check lock
    74 if ( $doing_cron_transient != $doing_wp_cron )
    75         return;
     116if ( $doing_cron_transient != $doing_wp_cron ) {
     117        $wp_cron_exit_handler( 'cron_lock_check_fail' );
     118}
    76119
     120/**
     121 * @todo docs
     122 */
     123do_action( 'wp_cron_before_crons_loop', $crons );
    77124foreach ( $crons as $timestamp => $cronhooks ) {
    78         if ( $timestamp > $gmt_time )
     125        if ( $timestamp > $gmt_time ) {
    79126                break;
     127        }
    80128
     129        /**
     130         * @todo docs
     131         */
     132        do_action( 'wp_cron_before_cronhooks_loop', $cronhooks );
    81133        foreach ( $cronhooks as $hook => $keys ) {
    82134
     135                /**
     136                 * @todo docs
     137                 */
     138                do_action( 'wp_cron_before_keys_loop', $keys );
    83139                foreach ( $keys as $k => $v ) {
    84140
    85141                        $schedule = $v['schedule'];
    86142
    87143                        if ( $schedule != false ) {
    88                                 $new_args = array($timestamp, $schedule, $hook, $v['args']);
    89                                 call_user_func_array('wp_reschedule_event', $new_args);
     144                                $new_args = array( $timestamp, $schedule, $hook, $v['args'] );
     145                                call_user_func_array( 'wp_reschedule_event', $new_args );
    90146                        }
    91147
    92148                        wp_unschedule_event( $timestamp, $hook, $v['args'] );
    93149
    94150                        /**
     151                         * @todo docs
     152                         */
     153                        do_action( 'wp_cron_before_hook', $hook, $v['args'], $schedule, $timestamp );
     154
     155                        /**
    95156                         * Fires scheduled events.
    96157                         *
    97158                         * @internal
    foreach ( $crons as $timestamp => $cronhooks ) { 
    100161                         * @param string $hook Name of the hook that was scheduled to be fired.
    101162                         * @param array  $args The arguments to be passed to the hook.
    102163                         */
    103                         do_action_ref_array( $hook, $v['args'] );
     164                        do_action_ref_array( $hook, $v['args'] );
     165
     166                        /**
     167                         * @todo docs
     168                         */
     169                        do_action( 'wp_cron_after_hook', $hook, $v['args'], $schedule, $timestamp );
    104170
    105171                        // If the hook ran too long and another cron process stole the lock, quit.
    106                         if ( _get_cron_lock() != $doing_wp_cron )
    107                                 return;
     172                        if ( _get_cron_lock() != $doing_wp_cron ) {
     173                                $wp_cron_exit_handler( 'ok_exit_prematurely' );
     174                        }
    108175                }
     176
     177                /**
     178                 * @todo docs
     179                 */
     180                do_action( 'wp_cron_after_keys_loop', $keys );
    109181        }
     182
     183        /**
     184         * @todo docs
     185         */
     186        do_action( 'wp_cron_after_cronhooks_loop', $cronhooks );
    110187}
     188/**
     189 * @todo docs
     190 */
     191do_action( 'wp_cron_after_crons_loop', $crons );
    111192
    112 if ( _get_cron_lock() == $doing_wp_cron )
     193if ( _get_cron_lock() == $doing_wp_cron ) {
    113194        delete_transient( 'doing_cron' );
     195}
    114196
    115 die();
     197$wp_cron_exit_handler( 'ok' );
  • src/wp-includes/functions.php

    diff --git src/wp-includes/functions.php src/wp-includes/functions.php
    index 33ace42..bc305e8 100644
    function wp_nonce_ays( $action ) { 
    22422242 * @param string|array $args Optional arguments to control behavior.
    22432243 */
    22442244function wp_die( $message = '', $title = '', $args = array() ) {
    2245         if ( defined( 'DOING_AJAX' ) && DOING_AJAX ) {
     2245        if ( ( defined( 'DOING_AJAX' ) && DOING_AJAX ) || ( defined( 'DOING_CRON' ) && DOING_CRON ) ) {
    22462246                /**
    22472247                 * Filter callback for killing WordPress execution for AJAX requests.
    22482248                 *