#57249 closed defect (bug) (invalid)
plugin_folder parameter in get_plugins returns empty array
Reported by: | antonynz | Owned by: | |
---|---|---|---|
Milestone: | Priority: | normal | |
Severity: | minor | Version: | 6.2 |
Component: | Plugins | Keywords: | |
Focuses: | Cc: |
Description
WordPress 2.6 added a caching mechanism for the get_plugins function. However this change would have stopped the plugin_folder parameter returning the desired result for a chosen plugin.
i.e get_plugins('classic-editor/classic-editor.php') returns empty when that plugin is installed.
Looking at the code, the wp_plugins data is added to the cache inside of an additional array, with the key matching the plugin_folder passed to the function:
$cache_plugins[ $plugin_folder ] = $wp_plugins;
When no plugin_folder is passed it will be set to "", and the plugins data will be nested inside of an empty key array.
Which means the parameter check earlier on wouldn't be able to check the nested array and only returns true if empty
if ( isset($cache_plugins[ $plugin_folder ]) ) return $cache_plugins[ $plugin_folder ];
This means the cache is probably inadvertently working, since leaving the plugin_parameter empty will match the empty parent array key of the cache i.e $cache_plugins[""] returns the cached array of the plugins.
This also means that anytime the parameter changes in the same request the cache will be bypassed, and the full function run as the parent key changes: eg on the same request:
get_plugins() - cached
get_plugins('test') - bypassed
get_plugins() - bypassed
get_plugins() - cached
As a fix I suggest removing the parent array of the cache and replacing:
$cache_plugins['plugin_folder'] = $wp_plugins;
with:
$cache_plugins = $wp_plugins;
And replacing the following the following:
if ( ! $cache_plugins = wp_cache_get('plugins', 'plugins') ) $cache_plugins = array();
with something similar to return the full cached results if the plugin_parameter is empty:
if ( ! $cache_plugins = wp_cache_get('plugins', 'plugins') ) { $cache_plugins = array(); } else if($plugin_folder == ""){ return $cache_plugins; }
Change History (3)
#2
in reply to:
↑ 1
;
follow-up:
↓ 3
@
22 months ago
- Resolution set to invalid
- Status changed from new to closed
Replying to petitphp:
Looking at usage in Core,
$plugin_folder
expect a relative path to a plugin folder :get_plugins('/classic-editor');
.
You're right. I should have looked further into the function. The documentation didn't have any specific examples and I had assumed it grabbed the cached version of all the plugin details based on the line below, and how the array keys were stored when all plugins were retrieved i.e (classic-editor/classic-editor.php):
if ( isset( $cache_plugins[ $plugin_folder ] ) ) {
return $cache_plugins[ $plugin_folder ];
}
get_plugins('/classic-editor'); does return the plugin details as expected (with the folder pruned from the array) so the returned array is different when a folder is added to the request, meaning any changes to the function would be difficult to implement.
wp_cache_flush(); get_plugins(); //miss cache get_plugins('/classic-editor'); //miss cache get_plugins(); //hit cache get_plugins(); //hit cache get_plugins('/classic-editor'); //hit cache
I can also replicate this. I had assumed it would clear the cached array but it just appends the new array each time so future duplicate requests return a cache hit.
This means plugins not in a directory (eg hello.php) would only be retrievable from requesting all plugins get_plugins(); ?
It's an unusual set up with the cache and didn't work how I initially expected but happy to mark this resolved.
#3
in reply to:
↑ 2
@
22 months ago
- Milestone Awaiting Review deleted
Thanks for the follow-up!
Replying to antonynz:
Looking at usage in Core,
$plugin_folder
expect a relative path to a plugin folder :get_plugins('/classic-editor');
.
You're right. I should have looked further into the function. The documentation didn't have any specific examples
Sounds like it might be a good idea to improve the function description and add an example or two, feel free to reopen the ticket if you have any suggestions to make the description more helpful.
Hi, Welcome back to WordPress Trac.
It doesn't seem to be the way the parameter
$plugin_folder
is intended to be used.Looking at usage in Core,
$plugin_folder
expect a relative path to a plugin folder :get_plugins('/classic-editor');
.This will only return plugin data for this plugin.
There might be ways to optimize further this function by refactoring how the cache is used. However, it should be done in a way that preserve the current array shape when for each case (for all plugins and for a specific plugin).
I couldn't reproduce the issue locally.
Doing multiple calls to
get_plugins
, the cache behaved as expected :