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

// Return early if the elements cannot be found on the page.
if ( ! checkItButton || ! pluginsList ) {
console.error( 'Missing form elements on page' );
return;
}

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

const pluginCheckData = new FormData();

// Collect the data to pass along for generating a check results.
pluginCheckData.append( 'action', 'plugin_check_run_checks' );
pluginCheckData.append( 'nonce', data.nonce );
pluginCheckData.append( 'plugin', pluginsList.value );

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

if ( ! data.success ) {
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.

Before checking this, we should check whether data even is an object, particularly when removing the above response.ok check. If the response is empty, then this line here would cause a JS error.

Suggested change
if ( ! data.success ) {
if ( ! data ) {
throw new Error( 'Response is empty or does not contain valid JSON' );
}
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 );
}

// If the response is successful and there is no message in the response.
if ( ! data.data || ! data.data.message ) {
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 );
}
)
.catch(
( error ) => { console.error( error ); }
);

} );

} )( PLUGIN_CHECK ); /* global PLUGIN_CHECK */
66 changes: 66 additions & 0 deletions includes/Admin/Admin_AJAX.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
<?php
/**
* Class WordPress\Plugin_Check\Admin\Admin_AJAX
*
* @package plugin-check
*/

namespace WordPress\Plugin_Check\Admin;

use WP_Error;

