diff --git a/projects/packages/scheduled-updates/changelog/add-endpoint-actions b/projects/packages/scheduled-updates/changelog/add-endpoint-actions new file mode 100644 index 0000000000000..8d57d0edfb1ca --- /dev/null +++ b/projects/packages/scheduled-updates/changelog/add-endpoint-actions @@ -0,0 +1,4 @@ +Significance: minor +Type: changed + +Scheduled Updates: Move arbitrary actions to callbacks diff --git a/projects/packages/scheduled-updates/src/class-scheduled-updates-logs.php b/projects/packages/scheduled-updates/src/class-scheduled-updates-logs.php index e643147cb5b9d..2cea6b2057003 100644 --- a/projects/packages/scheduled-updates/src/class-scheduled-updates-logs.php +++ b/projects/packages/scheduled-updates/src/class-scheduled-updates-logs.php @@ -162,7 +162,7 @@ public static function clear( string $schedule_id = null ) { */ public static function infer_status_from_logs( $schedule_id ) { $logs = self::get( $schedule_id ); - if ( is_wp_error( $logs ) || empty( $logs ) ) { + if ( empty( $logs ) ) { return false; } @@ -198,6 +198,41 @@ public static function infer_status_from_logs( $schedule_id ) { ); } + /** + * Replaces the logs with the old schedule ID with new ones. + * + * @param string $old_schedule_id The old schedule ID. + * @param string $new_schedule_id The new schedule ID. + */ + public static function replace_logs_schedule_id( $old_schedule_id, $new_schedule_id ) { + if ( $old_schedule_id === $new_schedule_id ) { + return; + } + + $logs = get_option( self::OPTION_NAME, array() ); + + if ( isset( $logs[ $old_schedule_id ] ) ) { + // Replace the logs with the old schedule ID with new ones. + $logs[ $new_schedule_id ] = $logs[ $old_schedule_id ]; + unset( $logs[ $old_schedule_id ] ); + + update_option( self::OPTION_NAME, $logs ); + } + } + + /** + * Deletes the logs for a schedule ID when the current request is a DELETE request. + * + * @param string $schedule_id The ID of the schedule to delete. + * @param object $event The deleted event object. + * @param \WP_REST_Request $request The request object. + */ + public static function delete_logs_schedule_id( $schedule_id, $event, $request ) { + if ( $request->get_method() === \WP_REST_Server::DELETABLE ) { + self::clear( $schedule_id ); + } + } + /** * Splits the logs into runs based on the PLUGIN_UPDATES_START action. * @@ -225,33 +260,4 @@ private static function split_logs_into_runs( $logs ) { return $runs; } - - /** - * Replaces the logs with the old schedule ID with new ones. - * - * @param string $old_schedule_id The old schedule ID. - * @param string $new_schedule_id The new schedule ID. - * - * @return bool True if the logs were successfully replaced, false otherwise. - */ - public static function replace_logs_schedule_id( $old_schedule_id, $new_schedule_id ) { - - if ( $old_schedule_id === $new_schedule_id ) { - return false; - } - - $logs = get_option( self::OPTION_NAME, array() ); - - if ( isset( $logs[ $old_schedule_id ] ) ) { - // Replace the logs with the old schedule ID with new ones - $logs[ $new_schedule_id ] = $logs[ $old_schedule_id ]; - unset( $logs[ $old_schedule_id ] ); - - update_option( self::OPTION_NAME, $logs ); - - return true; - } - - return false; - } } diff --git a/projects/packages/scheduled-updates/src/class-scheduled-updates.php b/projects/packages/scheduled-updates/src/class-scheduled-updates.php index 2ce7e58177db1..11f8b42ce0b81 100644 --- a/projects/packages/scheduled-updates/src/class-scheduled-updates.php +++ b/projects/packages/scheduled-updates/src/class-scheduled-updates.php @@ -57,6 +57,11 @@ public static function init() { add_filter( 'views_plugins', array( Scheduled_Updates_Admin::class, 'add_scheduled_updates_view' ) ); add_filter( 'plugin_auto_update_setting_html', array( Scheduled_Updates_Admin::class, 'show_scheduled_updates' ), 10, 2 ); + add_action( 'jetpack_scheduled_update_created', array( __CLASS__, 'maybe_disable_autoupdates' ), 10, 3 ); + add_action( 'jetpack_scheduled_update_deleted', array( __CLASS__, 'enable_autoupdates' ), 10, 2 ); + add_action( 'jetpack_scheduled_update_updated', array( Scheduled_Updates_Logs::class, 'replace_logs_schedule_id' ), 10, 2 ); + add_action( 'jetpack_scheduled_update_deleted', array( Scheduled_Updates_Logs::class, 'delete_logs_schedule_id' ), 10, 3 ); + // Update cron sync option after options update. $callback = array( __CLASS__, 'update_option_cron' ); @@ -251,6 +256,53 @@ public static function allowlist_scheduled_plugins( $update, $item ) { return $update; } + /** + * Maybe disable autoupdates. + * + * @param string $id The ID of the schedule. + * @param object $event The event object. + * @param \WP_REST_Request $request The request object. + */ + public static function maybe_disable_autoupdates( $id, $event, $request ) { + require_once ABSPATH . 'wp-admin/includes/update.php'; + + if ( wp_is_auto_update_enabled_for_type( 'plugin' ) ) { + // Remove the plugins that are now updated on a schedule from the auto-update list. + $auto_update_plugins = get_option( 'auto_update_plugins', array() ); + $auto_update_plugins = array_diff( $auto_update_plugins, $request['plugins'] ); + update_option( 'auto_update_plugins', $auto_update_plugins ); + } + } + + /** + * Enable autoupdates. + * + * @param string $id The ID of the schedule. + * @param object $event The deleted event object. + */ + public static function enable_autoupdates( $id, $event ) { + require_once ABSPATH . 'wp-admin/includes/update.php'; + + if ( ! wp_is_auto_update_enabled_for_type( 'plugin' ) ) { + return; + } + + $events = wp_get_scheduled_events( static::PLUGIN_CRON_HOOK ); + unset( $events[ $id ] ); + + // Find the plugins that are not part of any other schedule. + $plugins = $event->args; + foreach ( wp_list_pluck( $events, 'args' ) as $args ) { + $plugins = array_diff( $plugins, $args ); + } + + // Add the plugins that are no longer updated on a schedule to the auto-update list. + $auto_update_plugins = get_option( 'auto_update_plugins', array() ); + $auto_update_plugins = array_unique( array_merge( $auto_update_plugins, $plugins ) ); + usort( $auto_update_plugins, 'strnatcasecmp' ); + update_option( 'auto_update_plugins', $auto_update_plugins ); + } + /** * Registers the is_managed field for the plugin REST API. */ diff --git a/projects/packages/scheduled-updates/src/wpcom-endpoints/class-wpcom-rest-api-v2-endpoint-update-schedules.php b/projects/packages/scheduled-updates/src/wpcom-endpoints/class-wpcom-rest-api-v2-endpoint-update-schedules.php index 615d7438fffce..f22ce7136e9cc 100644 --- a/projects/packages/scheduled-updates/src/wpcom-endpoints/class-wpcom-rest-api-v2-endpoint-update-schedules.php +++ b/projects/packages/scheduled-updates/src/wpcom-endpoints/class-wpcom-rest-api-v2-endpoint-update-schedules.php @@ -265,17 +265,17 @@ public function create_item( $request ) { return $event; } - require_once ABSPATH . 'wp-admin/includes/update.php'; - - if ( wp_is_auto_update_enabled_for_type( 'plugin' ) ) { - // Remove the plugins that are now updated on a schedule from the auto-update list. - $auto_update_plugins = get_option( 'auto_update_plugins', array() ); - $auto_update_plugins = array_diff( $auto_update_plugins, $plugins ); - update_option( 'auto_update_plugins', $auto_update_plugins ); - } - $id = Scheduled_Updates::generate_schedule_id( $plugins ); + /** + * Fires when a scheduled update is created. + * + * @param string $id The ID of the schedule. + * @param object $event The event object. + * @param WP_REST_Request $request The request object. + */ + do_action( 'jetpack_scheduled_update_created', $id, $event, $request ); + return rest_ensure_response( $id ); } @@ -342,20 +342,21 @@ public function update_item( $request ) { return $result; } - $previous_schedule_status = Scheduled_Updates::get_scheduled_update_status( $request['schedule_id'] ); - - $clear_logs = false; - $deleted = $this->delete_item( $request, $clear_logs ); + $deleted = $this->delete_item( $request ); if ( is_wp_error( $deleted ) ) { return $deleted; } $item = $this->create_item( $request ); - // Sets the previous status. - if ( $previous_schedule_status ) { - Scheduled_Updates_Logs::replace_logs_schedule_id( $request['schedule_id'], $item->data ); - } + /** + * Fires when a scheduled update is updated. + * + * @param string $old_id The ID of the schedule to update. + * @param string $new_id The ID of the updated event. + * @param WP_REST_Request $request The request object. + */ + do_action( 'jetpack_scheduled_update_updated', $request['schedule_id'], $item->data, $request ); return $item; } @@ -472,10 +473,9 @@ public function delete_item_permissions_check( $request ) { // phpcs:ignore Vari * Deletes an existing update schedule. * * @param WP_REST_Request $request Request object. - * @param bool $clear_logs Whether to clear the logs or not. * @return WP_REST_Response|WP_Error */ - public function delete_item( $request, $clear_logs = true ) { + public function delete_item( $request ) { $events = wp_get_scheduled_events( Scheduled_Updates::PLUGIN_CRON_HOOK ); if ( ! isset( $events[ $request['schedule_id'] ] ) ) { @@ -493,28 +493,14 @@ public function delete_item( $request, $clear_logs = true ) { return new WP_Error( 'unschedule_event_error', __( 'Error during unschedule of the event.', 'jetpack-scheduled-updates' ), array( 'status' => 500 ) ); } - require_once ABSPATH . 'wp-admin/includes/update.php'; - - if ( wp_is_auto_update_enabled_for_type( 'plugin' ) ) { - unset( $events[ $request['schedule_id'] ] ); - - // Find the plugins that are not part of any other schedule. - $plugins = $event->args; - foreach ( wp_list_pluck( $events, 'args' ) as $args ) { - $plugins = array_diff( $plugins, $args ); - } - - // Add the plugins that are no longer updated on a schedule to the auto-update list. - $auto_update_plugins = get_option( 'auto_update_plugins', array() ); - $auto_update_plugins = array_unique( array_merge( $auto_update_plugins, $plugins ) ); - usort( $auto_update_plugins, 'strnatcasecmp' ); - update_option( 'auto_update_plugins', $auto_update_plugins ); - } - - // Delete logs - if ( $clear_logs ) { - Scheduled_Updates_Logs::clear( $request['schedule_id'] ); - } + /** + * Fires when a scheduled update is deleted. + * + * @param string $id The ID of the schedule to delete. + * @param object $event The deleted event object. + * @param WP_REST_Request $request The request object. + */ + do_action( 'jetpack_scheduled_update_deleted', $request['schedule_id'], $event, $request ); return rest_ensure_response( true ); } diff --git a/projects/packages/scheduled-updates/tests/php/class-wpcom-rest-api-v2-endpoint-update-schedules-test.php b/projects/packages/scheduled-updates/tests/php/class-wpcom-rest-api-v2-endpoint-update-schedules-test.php index 5b58c1e7d345f..9b0e6f785660a 100644 --- a/projects/packages/scheduled-updates/tests/php/class-wpcom-rest-api-v2-endpoint-update-schedules-test.php +++ b/projects/packages/scheduled-updates/tests/php/class-wpcom-rest-api-v2-endpoint-update-schedules-test.php @@ -641,13 +641,14 @@ public function test_update_item_with_status() { $this->assertSame( 200, $result->get_status() ); $schedule_id = $result->get_data(); - // Get the updated status + // Get the updated status. $updated_status = Scheduled_Updates::get_scheduled_update_status( $schedule_id ); + if ( $updated_status === false ) { $this->fail( 'Scheduled_Updates::get_scheduled_update_status() returned false.' ); } else { $this->assertIsArray( $updated_status, 'Scheduled_Updates::get_scheduled_update_status() should return an array.' ); - // doing these null checks for the static analyzer + // doing these null checks for the static analyzer. $this->assertSame( $timestamp, $updated_status['last_run_timestamp'] ?? null ); $this->assertSame( $status, $updated_status['last_run_status'] ?? null ); @@ -888,7 +889,7 @@ public function test_add_and_get_multiple_logs() { $schedule_id = $this->create_test_schedule(); - // Simulate 5 runs + // Simulate 5 runs. for ( $i = 0;$i < 5;$i++ ) { $request = new WP_REST_Request( 'PUT', '/wpcom/v2/update-schedules/' . $schedule_id . '/logs' ); $request->set_body_params( diff --git a/projects/plugins/mu-wpcom-plugin/changelog/add-endpoint-actions b/projects/plugins/mu-wpcom-plugin/changelog/add-endpoint-actions new file mode 100644 index 0000000000000..9aa70e3ec1f75 --- /dev/null +++ b/projects/plugins/mu-wpcom-plugin/changelog/add-endpoint-actions @@ -0,0 +1,5 @@ +Significance: patch +Type: changed +Comment: Updated composer.lock. + +