From 103161adfbbe0ac0523232b183161818ffb37bf4 Mon Sep 17 00:00:00 2001 From: Weston Ruter Date: Tue, 23 Apr 2024 11:39:21 -0700 Subject: [PATCH 01/10] Avoid passing incomplete data to perflab_render_plugin_card() --- includes/admin/plugins.php | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/includes/admin/plugins.php b/includes/admin/plugins.php index 1721cf4192..3ed57d22ee 100644 --- a/includes/admin/plugins.php +++ b/includes/admin/plugins.php @@ -74,13 +74,23 @@ function perflab_render_plugins_ui() { $experimental_plugins = array(); foreach ( perflab_get_standalone_plugin_data() as $plugin_slug => $plugin_data ) { + $api_data = perflab_query_plugin_info( $plugin_slug ); // Data from wordpress.org. + + // Skip if the plugin is not on WordPress.org or there was a network error. + if ( ! $api_data ) { + continue; + } + $plugin_data = array_merge( + array( + 'experimental' => false, + ), $plugin_data, // Data defined within Performance Lab. - perflab_query_plugin_info( $plugin_slug ) // Data from wordpress.org. + $api_data ); // Separate experimental plugins so that they're displayed after non-experimental plugins. - if ( isset( $plugin_data['experimental'] ) && $plugin_data['experimental'] ) { + if ( $plugin_data['experimental'] ) { $experimental_plugins[ $plugin_slug ] = $plugin_data; } else { $plugins[ $plugin_slug ] = $plugin_data; @@ -125,13 +135,9 @@ function perflab_render_plugins_ui() { * @see WP_Plugin_Install_List_Table::display_rows() * @link https://github.com/WordPress/wordpress-develop/blob/0b8ca16ea3bd9722bd1a38f8ab68901506b1a0e7/src/wp-admin/includes/class-wp-plugin-install-list-table.php#L467-L830 * - * @param array $plugin_data Plugin data from the WordPress.org API. + * @param array{name: string, slug: string, short_description: string, requires_php: ?string, requires: ?string, version: string, experimental: bool} $plugin_data Plugin data augmenting data from the WordPress.org API. */ function perflab_render_plugin_card( array $plugin_data ) { - // If no plugin data is returned, return. - if ( empty( $plugin_data ) ) { - return; - } // Remove any HTML from the description. $description = wp_strip_all_tags( $plugin_data['short_description'] ); @@ -193,7 +199,7 @@ function perflab_render_plugin_card( array $plugin_data ) { ); } - if ( isset( $plugin_data['slug'] ) && current_user_can( 'install_plugins' ) ) { + if ( current_user_can( 'install_plugins' ) ) { $title_link_attr = ' class="thickbox open-plugin-details-modal"'; $details_link = esc_url_raw( add_query_arg( From 1e4c0800106013804c16c212c249aa9bc4372067 Mon Sep 17 00:00:00 2001 From: Weston Ruter Date: Tue, 23 Apr 2024 11:40:02 -0700 Subject: [PATCH 02/10] Improve readability of PHP templating and remove needless checks --- includes/admin/plugins.php | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/includes/admin/plugins.php b/includes/admin/plugins.php index 3ed57d22ee..5e51577d57 100644 --- a/includes/admin/plugins.php +++ b/includes/admin/plugins.php @@ -305,23 +305,19 @@ function perflab_render_plugin_card( array $plugin_data ) { > - + - +

From e7db5ac8e121648e22d8fb4a8b66bc35f81f78e1 Mon Sep 17 00:00:00 2001 From: Weston Ruter Date: Tue, 23 Apr 2024 12:07:43 -0700 Subject: [PATCH 03/10] Show error when failed to query WordPress.org --- includes/admin/plugins.php | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/includes/admin/plugins.php b/includes/admin/plugins.php index 5e51577d57..6b1030d477 100644 --- a/includes/admin/plugins.php +++ b/includes/admin/plugins.php @@ -15,7 +15,7 @@ * @since 2.8.0 * * @param string $plugin_slug The string identifier for the plugin in questions slug. - * @return array Array of plugin data, or empty if none/error. + * @return array|WP_Error Array of plugin data or WP_Error if failed. */ function perflab_query_plugin_info( string $plugin_slug ) { $plugin = get_transient( 'perflab_plugin_info_' . $plugin_slug ); @@ -36,7 +36,7 @@ function perflab_query_plugin_info( string $plugin_slug ) { ); if ( is_wp_error( $plugin ) ) { - return array(); + return $plugin; } if ( is_object( $plugin ) ) { @@ -77,7 +77,18 @@ function perflab_render_plugins_ui() { $api_data = perflab_query_plugin_info( $plugin_slug ); // Data from wordpress.org. // Skip if the plugin is not on WordPress.org or there was a network error. - if ( ! $api_data ) { + if ( $api_data instanceof WP_Error ) { + wp_admin_notice( + esc_html( + sprintf( + /* translators: %s is the plugin slug */ + __( 'Failed to query WordPress.org Plugin Directory for plugin "%s".', 'performance-lab' ) . ' %s', + $plugin_slug, + $api_data->get_error_message() + ) + ), + array( 'type' => 'error' ) + ); continue; } From 7067d9eb8843c0d4e5f7d52728a0afd0b878de96 Mon Sep 17 00:00:00 2001 From: Weston Ruter Date: Tue, 23 Apr 2024 14:15:20 -0700 Subject: [PATCH 04/10] Only short-circuit if there are no plugins nor experimental plugins --- includes/admin/plugins.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/includes/admin/plugins.php b/includes/admin/plugins.php index 6b1030d477..1c56ba56d5 100644 --- a/includes/admin/plugins.php +++ b/includes/admin/plugins.php @@ -108,7 +108,7 @@ function perflab_render_plugins_ui() { } } - if ( empty( $plugins ) ) { + if ( ! $plugins && ! $experimental_plugins ) { return; } ?> From c3709063963668a6bc5fdf0c7c7c1b53865b6f61 Mon Sep 17 00:00:00 2001 From: Weston Ruter Date: Tue, 23 Apr 2024 15:12:31 -0700 Subject: [PATCH 05/10] Fix array shape for plugin API response --- includes/admin/plugins.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/includes/admin/plugins.php b/includes/admin/plugins.php index 1c56ba56d5..5be510e1e2 100644 --- a/includes/admin/plugins.php +++ b/includes/admin/plugins.php @@ -146,7 +146,7 @@ function perflab_render_plugins_ui() { * @see WP_Plugin_Install_List_Table::display_rows() * @link https://github.com/WordPress/wordpress-develop/blob/0b8ca16ea3bd9722bd1a38f8ab68901506b1a0e7/src/wp-admin/includes/class-wp-plugin-install-list-table.php#L467-L830 * - * @param array{name: string, slug: string, short_description: string, requires_php: ?string, requires: ?string, version: string, experimental: bool} $plugin_data Plugin data augmenting data from the WordPress.org API. + * @param array{name: string, slug: string, short_description: string, requires_php: string|false, requires: string|false, requires_plugins: string[], version: string, experimental: bool} $plugin_data Plugin data augmenting data from the WordPress.org API. */ function perflab_render_plugin_card( array $plugin_data ) { From d2086f881c5c86f0f1fa264ab4bbda5120b075b4 Mon Sep 17 00:00:00 2001 From: Weston Ruter Date: Tue, 23 Apr 2024 15:57:54 -0700 Subject: [PATCH 06/10] Request only the information needed from plugins API --- includes/admin/plugins.php | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/includes/admin/plugins.php b/includes/admin/plugins.php index 5be510e1e2..9c3f8569fb 100644 --- a/includes/admin/plugins.php +++ b/includes/admin/plugins.php @@ -15,7 +15,7 @@ * @since 2.8.0 * * @param string $plugin_slug The string identifier for the plugin in questions slug. - * @return array|WP_Error Array of plugin data or WP_Error if failed. + * @return array{name: string, slug: string, short_description: string, requires: string|false, requires_php: string|false, requires_plugins: string[], download_link: string}|WP_Error Array of plugin data or WP_Error if failed. */ function perflab_query_plugin_info( string $plugin_slug ) { $plugin = get_transient( 'perflab_plugin_info_' . $plugin_slug ); @@ -29,8 +29,13 @@ function perflab_query_plugin_info( string $plugin_slug ) { array( 'slug' => $plugin_slug, 'fields' => array( + 'name' => true, + 'slug' => true, 'short_description' => true, - 'icons' => true, + 'requires' => true, + 'requires_php' => true, + 'requires_plugins' => true, + 'download_link' => true, ), ) ); @@ -146,18 +151,15 @@ function perflab_render_plugins_ui() { * @see WP_Plugin_Install_List_Table::display_rows() * @link https://github.com/WordPress/wordpress-develop/blob/0b8ca16ea3bd9722bd1a38f8ab68901506b1a0e7/src/wp-admin/includes/class-wp-plugin-install-list-table.php#L467-L830 * - * @param array{name: string, slug: string, short_description: string, requires_php: string|false, requires: string|false, requires_plugins: string[], version: string, experimental: bool} $plugin_data Plugin data augmenting data from the WordPress.org API. + * @param array{name: string, slug: string, short_description: string, requires_php: string|false, requires: string|false, requires_plugins: string[], experimental: bool} $plugin_data Plugin data augmenting data from the WordPress.org API. */ function perflab_render_plugin_card( array $plugin_data ) { - // Remove any HTML from the description. + $name = wp_strip_all_tags( $plugin_data['name'] ); $description = wp_strip_all_tags( $plugin_data['short_description'] ); - $title = $plugin_data['name']; /** This filter is documented in wp-admin/includes/class-wp-plugin-install-list-table.php */ $description = apply_filters( 'plugin_install_description', $description, $plugin_data ); - $version = $plugin_data['version']; - $name = wp_strip_all_tags( $title . ' ' . $version ); $requires_php = isset( $plugin_data['requires_php'] ) ? $plugin_data['requires_php'] : null; $requires_wp = isset( $plugin_data['requires'] ) ? $plugin_data['requires'] : null; @@ -314,7 +316,7 @@ function perflab_render_plugin_card( array $plugin_data ) {

> - + From c85a7e4565b0e763a9172af16279aba22c007118 Mon Sep 17 00:00:00 2001 From: Weston Ruter Date: Tue, 23 Apr 2024 15:59:09 -0700 Subject: [PATCH 07/10] Fix showing error message when query fails in perflab_install_activate_plugin_callback() --- includes/admin/load.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/includes/admin/load.php b/includes/admin/load.php index d4a12608dc..c0405a7d9f 100644 --- a/includes/admin/load.php +++ b/includes/admin/load.php @@ -260,14 +260,14 @@ function perflab_install_activate_plugin_callback() { $api = perflab_query_plugin_info( $plugin_slug ); // Return early if plugin API returns an error. - if ( ! $api ) { + if ( $api instanceof WP_Error ) { wp_die( wp_kses( sprintf( /* translators: %s: Support forums URL. */ __( 'An unexpected error occurred. Something may be wrong with WordPress.org or this server’s configuration. If you continue to have problems, please try the support forums.', 'default' ), __( 'https://wordpress.org/support/forums/', 'default' ) - ), + ) . ' ' . $api->get_error_message(), array( 'a' => array( 'href' => true ) ) ) ); From 61c26edbe5036a46cd957a252df02be9ba017b9f Mon Sep 17 00:00:00 2001 From: Weston Ruter Date: Tue, 23 Apr 2024 16:22:52 -0700 Subject: [PATCH 08/10] Restore returning version from API request for install_plugin_install_status() --- includes/admin/plugins.php | 31 ++++++++++++++++++++----------- 1 file changed, 20 insertions(+), 11 deletions(-) diff --git a/includes/admin/plugins.php b/includes/admin/plugins.php index 9c3f8569fb..b9b46fa197 100644 --- a/includes/admin/plugins.php +++ b/includes/admin/plugins.php @@ -15,7 +15,7 @@ * @since 2.8.0 * * @param string $plugin_slug The string identifier for the plugin in questions slug. - * @return array{name: string, slug: string, short_description: string, requires: string|false, requires_php: string|false, requires_plugins: string[], download_link: string}|WP_Error Array of plugin data or WP_Error if failed. + * @return array{name: string, slug: string, short_description: string, requires: string|false, requires_php: string|false, requires_plugins: string[], download_link: string, version: string}|WP_Error Array of plugin data or WP_Error if failed. */ function perflab_query_plugin_info( string $plugin_slug ) { $plugin = get_transient( 'perflab_plugin_info_' . $plugin_slug ); @@ -24,19 +24,22 @@ function perflab_query_plugin_info( string $plugin_slug ) { return $plugin; } + $fields = array( + 'name', + 'slug', + 'short_description', + 'requires', + 'requires_php', + 'requires_plugins', + 'download_link', + 'version', // Needed by install_plugin_install_status(). + ); + $plugin = plugins_api( 'plugin_information', array( 'slug' => $plugin_slug, - 'fields' => array( - 'name' => true, - 'slug' => true, - 'short_description' => true, - 'requires' => true, - 'requires_php' => true, - 'requires_plugins' => true, - 'download_link' => true, - ), + 'fields' => array_fill_keys( $fields, true ), ) ); @@ -48,6 +51,12 @@ function perflab_query_plugin_info( string $plugin_slug ) { $plugin = (array) $plugin; } + // Only store what we need. + $plugin = wp_array_slice_assoc( $plugin, $fields ); + + // Make sure all fields default to false in case another plugin is modifying the response from WordPress.org via the plugins_api filter. + $plugin = array_merge( array_fill_keys( $fields, false ), $plugin ); + set_transient( 'perflab_plugin_info_' . $plugin_slug, $plugin, HOUR_IN_SECONDS ); return $plugin; @@ -151,7 +160,7 @@ function perflab_render_plugins_ui() { * @see WP_Plugin_Install_List_Table::display_rows() * @link https://github.com/WordPress/wordpress-develop/blob/0b8ca16ea3bd9722bd1a38f8ab68901506b1a0e7/src/wp-admin/includes/class-wp-plugin-install-list-table.php#L467-L830 * - * @param array{name: string, slug: string, short_description: string, requires_php: string|false, requires: string|false, requires_plugins: string[], experimental: bool} $plugin_data Plugin data augmenting data from the WordPress.org API. + * @param array{name: string, slug: string, short_description: string, requires_php: string|false, requires: string|false, requires_plugins: string[], version: string, experimental: bool} $plugin_data Plugin data augmenting data from the WordPress.org API. */ function perflab_render_plugin_card( array $plugin_data ) { From b1a2f02e4bf5909627b7383c0b25366182edede0 Mon Sep 17 00:00:00 2001 From: Weston Ruter Date: Tue, 23 Apr 2024 14:37:29 -0700 Subject: [PATCH 09/10] Use Kses to sanitize WP_Error message from activate_plugin() The error message may include markup such as is returned by validate_plugin_requirements(). --- includes/admin/load.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/includes/admin/load.php b/includes/admin/load.php index c0405a7d9f..e30c0062e0 100644 --- a/includes/admin/load.php +++ b/includes/admin/load.php @@ -304,7 +304,7 @@ function perflab_install_activate_plugin_callback() { $result = activate_plugin( $plugin_basename ); if ( is_wp_error( $result ) ) { - wp_die( esc_html( $result->get_error_message() ) ); + wp_die( wp_kses_post( $result->get_error_message() ) ); } $url = add_query_arg( From 2aa906b09b586888b1f2b59c2e793bd84e8e5ade Mon Sep 17 00:00:00 2001 From: Weston Ruter Date: Wed, 24 Apr 2024 06:16:13 -0700 Subject: [PATCH 10/10] Update translation string Co-authored-by: Pascal Birchler --- includes/admin/plugins.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/includes/admin/plugins.php b/includes/admin/plugins.php index b9b46fa197..52bc8f0709 100644 --- a/includes/admin/plugins.php +++ b/includes/admin/plugins.php @@ -95,8 +95,8 @@ function perflab_render_plugins_ui() { wp_admin_notice( esc_html( sprintf( - /* translators: %s is the plugin slug */ - __( 'Failed to query WordPress.org Plugin Directory for plugin "%s".', 'performance-lab' ) . ' %s', + /* translators: 1: plugin slug. 2: error message. */ + __( 'Failed to query WordPress.org Plugin Directory for plugin "%1$s". %2$s', 'performance-lab' ), $plugin_slug, $api_data->get_error_message() )