/**
* Class to handle the Admin AJAX requests.
*
* @since n.e.x.t
*/
class Admin_AJAX {

/**
* Nonce key.
*
* @since n.e.x.t
* @var string
*/
const NONCE_KEY = 'plugin-check-run-checks';

/**
* Registers WordPress hooks for the Admin AJAX.
*
* @since n.e.x.t
*/
public function add_hooks() {
add_action( 'wp_ajax_plugin_check_run_checks', array( $this, 'run_checks' ) );
}

/**
* Creates and returns the nonce.
*
* @since n.e.x.t
*/
public function get_nonce() {
return wp_create_nonce( self::NONCE_KEY );
}

/**
* Runs checks.
*
* @since n.e.x.t
*/
public function run_checks() {
$nonce = filter_input( INPUT_POST, 'nonce', FILTER_SANITIZE_STRING );

if ( ! wp_verify_nonce( $nonce, self::NONCE_KEY ) ) {
wp_send_json_error(
new WP_Error( 'invalid-nonce', __( 'Invalid nonce', 'plugin-check' ) ),
403
);
}

wp_send_json_success(
array(
'message' => __( 'Verified!', 'plugin-check' ),
)
);
}
}
67 changes: 62 additions & 5 deletions includes/Admin/Admin_Page.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,28 +15,87 @@
class Admin_Page {

/**
* Initializes hooks.
* Admin AJAX class instance.
*
* @since n.e.x.t
* @var Admin_AJAX
*/
protected $admin_ajax;

/**
* Constructor.
*
* @since n.e.x.t
*/
public function __construct() {
$this->admin_ajax = new Admin_AJAX();
}

/**
* Registers WordPress hooks for the admin page.
*
* @since n.e.x.t
*/
public function add_hooks() {
add_action( 'admin_menu', array( $this, 'add_page' ) );
add_filter( 'plugin_action_links', array( $this, 'filter_plugin_action_links' ), 10, 2 );

$this->admin_ajax->add_hooks();
}

/**
* Registers the admin page under the tools menu.
*
* @since n.e.x.t
*
* @return string The hook identifier for the admin page.
*/
public function add_page() {
add_management_page(
$hook = add_management_page(
__( 'Plugin Check', 'plugin-check' ),
__( 'Plugin Check', 'plugin-check' ),
'activate_plugins',
'plugin-check',
array( $this, 'render_page' )
);

add_action( "load-{$hook}", array( $this, 'initialize_page' ) );
Comment thread
felixarntz marked this conversation as resolved.

return $hook;
}

/**
* Initializes page hooks.
*
* @since n.e.x.t
*/
public function initialize_page() {
add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_scripts' ) );
}

/**
* Loads the check's script.
*
* @since n.e.x.t
*/
public function enqueue_scripts() {
wp_enqueue_script(
'plugin-check-admin',
WP_PLUGIN_CHECK_PLUGIN_DIR_URL . 'assets/js/plugin-check-admin.js',
array(),
WP_PLUGIN_CHECK_VERSION,
true
);

wp_add_inline_script(
'plugin-check-admin',
'const PLUGIN_CHECK = ' . json_encode(
array(
'nonce' => $this->admin_ajax->get_nonce(),
)
),
'before'
);
}

/**
Expand All @@ -63,7 +122,7 @@ private function get_available_plugins() {
}

/**
* Render the "Plugin Check" page.
* Renders the "Plugin Check" page.
*
* @since n.e.x.t
*/
Expand All @@ -85,9 +144,7 @@ public function render_page() {
* @return array The modified list of actions.
*/
public function filter_plugin_action_links( $actions, $plugin_file ) {

if ( current_user_can( 'activate_plugins' ) ) {

$actions[] = sprintf(
'<a href="%1$s">%2$s</a>',
esc_url( admin_url() . 'tools.php?page=plugin-check&plugin=' . $plugin_file ),
Expand Down
1 change: 1 addition & 0 deletions plugin-check.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
define( 'WP_PLUGIN_CHECK_MINIMUM_PHP', '5.6' );
define( 'WP_PLUGIN_CHECK_MAIN_FILE', __FILE__ );
define( 'WP_PLUGIN_CHECK_PLUGIN_DIR_PATH', plugin_dir_path( WP_PLUGIN_CHECK_MAIN_FILE ) );
define( 'WP_PLUGIN_CHECK_PLUGIN_DIR_URL', plugin_dir_url( WP_PLUGIN_CHECK_MAIN_FILE ) );

/**
* Checks basic requirements and loads the plugin.
Expand Down
6 changes: 3 additions & 3 deletions templates/admin-page.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,12 @@

<form>
<h2>
<label class="title" for="plugin-check__plugins">
<label class="title" for="plugin-check__plugins-dropdown">
<?php esc_html_e( 'Check the Plugin', 'plugin-check' ); ?>
</label>
</h2>

<select id="plugin-check__plugins" name="plugin_check_plugins">
<select id="plugin-check__plugins-dropdown" name="plugin_check_plugins">
<option><?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 ); ?>>
Expand All @@ -31,7 +31,7 @@
<?php } ?>
</select>

<input type="submit" value="<?php esc_attr_e( 'Check it!', 'plugin-check' ); ?>" />
<input type="submit" value="<?php esc_attr_e( 'Check it!', 'plugin-check' ); ?>" id="plugin-check__submit" class="button button-primary" />
</form>

<?php } else { ?>
Expand Down
32 changes: 32 additions & 0 deletions tests/Admin/Admin_AJAX_Tests.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<?php
/**
* Tests for the Admin_AJAX class.
*
* @package plugin-check
*/

namespace Admin;

use WordPress\Plugin_Check\Admin\Admin_AJAX;
use WP_UnitTestCase;

class Admin_AJAX_Tests extends WP_UnitTestCase {

protected $admin_ajax;

public function set_up() {
parent::set_up();
$this->admin_ajax = new Admin_AJAX();
}

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' ) ) );
}

public function test_get_nonce() {
$this->assertNotFalse(
wp_verify_nonce( $this->admin_ajax->get_nonce(), Admin_AJAX::NONCE_KEY )
);
}
}
10 changes: 7 additions & 3 deletions tests/Admin/Admin_Page_Tests.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
namespace Admin;

use WordPress\Plugin_Check\Admin\Admin_Page;
use WP_Object_Cache;
use WP_UnitTestCase;

class Admin_Page_Tests extends WP_UnitTestCase {
Expand Down Expand Up @@ -40,14 +39,19 @@ public function test_add_page() {
wp_set_current_user( $admin_user );
set_current_screen( 'dashboard' );

$this->admin_page->add_page();

$page_hook = $this->admin_page->add_page();
$parent_pages = $_parent_pages;

set_current_screen( $current_screen );

$this->assertArrayHasKey( 'plugin-check', $parent_pages );
$this->assertEquals( 'tools.php', $parent_pages['plugin-check'] );
Comment thread
felixarntz marked this conversation as resolved.
$this->assertNotFalse( has_action( "load-{$page_hook}", array( $this->admin_page, 'initialize_page' ) ) );
}

public function test_initialize_page() {
$this->admin_page->initialize_page();
$this->assertEquals( 10, has_action( 'admin_enqueue_scripts', array( $this->admin_page, 'enqueue_scripts' ) ) );
}

public function test_render_page() {
Expand Down