src/Service/TemplatesService.php line 202
<?phpdeclare(strict_types=1);/** This file is part of the guesthouse administration package.** (c) Alexander Elchlepp <info@fewohbee.de>** For the full copyright and license information, please view the LICENSE* file that was distributed with this source code.*/namespace App\Service;use App\Entity\Correspondence;use App\Entity\Entreprise;use App\Entity\FileCorrespondence;use App\Entity\Invoice;use App\Entity\Location;use App\Entity\MailAttachment;use App\Entity\Payment;use App\Entity\Reservation;use App\Entity\Template;use App\Entity\TemplateType;use App\Entity\User;use App\Interfaces\ITemplateRenderer;use Doctrine\ORM\EntityManagerInterface;use Symfony\Component\HttpFoundation\Request;use Symfony\Component\HttpFoundation\RequestStack;use Symfony\Contracts\Translation\TranslatorInterface;use Twig\Environment;class TemplatesService{private $em = null;private $app = null;private $requestStack;private $mpdfs;private $twig;private $webHost;private $translator;public function __construct(string $webHost, Environment $twig, EntityManagerInterface $em, RequestStack $requestStack, MpdfService $mpdfs, TranslatorInterface $translator){$this->em = $em;$this->requestStack = $requestStack;$this->mpdfs = $mpdfs;$this->twig = $twig;$this->webHost = $webHost;$this->translator = $translator;}/*** Extract form data and return Template object.** @param string $id** @return Template*/public function getEntityFromForm(Request $request, $id = 'new'){$template = new Template();if ('new' !== $id) {$template = $this->em->getRepository(Template::class)->find($id);}$templateId = $request->request->get('type-'.$id);$type = $this->em->getRepository(TemplateType::class)->find($templateId);if (!($type instanceof TemplateType)) {// throw ""}$template->setTemplateType($type);$template->setName(trim($request->request->get('name-'.$id)));$template->setText($request->request->get('text-'.$id));$template->setParams($request->request->get('params-'.$id));if ($request->request->has('default-'.$id)) {$template->setIsDefault(true);} else {$template->setIsDefault(false);}if ('new' === $id) {$userId = $request->request->get('user-'.$id);$user = $this->em->getRepository(User::class)->find($userId);$template->setCreatedBy($user);$marchand = $this->em->getRepository(Entreprise::class)->find($user->getEntreprise());$template->setMarchand($marchand);}return $template;}/*** Delete entity.** @param int $id** @return bool*/public function deleteEntity($id){$template = $this->em->getRepository(Template::class)->find($id);$this->em->remove($template);$this->em->flush();return true;}public function renderTemplateForReservations($templateId, $reservations){/* @var $template \App\Entity\Template */$template = $this->em->getRepository(Template::class)->find($templateId);$templateStr = $this->twig->createTemplate($template->getText());return $templateStr->render(['reservations' => $reservations,]);}public function renderTemplate(int $templateId, mixed $param, ITemplateRenderer $serviceObj, $type): string{/* @var $template Template */$template = $this->em->getRepository(Template::class)->find($templateId);$params = [];if($type == 2){$service = 'InvoiceTemplateService';}else{$service = $template->getTemplateType()->getService();}if (!empty($service)) {// each service must implement the ITemplateRenderer interface$params = $serviceObj->getRenderParams($template, $param);}$str = $this->replaceTwigSyntax($template->getText());$templateStr = $this->twig->createTemplate($str);return $templateStr->render($params);}public function getReferencedReservationsInSession(){$reservations = [];if ($this->requestStack->getSession()->has('selectedReservationIds')) {$selectedReservationIds = $this->requestStack->getSession()->get('selectedReservationIds');foreach ($selectedReservationIds as $id) {$reservations[] = $this->em->getReference(Location::class, $id);}}return $reservations;}public function addFileAsAttachment($cId, $reservations){$fileIds = [];foreach ($reservations as $reservation) {// save file ids in context of reservation id$fileIds[$reservation->getId()] = $cId;}$attachments = $this->requestStack->getSession()->get('templateAttachmentIds');$attachments[] = $fileIds;$this->requestStack->getSession()->set('templateAttachmentIds', $attachments);return true;}/*** Returns a MailAttachment entity which can be passed to Mailer.** @param type $attachmentId*/public function getMailAttachment($attachmentId): ?MailAttachment{/* @var $attachment \App\Entity\Correspondence */$attachment = $this->em->getRepository(Correspondence::class)->find($attachmentId);if ($attachment instanceof FileCorrespondence) {$data = $this->getPDFOutput($attachment->getText(), $attachment->getName(), $attachment->getTemplate(), true);return new MailAttachment($data, $attachment->getName().'.pdf', 'application/pdf');}return null;}public function getPDFOutput($input, $name, $template, $noResponseOutput = false){/** I: send the file inline to the browser. The plug-in is used if available. The name given by filename is used when one selects the "Save as" option on the link generating the PDF.* D: send to the browser and force a file download with the name given by filename.* F: save to a local file with the name given by filename (may include a path).* S: return the document as a string. filename is ignored.*/$dest = ($noResponseOutput ? 'S' : 'D');$mpdf = $this->mpdfs->getMpdf();$params = json_decode($template->getParams());$mpdf->addPage($params->orientation,'','','','',$params->marginLeft,$params->marginRight,$params->marginTop,$params->marginBottom,$params->marginHeader,$params->marginFooter);$inputMapped = $this->mapImageSrc($input);/** mode* 0 - Use this (default) if the text you pass is a complete HTML page including head and body and style definitions.* 1 - Use this when you want to set a CSS stylesheet* 2 - Write HTML code without the <head> information. Does not need to be contained in <body>*/$mpdf->WriteHTML($inputMapped, 0);return $mpdf->Output($name.'.pdf', $dest);}/*** This maps the src of images to the real web host.* This is sometimes needed e.g. when using it with docker.* The docker web host is "web" when the application is requested via "localhost" in the browser,* mpdf uses the host from the request, which is localhost. But there is no web server listening on localhost in the php container.* That's why we need to change the src to the real host "web".** @param string $input** @return string*/private function mapImageSrc($input){$host = rtrim($this->webHost, '/').'/';return preg_replace('/src="\/(.*)"/i', 'src="'.$host.'$1"', $input);}/*** Returns the default Template or null.** @param Template[] $templates*/public function getDefaultTemplate(array $templates): ?Template{// find default templateforeach ($templates as $template) {if ($template->getIsDefault()) {return $template;}}return null;}private function replaceTwigSyntax(string $string): string{$t1 = str_replace('[[', '{{', $string);$t2 = str_replace(']]', '}}', $t1);$t3 = str_replace('[%', '{%', $t2);$t4 = str_replace('%]', '%}', $t3);$t5 = str_replace('[#', '{#', $t4);$t6 = str_replace('#]', '#}', $t5);$t7 = preg_replace("/<div class=\"footer\">(.*)<\/div>/s", '<htmlpagefooter name="footer">$1</htmlpagefooter><sethtmlpagefooter name="footer" value="on"></sethtmlpagefooter>', $t6);return $t7;}public function getRenderParams(Template $template, mixed $param){$payments = [];$payment = $this->em->getRepository(Payment::class)->find($param);$payments[] = $payment;$invoice = $payment->getInvoice();$grandTotal = $payment->getAmount();$vatSums = [];$brutto = 0;$netto = 0;$appartmantTotal = 0;$miscTotal = 0;$params = ['invoice' => $invoice,'payments' => $payments,'grandTotal' => $grandTotal,'vats' => $vatSums,'brutto' => $brutto,'netto' => $netto,'bruttoFormated' => number_format($brutto, 2, ',', '.'),'nettoFormated' => number_format($brutto - $netto, 2, ',', '.'),'appartmentTotal' => number_format($appartmantTotal, 2, ',', '.'),'miscTotal' => number_format($miscTotal, 2, ',', '.'),];return $params;}}