') so the picker can never drift from the * frontend sprite. Parsed per file mtime and cached. */ final class IconCatalog { /** * @return array */ public static function groups(): array { $fa = include AKSRT_DIR . '/src/Icons/fa5-icons.php'; if (!is_array($fa)) { $fa = ['fas' => [], 'far' => [], 'fab' => []]; } return [ ['id' => 'fas', 'title' => __('FA 实色', 'aksrt'), 'type' => 'fa', 'icons' => array_values((array) ($fa['fas'] ?? []))], ['id' => 'far', 'title' => __('FA 常规', 'aksrt'), 'type' => 'fa', 'icons' => array_values((array) ($fa['far'] ?? []))], ['id' => 'fab', 'title' => __('FA 品牌', 'aksrt'), 'type' => 'fa', 'icons' => array_values((array) ($fa['fab'] ?? []))], ['id' => 'zibsvg', 'title' => __('主题内置 SVG', 'aksrt'), 'type' => 'svg', 'icons' => self::sprite_keys()], ['id' => 'custom', 'title' => __('自定义 SVG', 'aksrt'), 'type' => 'custom', 'icons' => []], ]; } /** * Sprite symbol keys, e.g. ['like', 'view', ...] — derived from the * frontend sprite file, cached until the file changes. * * @return string[] */ public static function sprite_keys(): array { $file = AKSRT_DIR . '/assets/js/runtime/svg-icon.js'; if (!is_readable($file)) { return []; } $mtime = (string) filemtime($file); $cache = get_transient('aksrt_sprite_keys_v1'); if (is_array($cache) && ($cache['mtime'] ?? '') === $mtime && isset($cache['keys'])) { return array_values((array) $cache['keys']); } $src = (string) file_get_contents($file); $keys = []; if (preg_match_all("/aksrt_svgs\\['([A-Za-z0-9_]+)'\\]\\s*=/", $src, $m)) { $keys = array_values(array_unique($m[1])); } set_transient('aksrt_sprite_keys_v1', ['mtime' => $mtime, 'keys' => $keys], MONTH_IN_SECONDS); return $keys; } }