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
194 changes: 187 additions & 7 deletions admin/load.php
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,12 @@ function perflab_load_modules_page( $modules = null, $focus_areas = null ) {
// Handle script enqueuing for settings page.
add_action( 'admin_enqueue_scripts', 'perflab_enqueue_modules_page_scripts' );

// Handle style for settings page.
add_action( 'admin_head', 'perflab_print_modules_page_style' );

// Handle admin notices for settings page.
add_action( 'admin_notices', 'perflab_plugin_admin_notices' );

// Register sections for all focus areas, plus 'Other'.
if ( ! is_array( $focus_areas ) ) {
$focus_areas = perflab_get_focus_areas();
Expand Down Expand Up @@ -531,6 +537,31 @@ function perflab_enqueue_modules_page_scripts() {
wp_enqueue_style( 'thickbox' );

wp_enqueue_script( 'plugin-install' );

// Bail early if module is not active.
$get_active_modules_with_standalone_plugins = perflab_get_active_modules_with_standalone_plugins();
if ( empty( $get_active_modules_with_standalone_plugins ) ) {
return;
}

wp_enqueue_script(
'perflab-module-migration-notice',
plugin_dir_url( __FILE__ ) . 'perflab-module-migration-notice.js',
array( 'wp-i18n' ),
'1.0.0',
array(
'strategy' => 'defer',
)
);

wp_localize_script(
'perflab-module-migration-notice',
'perflab_module_migration_notice',
array(
'ajaxurl' => admin_url( 'admin-ajax.php' ),
'nonce' => wp_create_nonce( 'perflab-install-activate-plugins' ),
)
);
}

/**
Expand Down Expand Up @@ -609,18 +640,95 @@ function perflab_deactivate_plugin() {
}
add_action( 'admin_action_perflab_deactivate_plugin', 'perflab_deactivate_plugin' );

// WordPress AJAX action to handle the button click event.
add_action( 'wp_ajax_perflab_install_activate_standalone_plugins', 'perflab_install_activate_standalone_plugins_callback' );

/**
* Callback function hooked to admin_notices to render plugin activate/deactivate notices.
* Handles the standalone plugin install and activation via AJAX.
*
* @since n.e.x.t
*
* @return void
*/
function perflab_plugin_admin_notices() {
if ( 'settings_page_perflab-modules' !== get_current_screen()->id ) {
return;
function perflab_install_activate_standalone_plugins_callback() {
if ( ! wp_verify_nonce( $_REQUEST['nonce'], 'perflab-install-activate-plugins' ) ) {
$status['errorMessage'] = __( 'Invalid nonce: Please refresh and try again.', 'performance-lab' );
wp_send_json_error( $status );
}

if ( ! current_user_can( 'install_plugins' ) || ! current_user_can( 'activate_plugins' ) ) {
$status['errorMessage'] = __( 'Sorry, you are not allowed to manage plugins for this site. Please contact the administrator.', 'performance-lab' );
wp_send_json_error( $status );
}

require_once ABSPATH . 'wp-admin/includes/plugin-install.php';
require_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php';
require_once ABSPATH . 'wp-admin/includes/class-wp-ajax-upgrader-skin.php';

$plugins_to_activate = perflab_get_active_modules_with_standalone_plugins();
$modules = perflab_get_module_settings();
$plugins = get_plugins();
$status = array();

foreach ( $plugins_to_activate as $module_slug ) {

// Skip checking for already activated plugin.
if ( perflab_is_standalone_plugin_loaded( $module_slug ) ) {
continue;
}

$plugin_slug = basename( $module_slug );
$plugin_basename = $plugin_slug . '/load.php';
$api = perflab_query_plugin_info( $plugin_slug );

// Return early if plugin API return an error.
if ( ! $api ) {
$status['errorMessage'] = html_entity_decode( __( 'An unexpected error occurred. Something may be wrong with WordPress.org or this server’s configuration.', 'performance-lab' ), ENT_QUOTES );
wp_send_json_error( $status );
}

if ( ! $plugin_slug ) {
$status['errorMessage'] = __( 'Invalid plugin.', 'performance-lab' );
wp_send_json_error( $status );
}

// Install the plugin if it is not installed yet.
if ( ! isset( $plugins[ $plugin_basename ] ) ) {
// Replace new Plugin_Installer_Skin with new Quiet_Upgrader_Skin when output needs to be suppressed.
$skin = new WP_Ajax_Upgrader_Skin( array( 'api' => $api ) );
$upgrader = new Plugin_Upgrader( $skin );
$result = $upgrader->install( $api['download_link'] );

if ( is_wp_error( $result ) ) {
$status['errorMessage'] = $result->get_error_message();
wp_send_json_error( $status );
} elseif ( is_wp_error( $skin->result ) ) {
$status['errorMessage'] = $skin->result->get_error_message();
wp_send_json_error( $status );
} elseif ( $skin->get_errors()->has_errors() ) {
$status['errorMessage'] = $skin->get_error_messages();
wp_send_json_error( $status );
}
}

$result = activate_plugin( $plugin_basename );
if ( is_wp_error( $result ) ) {
$status['errorMessage'] = $result->get_error_message();
wp_send_json_error( $status );
}

// Deactivate legacy modules.
unset( $modules[ $module_slug ] );

update_option( PERFLAB_MODULES_SETTING, $modules );
}
wp_send_json_success( $status );
}

/**
* Callback function hooked to admin_notices to render admin notices on the plugin's screen.
*
* @since n.e.x.t
*/
function perflab_plugin_admin_notices() {
if ( isset( $_GET['activate'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
?>
<div class="notice notice-success is-dismissible">
Expand All @@ -634,5 +742,77 @@ function perflab_plugin_admin_notices() {
</div>
<?php
}

$active_modules_with_plugins = perflab_get_active_modules_with_standalone_plugins();

if ( ! empty( $active_modules_with_plugins ) ) {
$module_data = perflab_get_modules();
$available_module_names = array();
foreach ( $active_modules_with_plugins as $module_slug ) {
if ( isset( $module_data[ $module_slug ] ) && ! perflab_is_standalone_plugin_loaded( $module_slug ) ) {
$available_module_names[] = $module_data[ $module_slug ]['name'];
}
}

$modules_count = count( $available_module_names );
if ( $modules_count < 1 ) {
return;
}

if ( 1 === $modules_count ) {
$message = '<p>';
$message .= sprintf(
/* translators: Module name */
esc_html__( 'Your site is using the "%s" module which will be removed in the future in favor of its equivalent standalone plugin.', 'performance-lab' ),
esc_attr( $available_module_names[0] )
);
$message .= ' ';
$message .= esc_html__( 'Please click the following button to install and activate the relevant plugin in favor of the module. This will not impact any of the underlying functionality.', 'performance-lab' );
$message .= '</p>';
} else {
$message = '<p>';
$message .= esc_html__( 'Your site is using modules which will be removed in the future in favor of their equivalent standalone plugins.', 'performance-lab' );
$message .= ' ';
$message .= esc_html__( 'Please click the following button to install and activate the relevant plugins in favor of the modules. This will not impact any of the underlying functionality.', 'performance-lab' );
$message .= '</p>';
$message .= '<strong>' . esc_html__( 'Available standalone plugins:', 'performance-lab' ) . '</strong>';
$message .= '<ol>';
foreach ( $available_module_names as $module_name ) {
$message .= sprintf( '<li>%s</li>', esc_html( $module_name ) );
}
$message .= '</ol>';
}

?>
<div class="notice notice-warning is-dismissible">
<?php echo wp_kses_post( $message ); ?>
<p class="perflab-button-wrapper">
<button type="button" class="button button-primary perflab-install-active-plugin">
<?php esc_html_e( 'Migrate legacy modules to standalone plugins', 'performance-lab' ); ?>
</button>
<span class="dashicons dashicons-update hidden"></span>
</p>
</div>
<?php
}
}

/**
* Callback function to handle admin inline style.
*
* @since n.e.x.t
*/
function perflab_print_modules_page_style() {
?>
<style type="text/css">
.perflab-button-wrapper {
display: flex;
align-items: center;
}
.perflab-button-wrapper span {
animation: rotation 2s infinite linear;
margin-left: 5px;
}
</style>
<?php
}
add_action( 'admin_notices', 'perflab_plugin_admin_notices' );
50 changes: 50 additions & 0 deletions admin/perflab-module-migration-notice.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
( function ( document ) {
document.addEventListener( 'DOMContentLoaded', function () {
document.addEventListener( 'click', function ( event ) {
if (
event.target.classList.contains(
'perflab-install-active-plugin'
)
) {
const target = event.target;
target.parentElement
.querySelector( 'span' )
.classList.remove( 'hidden' );

const data = new FormData();
data.append(
'action',
'perflab_install_activate_standalone_plugins'
);
data.append( 'nonce', perflab_module_migration_notice.nonce );

fetch( perflab_module_migration_notice.ajaxurl, {
method: 'POST',
credentials: 'same-origin',
body: data,
} )
.then( function ( response ) {
if ( ! response.ok ) {
throw new Error(
wp.i18n.__( 'Network response was not ok.', 'performance-lab' )
);
}
return response.json();
} )
.then( function ( result ) {
target.parentElement
.querySelector( 'span' )
.classList.add( 'hidden' );
if ( ! result.success ) {
alert( result.data.errorMessage );
}
window.location.reload();
} )
.catch( function ( error ) {
alert( error.errorMessage );
window.location.reload();
} );
}
} );
} );
} )( document );
17 changes: 17 additions & 0 deletions admin/plugins.php
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,23 @@ function perflab_get_standalone_plugins() {
);
}

/**
* Returns an array of standalone plugins with currently active modules.
*
* @since n.e.x.t
*
* @return string[]
*/
function perflab_get_active_modules_with_standalone_plugins() {
$modules = perflab_get_module_settings();
return array_filter(
array_keys( perflab_get_standalone_plugins_constants() ),
static function ( $module ) use ( $modules ) {
return ! empty( $modules[ $module ] ) && $modules[ $module ]['enabled'];
}
);
}

/**
* Renders plugin UI for managing standalone plugins within PL Settings screen.
*
Expand Down