@@ -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