-
Notifications
You must be signed in to change notification settings - Fork 101
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Use a single WordPress.org API request to get information for all plugins #1562
Use a single WordPress.org API request to get information for all plugins #1562
Conversation
The following accounts have interacted with this PR and/or linked issues. I will continue to update these lists as activity occurs. You can also manually ask me to refresh this list by adding the If you're merging code through a pull request on GitHub, copy and paste the following into the bottom of the merge commit message.
To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook. |
Co-authored-by: Weston Ruter <westonruter@google.com>
'download_link', | ||
'version', // Needed by install_plugin_install_status(). | ||
); | ||
$request = wp_remote_get( 'https://api.wordpress.org/plugins/info/1.2/?action=query_plugins&request[author]=wordpressdotorg&request[tag]=performance&request[per_page]=100' ); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why not use plugins_api()
here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@westonruter Thanks for reviewing this PR. I have not used plugins_api()
because this does not support passing multiple specific slugs (which would be ideal) . Please let me know if I am missing anything.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
plugins_api()
is a wrapper for any API calls to https://api.wordpress.org/plugins/
, so you can use it here too. It's only the API itself that doesn't support passing multiple specific slugs, but we're not doing that here anyway.
You can call the plugins_api()
function with the query_plugins
action and provide the relevant request arguments.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This seems to work fine:
$response = plugins_api(
'query_plugins',
array(
'author' => 'wordpressdotorg',
'tag' => 'performance',
'per_page' => 100,
)
);
I can see that $response->plugins
is populated as expected.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@felixarntz @westonruter Thanks for the feedback, I have implemented the same.
if ( is_wp_error( $request ) ) { | ||
return new WP_Error( 'api_error', __( 'Failed to retrieve plugins data from WordPress.org API.', 'default' ) ); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ideally the error being returned would be passed through.
This string isn't actually part of core, right? So default
can't be used.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have corrected the same, please check.
|
||
if ( is_wp_error( $plugin ) ) { | ||
return $plugin; | ||
if ( is_wp_error( $request ) ) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A better variable name would be $response
, right? But I think plugins_api()
should be used instead in any case.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@westonruter I have corrected the same please check.
$data = json_decode( $body, true ); | ||
|
||
if ( ! isset( $data['plugins'] ) || ! is_array( $data['plugins'] ) ) { | ||
return new WP_Error( 'no_plugins', __( 'No plugins found in the API response.', 'default' ) ); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Again, is this string actually found in core? If not, then default
cannot be used.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@westonruter This has been fixed.
Co-authored-by: Felix Arntz <flixos90@gmail.com>
'download_link', | ||
'version', // Needed by install_plugin_install_status(). | ||
); | ||
if ( is_array( $plugins ) && isset( $plugins[ $plugin_slug ] ) ) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The second check here is problematic. We can't check that in the same clause, otherwise a missing plugin will lead to endless re-issuing of the API request and bypassing the cache.
If the cache data is an array, we know it's a cache hit. So then we need to check on that data if the $plugin_slug
is not set, and if not return the same error as below.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@felixarntz I have implemented this, could you please take a look.
@westonruter @felixarntz I have implemented the feedbacks, could you please take a look and share your valuable feedback on this. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Minor point in comment styles
} | ||
|
||
if ( is_object( $plugin ) ) { | ||
$plugin = (array) $plugin; | ||
/* Check if the response contains plugins. */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
/* Check if the response contains plugins. */ | |
// Check if the response contains plugins. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@westonruter Thanks for the feedback, I have implemented this one.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@narenin This looks almost good to go. A few last notes.
Co-authored-by: Weston Ruter <westonruter@google.com>
// Ensure the 'requires_plugins' is always an array. | ||
if ( ! isset( $plugin_info['requires_plugins'] ) || ! is_array( $plugin_info['requires_plugins'] ) ) { | ||
$plugin_info['requires_plugins'] = array(); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is this code needed? Right below the if $plugin_info['requires_plugins']
is not set, then it is set to false
, which will then never occur. Apparently this if
statement could be removed?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
$plugins = array(); | ||
foreach ( $response->plugins as $plugin_data ) { | ||
$plugin_info = wp_array_slice_assoc( $plugin_data, $fields ); | ||
|
||
// Ensure the 'requires_plugins' is always an array. | ||
if ( ! isset( $plugin_info['requires_plugins'] ) || ! is_array( $plugin_info['requires_plugins'] ) ) { | ||
$plugin_info['requires_plugins'] = array(); | ||
} | ||
|
||
// 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 ); | ||
// Ensure 'requires' and 'requires_php' are either strings or false. | ||
$plugin_info['requires'] = isset( $plugin_info['requires'] ) ? $plugin_info['requires'] : false; | ||
$plugin_info['requires_php'] = isset( $plugin_info['requires_php'] ) ? $plugin_info['requires_php'] : false; | ||
|
||
set_transient( 'perflab_plugin_info_' . $plugin_slug, $plugin, HOUR_IN_SECONDS ); | ||
$plugins[ $plugin_data['slug'] ] = $plugin_info; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This would be the equivalent of the existing code:
$plugins = array();
foreach ( $response->plugins as $plugin_data ) {
$plugins[ $plugin_data['slug'] ] = wp_array_slice_assoc( $plugin_data, $fields );
}
I'm curious why the additional requires
and requires_php
checks are now present?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
Co-authored-by: Weston Ruter <westonruter@google.com>
Co-authored-by: Weston Ruter <westonruter@google.com>
@westonruter thanks for the suggestions, I have implemented them, please take a look. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@narenin Thank you for the PR, this looks great!
Thanks @westonruter @felixarntz for your continuous feedback and support. |
Summary
In this PR we have implemented a single
WordPress.org API
request to get plugin information because currently, the Performance features screen makes individual plugin_information queries to the WordPress.org API, which is rather inefficient, especially the more plugins we have.https://api.wordpress.org/plugins/info/1.2/?action=query_plugins&request[author]=wordpressdotorg&request[tag]=performance&request[per_page]=100
Fixes #1542
Relevant technical choices