Skip to content

Commit 1362cef

Browse files
committed
Account for possible recursive circular dependencies
1 parent 7a5c9b0 commit 1362cef

File tree

1 file changed

+21
-4
lines changed

1 file changed

+21
-4
lines changed

‎includes/admin/plugins.php‎

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -157,10 +157,16 @@ function perflab_render_plugins_ui() {
157157
* @since n.e.x.t
158158
* @see perflab_install_and_activate_plugin()
159159
*
160-
* @param array{name: string, slug: string, short_description: string, requires_php: string|false, requires: string|false, requires_plugins: string[], version: string} $plugin_data Plugin data from the WordPress.org API.
160+
* @param array{name: string, slug: string, short_description: string, requires_php: string|false, requires: string|false, requires_plugins: string[], version: string} $plugin_data Plugin data from the WordPress.org API.
161+
* @param array<string, array{compatible_php: bool, compatible_wp: bool, can_install: bool, can_activate: bool, activated: bool, installed: bool}> $processed_plugin_availabilities Plugin availabilities already processed. This param is only used by recursive calls.
161162
* @return array{compatible_php: bool, compatible_wp: bool, can_install: bool, can_activate: bool, activated: bool, installed: bool} Availability.
162163
*/
163-
function perflab_get_plugin_availability( array $plugin_data ): array {
164+
function perflab_get_plugin_availability( array $plugin_data, array &$processed_plugin_availabilities = array() ): array {
165+
if ( array_key_exists( $plugin_data['slug'], $processed_plugin_availabilities ) ) {
166+
// Prevent infinite recursion by returning the previously-computed value.
167+
return $processed_plugin_availabilities[ $plugin_data['slug'] ];
168+
}
169+
164170
$availability = array(
165171
'compatible_php' => (
166172
! $plugin_data['requires_php'] ||
@@ -191,6 +197,9 @@ function perflab_get_plugin_availability( array $plugin_data ): array {
191197
: current_user_can( 'activate_plugins' )
192198
);
193199

200+
// Store pending availability before recursing.
201+
$processed_plugin_availabilities[ $plugin_data['slug'] ] = $availability;
202+
194203
foreach ( $plugin_data['requires_plugins'] as $requires_plugin ) {
195204
$dependency_plugin_data = perflab_query_plugin_info( $requires_plugin );
196205
if ( $dependency_plugin_data instanceof WP_Error ) {
@@ -203,6 +212,7 @@ function perflab_get_plugin_availability( array $plugin_data ): array {
203212
}
204213
}
205214

215+
$processed_plugin_availabilities[ $plugin_data['slug'] ] = $availability;
206216
return $availability;
207217
}
208218

@@ -214,10 +224,17 @@ function perflab_get_plugin_availability( array $plugin_data ): array {
214224
* @since n.e.x.t
215225
* @see perflab_get_plugin_availability()
216226
*
217-
* @param string $plugin_slug Plugin slug.
227+
* @param string $plugin_slug Plugin slug.
228+
* @param string[] $processed_plugins Slugs for plugins which have already been processed. This param is only used by recursive calls.
218229
* @return WP_Error|null WP_Error on failure.
219230
*/
220-
function perflab_install_and_activate_plugin( string $plugin_slug ): ?WP_Error {
231+
function perflab_install_and_activate_plugin( string $plugin_slug, array &$processed_plugins = array() ): ?WP_Error {
232+
if ( in_array( $plugin_slug, $processed_plugins, true ) ) {
233+
// Prevent infinite recursion from possible circular dependency.
234+
return null;
235+
}
236+
$processed_plugins[] = $plugin_slug;
237+
221238
$plugin_data = perflab_query_plugin_info( $plugin_slug );
222239
if ( $plugin_data instanceof WP_Error ) {
223240
return $plugin_data;

0 commit comments

Comments
 (0)