From b7a1650a5223894debd027ec233a8a8109cc4784 Mon Sep 17 00:00:00 2001 From: Erick Hitter <git-contrib@ethitter.com> Date: Thu, 7 Sep 2017 17:23:23 -0700 Subject: [PATCH] Rough approach to run events and log results --- includes/functions.php | 42 ++++++++++++++++++++++++++++-------------- includes/run.php | 35 +++++++++++++++++++++++++++++------ 2 files changed, 57 insertions(+), 20 deletions(-) diff --git a/includes/functions.php b/includes/functions.php index 02c9778..7a3fce4 100644 --- a/includes/functions.php +++ b/includes/functions.php @@ -3,13 +3,13 @@ namespace Automattic\WP\WP_CLI_Cron_Control_Offload; /** - * Check if subcommand is allowed + * Check if command is allowed * - * @param string $subcommand + * @param string $command * @return bool */ -function is_subcommand_allowed( $subcommand ) { - return in_array( $subcommand, get_command_whitelist(), true ) && ! in_array( $subcommand, get_command_blacklist(), true ); +function is_command_allowed( $command ) { + return in_array( $command, get_command_whitelist(), true ) && ! in_array( $command, get_command_blacklist(), true ); } /** @@ -23,6 +23,8 @@ function get_command_whitelist() { 'cache', 'cap', 'comment', + 'cron-control', + 'cron-control-fixers', 'media', 'menu', 'network', @@ -80,7 +82,7 @@ function schedule_cli_command( $args ) { return $event_args; } - $scheduled = wp_schedule_single_event( strtotime( '+30 seconds' ), ACTION, $event_args ); + $scheduled = wp_schedule_single_event( strtotime( '+30 seconds' ), ACTION, array( 'command' => $event_args ) ); return false !== $scheduled; } @@ -88,21 +90,33 @@ function schedule_cli_command( $args ) { /** * Validate WP-CLI command to be scheduled * - * @param array $args + * @param string $args * @return array|\WP_Error */ function validate_args( $args ) { - $validated_args = array(); + // Strip `wp` if included + if ( 0 === stripos( $args, 'wp' ) ) { + $args = trim( substr( $args, 2 ) ); + } + + // Block disallowed commands + $command = explode( ' ', $args ); + $command = array_shift( $command ); + if ( ! is_command_allowed( $command ) ) { + return new \WP_Error( "$command not allowed" ); + } - // TODO: validate - // TODO: strip leading "wp" - // TODO: check first positional argument against `is_command_allowed()` + // Don't worry about the user WP-CLI runs as + if ( false === stripos( $args, '--allow-root' ) ) { + $args .= ' --allow-root'; + } - $validated_args['command'] = $args; + // TODO: validate further - if ( empty( $validated_args ) ) { - return new \WP_Error( 'Arguments could not be parsed for validation.' ); + // Nothing to run + if ( empty( $args ) ) { + return new \WP_Error( 'Invalid command provided' ); } - return $validated_args; + return $args; } diff --git a/includes/run.php b/includes/run.php index 95d6ca4..a4af0be 100644 --- a/includes/run.php +++ b/includes/run.php @@ -5,17 +5,40 @@ namespace Automattic\WP\WP_CLI_Cron_Control_Offload; /** * Intended for non-interactive use, so all output ends up in the error log * - * @param array $args + * @param string $command * @return null */ -function run_event( $args ) { +function run_event( $command ) { if ( ! defined( 'WP_CLI' ) || ! \WP_CLI ) { // TODO: reschedule at least once or twice - trigger_error( 'Attempted to run event without WP-CLI loaded. ' . var_export( $args, true ), E_USER_WARNING ); - return false; + trigger_error( 'Attempted to run event without WP-CLI loaded. (' . var_export( $command, true ) . ')', E_USER_WARNING ); + return; } - // TODO: run event, sending output to error log - trigger_error( var_export( $args, true ), E_USER_NOTICE ); + if ( ! validate_args( $command ) ) { + trigger_error( 'Attempted to run blocked WP-CLI command. (' . var_export( $command, true ) . ')', E_USER_WARNING ); + return; + } + + // TODO: time event execution + + $output = \WP_CLI::runcommand( $command, array( + 'return' => 'all', + ) ); + + // Command failed + if ( ! is_object( $output ) || is_wp_error( $output ) ) { + trigger_error( 'WP-CLI command failed. (' . var_export( $command, true ) . ')', E_USER_WARNING ); + trigger_error( var_export( $output, true ), E_USER_WARNING ); + return; + } + + // On success, reformat response for logging + $output->command = $command; + + $output = var_export( $output, true ); + $output = ACTION . ":\n{$output}"; + + error_log( $output ); } add_action( ACTION, __NAMESPACE__ . '\run_event' ); -- GitLab