use custom fonts in mpdf via twig template (#3509)

This commit is contained in:
Alexander Pankow
2022-09-04 00:58:54 +02:00
committed by GitHub
parent 3f4f63dc33
commit a04b72e866
8 changed files with 104 additions and 11 deletions

View File

@@ -57,7 +57,8 @@ services:
$settings: '%kimai.config%' $settings: '%kimai.config%'
App\Utils\MPdfConverter: App\Utils\MPdfConverter:
arguments: ['%kernel.cache_dir%'] arguments:
$cacheDirectory: '%kernel.cache_dir%'
App\Plugin\PluginManager: App\Plugin\PluginManager:
arguments: [!tagged kimai.plugin] arguments: [!tagged kimai.plugin]

View File

@@ -14,19 +14,34 @@ namespace App\Export;
*/ */
final class ExportContext final class ExportContext
{ {
/**
* @var array
*/
private $options = []; private $options = [];
public function setOption(string $key, string $value): void /**
* @param string $key
* @param string|array $value
* @return void
*/
public function setOption(string $key, $value): void
{ {
$this->options[$key] = $value; $this->options[$key] = $value;
} }
/**
* @return array
*/
public function getOptions(): array public function getOptions(): array
{ {
return $this->options; return $this->options;
} }
public function getOption(string $key): ?string /**
* @param string $key
* @return array|string|null
*/
public function getOption(string $key)
{ {
if (\array_key_exists($key, $this->options)) { if (\array_key_exists($key, $this->options)) {
return $this->options[$key]; return $this->options[$key];

View File

@@ -17,13 +17,19 @@ use Mpdf\Output\Destination;
class MPdfConverter implements HtmlToPdfConverter class MPdfConverter implements HtmlToPdfConverter
{ {
/**
* @var FileHelper
*/
private $fileHelper;
/** /**
* @var string * @var string
*/ */
private $cacheDirectory; private $cacheDirectory;
public function __construct(string $cacheDirectory) public function __construct(FileHelper $fileHelper, string $cacheDirectory)
{ {
$this->fileHelper = $fileHelper;
$this->cacheDirectory = $cacheDirectory; $this->cacheDirectory = $cacheDirectory;
} }
@@ -33,7 +39,7 @@ class MPdfConverter implements HtmlToPdfConverter
$fonts = new FontVariables(); $fonts = new FontVariables();
$allowed = [ $allowed = [
'mode', 'format', 'default_font_size', 'default_font', 'margin_left', 'margin_right', 'margin_top', 'mode', 'format', 'default_font_size', 'default_font', 'margin_left', 'margin_right', 'margin_top',
'margin_bottom', 'margin_header', 'margin_footer', 'orientation' 'margin_bottom', 'margin_header', 'margin_footer', 'orientation', 'fonts',
]; ];
$filtered = array_filter($options, function ($key) use ($allowed, $configs, $fonts) { $filtered = array_filter($options, function ($key) use ($allowed, $configs, $fonts) {
@@ -66,8 +72,7 @@ class MPdfConverter implements HtmlToPdfConverter
['tempDir' => $this->cacheDirectory, 'exposeVersion' => false] ['tempDir' => $this->cacheDirectory, 'exposeVersion' => false]
); );
$mpdf = new Mpdf($options); $mpdf = $this->initMpdf($options);
$mpdf->creator = Constants::SOFTWARE;
// some OS do not follow the PHP default settings // some OS do not follow the PHP default settings
if ((int) ini_get('pcre.backtrack_limit') < 1000000) { if ((int) ini_get('pcre.backtrack_limit') < 1000000) {
@@ -97,4 +102,50 @@ class MPdfConverter implements HtmlToPdfConverter
return $mpdf->Output('', Destination::STRING_RETURN); return $mpdf->Output('', Destination::STRING_RETURN);
} }
/**
* @param array $options
* @return Mpdf
* @throws \Mpdf\MpdfException
* @throws \Exception
*/
private function initMpdf(array $options): Mpdf
{
$options['fontDir'] = $this->getFontDirectories();
$options['fontdata'] = $this->mergeFontData($options);
$mpdf = new Mpdf($options);
$mpdf->creator = Constants::SOFTWARE;
return $mpdf;
}
/**
* @return array
* @throws \Exception
*/
private function getFontDirectories(): array
{
$defaultConfig = (new ConfigVariables())->getDefaults();
$fontDirectories = $defaultConfig['fontDir'];
$fontDirectories[] = $this->fileHelper->getDataDirectory('fonts');
return $fontDirectories;
}
/**
* @param array $options
* @return array
*/
private function mergeFontData(array $options): array
{
$defaultFontConfig = (new FontVariables())->getDefaults();
$fontData = $defaultFontConfig['fontdata'];
if (\array_key_exists('fonts', $options)) {
$fontData = array_merge($fontData, $options['fonts']);
}
return $fontData;
}
} }

View File

@@ -11,6 +11,7 @@ namespace App\Tests\Export\Renderer;
use App\Export\Renderer\PDFRenderer; use App\Export\Renderer\PDFRenderer;
use App\Project\ProjectStatisticService; use App\Project\ProjectStatisticService;
use App\Tests\Mocks\FileHelperFactory;
use App\Utils\HtmlToPdfConverter; use App\Utils\HtmlToPdfConverter;
use App\Utils\MPdfConverter; use App\Utils\MPdfConverter;
use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Request;
@@ -49,7 +50,7 @@ class PdfRendererTest extends AbstractRendererTest
$twig = $kernel->getContainer()->get('twig'); $twig = $kernel->getContainer()->get('twig');
$stack = $kernel->getContainer()->get('request_stack'); $stack = $kernel->getContainer()->get('request_stack');
$cacheDir = $kernel->getContainer()->getParameter('kernel.cache_dir'); $cacheDir = $kernel->getContainer()->getParameter('kernel.cache_dir');
$converter = new MPdfConverter($cacheDir); $converter = new MPdfConverter((new FileHelperFactory($this))->create(), $cacheDir);
$request = new Request(); $request = new Request();
$request->setLocale('en'); $request->setLocale('en');
$stack->push($request); $stack->push($request);

View File

@@ -11,6 +11,7 @@ namespace App\Tests\Export\Timesheet;
use App\Export\Timesheet\PDFRenderer; use App\Export\Timesheet\PDFRenderer;
use App\Project\ProjectStatisticService; use App\Project\ProjectStatisticService;
use App\Tests\Mocks\FileHelperFactory;
use App\Utils\HtmlToPdfConverter; use App\Utils\HtmlToPdfConverter;
use App\Utils\MPdfConverter; use App\Utils\MPdfConverter;
use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Request;
@@ -42,7 +43,7 @@ class PdfRendererTest extends AbstractRendererTest
$twig = $kernel->getContainer()->get('twig'); $twig = $kernel->getContainer()->get('twig');
$stack = $kernel->getContainer()->get('request_stack'); $stack = $kernel->getContainer()->get('request_stack');
$cacheDir = $kernel->getContainer()->getParameter('kernel.cache_dir'); $cacheDir = $kernel->getContainer()->getParameter('kernel.cache_dir');
$converter = new MPdfConverter($cacheDir); $converter = new MPdfConverter((new FileHelperFactory($this))->create(), $cacheDir);
$request = new Request(); $request = new Request();
$request->setLocale('en'); $request->setLocale('en');
$stack->push($request); $stack->push($request);

View File

@@ -10,6 +10,7 @@
namespace App\Tests\Invoice\Renderer; namespace App\Tests\Invoice\Renderer;
use App\Invoice\Renderer\PdfRenderer; use App\Invoice\Renderer\PdfRenderer;
use App\Tests\Mocks\FileHelperFactory;
use App\Utils\MPdfConverter; use App\Utils\MPdfConverter;
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase; use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Request;
@@ -56,7 +57,7 @@ class PdfRendererTest extends KernelTestCase
$loader = $twig->getLoader(); $loader = $twig->getLoader();
$loader->addPath(__DIR__ . '/../templates/', 'invoice'); $loader->addPath(__DIR__ . '/../templates/', 'invoice');
$sut = new PdfRenderer($twig, new MPdfConverter($cacheDir)); $sut = new PdfRenderer($twig, new MPdfConverter((new FileHelperFactory($this))->create(), $cacheDir));
$model = $this->getInvoiceModel(); $model = $this->getInvoiceModel();
$document = $this->getInvoiceDocument('default.pdf.twig', true); $document = $this->getInvoiceDocument('default.pdf.twig', true);

View File

@@ -0,0 +1,22 @@
<?php
/*
* This file is part of the Kimai time-tracking app.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace App\Tests\Mocks;
use App\Utils\FileHelper;
class FileHelperFactory extends AbstractMockFactory
{
public function create(): FileHelper
{
$data = realpath(__DIR__ . '/../../var/data/');
return new FileHelper($data);
}
}

View File

@@ -9,6 +9,7 @@
namespace App\Tests\Utils; namespace App\Tests\Utils;
use App\Tests\Mocks\FileHelperFactory;
use App\Utils\MPdfConverter; use App\Utils\MPdfConverter;
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase; use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
@@ -28,7 +29,7 @@ class MPdfConverterTest extends KernelTestCase
$kernel = self::bootKernel(); $kernel = self::bootKernel();
$cacheDir = $kernel->getContainer()->getParameter('kernel.cache_dir'); $cacheDir = $kernel->getContainer()->getParameter('kernel.cache_dir');
$sut = new MPdfConverter($cacheDir); $sut = new MPdfConverter((new FileHelperFactory($this))->create(), $cacheDir);
$result = $sut->convertToPdf('<h1>Test</h1>'); $result = $sut->convertToPdf('<h1>Test</h1>');
// Yeah, thats not a real test, I know ;-) // Yeah, thats not a real test, I know ;-)
$this->assertNotEmpty($result); $this->assertNotEmpty($result);