diff options
Diffstat (limited to '')
-rw-r--r-- | library/Icinga/Common/PdfExport.php | 105 |
1 files changed, 105 insertions, 0 deletions
diff --git a/library/Icinga/Common/PdfExport.php b/library/Icinga/Common/PdfExport.php new file mode 100644 index 0000000..afea9bf --- /dev/null +++ b/library/Icinga/Common/PdfExport.php @@ -0,0 +1,105 @@ +<?php +/* Icinga Web 2 | (c) 2022 Icinga GmbH | GPLv2+ */ + +namespace Icinga\Common; + +use Icinga\Application\Icinga; +use Icinga\Date\DateFormatter; +use Icinga\Exception\ConfigurationError; +use Icinga\Module\Pdfexport\PrintableHtmlDocument; +use Icinga\Util\Environment; +use Icinga\Web\Controller; +use ipl\Html\Html; +use ipl\Html\HtmlString; +use ipl\Html\ValidHtml; +use ipl\Web\Compat\CompatController; +use ipl\Web\Url; + +trait PdfExport +{ + /** @var string The image to show in a pdf exports page header */ + private $pdfHeaderImage = 'img/icinga-logo-big-dark.png'; + + /** + * Export the requested action to PDF and send it + * + * @return never + * @throws ConfigurationError If the pdfexport module is not available + */ + protected function sendAsPdf() + { + if (! Icinga::app()->getModuleManager()->has('pdfexport')) { + throw new ConfigurationError('The pdfexport module is required for exports to PDF'); + } + + putenv('ICINGAWEB_EXPORT_FORMAT=pdf'); + Environment::raiseMemoryLimit('512M'); + Environment::raiseExecutionTime(300); + + $time = DateFormatter::formatDateTime(time()); + $iconPath = is_readable($this->pdfHeaderImage) + ? $this->pdfHeaderImage + : Icinga::app()->getBootstrapDirectory() . '/' . $this->pdfHeaderImage; + $encodedIcon = is_readable($iconPath) ? base64_encode(file_get_contents($iconPath)) : null; + $html = $this instanceof CompatController && ! $this->content->isEmpty() + ? $this->content + : $this->renderControllerAction(); + + $doc = (new PrintableHtmlDocument()) + ->setTitle($this->view->title) + ->setHeader(Html::wantHtml([ + Html::tag('span', ['class' => 'title']), + $encodedIcon + ? Html::tag('img', ['height' => 13, 'src' => 'data:image/png;base64,' . $encodedIcon]) + : null, + Html::tag('time', null, $time) + ])) + ->setFooter(Html::wantHtml([ + Html::tag('span', null, [ + t('Page') . ' ', + Html::tag('span', ['class' => 'pageNumber']), + ' / ', + Html::tag('span', ['class' => 'totalPages']) + ]), + Html::tag('p', null, rawurldecode(Url::fromRequest()->setParams($this->params))) + ])) + ->addHtml($html); + + if (($moduleName = $this->getRequest()->getModuleName()) !== 'default') { + $doc->getAttributes()->add('class', 'icinga-module module-' . $moduleName); + } + + \Icinga\Module\Pdfexport\ProvidedHook\Pdfexport::first()->streamPdfFromHtml($doc, sprintf( + '%s-%s', + $this->view->title ?: $this->getRequest()->getActionName(), + $time + )); + } + + /** + * Render the requested action + * + * @return ValidHtml + */ + protected function renderControllerAction() + { + /** @var Controller $this */ + $this->view->compact = true; + + $viewRenderer = $this->getHelper('viewRenderer'); + $viewRenderer->postDispatch(); + + $layoutHelper = $this->getHelper('layout'); + $oldLayout = $layoutHelper->getLayout(); + $layout = $layoutHelper->setLayout('inline'); + + $layout->content = $this->getResponse(); + $html = $layout->render(); + + // Restore previous layout and reset content, to properly show errors + $this->getResponse()->clearBody($viewRenderer->getResponseSegment()); + $layoutHelper->setLayout($oldLayout); + + return HtmlString::create($html); + } +} |