Plugin Updates
This commit is contained in:
@@ -9,6 +9,8 @@ use Crontrol\Event\Table;
|
||||
use stdClass;
|
||||
use WP_Error;
|
||||
|
||||
use function Crontrol\Event\check_integrity;
|
||||
|
||||
const TRANSIENT = 'crontrol-message-%d';
|
||||
const PAUSED_OPTION = 'wp_crontrol_paused';
|
||||
|
||||
@@ -136,7 +138,7 @@ function action_handle_posts() {
|
||||
|
||||
$cr = $request->init( wp_unslash( $_POST ) );
|
||||
|
||||
if ( 'crontrol_cron_job' === $cr->hookname && ! current_user_can( 'edit_files' ) ) {
|
||||
if ( 'crontrol_cron_job' === $cr->hookname ) {
|
||||
wp_die( esc_html__( 'You are not allowed to add new PHP cron events.', 'wp-crontrol' ), 401 );
|
||||
}
|
||||
$args = json_decode( $cr->args, true );
|
||||
@@ -195,9 +197,13 @@ function action_handle_posts() {
|
||||
$cr = $request->init( wp_unslash( $_POST ) );
|
||||
|
||||
$next_run_local = ( 'custom' === $cr->next_run_date_local ) ? $cr->next_run_date_local_custom_date . ' ' . $cr->next_run_date_local_custom_time : $cr->next_run_date_local;
|
||||
$args = array(
|
||||
'code' => $cr->hookcode,
|
||||
'name' => $cr->eventname,
|
||||
|
||||
$args = array(
|
||||
array(
|
||||
'code' => $cr->hookcode,
|
||||
'name' => $cr->eventname,
|
||||
'hash' => wp_hash( $cr->hookcode ),
|
||||
),
|
||||
);
|
||||
|
||||
add_filter( 'schedule_event', function( $event ) {
|
||||
@@ -340,9 +346,13 @@ function action_handle_posts() {
|
||||
$cr = $request->init( wp_unslash( $_POST ) );
|
||||
|
||||
check_admin_referer( "crontrol-edit-cron_{$cr->original_hookname}_{$cr->original_sig}_{$cr->original_next_run_utc}" );
|
||||
|
||||
$args = array(
|
||||
'code' => $cr->hookcode,
|
||||
'name' => $cr->eventname,
|
||||
array(
|
||||
'code' => $cr->hookcode,
|
||||
'name' => $cr->eventname,
|
||||
'hash' => wp_hash( $cr->hookcode ),
|
||||
),
|
||||
);
|
||||
$hookname = ( ! empty( $cr->eventname ) ) ? $cr->eventname : __( 'PHP Cron', 'wp-crontrol' );
|
||||
$redirect = array(
|
||||
@@ -637,6 +647,11 @@ function action_handle_posts() {
|
||||
}
|
||||
|
||||
$hook = wp_unslash( $_GET['crontrol_id'] );
|
||||
|
||||
if ( 'crontrol_cron_job' === $hook ) {
|
||||
wp_die( esc_html__( 'You are not allowed to pause or resume cron events.', 'wp-crontrol' ), 401 );
|
||||
}
|
||||
|
||||
check_admin_referer( "crontrol-pause-hook_{$hook}" );
|
||||
|
||||
$paused = Event\pause( $hook );
|
||||
@@ -679,6 +694,11 @@ function action_handle_posts() {
|
||||
}
|
||||
|
||||
$hook = wp_unslash( $_GET['crontrol_id'] );
|
||||
|
||||
if ( 'crontrol_cron_job' === $hook ) {
|
||||
wp_die( esc_html__( 'You are not allowed to pause or resume cron events.', 'wp-crontrol' ), 401 );
|
||||
}
|
||||
|
||||
check_admin_referer( "crontrol-resume-hook_{$hook}" );
|
||||
|
||||
$resumed = Event\resume( $hook );
|
||||
@@ -766,7 +786,7 @@ function action_handle_posts() {
|
||||
}
|
||||
|
||||
if ( 'crontrol_cron_job' === $event->hook ) {
|
||||
$action = __( 'WP Crontrol', 'wp-crontrol' );
|
||||
$action = 'WP Crontrol';
|
||||
} else {
|
||||
$callbacks = array();
|
||||
|
||||
@@ -844,27 +864,48 @@ function admin_help_tab() {
|
||||
return;
|
||||
}
|
||||
|
||||
$content = '<p>' . __( 'There are several places to get help with issues relating to WP-Cron:', 'wp-crontrol' ) . '</p>';
|
||||
$content = '<p>' . esc_html__( 'There are several places to get help with issues relating to WP-Cron:', 'wp-crontrol' ) . '</p>';
|
||||
$content .= '<ul>';
|
||||
$content .= '<li>';
|
||||
$content .= sprintf(
|
||||
/* translators: %s: URL to the documentation */
|
||||
__( '<a href="%s">Read the WP Crontrol wiki</a> which contains information about events that have missed their schedule, problems with spawning a call to the WP-Cron system, and much more.', 'wp-crontrol' ),
|
||||
'https://github.com/johnbillion/wp-crontrol/wiki'
|
||||
$content .= wp_kses(
|
||||
sprintf(
|
||||
/* translators: %s: URL to the documentation */
|
||||
__( '<a href="%s">Read the WP Crontrol website</a> which contains information about events that have missed their schedule, problems with spawning a call to the WP-Cron system, and much more.', 'wp-crontrol' ),
|
||||
'https://wp-crontrol.com'
|
||||
),
|
||||
array(
|
||||
'a' => array(
|
||||
'href' => array(),
|
||||
),
|
||||
)
|
||||
);
|
||||
$content .= '</li>';
|
||||
$content .= '<li>';
|
||||
$content .= sprintf(
|
||||
/* translators: %s: URL to the documentation */
|
||||
__( '<a href="%s">Read the Frequently Asked Questions (FAQ)</a> which cover many common questions and answers.', 'wp-crontrol' ),
|
||||
'https://wordpress.org/plugins/wp-crontrol/faq/'
|
||||
$content .= wp_kses(
|
||||
sprintf(
|
||||
/* translators: %s: URL to the documentation */
|
||||
__( '<a href="%s">Read the Frequently Asked Questions (FAQ)</a> which cover many common questions and answers.', 'wp-crontrol' ),
|
||||
'https://wordpress.org/plugins/wp-crontrol/faq/'
|
||||
),
|
||||
array(
|
||||
'a' => array(
|
||||
'href' => array(),
|
||||
),
|
||||
)
|
||||
);
|
||||
$content .= '</li>';
|
||||
$content .= '<li>';
|
||||
$content .= sprintf(
|
||||
/* translators: %s: URL to the documentation */
|
||||
__( '<a href="%s">Read the WordPress.org documentation on WP-Cron</a> for more technical details about the WP-Cron system for developers.', 'wp-crontrol' ),
|
||||
'https://developer.wordpress.org/plugins/cron/'
|
||||
$content .= wp_kses(
|
||||
sprintf(
|
||||
/* translators: %s: URL to the documentation */
|
||||
__( '<a href="%s">Read the WordPress.org documentation on WP-Cron</a> for more technical details about the WP-Cron system for developers.', 'wp-crontrol' ),
|
||||
'https://developer.wordpress.org/plugins/cron/'
|
||||
),
|
||||
array(
|
||||
'a' => array(
|
||||
'href' => array(),
|
||||
),
|
||||
)
|
||||
);
|
||||
$content .= '</ul>';
|
||||
|
||||
@@ -900,7 +941,7 @@ function plugin_action_links( $actions, $plugin_file, $plugin_data, $context ) {
|
||||
),
|
||||
'crontrol-help' => sprintf(
|
||||
'<a href="%s">%s</a>',
|
||||
'https://github.com/johnbillion/wp-crontrol/wiki',
|
||||
'https://wp-crontrol.com',
|
||||
esc_html__( 'Help', 'wp-crontrol' )
|
||||
),
|
||||
);
|
||||
@@ -918,7 +959,7 @@ function network_plugin_action_links( $actions ) {
|
||||
$new = array(
|
||||
'crontrol-help' => sprintf(
|
||||
'<a href="%s">%s</a>',
|
||||
'https://github.com/johnbillion/wp-crontrol/wiki',
|
||||
'https://wp-crontrol.com',
|
||||
esc_html__( 'Help', 'wp-crontrol' )
|
||||
),
|
||||
);
|
||||
@@ -952,12 +993,12 @@ function filter_cron_schedules( array $scheds ) {
|
||||
function admin_options_page() {
|
||||
$messages = array(
|
||||
'2' => array(
|
||||
/* translators: 1: The name of the cron schedule. */
|
||||
/* translators: %s: The name of the cron schedule. */
|
||||
__( 'Deleted the cron schedule %s.', 'wp-crontrol' ),
|
||||
'success',
|
||||
),
|
||||
'3' => array(
|
||||
/* translators: 1: The name of the cron schedule. */
|
||||
/* translators: %s: The name of the cron schedule. */
|
||||
__( 'Added the cron schedule %s.', 'wp-crontrol' ),
|
||||
'success',
|
||||
),
|
||||
@@ -1083,7 +1124,7 @@ function test_cron_spawn( $cache = true ) {
|
||||
foreach ( $cron_runner_plugins as $class => $plugin ) {
|
||||
if ( class_exists( $class ) ) {
|
||||
return new WP_Error( 'crontrol_info', sprintf(
|
||||
/* translators: 1: The name of the plugin that controls the running of cron events. */
|
||||
/* translators: %s: The name of the plugin that controls the running of cron events. */
|
||||
__( 'WP-Cron spawning is being managed by the %s plugin.', 'wp-crontrol' ),
|
||||
$plugin
|
||||
) );
|
||||
@@ -1092,7 +1133,7 @@ function test_cron_spawn( $cache = true ) {
|
||||
|
||||
if ( defined( 'DISABLE_WP_CRON' ) && DISABLE_WP_CRON ) {
|
||||
return new WP_Error( 'crontrol_info', sprintf(
|
||||
/* translators: 1: The name of the PHP constant that is set. */
|
||||
/* translators: %s: The name of the PHP constant that is set. */
|
||||
__( 'The %s constant is set to true. WP-Cron spawning is disabled.', 'wp-crontrol' ),
|
||||
'DISABLE_WP_CRON'
|
||||
) );
|
||||
@@ -1100,7 +1141,7 @@ function test_cron_spawn( $cache = true ) {
|
||||
|
||||
if ( defined( 'ALTERNATE_WP_CRON' ) && ALTERNATE_WP_CRON ) {
|
||||
return new WP_Error( 'crontrol_info', sprintf(
|
||||
/* translators: 1: The name of the PHP constant that is set. */
|
||||
/* translators: %s: The name of the PHP constant that is set. */
|
||||
__( 'The %s constant is set to true.', 'wp-crontrol' ),
|
||||
'ALTERNATE_WP_CRON'
|
||||
) );
|
||||
@@ -1133,7 +1174,7 @@ function test_cron_spawn( $cache = true ) {
|
||||
return $result;
|
||||
} elseif ( wp_remote_retrieve_response_code( $result ) >= 300 ) {
|
||||
return new WP_Error( 'unexpected_http_response_code', sprintf(
|
||||
/* translators: 1: The HTTP response code. */
|
||||
/* translators: %s: The HTTP response code. */
|
||||
__( 'Unexpected HTTP response code: %s', 'wp-crontrol' ),
|
||||
intval( wp_remote_retrieve_response_code( $result ) )
|
||||
) );
|
||||
@@ -1166,9 +1207,8 @@ function show_cron_status( $tab ) {
|
||||
<?php
|
||||
printf(
|
||||
'<p>%1$s</p><p><a href="%2$s">%3$s</a></p>',
|
||||
/* translators: %s: Help page URL. */
|
||||
esc_html__( 'PHP default timezone is not set to UTC. This may cause issues with cron event timings.', 'wp-crontrol' ),
|
||||
'https://github.com/johnbillion/wp-crontrol/wiki/PHP-default-timezone-is-not-set-to-UTC',
|
||||
'https://wp-crontrol.com/help/php-default-timezone/',
|
||||
esc_html__( 'More information', 'wp-crontrol' )
|
||||
);
|
||||
?>
|
||||
@@ -1192,11 +1232,11 @@ function show_cron_status( $tab ) {
|
||||
printf(
|
||||
'<p>%1$s</p><p><a href="%2$s">%3$s</a></p>',
|
||||
sprintf(
|
||||
/* translators: 1: Error message text. */
|
||||
/* translators: %s: Error message text. */
|
||||
esc_html__( 'There was a problem spawning a call to the WP-Cron system on your site. This means WP-Cron events on your site may not work. The problem was: %s', 'wp-crontrol' ),
|
||||
'</p><p><strong>' . esc_html( $status->get_error_message() ) . '</strong>'
|
||||
),
|
||||
'https://github.com/johnbillion/wp-crontrol/wiki/Problems-with-spawning-a-call-to-the-WP-Cron-system',
|
||||
'https://wp-crontrol.com/help/problems-spawning-wp-cron/',
|
||||
esc_html__( 'More information', 'wp-crontrol' )
|
||||
);
|
||||
?>
|
||||
@@ -1309,7 +1349,7 @@ function show_cron_form( $editing ) {
|
||||
$helper_text = esc_html__( 'Cron events trigger actions in your code. Enter the schedule of the event, as well as the PHP code to execute when the action is triggered.', 'wp-crontrol' );
|
||||
} else {
|
||||
$helper_text = sprintf(
|
||||
/* translators: %s: A file name */
|
||||
/* translators: %1$s: A file name */
|
||||
esc_html__( 'Cron events trigger actions in your code. A cron event needs a corresponding action hook somewhere in code, e.g. the %1$s file in your theme.', 'wp-crontrol' ),
|
||||
'<code>functions.php</code>'
|
||||
);
|
||||
@@ -1351,13 +1391,15 @@ function show_cron_form( $editing ) {
|
||||
$next_run_time_local = '';
|
||||
}
|
||||
|
||||
if ( $is_editing_php ) {
|
||||
if ( ! isset( $existing['args']['code'] ) ) {
|
||||
$existing['args']['code'] = '';
|
||||
}
|
||||
if ( ! isset( $existing['args']['name'] ) ) {
|
||||
$existing['args']['name'] = '';
|
||||
}
|
||||
if ( $is_editing_php && isset( $existing['args']['code'] ) ) {
|
||||
// Support the args array format used prior to WP Crontrol 1.16.2
|
||||
$existing['args'] = array(
|
||||
array(
|
||||
'code' => $existing['args']['code'],
|
||||
'name' => $existing['args']['name'] ?? '',
|
||||
'hash' => null,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
$can_add_php = current_user_can( 'edit_files' ) && ! $editing;
|
||||
@@ -1378,6 +1420,7 @@ function show_cron_form( $editing ) {
|
||||
'<h1>%s</h1>',
|
||||
esc_html( $heading )
|
||||
);
|
||||
|
||||
printf(
|
||||
'<p>%s</p>',
|
||||
// phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
||||
@@ -1400,12 +1443,27 @@ function show_cron_form( $editing ) {
|
||||
} elseif ( $can_add_php ) {
|
||||
?>
|
||||
<tr class="hide-if-no-js">
|
||||
<th valign="top" scope="row">
|
||||
<th scope="row">
|
||||
<?php esc_html_e( 'Event Type', 'wp-crontrol' ); ?>
|
||||
</th>
|
||||
<td>
|
||||
<p><label><input type="radio" name="crontrol_action" value="new_cron" checked>Standard cron event</label></p>
|
||||
<p><label><input type="radio" name="crontrol_action" value="new_php_cron">PHP cron event</label></p>
|
||||
<fieldset>
|
||||
<legend class="screen-reader-text">
|
||||
<?php esc_html_e( 'Event Type', 'wp-crontrol' ); ?>
|
||||
</legend>
|
||||
<p>
|
||||
<label>
|
||||
<input type="radio" name="crontrol_action" value="new_cron" checked>
|
||||
<?php esc_html_e( 'Standard cron event', 'wp-crontrol' ); ?>
|
||||
</label>
|
||||
</p>
|
||||
<p>
|
||||
<label>
|
||||
<input type="radio" name="crontrol_action" value="new_php_cron">
|
||||
<?php esc_html_e( 'PHP cron event', 'wp-crontrol' ); ?>
|
||||
</label>
|
||||
</p>
|
||||
</fieldset>
|
||||
</td>
|
||||
</tr>
|
||||
<?php
|
||||
@@ -1418,12 +1476,22 @@ function show_cron_form( $editing ) {
|
||||
if ( $is_editing_php || $can_add_php ) {
|
||||
?>
|
||||
<tr class="crontrol-event-php">
|
||||
<th valign="top" scope="row">
|
||||
<th scope="row">
|
||||
<label for="crontrol_hookcode">
|
||||
<?php esc_html_e( 'PHP Code', 'wp-crontrol' ); ?>
|
||||
</label>
|
||||
</th>
|
||||
<td>
|
||||
<?php
|
||||
if ( $is_editing_php && ! check_integrity( $existing['args'][0]['code'], $existing['args'][0]['hash'] ) ) {
|
||||
printf(
|
||||
'<div class="notice notice-error inline"><p>%1$s</p><p><a href="%2$s">%3$s</a></p></div>',
|
||||
esc_html__( 'The PHP code in this event needs to be checked for integrity. This event will not run until you re-save it.', 'wp-crontrol' ),
|
||||
'https://wp-crontrol.com/help/check-php-cron-events/',
|
||||
esc_html__( 'Read what to do', 'wp-crontrol' )
|
||||
);
|
||||
}
|
||||
?>
|
||||
<p class="description">
|
||||
<?php
|
||||
printf(
|
||||
@@ -1433,18 +1501,18 @@ function show_cron_form( $editing ) {
|
||||
);
|
||||
?>
|
||||
</p>
|
||||
<p><textarea class="large-text code" rows="10" cols="50" id="crontrol_hookcode" name="crontrol_hookcode"><?php echo esc_textarea( $editing ? $existing['args']['code'] : '' ); ?></textarea></p>
|
||||
<p><textarea class="large-text code" rows="10" cols="50" id="crontrol_hookcode" name="crontrol_hookcode"><?php echo esc_textarea( $editing ? $existing['args'][0]['code'] : '' ); ?></textarea></p>
|
||||
<?php do_action( 'crontrol/manage/hookcode', $existing ); ?>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="crontrol-event-php">
|
||||
<th valign="top" scope="row">
|
||||
<th scope="row">
|
||||
<label for="crontrol_eventname">
|
||||
<?php esc_html_e( 'Event Name (optional)', 'wp-crontrol' ); ?>
|
||||
</label>
|
||||
</th>
|
||||
<td>
|
||||
<input type="text" class="regular-text" id="crontrol_eventname" name="crontrol_eventname" value="<?php echo esc_attr( $editing ? $existing['args']['name'] : '' ); ?>"/>
|
||||
<input type="text" class="regular-text" id="crontrol_eventname" name="crontrol_eventname" value="<?php echo esc_attr( $editing ? $existing['args'][0]['name'] : '' ); ?>"/>
|
||||
<?php do_action( 'crontrol/manage/eventname', $existing ); ?>
|
||||
</td>
|
||||
</tr>
|
||||
@@ -1454,7 +1522,7 @@ function show_cron_form( $editing ) {
|
||||
if ( ! $is_editing_php ) {
|
||||
?>
|
||||
<tr class="crontrol-event-standard">
|
||||
<th valign="top" scope="row">
|
||||
<th scope="row">
|
||||
<label for="crontrol_hookname">
|
||||
<?php esc_html_e( 'Hook Name', 'wp-crontrol' ); ?>
|
||||
</label>
|
||||
@@ -1465,15 +1533,15 @@ function show_cron_form( $editing ) {
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="crontrol-event-standard">
|
||||
<th valign="top" scope="row">
|
||||
<th scope="row">
|
||||
<label for="crontrol_args">
|
||||
<?php esc_html_e( 'Arguments (optional)', 'wp-crontrol' ); ?>
|
||||
</label>
|
||||
</th>
|
||||
<td>
|
||||
<input type="text" autocorrect="off" autocapitalize="off" spellcheck="false" class="regular-text code" id="crontrol_args" name="crontrol_args" value="<?php echo esc_attr( $display_args ); ?>"/>
|
||||
<input type="text" autocorrect="off" autocapitalize="off" spellcheck="false" class="regular-text code" id="crontrol_args" name="crontrol_args" value="<?php echo esc_attr( $display_args ); ?>" aria-describedby="crontrol_args_description"/>
|
||||
<?php do_action( 'crontrol/manage/args', $existing ); ?>
|
||||
<p class="description">
|
||||
<p class="description" id="crontrol_args_description">
|
||||
<?php
|
||||
printf(
|
||||
/* translators: 1, 2, and 3: Example values for an input field. */
|
||||
@@ -1490,34 +1558,37 @@ function show_cron_form( $editing ) {
|
||||
}
|
||||
?>
|
||||
<tr>
|
||||
<th valign="top" scope="row">
|
||||
<th scope="row">
|
||||
<label for="crontrol_next_run_date_local">
|
||||
<?php esc_html_e( 'Next Run', 'wp-crontrol' ); ?>
|
||||
</label>
|
||||
</th>
|
||||
<td>
|
||||
<ul>
|
||||
<li>
|
||||
<fieldset>
|
||||
<legend class="screen-reader-text">
|
||||
<?php esc_html_e( 'Next Run', 'wp-crontrol' ); ?>
|
||||
</legend>
|
||||
<p>
|
||||
<label>
|
||||
<input type="radio" name="crontrol_next_run_date_local" value="now" checked>
|
||||
<?php esc_html_e( 'Now', 'wp-crontrol' ); ?>
|
||||
</label>
|
||||
</li>
|
||||
<li>
|
||||
</p>
|
||||
<p>
|
||||
<label>
|
||||
<input type="radio" name="crontrol_next_run_date_local" value="+1 day">
|
||||
<?php esc_html_e( 'Tomorrow', 'wp-crontrol' ); ?>
|
||||
</label>
|
||||
</li>
|
||||
<li>
|
||||
</p>
|
||||
<p>
|
||||
<label>
|
||||
<input type="radio" name="crontrol_next_run_date_local" value="custom" id="crontrol_next_run_date_local_custom" <?php checked( $editing ); ?>>
|
||||
<?php
|
||||
printf(
|
||||
/* translators: %s: An input field for specifying a date and time */
|
||||
esc_html__( 'At: %s', 'wp-crontrol' ),
|
||||
esc_html__( 'At this time: %s', 'wp-crontrol' ),
|
||||
sprintf(
|
||||
'<br>
|
||||
'<br><br>
|
||||
<input type="date" autocorrect="off" autocapitalize="off" spellcheck="false" name="crontrol_next_run_date_local_custom_date" id="crontrol_next_run_date_local_custom_date" value="%1$s" placeholder="yyyy-mm-dd" pattern="\d{4}-\d{2}-\d{2}" />
|
||||
<input type="time" autocorrect="off" autocapitalize="off" spellcheck="false" name="crontrol_next_run_date_local_custom_time" id="crontrol_next_run_date_local_custom_time" value="%2$s" step="1" placeholder="hh:mm:ss" pattern="\d{2}:\d{2}:\d{2}" />',
|
||||
esc_attr( $next_run_date_local ),
|
||||
@@ -1526,8 +1597,8 @@ function show_cron_form( $editing ) {
|
||||
);
|
||||
?>
|
||||
</label>
|
||||
</li>
|
||||
</ul>
|
||||
</p>
|
||||
</fieldset>
|
||||
|
||||
<?php do_action( 'crontrol/manage/next_run', $existing ); ?>
|
||||
|
||||
@@ -1543,7 +1614,7 @@ function show_cron_form( $editing ) {
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th valign="top" scope="row">
|
||||
<th scope="row">
|
||||
<label for="crontrol_schedule">
|
||||
<?php esc_html_e( 'Recurrence', 'wp-crontrol' ); ?>
|
||||
</label>
|
||||
@@ -1585,42 +1656,42 @@ function show_cron_form( $editing ) {
|
||||
function admin_manage_page() {
|
||||
$messages = array(
|
||||
'1' => array(
|
||||
/* translators: 1: The name of the cron event. */
|
||||
/* translators: %s: The name of the cron event. */
|
||||
__( 'Scheduled the cron event %s to run now. The original event will not be affected.', 'wp-crontrol' ),
|
||||
'success',
|
||||
),
|
||||
'2' => array(
|
||||
/* translators: 1: The name of the cron event. */
|
||||
/* translators: %s: The name of the cron event. */
|
||||
__( 'Deleted all %s cron events.', 'wp-crontrol' ),
|
||||
'success',
|
||||
),
|
||||
'3' => array(
|
||||
/* translators: 1: The name of the cron event. */
|
||||
/* translators: %s: The name of the cron event. */
|
||||
__( 'There are no %s cron events to delete.', 'wp-crontrol' ),
|
||||
'info',
|
||||
),
|
||||
'4' => array(
|
||||
/* translators: 1: The name of the cron event. */
|
||||
/* translators: %s: The name of the cron event. */
|
||||
__( 'Saved the cron event %s.', 'wp-crontrol' ),
|
||||
'success',
|
||||
),
|
||||
'5' => array(
|
||||
/* translators: 1: The name of the cron event. */
|
||||
/* translators: %s: The name of the cron event. */
|
||||
__( 'Created the cron event %s.', 'wp-crontrol' ),
|
||||
'success',
|
||||
),
|
||||
'6' => array(
|
||||
/* translators: 1: The name of the cron event. */
|
||||
/* translators: %s: The name of the cron event. */
|
||||
__( 'Deleted the cron event %s.', 'wp-crontrol' ),
|
||||
'success',
|
||||
),
|
||||
'7' => array(
|
||||
/* translators: 1: The name of the cron event. */
|
||||
/* translators: %s: The name of the cron event. */
|
||||
__( 'Failed to the delete the cron event %s.', 'wp-crontrol' ),
|
||||
'error',
|
||||
),
|
||||
'8' => array(
|
||||
/* translators: 1: The name of the cron event. */
|
||||
/* translators: %s: The name of the cron event. */
|
||||
__( 'Failed to the execute the cron event %s.', 'wp-crontrol' ),
|
||||
'error',
|
||||
),
|
||||
@@ -1629,17 +1700,17 @@ function admin_manage_page() {
|
||||
'success',
|
||||
),
|
||||
'10' => array(
|
||||
/* translators: 1: The name of the cron event. */
|
||||
/* translators: %s: The name of the cron event. */
|
||||
__( 'Failed to save the cron event %s.', 'wp-crontrol' ),
|
||||
'error',
|
||||
),
|
||||
'11' => array(
|
||||
/* translators: 1: The name of the cron event. */
|
||||
/* translators: %s: The name of the cron event. */
|
||||
__( 'Paused the %s hook.', 'wp-crontrol' ),
|
||||
'success',
|
||||
),
|
||||
'12' => array(
|
||||
/* translators: 1: The name of the cron event. */
|
||||
/* translators: %s: The name of the cron event. */
|
||||
__( 'Resumed the %s hook.', 'wp-crontrol' ),
|
||||
'success',
|
||||
),
|
||||
@@ -1693,7 +1764,7 @@ function admin_manage_page() {
|
||||
|
||||
<form id="posts-filter" method="get" action="tools.php">
|
||||
<input type="hidden" name="page" value="crontrol_admin_manage_page" />
|
||||
<?php $table->search_box( __( 'Search Hook Names', 'wp-crontrol' ), 'cron-event' ); ?>
|
||||
<?php $table->search_box( esc_html__( 'Search Hook Names', 'wp-crontrol' ), 'cron-event' ); ?>
|
||||
</form>
|
||||
|
||||
<form method="post" action="tools.php?page=crontrol_admin_manage_page">
|
||||
@@ -1970,19 +2041,19 @@ function time_since( $older_date, $newer_date ) {
|
||||
function interval( $since ) {
|
||||
// Array of time period chunks.
|
||||
$chunks = array(
|
||||
/* translators: 1: The number of years in an interval of time. */
|
||||
/* translators: %s: The number of years in an interval of time. */
|
||||
array( YEAR_IN_SECONDS, _n_noop( '%s year', '%s years', 'wp-crontrol' ) ),
|
||||
/* translators: 1: The number of months in an interval of time. */
|
||||
/* translators: %s: The number of months in an interval of time. */
|
||||
array( MONTH_IN_SECONDS, _n_noop( '%s month', '%s months', 'wp-crontrol' ) ),
|
||||
/* translators: 1: The number of weeks in an interval of time. */
|
||||
/* translators: %s: The number of weeks in an interval of time. */
|
||||
array( WEEK_IN_SECONDS, _n_noop( '%s week', '%s weeks', 'wp-crontrol' ) ),
|
||||
/* translators: 1: The number of days in an interval of time. */
|
||||
/* translators: %s: The number of days in an interval of time. */
|
||||
array( DAY_IN_SECONDS, _n_noop( '%s day', '%s days', 'wp-crontrol' ) ),
|
||||
/* translators: 1: The number of hours in an interval of time. */
|
||||
/* translators: %s: The number of hours in an interval of time. */
|
||||
array( HOUR_IN_SECONDS, _n_noop( '%s hour', '%s hours', 'wp-crontrol' ) ),
|
||||
/* translators: 1: The number of minutes in an interval of time. */
|
||||
/* translators: %s: The number of minutes in an interval of time. */
|
||||
array( MINUTE_IN_SECONDS, _n_noop( '%s minute', '%s minutes', 'wp-crontrol' ) ),
|
||||
/* translators: 1: The number of seconds in an interval of time. */
|
||||
/* translators: %s: The number of seconds in an interval of time. */
|
||||
array( 1, _n_noop( '%s second', '%s seconds', 'wp-crontrol' ) ),
|
||||
);
|
||||
|
||||
@@ -2060,10 +2131,7 @@ function enqueue_assets( $hook_suffix ) {
|
||||
wp_enqueue_script(
|
||||
'wp-crontrol',
|
||||
plugin_dir_url( PLUGIN_FILE ) . 'js/wp-crontrol.js',
|
||||
array(
|
||||
'jquery',
|
||||
'wp-a11y',
|
||||
),
|
||||
array(),
|
||||
WP_CRONTROL_VERSION,
|
||||
true
|
||||
);
|
||||
@@ -2195,10 +2263,67 @@ function json_output( $input, $pretty = true ) {
|
||||
*
|
||||
* Therefore, the user access level required to execute arbitrary PHP code does not change with WP Crontrol activated.
|
||||
*
|
||||
* @param string $code The PHP code to evaluate.
|
||||
* The PHP code that's saved in a PHP cron event is protected with an integrity check which prevents it from being executed
|
||||
* if the code is tampered with.
|
||||
*
|
||||
* PHP cron events are secured via an integrity check that makes use of an HMAC to store a hash of the PHP code alongside
|
||||
* the code when the event is saved. When the event runs, the hash is checked to ensure the integrity of the PHP code and
|
||||
* confirm that it has not been tampered with. WP Crontrol will not execute the PHP code if the hashes do not match or if
|
||||
* a stored hash is not present.
|
||||
*
|
||||
* If an attacker with database-level access were to modify the PHP code in an event in an attempt to execute arbitrary
|
||||
* code, the code would no longer execute.
|
||||
*
|
||||
* @link https://wp-crontrol.com/docs/php-cron-events/
|
||||
*
|
||||
* @param array<string,string>|string $args The event args array, or a string containing the PHP code to evaluate.
|
||||
* @phpstan-param array{
|
||||
* code?: string,
|
||||
* name?: string,
|
||||
* hash?: string,
|
||||
* }|string $args
|
||||
* @return void
|
||||
*/
|
||||
function action_php_cron_event( $code ) {
|
||||
function action_php_cron_event( $args ) {
|
||||
if ( is_string( $args ) ) {
|
||||
// Prior to WP Crontrol 1.16.2, PHP cron events were saved with the associative arguments array at the top
|
||||
// level. This means arguments are passed as individual parameters to this function and the first parameter
|
||||
// contains the PHP code.
|
||||
$code = $args;
|
||||
$hash = null;
|
||||
} else {
|
||||
// Since WP Crontrol 1.16.2, PHP cron events are stored with the associative arguments array as the first element
|
||||
// in the args list. This means arguments are passed as a single associative array parameter to this function.
|
||||
$code = $args['code'] ?? null;
|
||||
$hash = $args['hash'] ?? null;
|
||||
}
|
||||
|
||||
if ( empty( $hash ) ) {
|
||||
// phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_trigger_error
|
||||
trigger_error(
|
||||
sprintf(
|
||||
'The stored hash is missing for a PHP cron event; for more information see %s',
|
||||
esc_url_raw( admin_url( 'tools.php?page=crontrol_admin_manage_page&crontrol_hooks_type=php' ) ),
|
||||
),
|
||||
E_USER_WARNING
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
// Check the integrity of the PHP code.
|
||||
if ( ! check_integrity( $code, $hash ) ) {
|
||||
// phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_trigger_error
|
||||
trigger_error(
|
||||
sprintf(
|
||||
'The stored hash for a PHP cron event is not valid; for more information see %s',
|
||||
esc_url_raw( admin_url( 'tools.php?page=crontrol_admin_manage_page&crontrol_hooks_type=php' ) ),
|
||||
),
|
||||
E_USER_WARNING
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
// Please see the function description above for information about the safety of this code.
|
||||
// phpcs:ignore Squiz.PHP.Eval.Discouraged
|
||||
eval( $code );
|
||||
}
|
||||
|
||||
@@ -90,15 +90,24 @@ class Table extends \WP_List_Table {
|
||||
|
||||
$this->items = array_slice( $events, $offset, $per_page );
|
||||
|
||||
$has_integrity_failures = (bool) array_filter( array_map( __NAMESPACE__ . '\\integrity_failed', $this->items ) );
|
||||
$has_late = (bool) array_filter( array_map( __NAMESPACE__ . '\\is_late', $this->items ) );
|
||||
|
||||
if ( $has_late ) {
|
||||
if ( $has_integrity_failures && empty( $_GET['crontrol_action'] ) ) {
|
||||
add_action( 'admin_notices', function() {
|
||||
printf(
|
||||
'<div id="crontrol-integrity-failures-message" class="notice notice-error"><p>%1$s</p><p><a href="%2$s">%3$s</a></p></div>',
|
||||
esc_html__( 'The PHP code in one or more of your PHP cron events needs to be checked for integrity. These events will not run until you check and re-save them.', 'wp-crontrol' ),
|
||||
'https://wp-crontrol.com/help/check-php-cron-events/',
|
||||
esc_html__( 'Read what to do', 'wp-crontrol' )
|
||||
);
|
||||
} );
|
||||
} elseif ( $has_late && empty( $_GET['crontrol_action'] ) ) {
|
||||
add_action( 'admin_notices', function() {
|
||||
printf(
|
||||
'<div id="crontrol-late-message" class="notice notice-warning"><p>%1$s</p><p><a href="%2$s">%3$s</a></p></div>',
|
||||
/* translators: %s: Help page URL. */
|
||||
esc_html__( 'One or more cron events have missed their schedule.', 'wp-crontrol' ),
|
||||
'https://github.com/johnbillion/wp-crontrol/wiki/Cron-events-that-have-missed-their-schedule',
|
||||
'https://wp-crontrol.com/help/missed-cron-events/',
|
||||
esc_html__( 'More information', 'wp-crontrol' )
|
||||
);
|
||||
} );
|
||||
@@ -136,13 +145,13 @@ class Table extends \WP_List_Table {
|
||||
return ( ! in_array( $event->hook, $all_core_hooks, true ) );
|
||||
} );
|
||||
|
||||
$paused = array_filter( $events, function( $event ) {
|
||||
return ( is_paused( $event ) );
|
||||
$filtered['php'] = array_filter( $events, function( $event ) {
|
||||
return ( 'crontrol_cron_job' === $event->hook );
|
||||
} );
|
||||
|
||||
if ( count( $paused ) > 0 ) {
|
||||
$filtered['paused'] = $paused;
|
||||
}
|
||||
$filtered['paused'] = array_filter( $events, function( $event ) {
|
||||
return ( is_paused( $event ) );
|
||||
} );
|
||||
|
||||
/**
|
||||
* Filters the available filtered events on the cron event listing screen.
|
||||
@@ -167,15 +176,17 @@ class Table extends \WP_List_Table {
|
||||
public function get_columns() {
|
||||
return array(
|
||||
'cb' => '<input type="checkbox" />',
|
||||
'crontrol_hook' => __( 'Hook', 'wp-crontrol' ),
|
||||
'crontrol_args' => __( 'Arguments', 'wp-crontrol' ),
|
||||
'crontrol_next' => sprintf(
|
||||
/* translators: %s: UTC offset */
|
||||
__( 'Next Run (%s)', 'wp-crontrol' ),
|
||||
\Crontrol\get_utc_offset()
|
||||
'crontrol_hook' => esc_html__( 'Hook', 'wp-crontrol' ),
|
||||
'crontrol_args' => esc_html__( 'Arguments', 'wp-crontrol' ),
|
||||
'crontrol_next' => esc_html(
|
||||
sprintf(
|
||||
/* translators: %s: UTC offset */
|
||||
__( 'Next Run (%s)', 'wp-crontrol' ),
|
||||
\Crontrol\get_utc_offset()
|
||||
),
|
||||
),
|
||||
'crontrol_actions' => __( 'Action', 'wp-crontrol' ),
|
||||
'crontrol_recurrence' => __( 'Recurrence', 'wp-crontrol' ),
|
||||
'crontrol_actions' => esc_html__( 'Action', 'wp-crontrol' ),
|
||||
'crontrol_recurrence' => esc_html__( 'Recurrence', 'wp-crontrol' ),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -238,6 +249,7 @@ class Table extends \WP_List_Table {
|
||||
'noaction' => __( 'Events with no action', 'wp-crontrol' ),
|
||||
'core' => __( 'WordPress core events', 'wp-crontrol' ),
|
||||
'custom' => __( 'Custom events', 'wp-crontrol' ),
|
||||
'php' => __( 'PHP events', 'wp-crontrol' ),
|
||||
'paused' => __( 'Paused events', 'wp-crontrol' ),
|
||||
);
|
||||
|
||||
@@ -263,6 +275,12 @@ class Table extends \WP_List_Table {
|
||||
continue;
|
||||
}
|
||||
|
||||
$count = count( $filtered[ $key ] );
|
||||
|
||||
if ( ! $count ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$link = ( 'all' === $key ) ? $url : add_query_arg( 'crontrol_hooks_type', $key, $url );
|
||||
|
||||
$views[ $key ] = sprintf(
|
||||
@@ -270,7 +288,7 @@ class Table extends \WP_List_Table {
|
||||
esc_url( $link ),
|
||||
$hooks_type === $key ? ' class="current"' : '',
|
||||
esc_html( $type ),
|
||||
number_format_i18n( count( $filtered[ $key ] ) )
|
||||
esc_html( number_format_i18n( $count ) )
|
||||
);
|
||||
}
|
||||
|
||||
@@ -309,7 +327,11 @@ class Table extends \WP_List_Table {
|
||||
public function single_row( $event ) {
|
||||
$classes = array();
|
||||
|
||||
if ( ( 'crontrol_cron_job' === $event->hook ) && ! empty( $event->args['syntax_error_message'] ) ) {
|
||||
if ( ( 'crontrol_cron_job' === $event->hook ) && isset( $event->args[0]['syntax_error_message'] ) ) {
|
||||
$classes[] = 'crontrol-error';
|
||||
}
|
||||
|
||||
if ( integrity_failed( $event ) ) {
|
||||
$classes[] = 'crontrol-error';
|
||||
}
|
||||
|
||||
@@ -374,10 +396,20 @@ class Table extends \WP_List_Table {
|
||||
);
|
||||
$link = add_query_arg( $link, admin_url( 'tools.php' ) );
|
||||
|
||||
$links[] = "<a href='" . esc_url( $link ) . "'>" . esc_html__( 'Edit', 'wp-crontrol' ) . '</a>';
|
||||
if ( integrity_failed( $event ) ) {
|
||||
$label = __( 'Check and edit', 'wp-crontrol' );
|
||||
} else {
|
||||
$label = __( 'Edit', 'wp-crontrol' );
|
||||
}
|
||||
|
||||
$links[] = sprintf(
|
||||
'<a href="%1$s">%2$s</a>',
|
||||
esc_url( $link ),
|
||||
esc_html( $label )
|
||||
);
|
||||
}
|
||||
|
||||
if ( ! is_paused( $event ) ) {
|
||||
if ( ! is_paused( $event ) && ! integrity_failed( $event ) ) {
|
||||
$link = array(
|
||||
'page' => 'crontrol_admin_manage_page',
|
||||
'crontrol_action' => 'run-cron',
|
||||
@@ -483,7 +515,7 @@ class Table extends \WP_List_Table {
|
||||
);
|
||||
} elseif ( ( 'crontrol_cron_job' !== $event->hook ) || self::$can_manage_php_crons ) {
|
||||
return sprintf(
|
||||
'<label class="screen-reader-text" for="%1$s">%2$s</label>
|
||||
'<label for="%1$s"><span class="screen-reader-text">%2$s</span></label>
|
||||
<input type="checkbox" name="crontrol_delete[%3$s][%4$s]" value="%5$s" id="%1$s">',
|
||||
esc_attr( $id ),
|
||||
esc_html__( 'Select this row', 'wp-crontrol' ),
|
||||
@@ -505,11 +537,20 @@ class Table extends \WP_List_Table {
|
||||
protected function column_crontrol_hook( $event ) {
|
||||
if ( 'crontrol_cron_job' === $event->hook ) {
|
||||
if ( ! empty( $event->args['name'] ) ) {
|
||||
/* translators: 1: The name of the PHP cron event. */
|
||||
return '<em>' . esc_html( sprintf( __( 'PHP Cron (%s)', 'wp-crontrol' ), $event->args['name'] ) ) . '</em>';
|
||||
/* translators: %s: The name of the PHP cron event. */
|
||||
$output = esc_html( sprintf( __( 'PHP Cron (%s)', 'wp-crontrol' ), $event->args['name'] ) );
|
||||
} else {
|
||||
return '<em>' . esc_html__( 'PHP Cron', 'wp-crontrol' ) . '</em>';
|
||||
$output = esc_html__( 'PHP Cron', 'wp-crontrol' );
|
||||
}
|
||||
|
||||
if ( integrity_failed( $event ) ) {
|
||||
$output .= sprintf(
|
||||
' — <strong class="status-crontrol-check post-state"><span class="dashicons dashicons-warning" aria-hidden="true"></span> %s</strong>',
|
||||
esc_html__( 'Needs checking', 'wp-crontrol' )
|
||||
);
|
||||
}
|
||||
|
||||
return $output;
|
||||
}
|
||||
|
||||
$output = esc_html( $event->hook );
|
||||
@@ -535,19 +576,25 @@ class Table extends \WP_List_Table {
|
||||
if ( 'crontrol_cron_job' === $event->hook ) {
|
||||
$return = '<em>' . esc_html__( 'PHP Code', 'wp-crontrol' ) . '</em>';
|
||||
|
||||
if ( ! empty( $event->args['syntax_error_message'] ) ) {
|
||||
if ( isset( $event->args['code'] ) ) {
|
||||
$args = $event->args;
|
||||
} else {
|
||||
$args = $event->args[0];
|
||||
}
|
||||
|
||||
if ( isset( $args['syntax_error_message'], $args['syntax_error_line'] ) ) {
|
||||
$return .= '<br><span class="status-crontrol-error"><span class="dashicons dashicons-warning" aria-hidden="true"></span> ';
|
||||
$return .= sprintf(
|
||||
/* translators: 1: Line number, 2: Error message text */
|
||||
esc_html__( 'Line %1$s: %2$s', 'wp-crontrol' ),
|
||||
esc_html( number_format_i18n( $event->args['syntax_error_line'] ) ),
|
||||
esc_html( $event->args['syntax_error_message'] )
|
||||
esc_html( number_format_i18n( $args['syntax_error_line'] ) ),
|
||||
esc_html( $args['syntax_error_message'] )
|
||||
);
|
||||
$return .= '</span>';
|
||||
}
|
||||
|
||||
if ( ! empty( $event->args['code'] ) ) {
|
||||
$lines = explode( "\n", trim( $event->args['code'] ) );
|
||||
if ( ! empty( $args['code'] ) ) {
|
||||
$lines = explode( "\n", trim( $args['code'] ) );
|
||||
$code = reset( $lines );
|
||||
$code = substr( $code, 0, 50 );
|
||||
|
||||
@@ -584,7 +631,7 @@ class Table extends \WP_List_Table {
|
||||
$hook_callbacks = \Crontrol\get_hook_callbacks( $event->hook );
|
||||
|
||||
if ( 'crontrol_cron_job' === $event->hook ) {
|
||||
return '<em>' . esc_html__( 'WP Crontrol', 'wp-crontrol' ) . '</em>';
|
||||
return 'WP Crontrol';
|
||||
} elseif ( ! empty( $hook_callbacks ) ) {
|
||||
$callbacks = array();
|
||||
|
||||
|
||||
@@ -70,7 +70,7 @@ function run( $hookname, $sig ) {
|
||||
return new WP_Error(
|
||||
'not_found',
|
||||
sprintf(
|
||||
/* translators: 1: The name of the cron event. */
|
||||
/* translators: %s: The name of the cron event. */
|
||||
__( 'The cron event %s could not be found.', 'wp-crontrol' ),
|
||||
$hookname
|
||||
)
|
||||
@@ -109,7 +109,7 @@ function force_schedule_single_event( $hook, $args = array() ) {
|
||||
return new WP_Error(
|
||||
'could_not_add',
|
||||
sprintf(
|
||||
/* translators: 1: The name of the cron event. */
|
||||
/* translators: %s: The name of the cron event. */
|
||||
__( 'Failed to schedule the cron event %s.', 'wp-crontrol' ),
|
||||
$hook
|
||||
)
|
||||
@@ -126,6 +126,7 @@ function force_schedule_single_event( $hook, $args = array() ) {
|
||||
* @param string $schedule The recurrence of the cron event.
|
||||
* @param string $hook The name of the hook to execute.
|
||||
* @param mixed[] $args Arguments to add to the cron event.
|
||||
* @phpstan-param list<mixed> $args
|
||||
* @return true|WP_error True if the addition was successful, WP_Error otherwise.
|
||||
*/
|
||||
function add( $next_run_local, $schedule, $hook, array $args ) {
|
||||
@@ -144,21 +145,25 @@ function add( $next_run_local, $schedule, $hook, array $args ) {
|
||||
|
||||
$next_run_utc = (int) get_gmt_from_date( gmdate( 'Y-m-d H:i:s', $next_run_local ), 'U' );
|
||||
|
||||
if ( ! is_array( $args ) ) {
|
||||
$args = array();
|
||||
}
|
||||
|
||||
if ( 'crontrol_cron_job' === $hook && ! empty( $args['code'] ) && class_exists( '\ParseError' ) ) {
|
||||
if ( 'crontrol_cron_job' === $hook && ! empty( $args[0]['code'] ) && class_exists( '\ParseError' ) ) {
|
||||
try {
|
||||
/**
|
||||
* The call to `eval()` below checks the syntax of the PHP code provided in the cron event. This is done to
|
||||
* add a flag to a cron event that contains invalid PHP code, so that the user can be informed of the syntax
|
||||
* error when viewing the event in the list table.
|
||||
*
|
||||
* Security: The code is not executed due to the early return statement that precedes it. The code is only
|
||||
* checked for syntax correctness.
|
||||
*/
|
||||
// phpcs:ignore Squiz.PHP.Eval.Discouraged
|
||||
eval( sprintf(
|
||||
'return true; %s',
|
||||
$args['code']
|
||||
$args[0]['code']
|
||||
) );
|
||||
// phpcs:ignore PHPCompatibility.Classes.NewClasses.parseerrorFound
|
||||
} catch ( \ParseError $e ) {
|
||||
$args['syntax_error_message'] = $e->getMessage();
|
||||
$args['syntax_error_line'] = $e->getLine();
|
||||
$args[0]['syntax_error_message'] = $e->getMessage();
|
||||
$args[0]['syntax_error_line'] = $e->getLine();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -236,7 +241,7 @@ function delete( $hook, $sig, $next_run_utc ) {
|
||||
return new WP_Error(
|
||||
'could_not_delete',
|
||||
sprintf(
|
||||
/* translators: 1: The name of the cron event. */
|
||||
/* translators: %s: The name of the cron event. */
|
||||
__( 'Failed to the delete the cron event %s.', 'wp-crontrol' ),
|
||||
$hook
|
||||
)
|
||||
@@ -267,7 +272,7 @@ function pause( $hook ) {
|
||||
return new WP_Error(
|
||||
'could_not_pause',
|
||||
sprintf(
|
||||
/* translators: 1: The name of the cron event. */
|
||||
/* translators: %s: The name of the cron event. */
|
||||
__( 'Failed to pause the cron event %s.', 'wp-crontrol' ),
|
||||
$hook
|
||||
)
|
||||
@@ -298,7 +303,7 @@ function resume( $hook ) {
|
||||
return new WP_Error(
|
||||
'could_not_resume',
|
||||
sprintf(
|
||||
/* translators: 1: The name of the cron event. */
|
||||
/* translators: %s: The name of the cron event. */
|
||||
__( 'Failed to resume the cron event %s.', 'wp-crontrol' ),
|
||||
$hook
|
||||
)
|
||||
@@ -372,7 +377,7 @@ function get_single( $hook, $sig, $next_run_utc ) {
|
||||
return new WP_Error(
|
||||
'not_found',
|
||||
sprintf(
|
||||
/* translators: 1: The name of the cron event. */
|
||||
/* translators: %s: The name of the cron event. */
|
||||
__( 'The cron event %s could not be found.', 'wp-crontrol' ),
|
||||
$hook
|
||||
)
|
||||
@@ -471,6 +476,47 @@ function is_paused( stdClass $event ) {
|
||||
return array_key_exists( $event->hook, $paused );
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether the integrity check of a PHP cron event has failed.
|
||||
*
|
||||
* @param stdClass $event The event.
|
||||
* @return bool Whether the event integrity check has failed.
|
||||
*/
|
||||
function integrity_failed( stdClass $event ): bool {
|
||||
// Only check PHP cron events.
|
||||
if ( 'crontrol_cron_job' !== $event->hook ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// This is a PHP cron event saved prior to WP Crontrol 1.16.2.
|
||||
if ( isset( $event->args['code'] ) ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$args = $event->args[0] ?? array();
|
||||
|
||||
return ! check_integrity( $args['code'] ?? null, $args['hash'] ?? null );
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks the integrity of a code string compared to its stored hash.
|
||||
*
|
||||
* @param string|null $code The code string.
|
||||
* @param string|null $stored_hash The stored HMAC of the code.
|
||||
* @return bool
|
||||
*/
|
||||
function check_integrity( $code, $stored_hash ): bool {
|
||||
// If there's no code or hash then the integrity check is not ok.
|
||||
if ( empty( $code ) || empty( $stored_hash ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$code_hash = wp_hash( $code );
|
||||
|
||||
// If the hashes match then the integrity check is ok.
|
||||
return hash_equals( $stored_hash, $code_hash );
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialises and returns the list table for events.
|
||||
*
|
||||
|
||||
@@ -76,9 +76,9 @@ class Schedule_List_Table extends \WP_List_Table {
|
||||
public function get_columns() {
|
||||
return array(
|
||||
'crontrol_icon' => '',
|
||||
'crontrol_name' => __( 'Internal Name', 'wp-crontrol' ),
|
||||
'crontrol_interval' => __( 'Interval', 'wp-crontrol' ),
|
||||
'crontrol_display' => __( 'Display Name', 'wp-crontrol' ),
|
||||
'crontrol_name' => esc_html__( 'Internal Name', 'wp-crontrol' ),
|
||||
'crontrol_interval' => esc_html__( 'Interval', 'wp-crontrol' ),
|
||||
'crontrol_display' => esc_html__( 'Display Name', 'wp-crontrol' ),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -159,7 +159,7 @@ class Schedule_List_Table extends \WP_List_Table {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the output for the schdule name cell of a table row.
|
||||
* Returns the output for the schedule name cell of a table row.
|
||||
*
|
||||
* @phpstan-param array{
|
||||
* interval: int,
|
||||
|
||||
Reference in New Issue
Block a user