diff --git a/library/Icinga/File/Pdf.php b/library/Icinga/File/Pdf.php index d95d0df3e..6239459fd 100644 --- a/library/Icinga/File/Pdf.php +++ b/library/Icinga/File/Pdf.php @@ -5,6 +5,7 @@ namespace Icinga\File; use \DOMPDF; use \DOMDocument; use \DOMXPath; +use \DOMNode; require_once 'vendor/dompdf/dompdf_config.inc.php'; @@ -20,7 +21,14 @@ class Pdf extends DOMPDF public $rowsPerPage = 10; /** - * If occuring tables should be split up into smaller tables to avoid errors in the document layout. + * If tables should only start at new pages. + * + * @var bool + */ + public $tableInitialPageBreak = false; + + /** + * If occurring tables should be split up into smaller tables to avoid errors in the document layout. * * @var bool */ @@ -45,7 +53,10 @@ class Pdf extends DOMPDF . '' . ''; if ($this->paginateTable === true) { - $html = $this->paginateHtmlTables($html); + $doc = new DOMDocument(); + @$doc->loadHTML($html); + $this->paginateHtmlTables($doc); + $html = $doc->saveHtml(); } $this->load_html($html); $this->render(); @@ -56,22 +67,23 @@ class Pdf extends DOMPDF * * NOTE: This is a workaround to fix the buggy page-break on table-rows in dompdf. * - * @param string A html-string. + * @param DOMDocument $doc The html document containing the tables. * - * @return string The html string with the paginated rows. + * @return array All paginated tables from the document. */ - private function paginateHtmlTables($html) + private function paginateHtmlTables(DOMDocument $doc) { - $doc = new DOMDocument(); - @$doc->loadHTML($html); - $xpath = new DOMXPath($doc); + $xpath = new DOMXPath($doc); + $tables = $xpath->query('.//table'); + $paginated = array(); + $j = 0; - $tables = $xpath->query('.//table'); foreach ($tables as $table) { $containerType = null; $rows = $xpath->query('.//tr', $table); $rowCnt = $rows->length; $tableCnt = (Integer)ceil($rowCnt / $this->rowsPerPage); + $paginated[$j] = array(); if ($rowCnt <= $this->rowsPerPage) { continue; } @@ -87,22 +99,21 @@ class Pdf extends DOMPDF $containers = array(); $pages = array(); - // insert page-break - $div = $doc->createElement('div'); - $div->setAttribute('style', 'page-break-before: always;'); - $table->parentNode->insertBefore($div, $table); - + if ($this->tableInitialPageBreak) { + $this->pageBreak($doc, $table); + } for ($i = 0; $i < $tableCnt; $i++) { // clone table $currentPage = $table->cloneNode(true); $pages[$i] = $currentPage; $table->parentNode->insertBefore($currentPage, $table); + // put it in current paginated table + $paginated[$j] = $currentPage; + // insert page-break if ($i < $tableCnt - 1) { - $div = $doc->createElement('div'); - $div->setAttribute('style', 'page-break-before: always;'); - $table->parentNode->insertBefore($div, $table); + $this->pageBreak($doc, $table); } // fetch row container @@ -114,14 +125,21 @@ class Pdf extends DOMPDF foreach ($rows as $row) { $p = (Integer)floor($i / $this->rowsPerPage); $containers[$p]->appendChild($row); - //echo "Inserting row $i into container $p
"; $i++; } // remove original table $table->parentNode->removeChild($table); + $j++; } - return $doc->saveHTML(); + return $paginated; + } + + private function pageBreak($doc, $before) + { + $div = $doc->createElement('div'); + $div->setAttribute('style', 'page-break-before: always;'); + $before->parentNode->insertBefore($div, $before); } /** @@ -136,40 +154,6 @@ class Pdf extends DOMPDF { $css = preg_replace('/\*:\s*before\s*,\s*/', '', $css); $css = preg_replace('/\*\s*:\s*after\s*\{[^\}]*\}/', '', $css); - - - // TODO: Move into own .css file that is loaded when requesting a pdf - return $css . "\n" - . '*, html { font-size: 100%; } ' . "\n" - - . 'form { display: none; }' . "\n" - - // Insert page breaks - . 'div.pdf-page { page-break-before: always; } ' . "\n" - - // Don't show any link outline - . 'a { outline: 0; }' . "\n" - - // Fix badge positioning - . 'span.badge { float: right; max-width: 5px; }' - - // prevent table rows from growing too big on page breaks - . 'tr { max-height: 30px; height: 30px; } ' . "\n" - - // Hide buttons - . '*.button { display: none; }' . "\n" - . '*.btn-group { display: none; }' . "\n" - . 'button > i { display: none; }' . "\n" - - // Hide navigation - . '*.nav {display: none; }' . "\n" - . '*.nav > li { display: none; }' . "\n" - . '*.nav > li > a { display: none; }' . "\n" - - // Hide pagination - . '*.pagination { display: none; }' . "\n" - . '*.pagination > li { display: none; }' . "\n" - . '*.pagination > li > a { display: none; }' . "\n" - . '*.pagination > li > span { display: none; }' . "\n"; + return $css; } } diff --git a/library/Icinga/Web/Controller/ActionController.php b/library/Icinga/Web/Controller/ActionController.php index 682bd25cd..9cef30dbe 100755 --- a/library/Icinga/Web/Controller/ActionController.php +++ b/library/Icinga/Web/Controller/ActionController.php @@ -241,44 +241,49 @@ class ActionController extends Zend_Controller_Action } } if ($this->_request->getParam('format') === 'pdf' && $this->_request->getControllerName() !== 'static') { - $this->sendAsPdf(); - die(); + $this->sendAsPdfAndDie(); } } - protected function sendAsPdf() + protected function sendAsPdfAndDie() { + $this->_helper->layout()->setLayout('inline'); $body = $this->view->render( $this->_request->getControllerName() . '/' . $this->_request->getActionName() . '.phtml' ); if (!headers_sent()) { $css = $this->view->getHelper('action')->action('stylesheet', 'static', 'application'); - $pdf = new PDF(); + // fix css for pdf + require_once 'vendor/lessphp/lessc.inc.php'; + $lessc = new \lessc(); + $publicDir = realpath(dirname($_SERVER['SCRIPT_FILENAME'])); + $css .= $lessc->compile($publicDir . '/css/icinga/pdf.less'); + + $pdf = new PDF(); if ($this->_request->getControllerName() === 'list') { switch ($this->_request->getActionName()) { case 'notifications': - $pdf->rowsPerPage = 8; + $pdf->rowsPerPage = 7; break; case 'comments': - $pdf->rowsPerPage = 8; + $pdf->rowsPerPage = 7; break; default: - $pdf->rowsPerPage = 12; + $pdf->rowsPerPage = 11; break; } } else { $pdf->paginateTable = false; } - $pdf->renderPage($body, $css); $pdf->stream( $this->_request->getControllerName() . '-' . $this->_request->getActionName() . '-' . time() . '.pdf' ); } else { Logger::error('Could not send pdf-response, content already written to output.'); - die(); } + die(); } /** diff --git a/modules/monitoring/application/views/helpers/SelectionToolbar.php b/modules/monitoring/application/views/helpers/SelectionToolbar.php index ce4aa2c34..32f07325b 100644 --- a/modules/monitoring/application/views/helpers/SelectionToolbar.php +++ b/modules/monitoring/application/views/helpers/SelectionToolbar.php @@ -13,13 +13,11 @@ class Zend_View_Helper_SelectionToolbar extends Zend_View_Helper_Abstract public function selectionToolbar($type, $target = null) { if ($type == 'multi') { - return 'Select - All - None '; - + return '
Select ' + . ' All ' + . ' None
'; } else if ($type == 'single') { - return 'Select None '; - + return '
Select None
'; } else { return ''; } diff --git a/public/css/icinga/pdf.less b/public/css/icinga/pdf.less new file mode 100644 index 000000000..c735ec95b --- /dev/null +++ b/public/css/icinga/pdf.less @@ -0,0 +1,100 @@ +// {{{ICINGA_LICENSE_HEADER}}} +/** + * This file is part of Icinga Web 2. + * + * Icinga Web 2 - Head for multiple monitoring backends. + * Copyright (C) 2013 Icinga Development Team + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * @copyright 2013 Icinga Development Team + * @license http://www.gnu.org/licenses/gpl-2.0.txt GPL, version 2 + * @author Icinga Development Team + * + */ +// {{{ICINGA_LICENSE_HEADER}}} + +*, html { + font-size: 100%; +} + +form { + display: none; +} + +// Insert page breaks +div.pdf-page { + page-break-before: always; +} + +div.selection-toolbar { + display: none; +} +div.selection-toolbar > a { + display: none; +} + +// Dont show any link outline +a { + outline: 0; +} + +// Fix badge positioning +span.badge { + float: right; + max-width: 5px; +} + +// prevent table rows from growing too big on page breaks +tr { + max-height: 30px; + height: 30px; +} + +// Hide buttons +*.button { + display: none; +} +*.btn-group, *.btn-group > a { + display: none; +} +button > i { + display: none; +} + +// Hide navigation +*.nav { + display: none; +} +*.nav > li { + display: none; +} +*.nav > li > a { + display: none; +} + +// Hide pagination +*.pagination { + display: none; +} +*.pagination > li { + display: none; +} +*.pagination > li > a { + display: none; +} +*.pagination > li > span { + display: none; +} \ No newline at end of file