1: <?php
2: namespace TIC\DpdfBundle\Service;
3:
4: use TIC\DpdfBundle\Base\PDFService as BaseService;
5:
6: use Dompdf\Dompdf;
7: use Dompdf\Options;
8: use Dompdf\Helpers;
9:
10: /**
11: * Service de génération de PDF avec DomPDF
12: * (à partir d'un contenu HMTL ou d'une vue Twig).
13: */
14: class DompdfService extends BaseService
15: {
16: use \TIC\DpdfBundle\Traits\DompdfWrapper;
17:
18: // ------------------------------------------------------------------------------------------ CONFIG
19:
20: /**
21: * Initialisation de l'objet Dompdf avec ses options.
22: * @See https://github.com/dompdf/dompdf/blob/master/src/Options.php
23: *
24: * private $fontDir;
25: * private $fontCache;
26: * private $chroot;
27: * private $allowedProtocols = ["file://" => ["rules" => []], "http://" => ["rules" => []], "https://" => ["rules" => []]
28: * private $httpContext;
29: *
30: * @param array $pdf_options Surcharge d'options pour Dompdf
31: * @return DompdfService
32: */
33: public function initEngine(array $pdf_options = []): DompdfService
34: {
35: $opts = isset($this->dompdf) ? $this->dompdf->getOptions() : new Options();
36:
37: // options complétée avec la configuration par défaut (surchargée par parameters)
38: $pdf_options+= $this->confs;
39: if (isset($pdf_options['debug'])) $this->debug = (bool)$pdf_options['debug'];
40:
41: switch (\strtolower($pdf_options['generator'])) {
42: case "image":
43: case "png":
44: case "gd":
45: $opts->set('pdfBackend', 'GD'); break;
46: case "cpdf":
47: $opts->set('pdfBackend', 'CPDF'); break;
48: case "pdflib":
49: $opts->set('pdfBackend', 'PDFLib'); break;
50: default: // auto, pdf...
51: $opts->set('pdfBackend', 'auto'); break;
52: }
53: if (! empty($pdf_options['pdflib_license'])) {
54: $opts->set('pdflibLicense', $pdf_options['pdflib_license']);
55: }
56:
57: $opts->set('isHtml5ParserEnabled', true);
58: $opts->set('isPhpEnabled', false);
59: $opts->set('isJavascriptEnabled', false);
60: $opts->set('isRemoteEnabled', true);
61: # $opts->set('isFontSubsettingEnabled', false);
62:
63: $opts->set('defaultPaperSize', $pdf_options['paper_size']);
64: $opts->set('defaultPaperOrientation', $pdf_options['orientation']);
65: $opts->set('defaultMediaType', $pdf_options['media_type']);
66: $opts->set('defaultFont', $pdf_options['default_font']);
67: $opts->set('fontHeightRatio', $pdf_options['font_ratio']);
68: $opts->set('dpi', (int)$pdf_options['dpi']);
69:
70: $opts->set('debugKeepTemp', $this->debug);
71: $opts->set('debugPng', $this->debug);
72: $opts->set('debugCss', $this->debug);
73: $opts->set('debugLayout', $this->debug);
74: $opts->set('debugLayoutLines', $this->debug);
75: $opts->set('debugLayoutBlocks', $this->debug);
76: $opts->set('debugLayoutInline', $this->debug);
77: $opts->set('debugLayoutPaddingBox', $this->debug);
78:
79: if (! empty($this->paths['root_dir'])) {
80: $opts->setChroot([ $opts->getRootDir(), $this->paths['root_dir'] ]);
81: }
82: if (! empty($this->paths['path_logdir']) && $this->debug) {
83: if (! \is_dir($this->paths['path_logdir'])) @\mkdir($this->paths['path_logdir'], 0750, true);
84: $opts->set('logOutputFile', $this->paths['path_logdir']."/tic_dompdf.log");
85: }
86: if (! empty($this->paths['path_tmpdir'])) {
87: if (! \is_dir($this->paths['path_tmpdir']."/temp")) @\mkdir($this->paths['path_tmpdir']."/temp", 0750, true);
88: $opts->set('tempDir', $this->paths['path_tmpdir']."/temp");
89: if (! \is_dir($this->paths['path_tmpdir']."/fonts")) @\mkdir($this->paths['path_tmpdir']."/fonts", 0750, true);
90: $opts->set('fontDir', $this->paths['path_tmpdir']."/fonts");
91: if (! \is_dir($this->paths['path_tmpdir']."/cache")) @\mkdir($this->paths['path_tmpdir']."/cache", 0750, true);
92: $opts->set('fontCache', $this->paths['path_tmpdir']."/cache");
93: }
94:
95: if ($this->debug) dump($opts);
96:
97: if (isset($this->dompdf))
98: $this->dompdf->setOptions($opts);
99: else
100: $this->dompdf = new Dompdf($opts);
101:
102: if (! empty($pdf_options['base_url'])) {
103: list($protocol, $baseHost, $basePath) = Helpers::explode_url($pdf_options['base_url']);
104: $this->dompdf->setProtocol($protocol);
105: $this->dompdf->setBaseHost($baseHost);
106: $this->dompdf->setBasePath($basePath);
107: }
108:
109: return $this;
110: }
111:
112: // ------------------------------------------------------------------------------------------ LOADER
113:
114: /**
115: * Initialisation de l'objet Dompdf à partir d'un fichier HTML.
116: *
117: * @param string $html_file Chemin du fichier HTML à charger
118: * @param array $pdf_options Surcharge d'options pour Dompdf
119: * @return DompdfService
120: */
121: public function loadHtmlFile(string $html_file, array $pdf_options = []): DompdfService
122: {
123: unset($this->dompdf);
124: $this->initEngine($pdf_options);
125: $this->dompdf->loadHtmlFile($this->fixHtmlFile($html_file));
126: $this->dompdf->render();
127: return $this;
128: }
129:
130: /**
131: * Initialisation de l'objet Dompdf à partir d'un contenu HTML.
132: *
133: * @param string $html_data Contenu du document HTML à charger
134: * @param array $pdf_options Surcharge d'options pour Dompdf
135: * @return DompdfService
136: */
137: public function loadHtmlData(string $html_data, array $pdf_options = []): DompdfService
138: {
139: unset($this->dompdf);
140: $this->initEngine($pdf_options);
141: $this->dompdf->loadHtml($html_data);
142: $this->dompdf->render();
143: return $this;
144: }
145:
146: // ------------------------------------------------------------------------------------------ RENDER
147:
148: /**
149: * Returns the PDF data as a string.
150: *
151: * @param bool $nocompress Désactivation de la compression PDF
152: * @return string Données binaires du document PDF
153: */
154: public function renderData(bool $nocompress = false): string
155: {
156: return $this->dompdf->output([
157: "compress" => $nocompress ? 0 : 1, // default 1
158: ]);
159: }
160:
161: /**
162: * Output the generated PDF to Browser (native Dompdf method).
163: *
164: * @param string $filename Nom du document PDF à télécharger
165: * @param bool $inline Affichage du PDF sans forcer son enregistrement
166: * @param bool $nocompress Désactivation de la compression PDF
167: */
168: public function renderDirect(?string $filename = null, bool $inline = false, bool $nocompress = false): void
169: {
170: $this->dompdf->stream($this->fixFilename($filename), [
171: "Attachment" => ($inline) ? 0 : 1, // default 1
172: "compress" => ($nocompress) ? 0 : 1, // default 1
173: ]);
174: \exit(0);
175: }
176:
177: // ------------------------------------------------------------------------------------------ ALTER
178:
179: /**
180: * Add meta informations to the PDF after rendering
181: *
182: * @param array $info Liste de clés/valeurs pour ajouter des metadata PDF
183: * @return DompdfService
184: */
185: public function metadata(array $info = []): DompdfService
186: {
187: foreach ($info as $label => $value) $this->dompdf->addInfo($label, $value);
188: return $this;
189: }
190:
191: // ------------------------------------------------------------------------------------------ CHECKS
192:
193: protected function getFileType(string $type = "PDF"): ?array
194: {
195: if ($this->dompdf && ($this->dompdf->getOptions()->get('pdfBackend') == "GD")) $type = "PNG";
196: return parent::getFileType($type);
197: }
198:
199: }
200: