All checks were successful
Deploy bericht / deploy (push) Successful in 1s
TCPDF_FONTS::addTTFfont registriert jede TTF als eigene Family ohne Styles (hackregular, hackbold, hackitalic, hackbolditalic). SetFont(key,'B') suchte dann nach 'hack.php' und brach mit 'Could not include font definition file' ab. Fix: hack_font_styles-Map ['' / B / I / BI] => family, SetFont-Override mapped den angeforderten Style auf die passende Family mit leerem Style und fällt kaskadierend zurück (BI→B→'', I→'').
135 lines
5.6 KiB
PHP
135 lines
5.6 KiB
PHP
<?php
|
|
/**
|
|
* BerichtPdf — TCPDF/FPDI-Subclass mit Header, Footer und Hack-Font-Setup
|
|
* für das Bericht-Modul.
|
|
*
|
|
* Header: links Bericht-Titel + Firmenname, rechts Firmen-Logo, Trennlinie.
|
|
* Footer: zentriert "Seite X / Y".
|
|
* Font: Hack-TTFs werden in ein beschreibbares DOL_DATA_ROOT/bericht/tcpdf_fonts/
|
|
* kompiliert und per AddFont an die PDF-Instance gebunden.
|
|
*/
|
|
|
|
trait BerichtPdfTrait
|
|
{
|
|
public $hack_font_key = 'helvetica';
|
|
public $hack_font_styles = array(); // style => font-family-key
|
|
public $bericht_title = '';
|
|
public $bericht_company = '';
|
|
public $bericht_logo = '';
|
|
|
|
/**
|
|
* Muss direkt nach der Konstruktion aufgerufen werden.
|
|
*/
|
|
public function berichtInit($title, $company, $logo_path)
|
|
{
|
|
$this->bericht_title = (string) $title;
|
|
$this->bericht_company = (string) $company;
|
|
$this->bericht_logo = (string) $logo_path;
|
|
|
|
// Hack-Font registrieren (Eddys Corporate-Font)
|
|
if (class_exists('TCPDF_FONTS') && defined('DOL_DATA_ROOT')) {
|
|
$fontdir = dirname(__DIR__).'/fonts/';
|
|
$outdir = DOL_DATA_ROOT.'/bericht/tcpdf_fonts/';
|
|
if (!is_dir($outdir)) @mkdir($outdir, 0755, true);
|
|
if (is_dir($outdir) && is_writable($outdir)) {
|
|
$map = array(
|
|
'' => 'Hack-Regular.ttf',
|
|
'B' => 'Hack-Bold.ttf',
|
|
'I' => 'Hack-Italic.ttf',
|
|
'BI' => 'Hack-BoldItalic.ttf',
|
|
);
|
|
foreach ($map as $style => $fn) {
|
|
$src = $fontdir.$fn;
|
|
if (!file_exists($src)) continue;
|
|
try {
|
|
$k = TCPDF_FONTS::addTTFfont($src, 'TrueTypeUnicode', '', 32, $outdir);
|
|
if ($k) {
|
|
$ffile = $outdir.$k.'.php';
|
|
if (file_exists($ffile)) {
|
|
// WICHTIG: Jede TTF wird als eigene Family mit style='' registriert,
|
|
// sonst sucht TCPDF bei SetFont(..., 'B') nach "hackB.php" und
|
|
// bricht mit "Could not include font definition file" ab.
|
|
$this->AddFont($k, '', $ffile);
|
|
$this->hack_font_styles[$style] = $k;
|
|
}
|
|
}
|
|
} catch (Throwable $e) {
|
|
error_log('[BerichtPdf] Hack-Font '.$fn.' fehlgeschlagen: '.$e->getMessage());
|
|
}
|
|
}
|
|
if (!empty($this->hack_font_styles[''])) {
|
|
$this->hack_font_key = $this->hack_font_styles[''];
|
|
}
|
|
} else {
|
|
error_log('[BerichtPdf] Font-Outdir nicht schreibbar: '.$outdir);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Leitet SetFont() um, wenn die Family einer unserer Hack-Varianten ist:
|
|
* ein Style-Wechsel ('B'/'I'/'BI') wird auf die passende Hack-Family mit
|
|
* leerem Style gemappt. So vermeiden wir den TCPDF-Fallback auf "hack.php".
|
|
*/
|
|
public function SetFont($family, $style = '', $size = null, $fontfile = '', $subset = 'default', $out = true)
|
|
{
|
|
$fam = strtolower($family);
|
|
$is_hack = in_array($fam, $this->hack_font_styles, true);
|
|
if ($is_hack && !empty($this->hack_font_styles)) {
|
|
$st = strtoupper(str_replace('U', '', (string) $style));
|
|
if (!isset($this->hack_font_styles[$st])) {
|
|
// Kaskade: BI → B → '', I → ''
|
|
if ($st === 'BI' && isset($this->hack_font_styles['B'])) $st = 'B';
|
|
elseif (isset($this->hack_font_styles[''])) $st = '';
|
|
}
|
|
$target = $this->hack_font_styles[$st] ?? $this->hack_font_styles[''] ?? $family;
|
|
return parent::SetFont($target, '', $size, $fontfile, $subset, $out);
|
|
}
|
|
return parent::SetFont($family, $style, $size, $fontfile, $subset, $out);
|
|
}
|
|
|
|
public function Header()
|
|
{
|
|
$pageW = $this->getPageWidth();
|
|
$logo_w = 0;
|
|
if ($this->bericht_logo && file_exists($this->bericht_logo)) {
|
|
$info = @getimagesize($this->bericht_logo);
|
|
if ($info && $info[0] && $info[1]) {
|
|
$maxW = 40; $maxH = 18;
|
|
$ratio = min($maxW / $info[0], $maxH / $info[1]);
|
|
$w = $info[0] * $ratio;
|
|
$h = $info[1] * $ratio;
|
|
$this->Image($this->bericht_logo, $pageW - 10 - $w, 6, $w, $h);
|
|
$logo_w = $w;
|
|
}
|
|
}
|
|
$this->SetTextColor(40, 40, 40);
|
|
$this->SetFont($this->hack_font_key, 'B', 13);
|
|
$this->SetXY(10, 8);
|
|
$textW = $pageW - 20 - $logo_w - 4;
|
|
$this->Cell($textW, 6, $this->bericht_title, 0, 2, 'L');
|
|
if ($this->bericht_company) {
|
|
$this->SetFont($this->hack_font_key, '', 9);
|
|
$this->SetX(10);
|
|
$this->Cell($textW, 5, $this->bericht_company, 0, 2, 'L');
|
|
}
|
|
$this->SetDrawColor(180, 180, 180);
|
|
$this->SetLineWidth(0.2);
|
|
$this->Line(10, 27, $pageW - 10, 27);
|
|
}
|
|
|
|
public function Footer()
|
|
{
|
|
$this->SetY(-12);
|
|
$this->SetFont($this->hack_font_key, '', 9);
|
|
$this->SetTextColor(100, 100, 100);
|
|
$txt = 'Seite '.$this->getAliasNumPage().' / '.$this->getAliasNbPages();
|
|
$this->Cell(0, 8, $txt, 0, 0, 'C');
|
|
}
|
|
}
|
|
|
|
class BerichtPdf extends TCPDF { use BerichtPdfTrait; }
|
|
|
|
if (class_exists('\\setasign\\Fpdi\\Tcpdf\\Fpdi')) {
|
|
class BerichtPdfFpdi extends \setasign\Fpdi\Tcpdf\Fpdi { use BerichtPdfTrait; }
|
|
}
|