Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
89 changes: 86 additions & 3 deletions assets/js/plugin-check-admin.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@
e.preventDefault();

getChecksToRun()
.then( setUpEnvironment )
.then( runChecks )
.then( cleanUpEnvironment )
.then(
( data ) => {
console.log( data.message );
Expand All @@ -25,17 +27,95 @@
);
} );

/**
* Setup the runtime environment if needed.
*
* @since n.e.x.t
*/
function setUpEnvironment( data ) {
const pluginCheckData = new FormData();
pluginCheckData.append( 'nonce', pluginCheck.nonce );
pluginCheckData.append( 'plugin', data.plugin );
pluginCheckData.append( 'action', 'plugin_check_set_up_environment' );

for (var i = 0; i < data.checks.length; i++) {
pluginCheckData.append( 'checks[]', data.checks[ i ] );
}

return fetch(
ajaxurl,
{
method: 'POST',
credentials: 'same-origin',
body: pluginCheckData
}
)
.then(
( response ) => {
return response.json();
}
)
.then( handleDataErrors )
.then(
( data ) => {
if ( ! data.data || ! data.data.message ) {
throw new Error( 'Response contains no data.' );
}

console.log( data.data.message );

return data.data;
}
);
Comment thread
spacedmonkey marked this conversation as resolved.
}

/**
* Cleanup the runtime environment.
*
* @since n.e.x.t
*/
function cleanUpEnvironment( data ) {
const pluginCheckData = new FormData();
pluginCheckData.append( 'nonce', pluginCheck.nonce );
pluginCheckData.append( 'action', 'plugin_check_clean_up_environment' );

return fetch(
ajaxurl,
{
method: 'POST',
credentials: 'same-origin',
body: pluginCheckData
}
)
.then(
Comment thread
spacedmonkey marked this conversation as resolved.
( response ) => {
return response.json();
}
)
.then( handleDataErrors )
.then(
( data ) => {
if ( ! data.data || ! data.data.message ) {
throw new Error( 'Response contains no data.' );
}

console.log( data.data.message );

return data.data;
}
);
}


