[...], 'plugins' => [...]]`) * @return array> 보강된 의존성 목록 (type 필드로 module/plugin 구분) */ public static function enrich(array $dependencies): array { $result = []; foreach (self::enrichByType($dependencies, 'modules') as $item) { $result[] = $item; } foreach (self::enrichByType($dependencies, 'plugins') as $item) { $result[] = $item; } return $result; } /** * 특정 타입(modules/plugins)의 의존성만 보강합니다. * * @param array $dependencies manifest 의 dependencies 배열 * @param string $type 'modules' 또는 'plugins' * @return array> 보강된 의존성 목록 */ protected static function enrichByType(array $dependencies, string $type): array { if (! isset($dependencies[$type]) || ! is_array($dependencies[$type])) { return []; } $singular = $type === 'modules' ? 'module' : 'plugin'; $repository = $type === 'modules' ? app(ModuleRepositoryInterface::class) : app(PluginRepositoryInterface::class); $result = []; foreach ($dependencies[$type] as $identifier => $versionConstraint) { $record = $repository->findByIdentifier($identifier); $activeRecord = $repository->findActiveByIdentifier($identifier); $installedVersion = $record?->version; $isActive = (bool) $activeRecord; $isMet = $isActive && $installedVersion && self::checkVersionConstraint($installedVersion, (string) $versionConstraint); $result[] = [ 'identifier' => $identifier, 'name' => self::resolveName($record, $identifier), 'type' => $singular, 'required_version' => $versionConstraint, 'installed_version' => $installedVersion, 'is_active' => $isActive, 'is_met' => $isMet, ]; } return $result; } /** * Semver 제약 조건을 검증합니다. * * @param string $installedVersion 설치된 버전 * @param string $versionConstraint 요구 버전 제약 * @return bool 제약 충족 여부 */ public static function checkVersionConstraint(string $installedVersion, string $versionConstraint): bool { try { return Semver::satisfies($installedVersion, $versionConstraint); } catch (\Exception $e) { return false; } } /** * 확장 모델에서 현재 로케일의 이름을 추출합니다. * * @param object|null $record 확장 모델 (Module/Plugin) * @param string $fallback 모델이 없을 때 반환할 식별자 * @return string 이름 */ protected static function resolveName(?object $record, string $fallback): string { if (! $record) { return $fallback; } $name = $record->name ?? null; if (is_array($name)) { $locale = App::getLocale(); $fallbackLocale = config('app.fallback_locale', 'ko'); return (string) ($name[$locale] ?? $name[$fallbackLocale] ?? reset($name) ?: $fallback); } if (is_string($name) && str_starts_with($name, '{')) { $decoded = json_decode($name, true); if (is_array($decoded)) { $locale = App::getLocale(); $fallbackLocale = config('app.fallback_locale', 'ko'); return (string) ($decoded[$locale] ?? $decoded[$fallbackLocale] ?? reset($decoded) ?: $fallback); } } return (string) ($name ?? $fallback); } }