get_plugins(), 'must-use' => get_mu_plugins() ) as $kind => $plugins ) { foreach ( $plugins as $file => $data ) { $must_use = $kind === 'must-use'; $network_active = ! $must_use && is_multisite() && is_plugin_active_for_network( $file ); $active = $must_use || $network_active || is_plugin_active( $file ); $name = sanitize_text_field( $data['Name'] ?? '' ); $slug = dirname( $file ) === '.' ? basename( $file, '.php' ) : dirname( $file ); // Read only relationship headers; also supports WordPress before 6.5. $headers = get_file_data( ( $must_use ? WPMU_PLUGIN_DIR : WP_PLUGIN_DIR ) . '/' . $file, array( 'RequiresPlugins' => 'Requires Plugins', 'WCRequiresAtLeast' => 'WC requires at least' ) ); $requires = array(); $raw_requires = $data['RequiresPlugins'] ?? ( $headers['RequiresPlugins'] ?? '' ); foreach ( explode( ',', is_string( $raw_requires ) ? $raw_requires : '' ) as $dependency ) { $dependency = trim( $dependency ); if ( preg_match( '/^[a-z0-9]+(?:-[a-z0-9]+)*$/D', $dependency ) ) { $requires[] = $dependency; } } $wc_minimum = $headers['WCRequiresAtLeast'] ?? ''; $metadata = array( 'file' => $file, 'slug' => $slug, 'version' => isset( $data['Version'] ) ? sanitize_text_field( $data['Version'] ) : null, 'author' => isset( $data['Author'] ) ? sanitize_text_field( $data['Author'] ) : null, 'kind' => $kind, 'active' => $active, 'network_active' => $network_active, 'must_use' => $must_use, 'requires_plugins' => array_values( array_unique( $requires ) ), 'wc_requires_at_least' => is_string( $wc_minimum ) && preg_match( '/^\d+(?:\.\d+){1,3}$/D', $wc_minimum ) ? $wc_minimum : null, ); // Separate prefixes prevent collisions between standard and MU files. $nodes[] = new Node( ( $must_use ? 'mu-plugin:' : 'plugin:' ) . $file, 'plugin', 'plugins', $name !== '' ? $name : $file, 'unknown', 0, $metadata ); } } return array( 'nodes' => $nodes, 'edges' => array() ); } }