breakdownCalculator->compute($booking); if (null === $breakdown) { throw new \RuntimeException('Für diese Buchung liegt keine Preisaufschlüsselung vor.'); } $html = $this->twig->render(self::TEMPLATE, [ 'booking' => $booking, 'priceBreakdown' => $breakdown, 'currency' => $booking->getPricingCurrency() ?? $breakdown['currency'], 'logoSrc' => $this->logoDataUri(), ]); $options = new Options(); // DejaVu Sans ships with dompdf and covers umlauts and the currency symbols // emitted by format_currency. $options->setDefaultFont('DejaVu Sans'); $options->setDefaultPaperSize('A4'); $options->setDefaultPaperOrientation('portrait'); $options->setIsRemoteEnabled(false); $dompdf = new Dompdf($options); $dompdf->loadHtml($html, 'UTF-8'); $dompdf->render(); return (string) $dompdf->output(); } /** * @throws \RuntimeException when the booking carries no price information */ public function createDownloadResponse(AccommodationBooking $booking): Response { $response = new Response($this->render($booking)); $response->headers->set('Content-Type', 'application/pdf'); $response->headers->set('Content-Disposition', $response->headers->makeDisposition( ResponseHeaderBag::DISPOSITION_ATTACHMENT, $this->buildFilename($booking) )); return $response; } /** * Named after arrival date and group rather than the entity id, which is a local * detail with no counterpart in BusPro and would read as a booking number. */ /** * @throws \RuntimeException when the booking carries no price information */ public function createAttachment(AccommodationBooking $booking): PdfAttachment { return new PdfAttachment($this->render($booking), $this->buildFilename($booking)); } private function buildFilename(AccommodationBooking $booking): string { $groupName = (new AsciiSlugger('de'))->slug((string) $booking->getGroupName())->lower()->toString(); return sprintf( '%s-%s%s.pdf', mb_strtolower($booking->recordLabel()), $booking->getDateFrom()?->format('Y-m-d') ?? 'ohne-datum', '' !== $groupName ? '-'.$groupName : '' ); } private function logoDataUri(): string { $logo = $this->projectDir.self::LOGO_PATH; if (false === is_readable($logo)) { throw new \RuntimeException('Das Logo konnte nicht gelesen werden: '.self::LOGO_PATH); } return 'data:image/png;base64,'.base64_encode((string) file_get_contents($logo)); } }