apiKey = $apiKey; $this->baseUrl = rtrim($baseUrl, '/'); $this->timeout = $timeout; } /** * Convert HTML to PDF. * * @param string $html HTML content * @param string|null $css Optional CSS to inject * @param PdfOptions|null $options PDF options * @return string Raw PDF bytes * @throws DocFastException */ public function html(string $html, ?string $css = null, ?PdfOptions $options = null): string { $body = ['html' => $html]; if ($css !== null) { $body['css'] = $css; } return $this->convert('/v1/convert/html', $body, $options); } /** * Convert Markdown to PDF. * * @param string $markdown Markdown content * @param string|null $css Optional CSS to inject * @param PdfOptions|null $options PDF options * @return string Raw PDF bytes * @throws DocFastException */ public function markdown(string $markdown, ?string $css = null, ?PdfOptions $options = null): string { $body = ['markdown' => $markdown]; if ($css !== null) { $body['css'] = $css; } return $this->convert('/v1/convert/markdown', $body, $options); } /** * Convert a URL to PDF. * * @param string $url URL to convert * @param PdfOptions|null $options PDF options * @return string Raw PDF bytes * @throws DocFastException */ public function url(string $url, ?PdfOptions $options = null): string { return $this->convert('/v1/convert/url', ['url' => $url], $options); } /** * List available templates. * * @return array * @throws DocFastException */ public function templates(): array { $data = $this->get('/v1/templates'); $result = json_decode($data, true); return $result['templates'] ?? []; } /** * Render a template to PDF. * * @param string $templateId Template ID * @param array $data Template data * @return string Raw PDF bytes * @throws DocFastException */ public function renderTemplate(string $templateId, array $data = []): string { return $this->post('/v1/templates/' . urlencode($templateId), ['data' => $data]); } private function convert(string $path, array $body, ?PdfOptions $options): string { if ($options !== null) { $body = array_merge($body, $options->toArray()); } return $this->post($path, $body); } private function post(string $path, array $body): string { $ch = curl_init($this->baseUrl . $path); curl_setopt_array($ch, [ CURLOPT_POST => true, CURLOPT_POSTFIELDS => json_encode($body), CURLOPT_RETURNTRANSFER => true, CURLOPT_TIMEOUT => $this->timeout, CURLOPT_HTTPHEADER => [ 'Authorization: Bearer ' . $this->apiKey, 'Content-Type: application/json', 'Accept: application/pdf', ], ]); $response = curl_exec($ch); $statusCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); $error = curl_error($ch); curl_close($ch); if ($response === false) { throw new DocFastException('Request failed: ' . $error, 0); } if ($statusCode >= 400) { $this->handleError($response, $statusCode); } return $response; } private function get(string $path): string { $ch = curl_init($this->baseUrl . $path); curl_setopt_array($ch, [ CURLOPT_RETURNTRANSFER => true, CURLOPT_TIMEOUT => $this->timeout, CURLOPT_HTTPHEADER => [ 'Authorization: Bearer ' . $this->apiKey, 'Accept: application/json', ], ]); $response = curl_exec($ch); $statusCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); $error = curl_error($ch); curl_close($ch); if ($response === false) { throw new DocFastException('Request failed: ' . $error, 0); } if ($statusCode >= 400) { $this->handleError($response, $statusCode); } return $response; } private function handleError(string $response, int $statusCode): never { $message = "HTTP $statusCode"; $code = null; $data = json_decode($response, true); if (is_array($data)) { $message = $data['error'] ?? $message; $code = $data['code'] ?? null; } throw new DocFastException($message, $statusCode, $code); } }