$item, 'title' => self::title($group, $roots[$group], $item), 'active' => in_array($item, $active, true)]; } } foreach (['mu-plugins', 'uploads', 'other'] as $group) { $out[$group] = self::top_level($roots[$group], $excludes[$group]); } $out['wp'] = (string) $wp_version; return $out; } /** * themes: the current theme and its parent; plugins: the items holding active plugins. Read as this site stores * them, not through the option filters other plugins may add. * * @return string[] */ public static function active(string $group): array { if ($group === 'themes') { return array_values(array_unique(array_filter([(string) get_option('stylesheet'), (string) get_option('template')]))); } if ($group === 'plugins') { global $wpdb; $raw = $wpdb->get_var("SELECT option_value FROM {$wpdb->options} WHERE option_name = 'active_plugins'"); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- the stored list itself: during a signed request Relay's mu-plugin filters active_plugins so only Relay loads $plugins = is_string($raw) ? maybe_unserialize($raw) : []; $items = []; foreach (is_array($plugins) ? $plugins : [] as $basename) { if (is_string($basename) && $basename !== '') { $items[] = RelPath::top($basename); } } return array_values(array_unique($items)); } return []; } /** @return string[] sorted names of the files and folders directly in $root that are not left out (no symlinks) */ public static function top_level(string $root, Excludes $excludes): array { $names = []; foreach (is_dir($root) ? (scandir($root) ?: []) : [] as $name) { if ($name === '.' || $name === '..' || is_link($root . '/' . $name) || !RelPath::valid($name) || $excludes->excluded($name)) { continue; } $names[] = $name; } sort($names); return $names; } private static function title(string $group, string $root, string $item): string { if ($group === 'themes') { $theme = wp_get_theme($item, $root); return $theme->exists() ? (string) $theme->get('Name') : $item; } $files = is_dir($root . '/' . $item) ? (glob($root . '/' . $item . '/*.php') ?: []) : [$root . '/' . $item]; foreach ($files as $file) { if (substr($file, -4) !== '.php' || !is_readable($file)) { continue; } $name = get_file_data($file, ['Name' => 'Plugin Name'])['Name'] ?? ''; if ($name !== '') { return $name; } } return $item; } }