From a04b72e866375a64b1c90a9f2514ef054d4a72ea Mon Sep 17 00:00:00 2001 From: Alexander Pankow Date: Sun, 4 Sep 2022 00:58:54 +0200 Subject: [PATCH] use custom fonts in mpdf via twig template (#3509) --- config/services.yaml | 3 +- src/Export/ExportContext.php | 19 ++++++- src/Utils/MPdfConverter.php | 59 ++++++++++++++++++++-- tests/Export/Renderer/PdfRendererTest.php | 3 +- tests/Export/Timesheet/PdfRendererTest.php | 3 +- tests/Invoice/Renderer/PdfRendererTest.php | 3 +- tests/Mocks/FileHelperFactory.php | 22 ++++++++ tests/Utils/MPdfConverterTest.php | 3 +- 8 files changed, 104 insertions(+), 11 deletions(-) create mode 100644 tests/Mocks/FileHelperFactory.php diff --git a/config/services.yaml b/config/services.yaml index 8c006e82..d066489f 100644 --- a/config/services.yaml +++ b/config/services.yaml @@ -57,7 +57,8 @@ services: $settings: '%kimai.config%' App\Utils\MPdfConverter: - arguments: ['%kernel.cache_dir%'] + arguments: + $cacheDirectory: '%kernel.cache_dir%' App\Plugin\PluginManager: arguments: [!tagged kimai.plugin] diff --git a/src/Export/ExportContext.php b/src/Export/ExportContext.php index b569db91..00233ede 100644 --- a/src/Export/ExportContext.php +++ b/src/Export/ExportContext.php @@ -14,19 +14,34 @@ namespace App\Export; */ final class ExportContext { + /** + * @var array + */ 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; } + /** + * @return array + */ public function getOptions(): array { 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)) { return $this->options[$key]; diff --git a/src/Utils/MPdfConverter.php b/src/Utils/MPdfConverter.php index 1b98f5cc..6168f02f 100644 --- a/src/Utils/MPdfConverter.php +++ b/src/Utils/MPdfConverter.php @@ -17,13 +17,19 @@ use Mpdf\Output\Destination; class MPdfConverter implements HtmlToPdfConverter { + /** + * @var FileHelper + */ + private $fileHelper; + /** * @var string */ private $cacheDirectory; - public function __construct(string $cacheDirectory) + public function __construct(FileHelper $fileHelper, string $cacheDirectory) { + $this->fileHelper = $fileHelper; $this->cacheDirectory = $cacheDirectory; } @@ -33,7 +39,7 @@ class MPdfConverter implements HtmlToPdfConverter $fonts = new FontVariables(); $allowed = [ '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) { @@ -66,8 +72,7 @@ class MPdfConverter implements HtmlToPdfConverter ['tempDir' => $this->cacheDirectory, 'exposeVersion' => false] ); - $mpdf = new Mpdf($options); - $mpdf->creator = Constants::SOFTWARE; + $mpdf = $this->initMpdf($options); // some OS do not follow the PHP default settings if ((int) ini_get('pcre.backtrack_limit') < 1000000) { @@ -97,4 +102,50 @@ class MPdfConverter implements HtmlToPdfConverter 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; + } } diff --git a/tests/Export/Renderer/PdfRendererTest.php b/tests/Export/Renderer/PdfRendererTest.php index d1a9b0f3..f5d545d5 100644 --- a/tests/Export/Renderer/PdfRendererTest.php +++ b/tests/Export/Renderer/PdfRendererTest.php @@ -11,6 +11,7 @@ namespace App\Tests\Export\Renderer; use App\Export\Renderer\PDFRenderer; use App\Project\ProjectStatisticService; +use App\Tests\Mocks\FileHelperFactory; use App\Utils\HtmlToPdfConverter; use App\Utils\MPdfConverter; use Symfony\Component\HttpFoundation\Request; @@ -49,7 +50,7 @@ class PdfRendererTest extends AbstractRendererTest $twig = $kernel->getContainer()->get('twig'); $stack = $kernel->getContainer()->get('request_stack'); $cacheDir = $kernel->getContainer()->getParameter('kernel.cache_dir'); - $converter = new MPdfConverter($cacheDir); + $converter = new MPdfConverter((new FileHelperFactory($this))->create(), $cacheDir); $request = new Request(); $request->setLocale('en'); $stack->push($request); diff --git a/tests/Export/Timesheet/PdfRendererTest.php b/tests/Export/Timesheet/PdfRendererTest.php index b4d1b880..a64339bd 100644 --- a/tests/Export/Timesheet/PdfRendererTest.php +++ b/tests/Export/Timesheet/PdfRendererTest.php @@ -11,6 +11,7 @@ namespace App\Tests\Export\Timesheet; use App\Export\Timesheet\PDFRenderer; use App\Project\ProjectStatisticService; +use App\Tests\Mocks\FileHelperFactory; use App\Utils\HtmlToPdfConverter; use App\Utils\MPdfConverter; use Symfony\Component\HttpFoundation\Request; @@ -42,7 +43,7 @@ class PdfRendererTest extends AbstractRendererTest $twig = $kernel->getContainer()->get('twig'); $stack = $kernel->getContainer()->get('request_stack'); $cacheDir = $kernel->getContainer()->getParameter('kernel.cache_dir'); - $converter = new MPdfConverter($cacheDir); + $converter = new MPdfConverter((new FileHelperFactory($this))->create(), $cacheDir); $request = new Request(); $request->setLocale('en'); $stack->push($request); diff --git a/tests/Invoice/Renderer/PdfRendererTest.php b/tests/Invoice/Renderer/PdfRendererTest.php index 2818c4ed..172a12bf 100644 --- a/tests/Invoice/Renderer/PdfRendererTest.php +++ b/tests/Invoice/Renderer/PdfRendererTest.php @@ -10,6 +10,7 @@ namespace App\Tests\Invoice\Renderer; use App\Invoice\Renderer\PdfRenderer; +use App\Tests\Mocks\FileHelperFactory; use App\Utils\MPdfConverter; use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase; use Symfony\Component\HttpFoundation\Request; @@ -56,7 +57,7 @@ class PdfRendererTest extends KernelTestCase $loader = $twig->getLoader(); $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(); $document = $this->getInvoiceDocument('default.pdf.twig', true); diff --git a/tests/Mocks/FileHelperFactory.php b/tests/Mocks/FileHelperFactory.php new file mode 100644 index 00000000..780e26ae --- /dev/null +++ b/tests/Mocks/FileHelperFactory.php @@ -0,0 +1,22 @@ +getContainer()->getParameter('kernel.cache_dir'); - $sut = new MPdfConverter($cacheDir); + $sut = new MPdfConverter((new FileHelperFactory($this))->create(), $cacheDir); $result = $sut->convertToPdf('

Test

'); // Yeah, thats not a real test, I know ;-) $this->assertNotEmpty($result);