From 6dfceffbcb9a63f7838bdc66f5142e44dcdbb8c1 Mon Sep 17 00:00:00 2001 From: Benjamin Bock Date: Thu, 23 Nov 2023 01:01:27 +0100 Subject: [PATCH] Add weasyprint pdf generation as alternative to wkhtmltopdf --- CRM/Admin/Form/Setting/Miscellaneous.php | 17 ++++++++- CRM/Utils/PDF/Utils.php | 35 ++++++++++++++++++- settings/Core.setting.php | 19 ++++++++++ .../CRM/Admin/Form/Setting/Miscellaneous.tpl | 6 ++++ 4 files changed, 75 insertions(+), 2 deletions(-) diff --git a/CRM/Admin/Form/Setting/Miscellaneous.php b/CRM/Admin/Form/Setting/Miscellaneous.php index cc221644ae..889434be98 100644 --- a/CRM/Admin/Form/Setting/Miscellaneous.php +++ b/CRM/Admin/Form/Setting/Miscellaneous.php @@ -35,6 +35,7 @@ class CRM_Admin_Form_Setting_Miscellaneous extends CRM_Admin_Form_Setting { 'dompdf_font_dir' => CRM_Core_BAO_Setting::SYSTEM_PREFERENCES_NAME, 'dompdf_chroot' => CRM_Core_BAO_Setting::SYSTEM_PREFERENCES_NAME, 'dompdf_enable_remote' => CRM_Core_BAO_Setting::SYSTEM_PREFERENCES_NAME, + 'weasyprintPath' => CRM_Core_BAO_Setting::SYSTEM_PREFERENCES_NAME, 'wkhtmltopdfPath' => CRM_Core_BAO_Setting::SYSTEM_PREFERENCES_NAME, 'recentItemsMaxCount' => CRM_Core_BAO_Setting::SYSTEM_PREFERENCES_NAME, 'recentItemsProviders' => CRM_Core_BAO_Setting::SYSTEM_PREFERENCES_NAME, @@ -118,6 +119,20 @@ class CRM_Admin_Form_Setting_Miscellaneous extends CRM_Admin_Form_Setting { $errors['recentItemsMaxCount'] = ts("Illegal stack size. Use values between 1 and %1.", [1 => CRM_Utils_Recent::MAX_ITEMS]); } + if (!empty($fields['weasyprintPath'])) { + // check and ensure that this path leads to the weasyprint binary + // and it is a valid executable binary + // Only check the first space separated piece to allow for a value + // such as /usr/bin/xvfb-run -- weasyprintPath (CRM-13292) + $pieces = explode(' ', $fields['weasyprintPath']); + $path = $pieces[0]; + if ( + !file_exists($path) || + !is_executable($path) + ) { + $errors['weasyprintPath'] = ts('The weasyprintPath does not exist or is not valid'); + } + } if (!empty($fields['wkhtmltopdfPath'])) { // check and ensure that this path leads to the wkhtmltopdf binary // and it is a valid executable binary @@ -129,7 +144,7 @@ class CRM_Admin_Form_Setting_Miscellaneous extends CRM_Admin_Form_Setting { !file_exists($path) || !is_executable($path) ) { - $errors['wkhtmltopdfPath'] = ts('The wkhtmltodfPath does not exist or is not valid'); + $errors['wkhtmltopdfPath'] = ts('The path for %1 does not exist or is not valid', [1 => 'wkhtmltopdf']); } } return $errors; diff --git a/CRM/Utils/PDF/Utils.php b/CRM/Utils/PDF/Utils.php index 847af31e82..197c6a9551 100644 --- a/CRM/Utils/PDF/Utils.php +++ b/CRM/Utils/PDF/Utils.php @@ -101,7 +101,10 @@ class CRM_Utils_PDF_Utils { "; - if (CRM_Core_Config::singleton()->wkhtmltopdfPath) { + if (CRM_Core_Config::singleton()->weasyprintPath) { + return self::_html2pdf_weasyprint($paper_size, $orientation, $margins, $html, $output, $fileName); + } + elseif (CRM_Core_Config::singleton()->wkhtmltopdfPath) { return self::_html2pdf_wkhtmltopdf($paper_size, $orientation, $margins, $html, $output, $fileName); } else { @@ -142,6 +145,36 @@ class CRM_Utils_PDF_Utils { $dompdf->stream($fileName); } + /** + * @param float|int[] $paper_size + * @param string $orientation + * @param array $margins + * @param string $html + * @param bool $output + * @param string $fileName + */ + public static function _html2pdf_weasyprint($paper_size, $orientation, $margins, $html, $output, $fileName) { + require_once 'php-weasyprint/src/autoload.php'; + $config = CRM_Core_Config::singleton(); + $weasyprint = new Pontedilana\PhpWeasyPrint\Pdf($config->weasyprintPath); + $weasyprint->setOption("page-width", $paper_size[2] . "pt"); + $weasyprint->setOption("page-height", $paper_size[3] . "pt"); + $weasyprint->setOption("orientation", $orientation); + $weasyprint->setOption("margin-top", $margins[1] . $margins[0]); + $weasyprint->setOption("margin-right", $margins[2] . $margins[0]); + $weasyprint->setOption("margin-bottom", $margins[3] . $margins[0]); + $weasyprint->setOption("margin-left", $margins[4] . $margins[0]); + $pdf = $weasyprint->getOutputFromHtml($html); + if ($output) { + return $pdf; + } + else { + CRM_Utils_System::setHttpHeader('Content-Type', 'application/pdf'); + CRM_Utils_System::setHttpHeader('Content-Disposition', 'attachment; filename="' . $fileName . '"'); + echo $pdf; + } + } + /** * @param float|int[] $paper_size * @param string $orientation diff --git a/settings/Core.setting.php b/settings/Core.setting.php index 9f2177c621..fdf1fcd97d 100644 --- a/settings/Core.setting.php +++ b/settings/Core.setting.php @@ -617,6 +617,25 @@ return [ 'help_text' => NULL, 'add' => '5.43', ], + 'weasyprintPath' => [ + 'group_name' => 'CiviCRM Preferences', + 'group' => 'core', + 'name' => 'weasyprintPath', + 'type' => 'String', + 'quick_form_type' => 'Element', + 'html_attributes' => [ + 'size' => 64, + 'maxlength' => 256, + ], + 'html_type' => 'text', + 'default' => NULL, + 'add' => '5.68', + 'title' => ts('Path to weasyprint executable'), + 'is_domain' => 1, + 'is_contact' => 0, + 'description' => NULL, + 'help_text' => NULL, + ], 'wkhtmltopdfPath' => [ 'group_name' => 'CiviCRM Preferences', 'group' => 'core', diff --git a/templates/CRM/Admin/Form/Setting/Miscellaneous.tpl b/templates/CRM/Admin/Form/Setting/Miscellaneous.tpl index 0f2cd40dfd..e8750fae96 100644 --- a/templates/CRM/Admin/Form/Setting/Miscellaneous.tpl +++ b/templates/CRM/Admin/Form/Setting/Miscellaneous.tpl @@ -74,6 +74,12 @@

{ts}Enable the use of remote images. By default this is enabled, but if not using remote images you may wish to turn it off for security reasons.{/ts}

+ + {$form.weasyprintPath.label} + {$form.weasyprintPath.html}
+

{ts 1="https://weasyprint.org/"}weasyprint is an alternative utility for generating PDF's which is a successor to the discontinued wkhtmltopdf. Your system administrator will need to download and install this utility, and enter the executable path here.{/ts}

+ + {$form.wkhtmltopdfPath.label} {$form.wkhtmltopdfPath.html}
-- 2.25.1