<?php
declare(strict_types=1); namespace NanoCart\Registry; final class Loader { private static bool $booted = false; private static array $themes = []; private static array $plugins = []; private static array $languages = []; public static function boot(): void { if (self::$booted) return; self::$booted = true; self::discoverThemes(); self::discoverPlugins(); self::discoverLanguages(); } public static function discoverThemes(): void { $base = FS_DIR_REGISTRY . 'themes/'; if (!is_dir($base)) return; foreach (new \DirectoryIterator($base) as $entry) { if ($entry->isDot() || !$entry->isDir()) continue; $manifest = $base . $entry->getFilename() . '/theme.json'; if (!file_exists($manifest)) continue; $data = json_decode(file_get_contents($manifest), true); if (!isset($data['name'])) continue; self::$themes[$data['name']] = [ 'path' => $base . $entry->getFilename() . '/', 'manifest' => $data, ]; } } public static function getTheme(string $name): ?array { return self::$themes[$name] ?? null; } public static function getThemes(): array { return self::$themes; } public static function getActiveThemePath(string $part = 'catalog'): string { $name = defined('ACTIVE_THEME') ? ACTIVE_THEME : 'nanocart-default'; $theme = self::getTheme($name); if (!$theme) $theme = self::getTheme('nanocart-default'); return ($theme['path'] ?? FS_DIR_REGISTRY . 'themes/nanocart-default/') . $part . '/'; } public static function discoverPlugins(): void { $base = FS_DIR_REGISTRY . 'plugins/'; if (!is_dir($base)) return; foreach (new \DirectoryIterator($base) as $typeEntry) { if ($typeEntry->isDot() || !$typeEntry->isDir()) continue; $type = $typeEntry->getFilename(); foreach (new \DirectoryIterator($typeEntry->getPathname()) as $pluginEntry) { if ($pluginEntry->isDot() || !$pluginEntry->isDir()) continue; $manifest = $pluginEntry->getPathname() . '/plugin.json'; if (!file_exists($manifest)) continue; $data = json_decode(file_get_contents($manifest), true); if (!isset($data['name'])) continue; self::$plugins[$type][$data['name']] = [ 'path' => $pluginEntry->getPathname() . '/', 'manifest' => $data, ]; } } } public static function getPlugin(string $type, string $name): ?array { return self::$plugins[$type][$name] ?? null; } public static function getPluginsByType(string $type): array { return self::$plugins[$type] ?? []; } public static function getPlugins(): array { return self::$plugins; } public static function resolvePluginFile(string $class): ?string { $prefixMap = [ 'pm_' => 'payment', 'sm_' => 'shipping', 'ot_' => 'order_total', 'cm_' => 'customer', 'om_' => 'order', 'job_' => 'jobs', ]; foreach ($prefixMap as $prefix => $type) { if (!str_starts_with($class, $prefix)) continue; if (!isset(self::$plugins[$type])) continue; foreach (self::$plugins[$type] as $name => $plugin) { $file = $plugin['path'] . $class . '.inc.php'; if (file_exists($file)) return $file; } } return null; } public static function discoverLanguages(): void { $base = FS_DIR_REGISTRY . 'languages/'; if (!is_dir($base)) return; foreach (new \DirectoryIterator($base) as $entry) { if ($entry->isDot() || !$entry->isDir()) continue; $manifest = $base . $entry->getFilename() . '/manifest.json'; if (!file_exists($manifest)) continue; $data = json_decode(file_get_contents($manifest), true); $code = $data['code'] ?? $entry->getFilename(); self::$languages[$code] = [ 'path' => $base . $entry->getFilename() . '/', 'manifest' => $data, ]; } } public static function getLanguage(string $code): ?array { return self::$languages[$code] ?? null; } public static function getLanguages(): array { return self::$languages; } } 