From d8e579a9e159929a33a9655584c23b3e044783a5 Mon Sep 17 00:00:00 2001 From: MyuTsu Date: Wed, 12 Nov 2025 16:33:53 +0100 Subject: [PATCH 1/2] fix(pdf): clean HTML tables to fit PDF page width to avoid overflow --- CHANGELOG.md | 5 + CHANGELOG.md.orig | 40 ++++ inc/simplepdf.class.php | 98 ++++++--- inc/simplepdf.class.php.orig | 415 +++++++++++++++++++++++++++++++++++ 4 files changed, 524 insertions(+), 34 deletions(-) create mode 100644 CHANGELOG.md.orig create mode 100644 inc/simplepdf.class.php.orig diff --git a/CHANGELOG.md b/CHANGELOG.md index c5290f6..48c52fd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,11 @@ and this project adheres to [Semantic Versioning](http://semver.org/). - GLPI 11 compatibility +### Fixed + +- Fixed table formatting and border in PDF +- Fixed table cell size in PDF generation + ## [4.0.2] - 2025-09-30 - Fix missing images in exported Knowledge Base PDFs diff --git a/CHANGELOG.md.orig b/CHANGELOG.md.orig new file mode 100644 index 0000000..99382f7 --- /dev/null +++ b/CHANGELOG.md.orig @@ -0,0 +1,40 @@ +# Change Log + +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](http://keepachangelog.com/) +and this project adheres to [Semantic Versioning](http://semver.org/). + +## [4.1.1] - 2025-10-30 + +## Fixed + +- Fix error message `Unknown '__s' function` + +## [4.1.0] - 2025-10-01 + +### Added + +- GLPI 11 compatibility + +### Fixed + +- Fixed table formatting and border in PDF +- Fixed table cell width in PDF generation + +## [4.0.2] - 2025-09-30 + +- Fix missing images in exported Knowledge Base PDFs +- Enhanced display of HTML content + +## [4.0.1] - 2025-03-10 + +### Added + +- Checking the compatibility of the Branding plugin + +## [4.0.0] - 2025-03-06 + +### Added + +- New option to use the Branding plugin logo in PDF headers diff --git a/inc/simplepdf.class.php b/inc/simplepdf.class.php index f1406f1..628e297 100644 --- a/inc/simplepdf.class.php +++ b/inc/simplepdf.class.php @@ -32,36 +32,6 @@ use Glpi\RichText\RichText; -/** - * ------------------------------------------------------------------------- - * LICENSE - * - * This file is part of PDF plugin for GLPI. - * - * PDF is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * PDF 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 Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with Reports. If not, see . - * - * @author Nelly Mahu-Lasson, Remi Collet, Teclib - * @copyright Copyright (c) 2009-2022 PDF plugin team - * @license AGPL License 3.0 or (at your option) any later version - * @link https://github.com/pluginsGLPI/pdf/ - * @link http://www.glpi-project.org/ - * @package pdf - * @since 2009 - * http://www.gnu.org/licenses/agpl-3.0-standalone.html - * -------------------------------------------------------------------------- - */ - //use TCPDF; define('K_PATH_IMAGES', ''); @@ -376,11 +346,29 @@ public function displayText($name, $content = '', $minline = 3, $maxline = 100) $this->setColumnsSize(100); $text = $name . ' ' . $content; - $content = RichText::getEnhancedHtml($text); - if (!preg_match("//", $content) && !preg_match('/

/', $content)) { - $content = nl2br($content); + $content = RichText::getEnhancedHtml($text, ['text_maxsize' => 0]); + + // Split content by tables, keeping tables in the result + $segments = preg_split('/(]*>.*?<\/table>)/is', $content, -1, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY); + + // Process segments and rebuild content + $formatted_content = ''; + foreach ($segments as $segment) { + if (str_contains($segment, 'cleanTableHtml($segment); + $formatted_content .= $segment; + } else { + // Apply nl2br only to text segments + if (!str_contains($segment, '')) { + $segment = nl2br($segment); + } + $formatted_content .= $segment; + } } - $this->displayInternal(240, 0.5, self::LEFT, $minline * 5, [$content]); + + $this->displayInternal(240, 0.5, self::LEFT, $minline * 5, [$formatted_content]); + /* Restore */ [$this->cols, $this->colsx, $this->colsw, $this->align, ] = $save; } @@ -395,6 +383,48 @@ public function displaySpace($nb = 1) $this->pdf->Ln(4 * $nb); } + /** + * Clean table HTML for proper PDF rendering + * Removes problematic attributes and styles that cause tables to overflow + * + * @param string $html Table HTML code + * @return string Cleaned HTML + */ + private function cleanTableHtml($html) + { + // Remove colgroup entirely (causes fixed widths) + $html = preg_replace('/]*>.*?<\/colgroup>/is', '', $html); + + // Remove table-layout:fixed style (prevents auto-sizing) + $html = preg_replace('/table-layout\s*:\s*fixed\s*;?/i', '', $html); + + // Remove ALL width styles from elements (including px, %, em, etc.) + $html = preg_replace('/\bwidth\s*:\s*[^;"\'>]+;?/i', '', $html); + + // Remove ALL height styles from elements + $html = preg_replace('/\bheight\s*:\s*[^;"\'>]+;?/i', '', $html); + + // Remove width attributes from any tag + $html = preg_replace('/(<[^>]+)\s+width\s*=\s*["\']?[^"\'\s>]+["\']?/i', '$1', $html); + + // Remove height attributes from any tag + $html = preg_replace('/(<[^>]+)\s+height\s*=\s*["\']?[^"\'\s>]+["\']?/i', '$1', $html); + + // Clean up empty style attributes and double spaces + $html = preg_replace('/\s+style\s*=\s*["\'][\s]*["\']/', '', $html); + $html = preg_replace('/\s+/', ' ', $html); + + // Add border to table if missing (for visibility) + if (!preg_match('/border\s*=\s*["\']?[1-9]/i', $html)) { + $html = preg_replace('/]*)>/i', '', $html, 1); + + return $html; + } + /** * Display an image * diff --git a/inc/simplepdf.class.php.orig b/inc/simplepdf.class.php.orig new file mode 100644 index 0000000..cbe36bd --- /dev/null +++ b/inc/simplepdf.class.php.orig @@ -0,0 +1,415 @@ +. + * + * @author Nelly Mahu-Lasson, Remi Collet, Teclib + * @copyright Copyright (c) 2009-2022 PDF plugin team + * @license AGPL License 3.0 or (at your option) any later version + * @link https://github.com/pluginsGLPI/pdf/ + * @link http://www.glpi-project.org/ + * @package pdf + * @since 2009 + * http://www.gnu.org/licenses/agpl-3.0-standalone.html + * -------------------------------------------------------------------------- + */ + +use Glpi\RichText\RichText; + +//use TCPDF; + +define('K_PATH_IMAGES', ''); +class PluginPdfSimplePDF +{ + // Page orientation + public const PORTRAIT = 'P'; + public const LANDSCAPE = 'L'; + + // Cell alignment + public const LEFT = 'L'; + public const CENTER = 'C'; + public const RIGHT = 'R'; + + private $pdf; + + // Page management + private $width; + private $height; + private $header = ''; // @phpstan-ignore-line - $header is never read, only written. + + // Columns management + private $cols = []; + private $colsx = []; + private $colsw = []; + private $align = []; + + /** + * Create a new PDF + * + * @param $format (default a4) + * @param $orient (default portrait) + **/ + public function __construct($format = 'A4', $orient = '') + { + /* Compat with 0.84 */ + if (empty($orient) || $orient == 'portrait') { + $orient = self::PORTRAIT; + } elseif ($orient == 'landscape') { + $orient = self::LANDSCAPE; + } + $format = strtoupper($format); + + $pdf = new TCPDF($orient, 'mm', $format, true, 'UTF-8', false); + + $pdf->SetCreator('GLPI'); + $pdf->SetAuthor('GLPI'); + $font = 'helvetica'; + if (isset($_SESSION['glpipdffont']) && $_SESSION['glpipdffont']) { + $font = $_SESSION['glpipdffont']; + } + + $pdf->setHeaderFont([$font, 'B', 8]); + $pdf->setFooterFont([$font, 'B', 8]); + + //set margins + $pdf->SetMargins(10, 20, 10); + $pdf->SetHeaderMargin(10); + $pdf->SetFooterMargin(10); + + //set auto page breaks + $pdf->SetAutoPageBreak(true, 15); + + + // For standard language + // set font + $pdf->SetFont($font, '', 8); + + $this->width = $pdf->getPageWidth() - 20; + $this->height = $pdf->getPageHeight() - 40; + $this->pdf = $pdf; + + $pdf->SetAllowLocalFiles(true); + } + + /** + * Set the title in each header + * + * @param $msg + **/ + public function setHeader($msg) + { + $this->header = $msg; + $this->pdf->resetHeaderTemplate(); + $this->pdf->SetTitle($msg); + $config = PluginPdfConfig::getInstance(); + + $params = [ + 'entities_id' => Session::getActiveEntity(), + 'logo' => '', + ]; + $hook = Plugin::doHookFunction('import_logo', $params); + if ( + !empty($hook['logo_path']) + && $config->getField('use_branding_logo') + ) { + $this->pdf->SetHeaderData($hook['logo_path'], 15, $msg, ''); + } else { + $path = Plugin::getPhpDir('pdf') . '/public/pics/'; + $this->pdf->SetHeaderData($path . 'fd_logo.png', 15, $msg, ''); + } + } + + /** + * Display the result in the browser + **/ + public function render() + { + $this->pdf->Output('glpi.pdf', 'I'); + } + + /** + * Get/save the result in the browser + * + * @param $name String optional filename + * + * @return string|void with PDF content if filename not provided + **/ + public function output($name = false) + { + if (!$name) { + return $this->pdf->Output('glpi.pdf', 'S'); + } + $this->pdf->Output($name, 'F'); + } + + /** + * Start a new page + **/ + public function newPage() + { + $this->pdf->AddPage(); + } + + /** + * Configure the width and number of colums + * + * param list of size in % of the page width + **/ + public function setColumnsSize() + { + $this->cols = $tmp = func_get_args(); + $this->colsx = []; + $this->colsw = []; + $this->align = []; + + $x = 10; + $w = floor($this->width - 2 * count($tmp)); + + while ($rel = array_shift($tmp)) { + $z = $w * $rel / 100; + $this->colsx[] = $x; + $this->colsw[] = $z; + $x += $z + 2; + } + } + + /** + * Configure the width and number of colums + * + * param list of alignment + **/ + public function setColumnsAlign() + { + $this->align = func_get_args(); + /* compat with 0.84 */ + foreach ($this->align as $k => $v) { + switch ($v) { + case 'left': $this->align[$k] = self::LEFT; + break; + case 'right': $this->align[$k] = self::RIGHT; + break; + case 'center': $this->align[$k] = self::CENTER; + break; + } + } + } + + /** + * does nothing, just raise a warning in the php-errors.log + * + * @deprecated, no more used (should have be private) + * + * @param $gray + **/ + public function displayBox($gray) + { + Toolbox::deprecated('Calling this function is deprecated'); + } + + /** + * display a row + * + * @param $gray Integer gray level of the backkgroun of each cell + * @param $padd Float cell padding (mm) + * @param $defalign String default column alignment is not set (setColumnsAlign) + * @param $miny Float minimum size of the row (mm) + * @param $msgs Array of strings to display + **/ + private function displayInternal($gray, $padd, $defalign, $miny, $msgs) + { + $this->pdf->SetFillColor($gray, $gray, $gray); + $this->pdf->SetCellPadding($padd); + + $max = $miny; + + /* dry run - compute max cell height */ + $this->pdf->startTransaction(); + $i = 0; + foreach ($msgs as $msg) { + if ($i < count($this->cols)) { + $this->pdf->writeHTMLCell( + $this->colsw[$i], // $w (float) Cell width. If 0, the cell extends up to the right margin. + $miny, // $h (float) Cell minimum height. The cell extends automatically if needed. + '', // $x (float) upper-left corner X coordinate + '', // $y (float) upper-left corner Y coordinate + $msg, // $html (string) html text to print. Default value: empty string. + 0, // $border (mixed) Indicates if borders must be drawn around the cell. The value can be a number:
  • 0: no border (default)
  • 1: frame
or a string containing some or all of the following characters (in any order):
  • L: left
  • T: top
  • R: right
  • B: bottom
or an array of line styles for each border group - for example: array('LTRB' => array('width' => 2, 'cap' => 'butt', 'join' => 'miter', 'dash' => 0, 'color' => array(0, 0, 0))) + 0, // $ln (int) Indicates where the current position should go after the call. Possible values are:
  • 0: to the right (or left for RTL language)
  • 1: to the beginning of the next line
  • 2: below
+ 1, // $fill (boolean) Indicates if the cell background must be painted (true) or transparent (false). + true, // $reseth (boolean) if true reset the last cell height (default true). + self::LEFT, // $align (string) Allows to center or align the text. Possible values are:
  • L : left align
  • C : center
  • R : right align
  • '' : empty string : left for LTR or right for RTL
+ true, // $autopadding (boolean) if true, uses internal padding and automatically adjust it to account for line width. + ); + if ($this->pdf->getLastH() > $max) { + $max = $this->pdf->getLastH(); + } + $i++; + } else { + break; + } + } + $this->pdf = $this->pdf->rollbackTransaction(); + + /* real run */ + $i = 0; + foreach ($msgs as $msg) { + if ($i < count($this->cols)) { + if (($i + 1) < count($msgs) && ($i + 1) < count($this->cols)) { + $ln = 0; // right + } else { + $ln = 1; // down + } + $this->pdf->SetX($this->colsx[$i]); + $align = ($this->align[$i] ?? $defalign); + $this->pdf->writeHTMLCell( + $this->colsw[$i], // $w (float) Cell width. If 0, the cell extends up to the right margin. + $max, // $h (float) Cell minimum height. The cell extends automatically if needed. + '', // $x (float) upper-left corner X coordinate + '', // $y (float) upper-left corner Y coordinate + $msg, // $html (string) html text to print. Default value: empty string. + 0, // $border (mixed) Indicates if borders must be drawn around the cell. The value can be a number:
  • 0: no border (default)
  • 1: frame
or a string containing some or all of the following characters (in any order):
  • L: left
  • T: top
  • R: right
  • B: bottom
or an array of line styles for each border group - for example: array('LTRB' => array('width' => 2, 'cap' => 'butt', 'join' => 'miter', 'dash' => 0, 'color' => array(0, 0, 0))) + $ln, // $ln (int) Indicates where the current position should go after the call. Possible values are:
  • 0: to the right (or left for RTL language)
  • 1: to the beginning of the next line
  • 2: below
+ 1, // $fill (boolean) Indicates if the cell background must be painted (true) or transparent (false). + true, // $reseth (boolean) if true reset the last cell height (default true). + $align, // $align (string) Allows to center or align the text. Possible values are:
  • L : left align
  • C : center
  • R : right align
  • '' : empty string : left for LTR or right for RTL
+ true, // $autopadding (boolean) if true, uses internal padding and automatically adjust it to account for line width. + ); + $i++; + } else { + break; + } + } + $this->pdf->SetY($this->pdf->GetY() + 1); + } + + /** + * display a Title row, centered with dark background + * + * param list of strings, one string per column + **/ + public function displayTitle() + { + $this->displayInternal(200, 1.0, self::CENTER, 1, func_get_args()); + } + + /** + * display a nomal row, default to left, with light background + * + * param list of strings, one string per column + **/ + public function displayLine() + { + $this->displayInternal(240, 0.5, self::LEFT, 1, func_get_args()); + } + + /** + * Display a single cell with a string + * + * @deprecated use displayLine with HTML + * + * @param $name String displayed text + * @param $URL String link + **/ + public function displayLink($name, $URL) + { + $this->displayInternal(240, 0.5, self::LEFT, 1, [sprintf('%s', $URL, $name)]); + } + + /** + * Display a multi-line Box : 1 column only + * + * @param $name string display on the left, before text + * @param $content string of text display on right (multi-line) + * @param $minline integer for minimum box size (default 3) + * @param $maxline integer for maximum box size (1 page = 80 lines) (default 100) (ignored) + **/ + public function displayText($name, $content = '', $minline = 3, $maxline = 100) + { + /* Save columns */ + $save = [$this->cols, $this->colsx, $this->colsw, $this->align]; + + $this->setColumnsSize(100); + $text = $name . ' ' . $content; + $content = RichText::getEnhancedHtml($text, ['text_maxsize' => 0]); + + // Split content by tables, keeping tables in the result + $segments = preg_split('/(]*>.*?<\/table>)/is', $content, -1, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY); + + // Process segments and rebuild content + $formatted_content = ''; + foreach ($segments as $segment) { + if (str_contains($segment, '')) { + $segment = nl2br($segment); + } + $formatted_content .= $segment; + } + } + + $this->displayInternal(240, 0.5, self::LEFT, $minline * 5, [$formatted_content]); + + /* Restore */ + [$this->cols, $this->colsx, $this->colsw, $this->align, ] = $save; + } + + /** + * Display space between row + * + * @param $nb (default 1) + **/ + public function displaySpace($nb = 1) + { + $this->pdf->Ln(4 * $nb); + } + + /** + * Display an image + * + * @param $image String path of the PNF file + * @param $dst_w Intefer Width in Pixels + * @param $dst_h Integer Height in Pixels + **/ + public function addPngFromFile($image, $dst_w, $dst_h) + { + $w = $this->pdf->pixelsToUnits($dst_w); + $h = $this->pdf->pixelsToUnits($dst_h); + + if ($this->pdf->GetY() + $h - 20 > $this->height) { /* autopagebreak seems broken */ + $this->pdf->AddPage(); + } + $this->pdf->Image( + $image, + '', // x + '', // y + $w, // $w + $h, // $w + 'PNG', // type + ); + + $this->pdf->SetY($this->pdf->GetY() + $h + 2); + } +} From 55150a5e84f4e2e2296a731afb6987420ed64746 Mon Sep 17 00:00:00 2001 From: MyuTsu Date: Wed, 12 Nov 2025 16:35:00 +0100 Subject: [PATCH 2/2] fix --- CHANGELOG.md.orig | 40 ---- inc/simplepdf.class.php.orig | 415 ----------------------------------- 2 files changed, 455 deletions(-) delete mode 100644 CHANGELOG.md.orig delete mode 100644 inc/simplepdf.class.php.orig diff --git a/CHANGELOG.md.orig b/CHANGELOG.md.orig deleted file mode 100644 index 99382f7..0000000 --- a/CHANGELOG.md.orig +++ /dev/null @@ -1,40 +0,0 @@ -# Change Log - -All notable changes to this project will be documented in this file. - -The format is based on [Keep a Changelog](http://keepachangelog.com/) -and this project adheres to [Semantic Versioning](http://semver.org/). - -## [4.1.1] - 2025-10-30 - -## Fixed - -- Fix error message `Unknown '__s' function` - -## [4.1.0] - 2025-10-01 - -### Added - -- GLPI 11 compatibility - -### Fixed - -- Fixed table formatting and border in PDF -- Fixed table cell width in PDF generation - -## [4.0.2] - 2025-09-30 - -- Fix missing images in exported Knowledge Base PDFs -- Enhanced display of HTML content - -## [4.0.1] - 2025-03-10 - -### Added - -- Checking the compatibility of the Branding plugin - -## [4.0.0] - 2025-03-06 - -### Added - -- New option to use the Branding plugin logo in PDF headers diff --git a/inc/simplepdf.class.php.orig b/inc/simplepdf.class.php.orig deleted file mode 100644 index cbe36bd..0000000 --- a/inc/simplepdf.class.php.orig +++ /dev/null @@ -1,415 +0,0 @@ -. - * - * @author Nelly Mahu-Lasson, Remi Collet, Teclib - * @copyright Copyright (c) 2009-2022 PDF plugin team - * @license AGPL License 3.0 or (at your option) any later version - * @link https://github.com/pluginsGLPI/pdf/ - * @link http://www.glpi-project.org/ - * @package pdf - * @since 2009 - * http://www.gnu.org/licenses/agpl-3.0-standalone.html - * -------------------------------------------------------------------------- - */ - -use Glpi\RichText\RichText; - -//use TCPDF; - -define('K_PATH_IMAGES', ''); -class PluginPdfSimplePDF -{ - // Page orientation - public const PORTRAIT = 'P'; - public const LANDSCAPE = 'L'; - - // Cell alignment - public const LEFT = 'L'; - public const CENTER = 'C'; - public const RIGHT = 'R'; - - private $pdf; - - // Page management - private $width; - private $height; - private $header = ''; // @phpstan-ignore-line - $header is never read, only written. - - // Columns management - private $cols = []; - private $colsx = []; - private $colsw = []; - private $align = []; - - /** - * Create a new PDF - * - * @param $format (default a4) - * @param $orient (default portrait) - **/ - public function __construct($format = 'A4', $orient = '') - { - /* Compat with 0.84 */ - if (empty($orient) || $orient == 'portrait') { - $orient = self::PORTRAIT; - } elseif ($orient == 'landscape') { - $orient = self::LANDSCAPE; - } - $format = strtoupper($format); - - $pdf = new TCPDF($orient, 'mm', $format, true, 'UTF-8', false); - - $pdf->SetCreator('GLPI'); - $pdf->SetAuthor('GLPI'); - $font = 'helvetica'; - if (isset($_SESSION['glpipdffont']) && $_SESSION['glpipdffont']) { - $font = $_SESSION['glpipdffont']; - } - - $pdf->setHeaderFont([$font, 'B', 8]); - $pdf->setFooterFont([$font, 'B', 8]); - - //set margins - $pdf->SetMargins(10, 20, 10); - $pdf->SetHeaderMargin(10); - $pdf->SetFooterMargin(10); - - //set auto page breaks - $pdf->SetAutoPageBreak(true, 15); - - - // For standard language - // set font - $pdf->SetFont($font, '', 8); - - $this->width = $pdf->getPageWidth() - 20; - $this->height = $pdf->getPageHeight() - 40; - $this->pdf = $pdf; - - $pdf->SetAllowLocalFiles(true); - } - - /** - * Set the title in each header - * - * @param $msg - **/ - public function setHeader($msg) - { - $this->header = $msg; - $this->pdf->resetHeaderTemplate(); - $this->pdf->SetTitle($msg); - $config = PluginPdfConfig::getInstance(); - - $params = [ - 'entities_id' => Session::getActiveEntity(), - 'logo' => '', - ]; - $hook = Plugin::doHookFunction('import_logo', $params); - if ( - !empty($hook['logo_path']) - && $config->getField('use_branding_logo') - ) { - $this->pdf->SetHeaderData($hook['logo_path'], 15, $msg, ''); - } else { - $path = Plugin::getPhpDir('pdf') . '/public/pics/'; - $this->pdf->SetHeaderData($path . 'fd_logo.png', 15, $msg, ''); - } - } - - /** - * Display the result in the browser - **/ - public function render() - { - $this->pdf->Output('glpi.pdf', 'I'); - } - - /** - * Get/save the result in the browser - * - * @param $name String optional filename - * - * @return string|void with PDF content if filename not provided - **/ - public function output($name = false) - { - if (!$name) { - return $this->pdf->Output('glpi.pdf', 'S'); - } - $this->pdf->Output($name, 'F'); - } - - /** - * Start a new page - **/ - public function newPage() - { - $this->pdf->AddPage(); - } - - /** - * Configure the width and number of colums - * - * param list of size in % of the page width - **/ - public function setColumnsSize() - { - $this->cols = $tmp = func_get_args(); - $this->colsx = []; - $this->colsw = []; - $this->align = []; - - $x = 10; - $w = floor($this->width - 2 * count($tmp)); - - while ($rel = array_shift($tmp)) { - $z = $w * $rel / 100; - $this->colsx[] = $x; - $this->colsw[] = $z; - $x += $z + 2; - } - } - - /** - * Configure the width and number of colums - * - * param list of alignment - **/ - public function setColumnsAlign() - { - $this->align = func_get_args(); - /* compat with 0.84 */ - foreach ($this->align as $k => $v) { - switch ($v) { - case 'left': $this->align[$k] = self::LEFT; - break; - case 'right': $this->align[$k] = self::RIGHT; - break; - case 'center': $this->align[$k] = self::CENTER; - break; - } - } - } - - /** - * does nothing, just raise a warning in the php-errors.log - * - * @deprecated, no more used (should have be private) - * - * @param $gray - **/ - public function displayBox($gray) - { - Toolbox::deprecated('Calling this function is deprecated'); - } - - /** - * display a row - * - * @param $gray Integer gray level of the backkgroun of each cell - * @param $padd Float cell padding (mm) - * @param $defalign String default column alignment is not set (setColumnsAlign) - * @param $miny Float minimum size of the row (mm) - * @param $msgs Array of strings to display - **/ - private function displayInternal($gray, $padd, $defalign, $miny, $msgs) - { - $this->pdf->SetFillColor($gray, $gray, $gray); - $this->pdf->SetCellPadding($padd); - - $max = $miny; - - /* dry run - compute max cell height */ - $this->pdf->startTransaction(); - $i = 0; - foreach ($msgs as $msg) { - if ($i < count($this->cols)) { - $this->pdf->writeHTMLCell( - $this->colsw[$i], // $w (float) Cell width. If 0, the cell extends up to the right margin. - $miny, // $h (float) Cell minimum height. The cell extends automatically if needed. - '', // $x (float) upper-left corner X coordinate - '', // $y (float) upper-left corner Y coordinate - $msg, // $html (string) html text to print. Default value: empty string. - 0, // $border (mixed) Indicates if borders must be drawn around the cell. The value can be a number:
  • 0: no border (default)
  • 1: frame
or a string containing some or all of the following characters (in any order):
  • L: left
  • T: top
  • R: right
  • B: bottom
or an array of line styles for each border group - for example: array('LTRB' => array('width' => 2, 'cap' => 'butt', 'join' => 'miter', 'dash' => 0, 'color' => array(0, 0, 0))) - 0, // $ln (int) Indicates where the current position should go after the call. Possible values are:
  • 0: to the right (or left for RTL language)
  • 1: to the beginning of the next line
  • 2: below
- 1, // $fill (boolean) Indicates if the cell background must be painted (true) or transparent (false). - true, // $reseth (boolean) if true reset the last cell height (default true). - self::LEFT, // $align (string) Allows to center or align the text. Possible values are:
  • L : left align
  • C : center
  • R : right align
  • '' : empty string : left for LTR or right for RTL
- true, // $autopadding (boolean) if true, uses internal padding and automatically adjust it to account for line width. - ); - if ($this->pdf->getLastH() > $max) { - $max = $this->pdf->getLastH(); - } - $i++; - } else { - break; - } - } - $this->pdf = $this->pdf->rollbackTransaction(); - - /* real run */ - $i = 0; - foreach ($msgs as $msg) { - if ($i < count($this->cols)) { - if (($i + 1) < count($msgs) && ($i + 1) < count($this->cols)) { - $ln = 0; // right - } else { - $ln = 1; // down - } - $this->pdf->SetX($this->colsx[$i]); - $align = ($this->align[$i] ?? $defalign); - $this->pdf->writeHTMLCell( - $this->colsw[$i], // $w (float) Cell width. If 0, the cell extends up to the right margin. - $max, // $h (float) Cell minimum height. The cell extends automatically if needed. - '', // $x (float) upper-left corner X coordinate - '', // $y (float) upper-left corner Y coordinate - $msg, // $html (string) html text to print. Default value: empty string. - 0, // $border (mixed) Indicates if borders must be drawn around the cell. The value can be a number:
  • 0: no border (default)
  • 1: frame
or a string containing some or all of the following characters (in any order):
  • L: left
  • T: top
  • R: right
  • B: bottom
or an array of line styles for each border group - for example: array('LTRB' => array('width' => 2, 'cap' => 'butt', 'join' => 'miter', 'dash' => 0, 'color' => array(0, 0, 0))) - $ln, // $ln (int) Indicates where the current position should go after the call. Possible values are:
  • 0: to the right (or left for RTL language)
  • 1: to the beginning of the next line
  • 2: below
- 1, // $fill (boolean) Indicates if the cell background must be painted (true) or transparent (false). - true, // $reseth (boolean) if true reset the last cell height (default true). - $align, // $align (string) Allows to center or align the text. Possible values are:
  • L : left align
  • C : center
  • R : right align
  • '' : empty string : left for LTR or right for RTL
- true, // $autopadding (boolean) if true, uses internal padding and automatically adjust it to account for line width. - ); - $i++; - } else { - break; - } - } - $this->pdf->SetY($this->pdf->GetY() + 1); - } - - /** - * display a Title row, centered with dark background - * - * param list of strings, one string per column - **/ - public function displayTitle() - { - $this->displayInternal(200, 1.0, self::CENTER, 1, func_get_args()); - } - - /** - * display a nomal row, default to left, with light background - * - * param list of strings, one string per column - **/ - public function displayLine() - { - $this->displayInternal(240, 0.5, self::LEFT, 1, func_get_args()); - } - - /** - * Display a single cell with a string - * - * @deprecated use displayLine with HTML - * - * @param $name String displayed text - * @param $URL String link - **/ - public function displayLink($name, $URL) - { - $this->displayInternal(240, 0.5, self::LEFT, 1, [sprintf('%s', $URL, $name)]); - } - - /** - * Display a multi-line Box : 1 column only - * - * @param $name string display on the left, before text - * @param $content string of text display on right (multi-line) - * @param $minline integer for minimum box size (default 3) - * @param $maxline integer for maximum box size (1 page = 80 lines) (default 100) (ignored) - **/ - public function displayText($name, $content = '', $minline = 3, $maxline = 100) - { - /* Save columns */ - $save = [$this->cols, $this->colsx, $this->colsw, $this->align]; - - $this->setColumnsSize(100); - $text = $name . ' ' . $content; - $content = RichText::getEnhancedHtml($text, ['text_maxsize' => 0]); - - // Split content by tables, keeping tables in the result - $segments = preg_split('/(]*>.*?<\/table>)/is', $content, -1, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY); - - // Process segments and rebuild content - $formatted_content = ''; - foreach ($segments as $segment) { - if (str_contains($segment, '')) { - $segment = nl2br($segment); - } - $formatted_content .= $segment; - } - } - - $this->displayInternal(240, 0.5, self::LEFT, $minline * 5, [$formatted_content]); - - /* Restore */ - [$this->cols, $this->colsx, $this->colsw, $this->align, ] = $save; - } - - /** - * Display space between row - * - * @param $nb (default 1) - **/ - public function displaySpace($nb = 1) - { - $this->pdf->Ln(4 * $nb); - } - - /** - * Display an image - * - * @param $image String path of the PNF file - * @param $dst_w Intefer Width in Pixels - * @param $dst_h Integer Height in Pixels - **/ - public function addPngFromFile($image, $dst_w, $dst_h) - { - $w = $this->pdf->pixelsToUnits($dst_w); - $h = $this->pdf->pixelsToUnits($dst_h); - - if ($this->pdf->GetY() + $h - 20 > $this->height) { /* autopagebreak seems broken */ - $this->pdf->AddPage(); - } - $this->pdf->Image( - $image, - '', // x - '', // y - $w, // $w - $h, // $w - 'PNG', // type - ); - - $this->pdf->SetY($this->pdf->GetY() + $h + 2); - } -}