diff --git a/includes/Checker/AJAX_Runner.php b/includes/Checker/AJAX_Runner.php new file mode 100644 index 000000000..eb46bc0df --- /dev/null +++ b/includes/Checker/AJAX_Runner.php @@ -0,0 +1,88 @@ +checks ) ) { + if ( ! isset( $_REQUEST['plugin'] ) ) { + throw new Exception( 'Invalid plugin slug: Plugin slug must not be empty.' ); + } + + // Get the plugin name from the AJAX request. + $plugin_file = Plugin_Request_Utility::get_plugin_basename_from_input( $_REQUEST['plugin'] ); + + $this->checks = new Checks( WP_PLUGIN_DIR . '/' . $plugin_file ); + } + + return $this->checks; + } + + /** + * Returns an array of Check slugs to run based on the request. + * + * @since n.e.x.t + * + * @return array An array of Check slugs to run. + */ + protected function get_check_slugs_to_run() { + $checks = array(); + + if ( isset( $_REQUEST['checks'] ) ) { + // Checks are passed as a comma separated string. + $checks = wp_parse_list( $_REQUEST['checks'] ); + } + + return $checks; + } +} diff --git a/includes/Checker/Abstract_Check_Runner.php b/includes/Checker/Abstract_Check_Runner.php index d3d44c6ce..b1762344a 100644 --- a/includes/Checker/Abstract_Check_Runner.php +++ b/includes/Checker/Abstract_Check_Runner.php @@ -30,7 +30,7 @@ abstract public function is_plugin_check(); * * @since n.e.x.t * - * @return Checks An instances of the Checks class. + * @return Checks An instance of the Checks class. */ abstract protected function get_checks_instance(); diff --git a/includes/Checker/CLI_Runner.php b/includes/Checker/CLI_Runner.php index d240ebf2c..a084b61ae 100644 --- a/includes/Checker/CLI_Runner.php +++ b/includes/Checker/CLI_Runner.php @@ -17,7 +17,7 @@ class CLI_Runner extends Abstract_Check_Runner { /** - * An instances of the Checks class. + * An instance of the Checks class. * * @since n.e.x.t * @var Checks @@ -29,7 +29,7 @@ class CLI_Runner extends Abstract_Check_Runner { * * @since n.e.x.t * - * @return bool + * @return bool Returns true if is an CLI request for the plugin check else false. */ public function is_plugin_check() { if ( empty( $_SERVER['argv'] ) || 3 > count( $_SERVER['argv'] ) ) { @@ -48,11 +48,11 @@ public function is_plugin_check() { } /** - * Retruns an instance of the Checks class. + * Creates and returns an instance of the Checks class based on the request. * * @since n.e.x.t * - * @return Checks + * @return Checks An instance of the Checks class. * * @throws Exception Thrown if the plugin main file cannot be found based on the CLI input. */ @@ -69,11 +69,11 @@ protected function get_checks_instance() { } /** - * Returns an array of Check instances to run. + * Returns an array of Check slugs to run based on the request. * * @since n.e.x.t * - * @return array An array of Check instances to run. + * @return array An array of Check slugs to run. */ protected function get_check_slugs_to_run() { $checks = array(); diff --git a/tests/Checker/AJAX_Runner_Tests.php b/tests/Checker/AJAX_Runner_Tests.php new file mode 100644 index 000000000..52a4160c3 --- /dev/null +++ b/tests/Checker/AJAX_Runner_Tests.php @@ -0,0 +1,153 @@ +assertTrue( $runner->is_plugin_check() ); + } + + public function test_is_plugin_check_returns_false() { + // Mock the AJAX request. + add_filter( 'wp_doing_ajax', '__return_true' ); + $_REQUEST['action'] = 'a_different_ajax_request'; + + $runner = new AJAX_Runner(); + + $this->assertFalse( $runner->is_plugin_check() ); + } + + public function test_is_plugin_check_returns_false_not_ajax() { + // Mock the AJAX request. + add_filter( 'wp_doing_ajax', '__return_false' ); + + $runner = new AJAX_Runner(); + + $this->assertFalse( $runner->is_plugin_check() ); + } + + public function test_prepare_with_runtime_check() { + add_filter( 'wp_doing_ajax', '__return_true' ); + $_REQUEST['action'] = 'plugin_check_run_checks'; + $_REQUEST['plugin'] = 'plugin-check'; + $_REQUEST['checks'] = 'runtime_check'; + + add_filter( + 'wp_plugin_check_checks', + function( $checks ) { + return array( + 'runtime_check' => new WordPress\Plugin_Check\Test_Data\Runtime_Check(), + ); + } + ); + + $runner = new AJAX_Runner(); + $cleanup = $runner->prepare(); + + $this->assertIsCallable( $cleanup ); + + // Assert the Universal_Runtume_Preparation was run. + $this->assertTrue( has_filter( 'option_active_plugins' ) ); + $this->assertTrue( has_filter( 'default_option_active_plugins' ) ); + $this->assertTrue( has_filter( 'stylesheet' ) ); + $this->assertTrue( has_filter( 'template' ) ); + $this->assertTrue( has_filter( 'pre_option_template' ) ); + $this->assertTrue( has_filter( 'pre_option_stylesheet' ) ); + $this->assertTrue( has_filter( 'pre_option_current_theme' ) ); + $this->assertTrue( has_filter( 'pre_option_template_root' ) ); + $this->assertTrue( has_filter( 'pre_option_stylesheet_root' ) ); + } + + public function test_prepare_with_static_check() { + add_filter( 'wp_doing_ajax', '__return_true' ); + $_REQUEST['action'] = 'plugin_check_run_checks'; + $_REQUEST['plugin'] = 'plugin-check'; + $_REQUEST['checks'] = 'empty_check'; + + add_filter( + 'wp_plugin_check_checks', + function( $checks ) { + return array( + 'empty_check' => new WordPress\Plugin_Check\Test_Data\Empty_Check(), + ); + } + ); + + $runner = new AJAX_Runner(); + $cleanup = $runner->prepare(); + + $this->assertIsCallable( $cleanup ); + + // Assert the Universal_Runtume_Preparation was not run. + $this->assertFalse( has_filter( 'option_active_plugins' ) ); + $this->assertFalse( has_filter( 'default_option_active_plugins' ) ); + $this->assertFalse( has_filter( 'stylesheet' ) ); + $this->assertFalse( has_filter( 'template' ) ); + $this->assertFalse( has_filter( 'pre_option_template' ) ); + $this->assertFalse( has_filter( 'pre_option_stylesheet' ) ); + $this->assertFalse( has_filter( 'pre_option_current_theme' ) ); + $this->assertFalse( has_filter( 'pre_option_template_root' ) ); + $this->assertFalse( has_filter( 'pre_option_stylesheet_root' ) ); + } + + public function test_run() { + add_filter( 'wp_doing_ajax', '__return_true' ); + $_REQUEST['action'] = 'plugin_check_run_checks'; + $_REQUEST['plugin'] = 'plugin-check'; + $_REQUEST['checks'] = 'empty_check'; + + add_filter( + 'wp_plugin_check_checks', + function( $checks ) { + return array( + 'empty_check' => new WordPress\Plugin_Check\Test_Data\Empty_Check(), + ); + } + ); + + $runner = new AJAX_Runner(); + $runner->prepare(); + $results = $runner->run(); + + $this->assertInstanceOf( Check_Result::class, $results ); + $this->assertEmpty( $results->get_warnings() ); + $this->assertEmpty( $results->get_errors() ); + } + + public function test_run_with_errors() { + add_filter( 'wp_doing_ajax', '__return_true' ); + $_REQUEST['action'] = 'plugin_check_run_checks'; + $_REQUEST['plugin'] = 'plugin-check'; + $_REQUEST['checks'] = 'error_check'; + + add_filter( + 'wp_plugin_check_checks', + function( $checks ) { + return array( + 'error_check' => new WordPress\Plugin_Check\Test_Data\Error_Check(), + ); + } + ); + + $runner = new AJAX_Runner(); + $runner->prepare(); + $results = $runner->run(); + + $this->assertInstanceOf( Check_Result::class, $results ); + $this->assertEmpty( $results->get_warnings() ); + $this->assertNotEmpty( $results->get_errors() ); + } +}