2025-11-28 15:38:02 +01:00
|
|
|
<?php
|
|
|
|
|
|
|
|
|
|
namespace Web2Print\Services;
|
|
|
|
|
|
|
|
|
|
class PdfGenerator
|
|
|
|
|
{
|
|
|
|
|
private array $config;
|
|
|
|
|
|
|
|
|
|
public function __construct(array $config)
|
|
|
|
|
{
|
|
|
|
|
$this->config = $config;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function generate(string $html, ?string $css = null, array $options = []): string
|
|
|
|
|
{
|
|
|
|
|
// Créer un fichier HTML temporaire
|
|
|
|
|
$htmlFile = $this->createTempFile($html, $css);
|
|
|
|
|
$pdfFile = tempnam($this->config['tmp_dir'], 'pdf_') . '.pdf';
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
// Construire la commande Paged.js CLI
|
|
|
|
|
$command = $this->buildCommand($htmlFile, $pdfFile, $options);
|
|
|
|
|
|
|
|
|
|
// Exécuter Paged.js CLI
|
|
|
|
|
$output = [];
|
|
|
|
|
$returnCode = 0;
|
|
|
|
|
exec($command . ' 2>&1', $output, $returnCode);
|
|
|
|
|
|
|
|
|
|
if ($returnCode !== 0) {
|
|
|
|
|
$this->log('Paged.js CLI error: ' . implode("\n", $output));
|
|
|
|
|
throw new \Exception('PDF generation failed: ' . implode("\n", $output));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Lire le PDF généré
|
|
|
|
|
if (!file_exists($pdfFile)) {
|
|
|
|
|
throw new \Exception('PDF file not created');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$pdfContent = file_get_contents($pdfFile);
|
|
|
|
|
|
|
|
|
|
return $pdfContent;
|
|
|
|
|
|
|
|
|
|
} finally {
|
|
|
|
|
// Nettoyer les fichiers temporaires
|
|
|
|
|
@unlink($htmlFile);
|
|
|
|
|
@unlink($pdfFile);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2026-03-05 08:08:38 +01:00
|
|
|
public function generateFromUrl(string $url, array $options = []): string
|
|
|
|
|
{
|
|
|
|
|
$pdfFile = tempnam($this->config['tmp_dir'], 'pdf_') . '.pdf';
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
$cmd = escapeshellcmd($this->config['pagedjs_bin']);
|
|
|
|
|
$cmd .= ' ' . escapeshellarg($url);
|
|
|
|
|
$cmd .= ' -o ' . escapeshellarg($pdfFile);
|
|
|
|
|
|
|
|
|
|
if (!empty($options['timeout'])) {
|
|
|
|
|
$cmd .= ' --timeout ' . (int)$options['timeout'];
|
|
|
|
|
} else {
|
|
|
|
|
$cmd .= ' --timeout ' . ($this->config['pagedjs_timeout'] * 1000);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$output = [];
|
|
|
|
|
$returnCode = 0;
|
|
|
|
|
exec($cmd . ' 2>&1', $output, $returnCode);
|
|
|
|
|
|
|
|
|
|
if ($returnCode !== 0) {
|
|
|
|
|
$this->log('Paged.js CLI error (URL): ' . implode("\n", $output));
|
|
|
|
|
throw new \Exception('PDF generation failed: ' . implode("\n", $output));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!file_exists($pdfFile)) {
|
|
|
|
|
throw new \Exception('PDF file not created');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return file_get_contents($pdfFile);
|
|
|
|
|
|
|
|
|
|
} finally {
|
|
|
|
|
@unlink($pdfFile);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-11-28 15:38:02 +01:00
|
|
|
private function createTempFile(string $html, ?string $css): string
|
|
|
|
|
{
|
|
|
|
|
$fullHtml = $html;
|
|
|
|
|
|
|
|
|
|
// Injecter le CSS dans le HTML si fourni
|
|
|
|
|
if ($css) {
|
|
|
|
|
$styleTag = "<style>{$css}</style>";
|
|
|
|
|
if (stripos($html, '</head>') !== false) {
|
|
|
|
|
$fullHtml = str_ireplace('</head>', $styleTag . '</head>', $html);
|
|
|
|
|
} else {
|
|
|
|
|
// Si pas de <head>, créer une structure HTML complète
|
|
|
|
|
$fullHtml = "<!DOCTYPE html><html><head><meta charset='utf-8'>{$styleTag}</head><body>{$html}</body></html>";
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// S'assurer que le HTML a une structure complète
|
|
|
|
|
if (stripos($fullHtml, '<!DOCTYPE') === false) {
|
|
|
|
|
$fullHtml = "<!DOCTYPE html><html><head><meta charset='utf-8'></head><body>{$fullHtml}</body></html>";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$tempFile = tempnam($this->config['tmp_dir'], 'html_') . '.html';
|
|
|
|
|
file_put_contents($tempFile, $fullHtml);
|
|
|
|
|
|
|
|
|
|
return $tempFile;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private function buildCommand(string $htmlFile, string $pdfFile, array $options): string
|
|
|
|
|
{
|
|
|
|
|
$cmd = escapeshellcmd($this->config['pagedjs_bin']);
|
|
|
|
|
$cmd .= ' ' . escapeshellarg($htmlFile);
|
|
|
|
|
$cmd .= ' -o ' . escapeshellarg($pdfFile);
|
|
|
|
|
|
|
|
|
|
// Options supplémentaires pour Paged.js CLI
|
|
|
|
|
// Note: Paged.js utilise les règles CSS @page pour le format
|
|
|
|
|
// Les options sont limitées dans la CLI
|
|
|
|
|
|
|
|
|
|
// Timeout (millisecondes)
|
|
|
|
|
if (!empty($options['timeout'])) {
|
|
|
|
|
$cmd .= ' --timeout ' . (int)$options['timeout'];
|
|
|
|
|
} else {
|
|
|
|
|
$cmd .= ' --timeout ' . ($this->config['pagedjs_timeout'] * 1000);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return $cmd;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private function log(string $message): void
|
|
|
|
|
{
|
|
|
|
|
$timestamp = date('Y-m-d H:i:s');
|
|
|
|
|
$logMessage = "[{$timestamp}] {$message}\n";
|
|
|
|
|
file_put_contents($this->config['log_file'], $logMessage, FILE_APPEND);
|
|
|
|
|
}
|
|
|
|
|
}
|