diff --git a/admin/load.php b/admin/load.php index 5976df25f8..dcf82340ae 100644 --- a/admin/load.php +++ b/admin/load.php @@ -53,6 +53,9 @@ function perflab_add_modules_page() { function perflab_load_modules_page( $modules = null, $focus_areas = null ) { global $wp_settings_sections; + // Handle script enqueuing for settings page. + add_action( 'admin_enqueue_scripts', 'perflab_enqueue_modules_page_scripts' ); + // Register sections for all focus areas, plus 'Other'. if ( ! is_array( $focus_areas ) ) { $focus_areas = perflab_get_focus_areas(); @@ -107,9 +110,11 @@ static function () use ( $module_slug, $module_data, $module_settings ) { function perflab_render_modules_page() { ?>
-

+ + +

-

+
@@ -503,3 +508,129 @@ function perflab_dismiss_wp_pointer_wrapper() { check_ajax_referer( 'dismiss_pointer' ); } add_action( 'wp_ajax_dismiss-wp-pointer', 'perflab_dismiss_wp_pointer_wrapper', 0 ); + +/** + * Callback function to handle admin scripts. + * + * @since n.e.x.t + */ +function perflab_enqueue_modules_page_scripts() { + wp_enqueue_script( 'updates' ); + + wp_localize_script( + 'updates', + '_wpUpdatesItemCounts', + array( + 'settings' => array( + 'totals' => wp_get_update_data(), + ), + ) + ); + + wp_enqueue_script( 'thickbox' ); + wp_enqueue_style( 'thickbox' ); +} + +/** + * Callback function hooked to admin_action_perflab_activate_plugin to handle plugin activation. + * + * @since n.e.x.t + */ +function perflab_activate_plugin() { + // Do not proceed if plugin query arg is not present. + if ( empty( $_GET['plugin'] ) ) { + return; + } + + // The plugin being activated. + $plugin = sanitize_text_field( wp_unslash( $_GET['plugin'] ) ); + + check_admin_referer( "perflab_activate_plugin_{$plugin}" ); + + if ( ! current_user_can( 'activate_plugin', $plugin ) ) { + wp_die( esc_html__( 'Sorry, you are not allowed to activate this plugin.', 'default' ) ); + } + + // Activate the plugin in question and return to prior screen. + $do_plugin_activation = activate_plugins( $plugin ); + $referer = wp_get_referer(); + if ( ! is_wp_error( $do_plugin_activation ) ) { + $referer = add_query_arg( + array( + 'activate' => true, + ), + $referer + ); + } + + if ( wp_safe_redirect( $referer ) ) { + exit; + } +} +add_action( 'admin_action_perflab_activate_plugin', 'perflab_activate_plugin' ); + +/** + * Callback function hooked to admin_action_perflab_deactivate_plugin to handle plugin deactivation. + * + * @since n.e.x.t + */ +function perflab_deactivate_plugin() { + // Do not proceed if plugin query arg is not present. + if ( empty( $_GET['plugin'] ) ) { + return; + } + + // The plugin being deactivated. + $plugin = sanitize_text_field( wp_unslash( $_GET['plugin'] ) ); + + check_admin_referer( "perflab_deactivate_plugin_{$plugin}" ); + + if ( ! current_user_can( 'deactivate_plugin', $plugin ) ) { + wp_die( esc_html__( 'Sorry, you are not allowed to deactivate this plugin.', 'default' ) ); + } + + // Deactivate the plugin in question and return to prior screen. + $do_plugin_deactivation = deactivate_plugins( $plugin ); + $referer = wp_get_referer(); + if ( ! is_wp_error( $do_plugin_deactivation ) ) { + $referer = add_query_arg( + array( + 'deactivate' => true, + ), + $referer + ); + } + + if ( wp_safe_redirect( $referer ) ) { + exit; + } +} +add_action( 'admin_action_perflab_deactivate_plugin', 'perflab_deactivate_plugin' ); + +/** + * Callback function hooked to admin_notices to render plugin activate/deactivate notices. + * + * @since n.e.x.t + * + * @return void + */ +function perflab_plugin_admin_notices() { + if ( 'settings_page_perflab-modules' !== get_current_screen()->id ) { + return; + } + + if ( isset( $_GET['activate'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended + ?> +
+

+
+ +
+

+
+ $plugin_slug, + 'fields' => array( + 'short_description' => true, + 'icons' => true, + ), + ) + ); + + if ( is_wp_error( $plugin ) ) { + return array(); + } + + if ( is_object( $plugin ) ) { + $plugin = (array) $plugin; + } + + return $plugin; +} + +/** + * Returns an array of WPP standalone plugins. + * + * @since n.e.x.t + * + * @return array of wpp standalone plugins as slugs. + */ +function perflab_get_standalone_plugins() { + return array( + 'webp-uploads', + 'performant-translations', + 'dominant-color-images', + ); +} + +/** + * Renders plugin UI for managing standalone plugins within PL Settings screen. + * + * @since n.e.x.t + */ +function perflab_render_plugins_ui() { + require_once ABSPATH . 'wp-admin/includes/plugin-install.php'; + require_once ABSPATH . 'wp-admin/includes/plugin.php'; + + $standalone_plugins = array(); + foreach ( perflab_get_standalone_plugins() as $managed_standalone_plugin_slug ) { + $standalone_plugins[ $managed_standalone_plugin_slug ] = array( + 'plugin_data' => perflab_query_plugin_info( $managed_standalone_plugin_slug ), + ); + } + + if ( empty( $standalone_plugins ) ) { + return; + } + ?> +
+

+

+
+ +
+

+
+ +
+
+ +
+
+
+ ' . sprintf( __( 'By %s', 'default' ), $author ) . ''; + } + + $requires_php = isset( $plugin_data['requires_php'] ) ? $plugin_data['requires_php'] : null; + $requires_wp = isset( $plugin_data['requires'] ) ? $plugin_data['requires'] : null; + + $compatible_php = is_php_version_compatible( $requires_php ); + $compatible_wp = is_wp_version_compatible( $requires_wp ); + $tested_wp = ( empty( $plugin_data['tested'] ) || version_compare( get_bloginfo( 'version' ), $plugin_data['tested'], '<=' ) ); + $action_links = array(); + + $status = install_plugin_install_status( $plugin_data ); + + switch ( $status['status'] ) { + case 'install': + if ( $status['url'] ) { + if ( $compatible_php && $compatible_wp && current_user_can( 'install_plugins' ) ) { + $action_links[] = sprintf( + '%s', + esc_attr( $plugin_data['slug'] ), + esc_url( $status['url'] ), + /* translators: %s: Plugin name and version. */ + esc_attr( sprintf( _x( 'Install %s now', 'plugin', 'default' ), $name ) ), + esc_attr( $name ), + esc_html__( 'Install Now', 'default' ) + ); + } else { + $action_links[] = sprintf( + '', + esc_html( _x( 'Cannot Install', 'plugin', 'default' ) ) + ); + } + } + break; + + case 'update_available': + case 'latest_installed': + case 'newer_installed': + if ( is_plugin_active( $status['file'] ) ) { + $action_links[] = sprintf( + '', + esc_html( _x( 'Active', 'plugin', 'default' ) ) + ); + if ( current_user_can( 'deactivate_plugin', $status['file'] ) ) { + global $page; + $s = isset( $_REQUEST['s'] ) ? $_REQUEST['s'] : ''; // phpcs:ignore WordPress.Security.NonceVerification.Recommended + $context = $status['status']; + + $action_links[] = sprintf( + '%s', + add_query_arg( + array( + '_wpnonce' => wp_create_nonce( 'perflab_deactivate_plugin_' . $status['file'] ), + 'action' => 'perflab_deactivate_plugin', + 'plugin' => $status['file'], + ), + network_admin_url( 'plugins.php' ) + ), + esc_attr( $plugin_data['slug'] ), + /* translators: %s: Plugin name. */ + esc_attr( sprintf( _x( 'Deactivate %s', 'plugin', 'default' ), $plugin_data['slug'] ) ), + esc_html__( 'Deactivate', 'default' ) + ); + } + } elseif ( current_user_can( 'activate_plugin', $status['file'] ) ) { + if ( $compatible_php && $compatible_wp ) { + $button_text = __( 'Activate', 'default' ); + /* translators: %s: Plugin name. */ + $button_label = _x( 'Activate %s', 'plugin', 'default' ); + $activate_url = add_query_arg( + array( + '_wpnonce' => wp_create_nonce( 'perflab_activate_plugin_' . $status['file'] ), + 'action' => 'perflab_activate_plugin', + 'plugin' => $status['file'], + ), + network_admin_url( 'plugins.php' ) + ); + + $action_links[] = sprintf( + '%3$s', + esc_url( $activate_url ), + esc_attr( sprintf( $button_label, $plugin_data['name'] ) ), + esc_html( $button_text ) + ); + } else { + $action_links[] = sprintf( + '', + esc_html( _x( 'Cannot Activate', 'plugin', 'default' ) ) + ); + } + } else { + $action_links[] = sprintf( + '', + esc_html( _x( 'Installed', 'plugin', 'default' ) ) + ); + } + break; + } + + $details_link = esc_url_raw( + add_query_arg( + array( + 'tab' => 'plugin-information', + 'plugin' => $plugin_data['slug'], + 'TB_iframe' => 'true', + 'width' => 600, + 'height' => 550, + ), + admin_url( 'plugin-install.php' ) + ) + ); + + $action_links[] = sprintf( + '%s', + esc_url( $details_link ), + /* translators: %s: Plugin name and version. */ + esc_attr( sprintf( __( 'More information about %s', 'default' ), $name ) ), + esc_attr( $name ), + esc_html__( 'More Details', 'default' ) + ); + + if ( ! empty( $plugin_data['icons']['svg'] ) ) { + $plugin_icon_url = $plugin_data['icons']['svg']; + } elseif ( ! empty( $plugin_data['icons']['2x'] ) ) { + $plugin_icon_url = $plugin_data['icons']['2x']; + } elseif ( ! empty( $plugin_data['icons']['1x'] ) ) { + $plugin_icon_url = $plugin_data['icons']['1x']; + } else { + $plugin_icon_url = $plugin_data['icons']['default']; + } + + /** This filter is documented in wp-admin/includes/class-wp-plugin-install-list-table.php */ + $action_links = apply_filters( 'plugin_install_action_links', $action_links, $plugin_data ); + + $last_updated_timestamp = strtotime( $plugin_data['last_updated'] ); + ?> +
+ '; + if ( ! $compatible_php && ! $compatible_wp ) { + echo '

' . esc_html_e( 'This plugin does not work with your versions of WordPress and PHP.', 'default' ) . '

'; + if ( current_user_can( 'update_core' ) && current_user_can( 'update_php' ) ) { + echo wp_kses_post( + /* translators: 1: URL to WordPress Updates screen, 2: URL to Update PHP page. */ + ' ' . __( 'Please update WordPress, and then learn more about updating PHP.', 'default' ), + esc_url( self_admin_url( 'update-core.php' ) ), + esc_url( wp_get_update_php_url() ) + ); + wp_update_php_annotation( '

', '

' ); + } elseif ( current_user_can( 'update_core' ) ) { + echo wp_kses_post( + /* translators: %s: URL to WordPress Updates screen. */ + ' ' . __( 'Please update WordPress.', 'default' ), + esc_url( self_admin_url( 'update-core.php' ) ) + ); + } elseif ( current_user_can( 'update_php' ) ) { + echo wp_kses_post( + /* translators: %s: URL to Update PHP page. */ + ' ' . __( 'Learn more about updating PHP.', 'default' ), + esc_url( wp_get_update_php_url() ) + ); + wp_update_php_annotation( '

', '

' ); + } + } elseif ( ! $compatible_wp ) { + esc_html_e( 'This plugin does not work with your version of WordPress.', 'default' ); + if ( current_user_can( 'update_core' ) ) { + echo wp_kses_post( + /* translators: %s: URL to WordPress Updates screen. */ + ' ' . __( 'Please update WordPress.', 'default' ), + esc_url( self_admin_url( 'update-core.php' ) ) + ); + } + } elseif ( ! $compatible_php ) { + esc_html_e( 'This plugin does not work with your version of PHP.', 'default' ); + if ( current_user_can( 'update_php' ) ) { + echo wp_kses_post( + /* translators: %s: URL to Update PHP page. */ + ' ' . __( 'Learn more about updating PHP.', 'default' ), + esc_url( wp_get_update_php_url() ) + ); + wp_update_php_annotation( '

', '

' ); + } + } + echo '
'; + } + ?> +
+
+

+ + + + +

+
+ +
+

+

+
+
+
+
+ $plugin_data['rating'], + 'type' => 'percent', + 'number' => $plugin_data['num_ratings'], + ) + ); + ?> + +
+
+ + +
+
+ = 1000000 ) { + $active_installs_millions = floor( $plugin_data['active_installs'] / 1000000 ); + $active_installs_text = sprintf( + /* translators: %s: Number of millions. */ + _nx( '%s+ Million', '%s+ Million', $active_installs_millions, 'Active plugin installations', 'default' ), + number_format_i18n( $active_installs_millions ) + ); + } elseif ( 0 === $plugin_data['active_installs'] ) { + $active_installs_text = _x( 'Less Than 10', 'Active plugin installations', 'default' ); + } else { + $active_installs_text = number_format_i18n( $plugin_data['active_installs'] ) . '+'; + } + /* translators: %s: Number of installations. */ + printf( esc_html__( '%s Active Installations', 'default' ), esc_html( $active_installs_text ) ); + ?> +
+
+ ' . esc_html__( 'Untested with your version of WordPress', 'default' ) . ''; + } elseif ( ! $compatible_wp ) { + echo '' . wp_kses_post( __( 'Incompatible with your version of WordPress', 'default' ) ) . ''; + } else { + echo '' . wp_kses_post( __( 'Compatible with your version of WordPress', 'default' ) ) . ''; + } + ?> +
+
+
+