$report * @return array{status:bool,message?:string,content?:string,filename?:string} */ public function generateFromReport(array $report, int $policyId): array { $vm = $report['view_model'] ?? $report; $policyNo = trim((string) ($report['header']['policy_number'] ?? (string) $policyId)); $html = view('claims_mis_vidal', [ 'report' => $report, 'view_model' => $vm, 'policy_id' => $policyId, 'pdf_url' => '', 'embed' => true, ]); return $this->generate($html, $policyNo); } /** * @return array{status:bool,message?:string,content?:string,filename?:string} */ public function generate(string $html, string $policyNo): array { $safePolicy = preg_replace('/[^A-Za-z0-9_\-]+/', '_', $policyNo) ?: 'policy'; $filename = 'VIDAL_MIS_' . $safePolicy . '_' . date('Ymd') . '.pdf'; try { $options = new Options(); $options->set('isHtml5ParserEnabled', true); $options->set('isRemoteEnabled', true); $options->set('isFontSubsettingEnabled', true); $options->set('defaultFont', 'DejaVu Sans'); $options->setChroot([ rtrim(ROOTPATH, '/\\'), rtrim(FCPATH, '/\\'), rtrim(WRITEPATH, '/\\'), sys_get_temp_dir(), ]); $dompdf = new Dompdf($options); $dompdf->loadHtml($this->prepareHtml($html)); $dompdf->setPaper('A4', 'portrait'); $dompdf->render(); $content = $dompdf->output(); if ($content === '' || $content === null) { return ['status' => false, 'message' => 'PDF generation failed: empty output.']; } return [ 'status' => true, 'content' => $content, 'filename' => $filename, ]; } catch (\Throwable $e) { log_message('error', 'VidalMisPdfService::generate failed | ' . $e->getMessage()); return ['status' => false, 'message' => 'PDF generation failed: ' . $e->getMessage()]; } } private function prepareHtml(string $html): string { $html = preg_replace('#]*>.*?#is', '', $html) ?? $html; $html = preg_replace('/[\x{1F300}-\x{1FAFF}]/u', '', $html) ?? $html; $vars = [ 'var(--blue)' => '#0072bc', 'var(--header-blue)' => '#dbe9f5', 'var(--group-header)' => '#b9d6ec', 'var(--border)' => '#888', 'var(--text)' => '#111', 'var(--muted)' => '#444', 'var(--male)' => '#4472c4', 'var(--female)' => '#ed7d31', ]; $html = str_replace(array_keys($vars), array_values($vars), $html); $html = preg_replace('#:root\s*\{[^}]*\}#is', '', $html) ?? $html; $html = preg_replace_callback( '#(]*\bsrc=["\'])([^"\']+)(["\'][^>]*>)#i', function (array $m): string { $src = html_entity_decode($m[2], ENT_QUOTES); $dataUri = $this->toDataUri($src); return $m[1] . ($dataUri ?: $src) . $m[3]; }, $html ) ?? $html; return $html; } private function toDataUri(string $path): ?string { $path = trim($path); if ($path === '' || str_starts_with($path, 'data:')) { return null; } if (preg_match('#^file://#i', $path)) { $path = preg_replace('#^file://#i', '', $path) ?? $path; } if (!is_file($path) || !is_readable($path)) { return null; } $ext = strtolower(pathinfo($path, PATHINFO_EXTENSION)); $mime = match ($ext) { 'png' => 'image/png', 'jpg', 'jpeg' => 'image/jpeg', 'gif' => 'image/gif', 'webp' => 'image/webp', default => 'application/octet-stream', }; $bytes = @file_get_contents($path); if ($bytes === false || $bytes === '') { return null; } return 'data:' . $mime . ';base64,' . base64_encode($bytes); } }