From adaf0fbb5bcfe14a024ceb96a574bfd8a4ca0f64 Mon Sep 17 00:00:00 2001 From: John Blackbourn Date: Fri, 19 Sep 2025 18:05:19 +0100 Subject: [PATCH 1/5] Introduce support for a `CRONTROL_DISALLOW_URL_EVENTS` constant. --- phpstan.neon.dist | 1 + src/bootstrap.php | 30 ++++++++++++++++++++++++++++++ 2 files changed, 31 insertions(+) diff --git a/phpstan.neon.dist b/phpstan.neon.dist index 2c680c57..4f3747db 100644 --- a/phpstan.neon.dist +++ b/phpstan.neon.dist @@ -16,6 +16,7 @@ parameters: - tests/phpstan/stubs.php dynamicConstantNames: - CRONTROL_DISALLOW_PHP_EVENTS + - CRONTROL_DISALLOW_URL_EVENTS WPCompat: pluginFile: wp-crontrol.php ignoreErrors: diff --git a/src/bootstrap.php b/src/bootstrap.php index fd69bdff..6a4c05ff 100644 --- a/src/bootstrap.php +++ b/src/bootstrap.php @@ -2657,6 +2657,11 @@ function json_output( $input, $pretty = true ) { /** * Fetches the URL in a URL cron event using the HTTP API. * + * If the `CRONTROL_DISALLOW_URL_EVENTS` constant is defined and set to `true` then URL cron events will be disabled + * completely. Any existing URL cron events will remain in place but their URL will not be fetched, and no URL cron + * events can be added, edited, or manually run. Users with permission to edit URL cron events will still be able to + * delete these events. + * * The URL that's saved in a URL cron event is protected with an integrity check which prevents it from being fetched * if the URL is tampered with. * @@ -2681,6 +2686,10 @@ function json_output( $input, $pretty = true ) { * } $args */ function action_url_cron_event( array $args ): void { + if ( ! url_cron_events_enabled() ) { + return; + } + list( 'url' => $url, 'method' => $method, @@ -2855,3 +2864,24 @@ function php_cron_events_enabled(): bool { function current_user_can_manage_php_cron_events(): bool { return ( php_cron_events_enabled() && current_user_can( 'edit_files' ) ); } + +/** + * Returns whether URL cron events are enabled. + * + * The URL cron event functionality can be disabled by defining the `CRONTROL_DISALLOW_URL_EVENTS` constant and setting + * its value to `true`. This constant can be defined in the `wp-config.php` file. + */ +function url_cron_events_enabled(): bool { + if ( defined( 'CRONTROL_DISALLOW_URL_EVENTS' ) && CRONTROL_DISALLOW_URL_EVENTS ) { + return false; + } + + return true; +} + +/** + * Returns whether URL cron events are enabled and can be managed by the current user. + */ +function current_user_can_manage_url_cron_events(): bool { + return ( url_cron_events_enabled() && current_user_can( 'manage_options' ) ); +} From 8e36e589a70a84ae4b3136d3f86b811b26f814a2 Mon Sep 17 00:00:00 2001 From: John Blackbourn Date: Fri, 19 Sep 2025 18:10:38 +0100 Subject: [PATCH 2/5] Account for disabling URL cron events throughout the plugin. --- src/bootstrap.php | 48 +++++++++++++++++++++------ src/event-list-table.php | 72 ++++++++++++++++++++++++++++++++++++---- 2 files changed, 102 insertions(+), 18 deletions(-) diff --git a/src/bootstrap.php b/src/bootstrap.php index 6a4c05ff..c9904ccb 100644 --- a/src/bootstrap.php +++ b/src/bootstrap.php @@ -163,6 +163,9 @@ function action_handle_posts() { if ( 'crontrol_cron_job' === $cr->hookname ) { wp_die( esc_html__( 'You are not allowed to add new PHP cron events.', 'wp-crontrol' ), 401 ); } + if ( 'crontrol_url_cron_job' === $cr->hookname ) { + wp_die( esc_html__( 'You are not allowed to add new URL cron events.', 'wp-crontrol' ), 401 ); + } $args = json_decode( $cr->args, true ); if ( empty( $args ) || ! is_array( $args ) ) { @@ -211,8 +214,8 @@ function action_handle_posts() { exit; } elseif ( isset( $_POST['crontrol_action'] ) && ( 'new_url_cron' === $_POST['crontrol_action'] ) ) { - if ( ! current_user_can( 'manage_options' ) ) { - wp_die( esc_html__( 'You are not allowed to add new cron events.', 'wp-crontrol' ), 401 ); + if ( ! current_user_can_manage_url_cron_events() ) { + wp_die( esc_html__( 'You are not allowed to add new URL cron events.', 'wp-crontrol' ), 401 ); } check_admin_referer( 'crontrol-new-cron' ); @@ -339,6 +342,10 @@ function action_handle_posts() { wp_die( esc_html__( 'You are not allowed to edit PHP cron events.', 'wp-crontrol' ), 401 ); } + if ( 'crontrol_url_cron_job' === $cr->hookname && ! current_user_can_manage_url_cron_events() ) { + wp_die( esc_html__( 'You are not allowed to edit URL cron events.', 'wp-crontrol' ), 401 ); + } + $args = json_decode( $cr->args, true ); if ( empty( $args ) || ! is_array( $args ) ) { @@ -737,10 +744,13 @@ function action_handle_posts() { $deleted = false; check_admin_referer( "crontrol-delete-hook_{$hook}" ); - // Sanity check + // Sanity checks if ( 'crontrol_cron_job' === $hook ) { wp_die( esc_html__( 'You are not allowed to delete PHP cron events.', 'wp-crontrol' ), 401 ); } + if ( 'crontrol_url_cron_job' === $hook ) { + wp_die( esc_html__( 'You are not allowed to delete URL cron events.', 'wp-crontrol' ), 401 ); + } $deleted = wp_unschedule_hook( $hook, true ); @@ -790,6 +800,10 @@ function action_handle_posts() { wp_die( esc_html__( 'You are not allowed to run cron events.', 'wp-crontrol' ), 401 ); } + if ( ( 'crontrol_url_cron_job' === $hook ) && ! url_cron_events_enabled() ) { + wp_die( esc_html__( 'You are not allowed to run cron events.', 'wp-crontrol' ), 401 ); + } + $ran = Event\run( $hook, $sig ); $redirect = array( @@ -871,7 +885,7 @@ function action_handle_posts() { $hook = wp_unslash( $_GET['crontrol_id'] ); - if ( 'crontrol_cron_job' === $hook ) { + if ( ( 'crontrol_cron_job' === $hook ) || ( 'crontrol_url_cron_job' === $hook ) ) { wp_die( esc_html__( 'You are not allowed to pause or resume cron events.', 'wp-crontrol' ), 401 ); } @@ -1663,7 +1677,15 @@ function show_cron_form( $editing ) { } $can_manage_php = current_user_can_manage_php_cron_events(); - $allowed = ( ! $is_editing_php || $can_manage_php ); + $can_manage_url = current_user_can_manage_url_cron_events(); + + if ( $is_editing_php ) { + $allowed = $can_manage_php; + } elseif ( $is_editing_url ) { + $allowed = $can_manage_url; + } else { + $allowed = true; + } ?>
', esc_attr( $action ) ); + } elseif ( ! $can_manage_php && ! $can_manage_url ) { + echo ''; } else { ?> @@ -1726,12 +1750,14 @@ function show_cron_form( $editing ) {

-

- -

+ +

+ +

+