Reorganize project structure and migrate CI to Forgejo
Some checks are pending
Deploy / deploy (push) Waiting to run

Move all files from deploy/ to project root, replace .gitlab-ci.yml
with .forgejo/workflows/deploy.yml using Gitea Actions format.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
isUnknown 2026-03-05 06:54:52 +01:00
parent baa36144a8
commit b130f5c9d8
13 changed files with 71 additions and 66 deletions

View file

@ -0,0 +1,71 @@
<?php
namespace Web2Print\Controllers;
use Web2Print\Services\PdfGenerator;
class GenerateController
{
private PdfGenerator $generator;
private array $config;
public function __construct(PdfGenerator $generator, array $config)
{
$this->generator = $generator;
$this->config = $config;
}
public function handle(): void
{
// Vérifier la méthode HTTP
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
$this->sendError(405, 'Method not allowed');
return;
}
// Lire le body JSON
$input = file_get_contents('php://input');
if (strlen($input) > $this->config['max_html_size']) {
$this->sendError(413, 'Request too large');
return;
}
$data = json_decode($input, true);
if (json_last_error() !== JSON_ERROR_NONE) {
$this->sendError(400, 'Invalid JSON');
return;
}
// Valider les données
if (empty($data['html'])) {
$this->sendError(400, 'HTML content required');
return;
}
try {
// Générer le PDF
$pdf = $this->generator->generate(
$data['html'],
$data['css'] ?? null,
$data['options'] ?? []
);
// Retourner le PDF
header('Content-Type: application/pdf');
header('Content-Length: ' . strlen($pdf));
echo $pdf;
} catch (\Exception $e) {
$this->sendError(500, 'PDF generation error: ' . $e->getMessage());
}
}
private function sendError(int $code, string $message): void
{
http_response_code($code);
header('Content-Type: application/json');
echo json_encode(['error' => $message]);
}
}

View file

@ -0,0 +1,38 @@
<?php
namespace Web2Print\Middleware;
class AuthMiddleware
{
private array $config;
public function __construct(array $config)
{
$this->config = $config;
}
public function authenticate(): bool
{
$apiKey = $_SERVER['HTTP_X_API_KEY'] ?? '';
if (empty($apiKey)) {
$this->sendError(401, 'API key missing');
return false;
}
if (!in_array($apiKey, $this->config['api_keys'], true)) {
$this->sendError(403, 'Invalid API key');
return false;
}
return true;
}
private function sendError(int $code, string $message): void
{
http_response_code($code);
header('Content-Type: application/json');
echo json_encode(['error' => $message]);
exit;
}
}

View file

@ -0,0 +1,102 @@
<?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);
}
}
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);
}
}