@php
$hexToRgba = function (?string $hex, float $alpha = 1.0): string {
if (!$hex) {
$hex = '#000000';
}
if ($hex === 'transparent') {
return 'transparent';
}
$normalized = ltrim($hex, '#');
if (strlen($normalized) === 3) {
$normalized = implode('', array_map(fn ($char) => $char . $char, str_split($normalized)));
}
$int = hexdec($normalized);
$r = ($int >> 16) & 255;
$g = ($int >> 8) & 255;
$b = $int & 255;
return sprintf('rgba(%d, %d, %d, %.2f)', $r, $g, $b, $alpha);
};
@endphp
@php
// Récupérer toutes les pages (avec blocs ou avec fond uniquement)
$allPages = array_unique(array_merge(
array_keys($blocksByPage),
array_keys($backgrounds)
));
sort($allPages);
// Si aucune page, créer la page 1 par défaut
if (empty($allPages)) {
$allPages = [1];
}
@endphp
@foreach($allPages as $pageNum)
@php
$pageBackground = $backgrounds[$pageNum] ?? null;
$pageStyle = 'position: relative;';
if ($pageBackground && !empty($pageBackground['path'])) {
$bgPath = $pageBackground['path'];
// Si c'est une donnée base64 (data:image/...), l'utiliser directement
if (str_starts_with($bgPath, 'data:image/')) {
// Les données base64 peuvent être très longues, les utiliser directement
$pageStyle .= "background-image: url('".$bgPath."'); background-size: cover; background-position: center;";
} elseif (str_starts_with($bgPath, 'http://') || str_starts_with($bgPath, 'https://')) {
// Si c'est une URL HTTP/HTTPS, l'utiliser directement
$bgPathEscaped = htmlspecialchars($bgPath, ENT_QUOTES, 'UTF-8');
$pageStyle .= "background-image: url('".$bgPathEscaped."'); background-size: cover; background-position: center;";
} elseif (file_exists($bgPath)) {
// Si c'est un chemin local, s'assurer qu'il est absolu
$absolutePath = realpath($bgPath) ?: $bgPath;
// DomPDF avec enable-local-file-access peut accéder aux fichiers locaux
// Convertir les backslashes en slashes pour Windows
$bgPathEscaped = str_replace('\\', '/', $absolutePath);
// Échapper les caractères spéciaux pour l'URL CSS
$bgPathEscaped = str_replace("'", "\\'", $bgPathEscaped);
// Utiliser le chemin absolu directement (DomPDF le gère avec enable-local-file-access)
$pageStyle .= "background-image: url('".$bgPathEscaped."'); background-size: cover; background-position: center;";
}
}
$blocks = $blocksByPage[$pageNum] ?? [];
@endphp
@foreach($blocks as $data)
@php
$position = $data->position;
$json = $data->json ?? [];
$imageSource = null;
$isSignatureBlock = !empty($json['is_signature']);
// En prod / préprod, on ne veut plus afficher visuellement les cadres de signature
$hideSignatureFrame = $isSignatureBlock && app()->environment('production');
if (!empty($json['is_image'])) {
if (!empty($json['image_absolute_path']) && file_exists($json['image_absolute_path'])) {
$imageSource = $json['image_absolute_path'];
} elseif (!empty($json['image_path']) && \Illuminate\Support\Facades\Storage::disk('public')->exists($json['image_path'])) {
$imageSource = \Illuminate\Support\Facades\Storage::disk('public')->path($json['image_path']);
} elseif (!empty($json['image_url'])) {
$imageSource = $json['image_url'];
}
}
// Décalage pour ajuster la position dans le PDF généré
// X : décaler vers la droite (augmenter)
// Y : décaler vers le haut (diminuer)
$offsetX = 5; // pixels vers la droite
$offsetY = -10; // pixels vers le haut
$adjustedX = $position ? (($position->x ?? 0) + $offsetX) : $offsetX;
$adjustedY = $position ? (($position->y ?? 0) + $offsetY) : $offsetY;
@endphp
@if(!empty($json['is_image']) && $imageSource)
@elseif($hideSignatureFrame)
{{-- Bloc de signature : ne rien afficher visuellement en production (cadre caché), mais conserver la position pour Yousign --}}
@else
{!! $json['content'] ?? '' !!}
@endif