src/Services/PDFGenerator.php line 60

Open in your IDE?
  1. <?php
  2. declare(strict_types=1);
  3. /**
  4.  * @author Mehrez Labidi
  5.  */
  6. namespace App\Services;
  7. use Symfony\Component\HttpFoundation\StreamedResponse;
  8. use Symfony\Component\HttpFoundation\{
  9.     Request,
  10.     RedirectResponse,
  11.     Response
  12. };
  13. use Dompdf\Dompdf;
  14. use Dompdf\Options;
  15. use Twig\Environment;
  16. class PDFGenerator {
  17.     /**
  18.      * @var string
  19.      */
  20.     public static $directory_storage_pdf;
  21.     /**
  22.      * @var Environment
  23.      */
  24.     private Environment $templating;
  25.     /**
  26.      * @param Environment $twig
  27.      * @param string      $directory_storage_pdf
  28.      */
  29.     public function __construct(Environment $twigstring $directory_storage_pdf) {
  30.         $this->templating $twig;
  31.         static::$directory_storage_pdf $directory_storage_pdf;
  32.     }
  33.     /**
  34.      *
  35.      * @param type $view
  36.      * @param type $var
  37.      * @param type $fileName
  38.      * @param type $title
  39.      * @param type $footerText
  40.      */
  41.     public function generatePDFviewBrowser($view$var$fileName$title$footerText "") {
  42.         $pdfOptions = new Options();
  43.         $pdfOptions->set('isRemoteEnabled'true);
  44.         $pdfOptions->set('isPhpEnabled'true);
  45.         $pdfOptions->set('defaultFont''helvetica');
  46.         // Instantiate Dompdf with our options
  47.         $dompdf = new Dompdf($pdfOptions);
  48.         // Retrieve the HTML generated in our twig file
  49.         $vars = ['title' => $title];
  50.         foreach ($var as $keyItem => $valueItem) {
  51.             $vars[$keyItem] = $valueItem;
  52.         }
  53.         $html $this->templating->render($view$vars);
  54.         // Load HTML to Dompdf
  55.         $dompdf->loadHtml($html);
  56.         // (Optional) Setup the paper size and orientation 'portrait' or 'portrait'
  57.         $dompdf->setPaper('A4''portrait');
  58.         // Render the HTML as PDF
  59.         $dompdf->render();
  60.         if ($footerText) {
  61.             // Solution Canvas qui fonctionne sur TOUTES les pages
  62.             $canvas $dompdf->getCanvas();
  63.             $fontMetrics $dompdf->getFontMetrics();
  64.             // Méthode page_script pour Dompdf 3.0
  65.             $canvas->page_script(function ($pageNumber$pageCount$canvas$fontMetrics) use ($footerText) {
  66.                 // Police en italique
  67.                 $font $fontMetrics->get_font("helvetica""italic");
  68.                 $fontSize 8;
  69.                 // Texte du footer
  70.                 $text $footerText;
  71.                 // Dimensions de la page
  72.                 $pageWidth $canvas->get_width();
  73.                 $pageHeight $canvas->get_height();
  74.                 // Marges identiques au body
  75.                 $leftMargin 50;
  76.                 $rightMargin 50// Ajout d'une marge droite pour équilibrer
  77.                 // Largeur disponible pour le texte
  78.                 $availableWidth $pageWidth $leftMargin $rightMargin;
  79.                 // Fonction pour découper le texte en lignes
  80.                 $lines = [];
  81.                 $words preg_split('/\s+/'$text);
  82.                 $currentLine '';
  83.                 foreach ($words as $word) {
  84.                     $testLine $currentLine . ($currentLine ' ' '') . $word;
  85.                     $testWidth $fontMetrics->get_text_width($testLine$font$fontSize);
  86.                     if ($testWidth $availableWidth && $currentLine !== '') {
  87.                         // La ligne est trop longue, on ajoute la ligne courante et on commence une nouvelle
  88.                         $lines[] = $currentLine;
  89.                         $currentLine $word;
  90.                     } else {
  91.                         // Le mot tient sur la ligne courante
  92.                         $currentLine $testLine;
  93.                     }
  94.                 }
  95.                 // Ajouter la dernière ligne si elle n'est pas vide
  96.                 if ($currentLine !== '') {
  97.                     $lines[] = $currentLine;
  98.                 }
  99.                 // Interligne
  100.                 $lineHeight 12// Hauteur de ligne (ajustable)
  101.                 // Calculer la position Y de départ pour centrer verticalement le bloc de texte
  102.                 $totalTextHeight count($lines) * $lineHeight;
  103.                 $baseY $pageHeight 30 - ($totalTextHeight $lineHeight);
  104.                 // Position de la ligne de séparation (au-dessus du texte)
  105.                 $separatorY $baseY 10;
  106.                 // Dessiner chaque ligne de texte
  107.                 $x $leftMargin;
  108.                 $y $baseY;
  109.                 foreach ($lines as $line) {
  110.                     // Changement ici : [0, 0, 0] pour noir au lieu de [0.5, 0.5, 0.5] pour gris
  111.                     $canvas->text($x$y$line$font$fontSize, [000]);
  112.                     $y += $lineHeight;
  113.                 }
  114.             });
  115.         }
  116. //        // Output the generated PDF to Browser (inline view)
  117. //        $dompdf->stream("$fileName.pdf", [
  118. //            'Attachment' => false,
  119. //        ]);
  120.         // ⚠️ Très important : ne rien envoyer en direct, vider tout tampon éventuel
  121.         while (ob_get_level() > 0) {
  122.             @ob_end_clean();
  123.         }
  124.         $pdf $dompdf->output();
  125.         return new Response($pdf200, [
  126.             'Content-Type' => 'application/pdf',
  127.             'Content-Disposition' => 'inline; filename="' $fileName '.pdf"',
  128.             'Content-Length' => (string) strlen($pdf),
  129.             // Optionnel: forcer no-cache si besoin
  130.             'Cache-Control' => 'private, must-revalidate, max-age=0',
  131.             'Pragma' => 'public',
  132.         ]);
  133.     }
  134.     /**
  135.      * @param $view
  136.      * @param $var
  137.      * @param $fileName
  138.      * @param $title
  139.      *
  140.      * @throws \Twig\Error\LoaderError
  141.      * @throws \Twig\Error\RuntimeError
  142.      * @throws \Twig\Error\SyntaxError
  143.      */
  144.     public function generatePDFStoreDisk($view$var$fileName$title) {
  145.         $pdfOptions = new Options();
  146.         $pdfOptions->set('defaultFont''Arial');
  147.         $dompdf = new Dompdf($pdfOptions);
  148.         $vars = ['title' => $title];
  149.         foreach ($var as $keyItem => $valueItem) {
  150.             $vars[$keyItem] = $valueItem;
  151.         }
  152.         $html $this->templating->render($view$vars);
  153.         // Load HTML to Dompdf
  154.         $dompdf->loadHtml($html);
  155.         // (Optional) Setup the paper size and orientation 'portrait' or 'portrait'
  156.         $dompdf->setPaper('A4''portrait');
  157.         // Render the HTML as PDF
  158.         $dompdf->render();
  159.         // Store PDF Binary Data
  160.         $output $dompdf->output();
  161.         // In this case, we want to write the file in the public directory
  162.         $publicDirectory self::$directory_storage_pdf;
  163.         if (!is_dir($publicDirectory)) {
  164.             mkdir($publicDirectory0777true);
  165.         }
  166.         // e.g /var/www/project/public/mypdf.pdf
  167.         $pdfFilepath $publicDirectory $fileName '.pdf';
  168.         // Write file to the desired path
  169.         file_put_contents($pdfFilepath$output);
  170.     }
  171.     /**
  172.      * @param string $url
  173.      * @return void
  174.      */
  175.     public function displayPDFByURL(string $url): StreamedResponse {
  176.         return new StreamedResponse(function () use ($url) {
  177.                     readfile($url);
  178.                 }, 200, [
  179.             'Content-Type' => 'application/pdf',
  180.             'Content-Disposition' => 'inline; filename="' basename($url) . '"',
  181.         ]);
  182.     }
  183. }