@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) Bloc image @elseif($hideSignatureFrame) {{-- Bloc de signature : ne rien afficher visuellement en production (cadre caché), mais conserver la position pour Yousign --}} @else {!! $json['content'] ?? '' !!} @endif
@endforeach
@endforeach