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
110 changes: 88 additions & 22 deletions assets/js/plugin-check-admin.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
( function ( data ) {
( function ( pluginCheck ) {
const checkItButton = document.getElementById( 'plugin-check__submit' );
const pluginsList = document.getElementById( 'plugin-check__plugins-dropdown' );

Expand All @@ -8,17 +8,37 @@
return;
}

checkItButton.addEventListener( 'click', (e) => {
checkItButton.addEventListener( 'click', ( e ) => {
e.preventDefault();

const pluginCheckData = new FormData();
getChecksToRun()
.then( runChecks )
.then(
( data ) => {
console.log( data.message );
}
)
.catch(
( error ) => {
console.error( error );
}
);
} );

/**
* Get the Checks to run.
*
* @since n.e.x.t
*/
function getChecksToRun() {
// Collect the data to pass along for generating a check results.
pluginCheckData.append( 'action', 'plugin_check_run_checks' );
pluginCheckData.append( 'nonce', data.nonce );
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' );

fetch(
return fetch(
ajaxurl,
{
method: 'POST',
Expand All @@ -31,35 +51,81 @@
return response.json();
}
)
.then( handleDataErrors )
.then(
( data ) => {
if ( ! data ) {
throw new Error( 'Response contains no data' );
if ( ! data.data || ! data.data.plugin || ! data.data.checks ) {
throw new Error( 'Plugin and Checks are missing from the response.' );
}

if ( ! data.success ) {
// // If not successful and no message in the response.
if ( ! data.data || ! data.data[0].message ) {
throw new Error( 'Response contains no data' );
}
return data.data;
}
);
}

// If not successful and there is a message in the response.
throw new Error( data.data[0].message );
}

/**
* Run Checks.
*
* @since n.e.x.t
*/
function runChecks( data ) {
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' );

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

// If the response is successful and there is a message in the response.
console.log( data.data.message );
return data.data;
}
)
.catch(
( error ) => { console.error( error ); }
);
}

} );
/**
* Handles any errors in the data returned from the response.
*
* @since n.e.x.t
*
* @param {Object} data The response data.
* @return {Object} The response data.
*/
function handleDataErrors( data ) {
if ( ! data ) {
throw new Error( 'Response contains no data' );
}

if ( ! data.success ) {
// If not successful and no message in the response.
if ( ! data.data || ! data.data[0].message ) {
throw new Error( 'Response contains no data' );
}

// If not successful and there is a message in the response.
throw new Error( data.data[0].message );
}

return data;
}

} )( PLUGIN_CHECK ); /* global PLUGIN_CHECK */
118 changes: 112 additions & 6 deletions includes/Admin/Admin_AJAX.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,10 @@
namespace WordPress\Plugin_Check\Admin;

use WP_Error;

use Exception;
use WordPress\Plugin_Check\Checker\Checks;
use WordPress\Plugin_Check\Checker\Runtime_Check;
use WordPress\Plugin_Check\Utilities\Plugin_Request_Utility;
/**
* Class to handle the Admin AJAX requests.
*
Expand All @@ -30,6 +33,7 @@ class Admin_AJAX {
* @since n.e.x.t
*/
public function add_hooks() {
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 @@ -43,24 +47,126 @@ public function get_nonce() {
}

/**
* Runs checks.
* Handles the AJAX request that returns the checks to run.
*
* @since n.e.x.t
*/
public function run_checks() {
$nonce = filter_input( INPUT_POST, 'nonce', FILTER_SANITIZE_STRING );
public function get_checks_to_run() {
// Verify the nonce before continuing.
$valid_nonce = $this->verify_nonce( filter_input( INPUT_POST, 'nonce', FILTER_SANITIZE_STRING ) );

if ( ! wp_verify_nonce( $nonce, self::NONCE_KEY ) ) {
if ( is_wp_error( $valid_nonce ) ) {
wp_send_json_error( $valid_nonce, 403 );
}

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

// Attempt to get the plugin basename based on the request.
try {
$plugin_basename = Plugin_Request_Utility::get_plugin_basename_from_input( $plugin );
} catch ( Exception $error ) {
wp_send_json_error(
new WP_Error( 'invalid-nonce', __( 'Invalid nonce', 'plugin-check' ) ),
new WP_Error( 'invalid-plugin', $error->getMessage() ),
403
);
}

$plugin_active = is_plugin_active( $plugin_basename );

// Create the checks instance.
$checks_instance = new Checks( WP_PLUGIN_DIR . '/' . $plugin_basename );
$all_checks = $checks_instance->get_checks();

// If specific checks are requested to run.
if ( ! empty( $checks ) ) {
// Get the check instances based on the requested checks.
$checks_to_run = array_intersect_key( $all_checks, array_flip( $checks ) );

// Return an error if at least 1 runtime check is requested to run against an inactive plugin.
if ( ! $plugin_active && $this->has_runtime_check( $checks_to_run ) ) {
wp_send_json_error(
new WP_Error(
'inactive-plugin',
__( 'Runtime checks cannot be run against inactive plugins.', 'plugin-check' )
),
403
);
}
} else {
// Run all checks for the plugin.
$checks_to_run = $all_checks;

// Only run static checks if the plugin is inactive.
if ( ! $plugin_active ) {
$checks_to_run = array_filter(
$checks_to_run,
function ( $check ) {
return ! $check instanceof Runtime_Check;
}
);
}
}

wp_send_json_success(
array(
'plugin' => $plugin,
'checks' => array_keys( $checks_to_run ),
)
);
}

/**
* Run checks.
*
* @since n.e.x.t
*/
public function run_checks() {
// 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 );
}

wp_send_json_success(
array(
'message' => __( 'Verified!', 'plugin-check' ),
)
);
}

/**
* Verify the nonce passed in the request.
*
* @since n.e.x.t
*
* @param string $nonce The request nonce passed.
* @return bool|WP_Error True if the nonce is valid. WP_Error if invalid.
*/
protected function verify_nonce( $nonce ) {
if ( ! wp_verify_nonce( $nonce, self::NONCE_KEY ) ) {
new WP_Error( 'invalid-nonce', __( 'Invalid nonce', 'plugin-check' ) );
}

return true;
}

/**
* Check for a Runtime_Check in a list of checks
*
* @since n.e.x.t
*
* @param array $checks An array of Check instances.
* @return bool True if a Runtime_Check exists in the array, false if not.
*/
protected function has_runtime_check( array $checks ) {
foreach ( $checks as $check ) {
if ( $check instanceof Runtime_Check ) {
return true;
}
}

return false;
}
}
2 changes: 1 addition & 1 deletion templates/admin-page.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
</h2>

<select id="plugin-check__plugins-dropdown" name="plugin_check_plugins">
<option><?php esc_html_e( 'Select Plugin', 'plugin-check' ); ?></option>
<option value=""><?php esc_html_e( 'Select Plugin', 'plugin-check' ); ?></option>
<?php foreach ( $available_plugins as $plugin_basename => $available_plugin ) { ?>
<option value="<?php echo esc_attr( $plugin_basename ); ?>"<?php selected( $selected_plugin_basename, $plugin_basename ); ?>>
<?php echo esc_html( $available_plugin['Name'] ); ?>
Expand Down
1 change: 1 addition & 0 deletions tests/Admin/Admin_AJAX_Tests.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ public function set_up() {
public function test_add_hooks() {
$this->admin_ajax->add_hooks();
$this->assertEquals( 10, has_action( 'wp_ajax_plugin_check_run_checks', array( $this->admin_ajax, 'run_checks' ) ) );
$this->assertEquals( 10, has_action( 'wp_ajax_plugin_check_get_checks_to_run', array( $this->admin_ajax, 'get_checks_to_run' ) ) );
}

public function test_get_nonce() {
Expand Down