isConfigured()) { return new ProviderStatus($this->getName(), ProviderStatusType::NotConfigured); } try { $this->ping(); return new ProviderStatus($this->getName(), ProviderStatusType::Ok); } catch (\Throwable $e) { return $this->statusFromException($e); } } private function statusFromException(\Throwable $e): ProviderStatus { [$error, $message] = $this->classifyException($e); return new ProviderStatus($this->getName(), ProviderStatusType::Error, $error, $message); } /** @return array{ProviderErrorCode, string} */ private function classifyException(\Throwable $e): array { if ($e instanceof TransportExceptionInterface) { return [ProviderErrorCode::UrlUnreachable, 'Could not reach the server: ' . $e->getMessage()]; } if ($e instanceof HttpExceptionInterface) { $code = $e->getResponse()->getStatusCode(); return match (true) { $code === 401 => [ProviderErrorCode::AuthFailed, 'Invalid or expired token — verify your credentials'], $code === 403 => [ProviderErrorCode::AuthFailed, 'Access denied — token lacks the required scopes'], $code === 404 => [ProviderErrorCode::UrlUnreachable, 'Endpoint not found — check the configured URL'], default => [ProviderErrorCode::Unknown, "HTTP {$code}: " . $e->getMessage()], }; } $msg = $e->getMessage(); $lower = strtolower($msg); $error = match (true) { str_contains($msg, 'not found') || str_contains($msg, 'Could not resolve') => ProviderErrorCode::UserNotFound, str_contains($msg, 'GraphQL error') && (str_contains($lower, 'unauthorized') || str_contains($lower, 'bad credentials')) => ProviderErrorCode::AuthFailed, default => ProviderErrorCode::Unknown, }; return [$error, $msg]; } }