/**
* Get the Checks to run.
*
* @since n.e.x.t
*/
function getChecksToRun() {
// Collect the data to pass along for generating a check results.
const pluginCheckData = new FormData();
pluginCheckData.append( 'nonce', pluginCheck.nonce );
pluginCheckData.append( 'plugin', pluginsList.value );
pluginCheckData.append( 'checks', [] );
pluginCheckData.append( 'action', 'plugin_check_get_checks_to_run' );

return fetch(
Expand Down Expand Up @@ -73,9 +153,12 @@
const pluginCheckData = new FormData();
pluginCheckData.append( 'nonce', pluginCheck.nonce );
pluginCheckData.append( 'plugin', data.plugin );
pluginCheckData.append( 'checks', data.checks );
pluginCheckData.append( 'action', 'plugin_check_run_checks' );

for (var i = 0; i < data.checks.length; i++) {
pluginCheckData.append( 'checks[]', data.checks[ i ] );
}

return fetch(
ajaxurl,
{
Expand Down
102 changes: 100 additions & 2 deletions includes/Admin/Admin_AJAX.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@
use Exception;
use WordPress\Plugin_Check\Checker\AJAX_Runner;
use WordPress\Plugin_Check\Checker\Runtime_Check;
use WordPress\Plugin_Check\Checker\Runtime_Environment_Setup;
use WordPress\Plugin_Check\Utilities\Plugin_Request_Utility;

/**
* Class to handle the Admin AJAX requests.
*
Expand All @@ -33,6 +35,8 @@ class Admin_AJAX {
* @since n.e.x.t
*/
public function add_hooks() {
add_action( 'wp_ajax_plugin_check_clean_up_environment', array( $this, 'clean_up_environment' ) );
add_action( 'wp_ajax_plugin_check_set_up_environment', array( $this, 'set_up_environment' ) );
add_action( 'wp_ajax_plugin_check_get_checks_to_run', array( $this, 'get_checks_to_run' ) );
add_action( 'wp_ajax_plugin_check_run_checks', array( $this, 'run_checks' ) );
}
Expand All @@ -46,6 +50,100 @@ public function get_nonce() {
return wp_create_nonce( self::NONCE_KEY );
}

/**
* Handles the AJAX request to setup the runtime environment if needed.
*
* @since n.e.x.t
*/
public function set_up_environment() {
// Verify the nonce before continuing.
$valid_nonce = $this->verify_nonce( filter_input( INPUT_POST, 'nonce', FILTER_SANITIZE_STRING ) );
Comment thread
joemcgill marked this conversation as resolved.

if ( is_wp_error( $valid_nonce ) ) {
wp_send_json_error( $valid_nonce, 403 );
}
$runner = Plugin_Request_Utility::get_runner();

if ( is_null( $runner ) ) {
$runner = new AJAX_Runner();
}

// Make sure we are using the correct runner instance.
if ( ! ( $runner instanceof AJAX_Runner ) ) {
wp_send_json_error(
new WP_Error( 'invalid-runner', __( 'AJAX Runner was not initialized correctly.', 'plugin-check' ) ),
500
);
}

$checks = filter_input( INPUT_POST, 'checks', FILTER_DEFAULT, FILTER_FORCE_ARRAY );
$plugin = filter_input( INPUT_POST, 'plugin', FILTER_SANITIZE_STRING );

try {
$runner->set_check_slugs( $checks );
$runner->set_plugin( $plugin );
$checks_to_run = $runner->get_checks_to_run();
} catch ( Exception $error ) {
wp_send_json_error(
new WP_Error( 'invalid-request', $error->getMessage() ),
400
);
}

$message = __( 'No runtime checks, runtime environment was not setup.', 'plugin-check' );

if ( $this->has_runtime_check( $checks_to_run ) ) {
$runtime = new Runtime_Environment_Setup();
$runtime->setup();
$message = __( 'Runtime environment setup successful.', 'plugin-check' );
}

wp_send_json_success(
array(
'message' => $message,
'plugin' => $plugin,
'checks' => $checks,
Comment on lines +104 to +105
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see you're returning all these values from every AJAX endpoint just to be able to chain the AJAX requests in the JS file. I think that makes for a confusing architecture and requires us to include unnecessary data in the AJAX responses. No need to fix that here since it's already happening in existing code, but I think that will be something we should resolve as part of the architecture review.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @felixarntz I agree and let's tackle this as part of the architectural review.

)
);
}

/**
* Handles the AJAX request to cleanup the runtime environment.
*
* @since n.e.x.t
*/
public function clean_up_environment() {
global $wpdb;

// Verify the nonce before continuing.
$valid_nonce = $this->verify_nonce( filter_input( INPUT_POST, 'nonce', FILTER_SANITIZE_STRING ) );

if ( is_wp_error( $valid_nonce ) ) {
wp_send_json_error( $valid_nonce, 403 );
}

// Set the new prefix.
$old_prefix = $wpdb->set_prefix( 'wppc_' );

$message = __( 'Runtime environment was not prepared, cleanup was not run.', 'plugin-check' );

// Test if the runtime environment tables exist.
if ( 'wppc_posts' === $wpdb->get_var( "SHOW TABLES LIKE 'wppc_posts'" ) || defined( 'WP_PLUGIN_CHECK_OBJECT_CACHE_DROPIN_VERSION' ) ) {
$runtime = new Runtime_Environment_Setup();
$runtime->cleanup();
$message = __( 'Runtime environment cleanup successful.', 'plugin-check' );
}

// Restore the old prefix.
$wpdb->set_prefix( $old_prefix );

wp_send_json_success(
array(
'message' => $message,
)
);
}

/**
* Handles the AJAX request that returns the checks to run.
*
Expand All @@ -59,9 +157,9 @@ public function get_checks_to_run() {
wp_send_json_error( $valid_nonce, 403 );
}

$checks = filter_input( INPUT_POST, 'checks', FILTER_DEFAULT, FILTER_REQUIRE_ARRAY );
$checks = filter_input( INPUT_POST, 'checks', FILTER_DEFAULT, FILTER_FORCE_ARRAY );
$checks = is_null( $checks ) ? array() : $checks;
$plugin = filter_input( INPUT_POST, 'plugin', FILTER_SANITIZE_STRING );

$runner = Plugin_Request_Utility::get_runner();

if ( is_null( $runner ) ) {
Expand Down
9 changes: 1 addition & 8 deletions includes/Checker/AJAX_Runner.php
Original file line number Diff line number Diff line change
Expand Up @@ -70,13 +70,6 @@ protected function get_plugin_param() {
* @return array An array of Check slugs to run.
*/
protected function get_check_slugs_param() {
$checks = array();

if ( isset( $_REQUEST['checks'] ) ) {
// Checks are passed as a comma separated string.
$checks = wp_parse_list( $_REQUEST['checks'] );
}

return $checks;
return filter_input( INPUT_POST, 'checks', FILTER_DEFAULT, FILTER_FORCE_ARRAY );
Comment thread
spacedmonkey marked this conversation as resolved.
}
}
4 changes: 2 additions & 2 deletions includes/Checker/Abstract_Check_Runner.php
Original file line number Diff line number Diff line change
Expand Up @@ -195,12 +195,12 @@ public function run() {
}

/**
* Determines if any of the checks contains at least one runtime check.
* Determines if any of the checks are a runtime check.
*
* @since n.e.x.t
*
* @param array $checks An array of check instances to run.
* @return bool Returns true if one or more checks contains at least one runtime check.
* @return bool Returns true if one or more checks is a runtime check.
*/
protected function has_runtime_check( array $checks ) {
foreach ( $checks as $check ) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,14 @@ public function prepare() {
public function filter_active_plugins( $active_plugins ) {
if ( is_array( $active_plugins ) && in_array( $this->plugin_basename, $active_plugins, true ) ) {

$plugin_base_file = plugin_basename( WP_PLUGIN_CHECK_MAIN_FILE );
if ( defined( 'WP_PLUGIN_CHECK_MAIN_FILE' ) ) {
$plugin_check_file = WP_PLUGIN_CHECK_MAIN_FILE;
} else {
$plugins_dir = defined( 'WP_PLUGIN_DIR' ) ? WP_PLUGIN_DIR : WP_CONTENT_DIR . '/plugins';
Comment thread
spacedmonkey marked this conversation as resolved.
$plugin_check_file = $plugins_dir . '/plugin-check/plugin-check.php';
}

$plugin_base_file = plugin_basename( $plugin_check_file );

// If the plugin-check is the only available plugin then return that one only.
if ( $this->plugin_basename === $plugin_base_file ) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,14 @@ public function prepare() {

$cleanup_functions = array();

$use_minimal_theme_preparation = new Use_Minimal_Theme_Preparation( 'wp-empty-theme', WP_PLUGIN_CHECK_PLUGIN_DIR_PATH . '/test-content/themes' );
if ( ! defined( 'WP_PLUGIN_CHECK_PLUGIN_DIR_PATH' ) ) {
$plugins_dir = defined( 'WP_PLUGIN_DIR' ) ? WP_PLUGIN_DIR : WP_CONTENT_DIR . '/plugins';
$theme_folder = $plugins_dir . '/plugin-check/test-content/themes';
} else {
$theme_folder = WP_PLUGIN_CHECK_PLUGIN_DIR_PATH . 'test-content/themes';
}
Comment on lines +57 to +62
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.


$use_minimal_theme_preparation = new Use_Minimal_Theme_Preparation( 'wp-empty-theme', $theme_folder );
$cleanup_functions[] = $use_minimal_theme_preparation->prepare();

$force_single_plugin_preparation = new Force_Single_Plugin_Preparation( $this->check_context->basename() );
Expand Down
11 changes: 8 additions & 3 deletions includes/Utilities/Plugin_Request_Utility.php
Original file line number Diff line number Diff line change
Expand Up @@ -93,9 +93,14 @@ public static function initialize_runner() {

foreach ( $runners as $runner ) {
if ( $runner->is_plugin_check() ) {
// @TODO: Handle the cleanup function in later issue with shutdown action or method that returns cleanup functions.
static::$cleanup = $runner->prepare();
static::$runner = $runner;
add_action(
'muplugins_loaded',
function() use ( $runner ) {
static::$cleanup = $runner->prepare();
static::$runner = $runner;
}
);

break;
}
}
Expand Down
12 changes: 6 additions & 6 deletions tests/Checker/AJAX_Runner_Tests.php
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ 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';
$_REQUEST['checks'] = array( 'runtime_check' );

add_filter(
'wp_plugin_check_checks',
Expand Down Expand Up @@ -89,7 +89,7 @@ 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';
$_REQUEST['checks'] = array( 'empty_check' );

add_filter(
'wp_plugin_check_checks',
Expand Down Expand Up @@ -121,7 +121,7 @@ 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';
$_REQUEST['checks'] = array( 'empty_check' );

add_filter(
'wp_plugin_check_checks',
Expand All @@ -145,7 +145,7 @@ 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';
$_REQUEST['checks'] = array( 'error_check' );

add_filter(
'wp_plugin_check_checks',
Expand Down Expand Up @@ -174,7 +174,7 @@ public function test_runner_initialized_early_throws_plugin_basename_exception()
add_filter( 'wp_doing_ajax', '__return_true' );
$_REQUEST['action'] = 'plugin_check_run_checks';
$_REQUEST['plugin'] = 'plugin-check';
$_REQUEST['checks'] = 'empty_check';
$_REQUEST['checks'] = array( 'empty_check' );

$muplugins_loaded = $wp_actions['muplugins_loaded'];
unset( $wp_actions['muplugins_loaded'] );
Expand All @@ -198,7 +198,7 @@ public function test_runner_initialized_early_throws_checks_exception() {
add_filter( 'wp_doing_ajax', '__return_true' );
$_REQUEST['action'] = 'plugin_check_run_checks';
$_REQUEST['plugin'] = 'plugin-check';
$_REQUEST['checks'] = 'empty_check';
$_REQUEST['checks'] = array( 'empty_check' );

$muplugins_loaded = $wp_actions['muplugins_loaded'];
unset( $wp_actions['muplugins_loaded'] );
Expand Down
Loading