*/ protected function sharedRecordResolvers(): array { return [ ['permissions', fn (string $type, string $id): int => app(PermissionRepositoryInterface::class) ->getByExtension(ExtensionOwnerType::from($type), $id) ->count(), ], ['menus', fn (string $type, string $id): int => app(MenuRepositoryInterface::class) ->getMenusByExtension(ExtensionOwnerType::from($type), $id) ->count(), ], ['notification_definitions', fn (string $type, string $id): int => app(NotificationDefinitionRepositoryInterface::class) ->getByExtension($type, $id) ->count(), ], ['identity_policies', fn (string $type, string $id): int => app(IdentityPolicyRepositoryInterface::class) ->countBySource($type, $id), ], ['identity_message_definitions', fn (string $type, string $id): int => app(IdentityMessageDefinitionRepositoryInterface::class) ->getByExtension($type, $id) ->count(), ], ]; } /** * 코어 공유 테이블에 적재된 확장 영역 레코드 정보를 조회합니다. * * 0건인 항목은 결과에서 제외 (모달에서 빈 항목 노이즈 회피). * Repository/Schema 예외는 경고 로그만 남기고 skip — uninstall 모달이 부분적으로라도 * 동작하도록 보장 (예: 마이그레이션 미실행 환경). * * @param string $extensionType 'module' 또는 'plugin' * @param string $extensionIdentifier 확장 식별자 * @return array */ protected function resolveExtensionSharedRecords(string $extensionType, string $extensionIdentifier): array { $records = []; foreach ($this->sharedRecordResolvers() as [$labelKey, $resolver]) { try { $count = (int) $resolver($extensionType, $extensionIdentifier); } catch (\Throwable $e) { Log::warning('확장 공유 레코드 조회 실패', [ 'label' => $labelKey, 'extension' => "{$extensionType}/{$extensionIdentifier}", 'error' => $e->getMessage(), ]); continue; } if ($count === 0) { continue; } $records[] = [ 'table' => $labelKey, 'label_key' => $labelKey, 'count' => $count, ]; } return $records; } }