Fix: Add CKEditor special character sanitization for PDF generation

Added sanitizeCKEditorSpecialChars() method to handle smart quotes, zero-width spaces, em/en dashes, and other special characters that can break mPDF.

Removes invisible Unicode chars, replaces special punctuation with ASCII equivalents, cleans HTML comments.
This commit is contained in:
DevSoftTech Server 2026-06-07 13:53:03 +05:30
parent 328de6279d
commit 69373af48c

View File

@ -6290,6 +6290,9 @@ class Ipd_discharge extends BaseController
$out = str_replace("\0", '', $html);
$out = (string) preg_replace('/^\xEF\xBB\xBF/u', '', $out);
// Sanitize CKEditor special characters that can break mPDF
$out = $this->sanitizeCKEditorSpecialChars($out);
if ($stripNamedHeaderFooterWrappers) {
// For body/template HTML, strip legacy named header/footer wrapper blocks.
$out = (string) preg_replace('/<htmlpageheader\b[^>]*>[\s\S]*?<\/htmlpageheader>/i', '', $out);
@ -6307,6 +6310,57 @@ class Ipd_discharge extends BaseController
return $this->forceValidUtf8($out);
}
private function sanitizeCKEditorSpecialChars(string $html): string
{
if ($html === '') {
return '';
}
// Remove zero-width spaces and other invisible characters
$html = str_replace([
"\xE2\x80\x8B", // Zero-width space
"\xE2\x80\x8C", // Zero-width non-joiner
"\xE2\x80\x8D", // Zero-width joiner
"\xE2\x80\x8E", // Left-to-right mark
"\xE2\x80\x8F", // Right-to-left mark
"\xEF\xBB\xBF", // Zero-width no-break space (BOM)
], '', $html);
// Replace smart quotes and special punctuation with standard ASCII equivalents
$replacements = [
// Smart quotes
"\xE2\x80\x9C" => '"', // Left double quote
"\xE2\x80\x9D" => '"', // Right double quote
"\xE2\x80\x98" => "'", // Left single quote
"\xE2\x80\x99" => "'", // Right single quote
"\xE2\x80\x9B" => "'", // Single high-reversed-9 quotation mark
// Dashes
"\xE2\x80\x93" => '-', // En dash
"\xE2\x80\x94" => '-', // Em dash
"\xE2\x80\x95" => '-', // Horizontal bar
// Ellipsis
"\xE2\x80\xA6" => '...', // Horizontal ellipsis
// Spaces (keep non-breaking space as HTML entity)
"\xC2\xA0" => '&nbsp;', // Non-breaking space
];
$html = str_replace(array_keys($replacements), array_values($replacements), $html);
// Decode HTML entities to actual characters (mPDF handles UTF-8 better than entities)
$html = html_entity_decode($html, ENT_QUOTES | ENT_HTML5, 'UTF-8');
// Remove or replace problematic HTML comments that might break parsing
$html = (string) preg_replace('/<!--\[if[^\]]*\]>[\s\S]*?<!\[endif\]-->/i', '', $html);
// Clean up any malformed or nested comment blocks
$html = (string) preg_replace('/<!--(?!<!)[^\[>][\s\S]*?-->/s', '', $html);
return $html;
}
private function forceValidUtf8(string $text): string
{
if ($text === '') {