<?php
declare(strict_types=1);
namespace Butschster\ContextGenerator\Lib\GithubClient;
use Butschster\ContextGenerator\Lib\GithubClient\Model\GithubRepository;
use Butschster\ContextGenerator\Lib\HttpClient\HttpClientInterface;
final class GithubClient implements GithubClientInterface
{
/** GitHub API base URL */
private const string API_BASE_URL = 'https://api.github.com';
/**
* @param HttpClientInterface $httpClient HTTP client for API requests
* @param string|null $token GitHub API token
*/
public function __construct(
private readonly HttpClientInterface $httpClient,
private ?string $token = null,
) {}
public function getContents(GithubRepository $repository, string $path = ''): array
{
$url = \sprintf(
'/repos/%s/contents/%s?ref=%s',
$repository->repository,
$path ? \urlencode($path) : '',
\urlencode($repository->branch),
);
$response = $this->sendRequest('GET', $url);
/**
* Check if we got a single file or a directory
*/
if (isset($response['type']) && $response['type'] === 'file') {
return [$response];
}
return $response;
}
public function getFileContent(GithubRepository $repository, string $path): string
{
$url = \sprintf(
'/repos/%s/contents/%s?ref=%s',
$repository->repository,
\urlencode($path),
\urlencode($repository->branch),
);
$response = $this->sendRequest('GET', $url);
if (!isset($response['content'])) {
throw new \RuntimeException("Could not get content for file: $path");
}
// GitHub API returns base64 encoded content
return (string) \base64_decode((string) $response['content'], true);
}
public function setToken(?string $token): void
{
$this->token = $token;
}
public function getReleaseManager(GithubRepository $repository): ReleaseManager
{
return new ReleaseManager(
$this->httpClient,
$repository,
$this->token,
);
}
/**
* Send an HTTP request to the GitHub API
*
* @param string $method HTTP method
* @param string $path API path
* @return array<string, mixed> JSON response data
* @throws \RuntimeException If the request fails
*/
private function sendRequest(string $method, string $path): array
{
$url = self::API_BASE_URL . $path;
// Add headers
$headers = [
'Accept' => 'application/vnd.github.v3+json',
'User-Agent' => 'ContextGenerator',
];
// Add authentication if token is provided
if ($this->token) {
$headers['Authorization'] = 'token ' . $this->token;
}
// Send the request
try {
$response = $this->httpClient->get($url, $headers);
// Check for success status code
if (!$response->isSuccess()) {
throw new \RuntimeException(
"GitHub API request failed with status code " . $response->getStatusCode(),
);
}
// Parse JSON response
return $response->getJson();
} catch (\Throwable $e) {
throw new \RuntimeException('GitHub API request failed: ' . $e->getMessage(), 0, $e);
}
}
}