215 lines
6.3 KiB
PHP
215 lines
6.3 KiB
PHP
<?php
|
|
/**
|
|
* DescriptionFormatter: Converts plain text product descriptions to formatted HTML
|
|
* This ensures rich text formatting (bold, italics, lists) is properly supported
|
|
* in PDF generation.
|
|
*/
|
|
|
|
class DescriptionFormatter {
|
|
|
|
/**
|
|
* Convert plain text description to HTML with formatting
|
|
*
|
|
* Handles:
|
|
* - Bold formatting for key labels (Item Code:, Type:, etc.)
|
|
* - Ordered lists (lines starting with "1. ", "2. ", etc.)
|
|
* - Italic formatting for specific phrases
|
|
* - Proper HTML entity escaping for special characters
|
|
*
|
|
* @param string $text Plain text description
|
|
* @return string HTML-formatted description
|
|
*/
|
|
public static function format($text) {
|
|
if (empty($text)) {
|
|
return '';
|
|
}
|
|
|
|
// Escape HTML special characters that aren't part of our formatting
|
|
// We need to do this carefully to preserve our HTML tags
|
|
$text = htmlspecialchars($text, ENT_QUOTES, 'UTF-8');
|
|
|
|
// Split into lines for processing
|
|
$lines = explode("\n", $text);
|
|
$result = array();
|
|
$inOrderedList = false;
|
|
$listItems = array();
|
|
|
|
foreach ($lines as $line) {
|
|
$trimmed = trim($line);
|
|
|
|
if (empty($trimmed)) {
|
|
// Flush any pending list before adding empty line
|
|
if ($inOrderedList && count($listItems) > 0) {
|
|
$result[] = self::formatOrderedList($listItems);
|
|
$listItems = array();
|
|
$inOrderedList = false;
|
|
}
|
|
$result[] = '';
|
|
continue;
|
|
}
|
|
|
|
// Check if this is an ordered list item (starts with "1. ", "2. ", etc.)
|
|
if (self::isOrderedListItem($trimmed)) {
|
|
if (!$inOrderedList) {
|
|
$inOrderedList = true;
|
|
$listItems = array();
|
|
}
|
|
// Extract text after the number
|
|
$listItems[] = self::extractListItemText($trimmed);
|
|
} else {
|
|
// Flush any pending list before processing non-list line
|
|
if ($inOrderedList && count($listItems) > 0) {
|
|
$result[] = self::formatOrderedList($listItems);
|
|
$listItems = array();
|
|
$inOrderedList = false;
|
|
}
|
|
|
|
// Process regular line
|
|
$formatted = self::formatLine($trimmed);
|
|
$result[] = $formatted;
|
|
}
|
|
}
|
|
|
|
// Flush any remaining list
|
|
if ($inOrderedList && count($listItems) > 0) {
|
|
$result[] = self::formatOrderedList($listItems);
|
|
}
|
|
|
|
// Join with line breaks
|
|
$html = implode('<br>', $result);
|
|
|
|
// Clean up excessive line breaks
|
|
$html = preg_replace('/<br><br><br>+/', '<br><br>', $html);
|
|
|
|
return $html;
|
|
}
|
|
|
|
/**
|
|
* Check if a line is an ordered list item (e.g., "1. text")
|
|
*/
|
|
private static function isOrderedListItem($line) {
|
|
return preg_match('/^\d+\.\s+/', $line) === 1;
|
|
}
|
|
|
|
/**
|
|
* Extract the text part of a list item, removing the number
|
|
*/
|
|
private static function extractListItemText($line) {
|
|
$matches = array();
|
|
if (preg_match('/^\d+\.\s+(.*)$/', $line, $matches)) {
|
|
return isset($matches[1]) ? $matches[1] : $line;
|
|
}
|
|
return $line;
|
|
}
|
|
|
|
/**
|
|
* Convert an array of list items to HTML ordered list
|
|
*/
|
|
private static function formatOrderedList($items) {
|
|
if (count($items) === 0) {
|
|
return '';
|
|
}
|
|
|
|
$html = '<ol>';
|
|
foreach ($items as $item) {
|
|
$html .= '<li>' . $item . '</li>';
|
|
}
|
|
$html .= '</ol>';
|
|
|
|
return $html;
|
|
}
|
|
|
|
/**
|
|
* Format a single line - mainly applying bold to key labels
|
|
*/
|
|
private static function formatLine($line) {
|
|
// Match "Key: value" pattern
|
|
if (preg_match('/^([^:]+):\s*(.*)$/', $line, $matches)) {
|
|
$key = $matches[1];
|
|
$value = isset($matches[2]) ? $matches[2] : '';
|
|
|
|
// Check if this key should be bolded
|
|
if (self::shouldBoldKey($key)) {
|
|
$line = '<strong>' . htmlspecialchars($key, ENT_QUOTES, 'UTF-8') . ':</strong> ' . $value;
|
|
}
|
|
}
|
|
|
|
// Apply italics to specific phrases
|
|
$line = self::applyItalics($line);
|
|
|
|
return $line;
|
|
}
|
|
|
|
/**
|
|
* Determine if a key should be bolded (heuristic)
|
|
*/
|
|
private static function shouldBoldKey($key) {
|
|
$key = trim($key);
|
|
|
|
// List of known keys that should be bolded
|
|
$knownKeys = array(
|
|
'Item Code' => true,
|
|
'Item Description' => true,
|
|
'Type' => true,
|
|
'Cable Length' => true,
|
|
'Ui' => true,
|
|
'li' => true,
|
|
'Li, Ci' => true,
|
|
'II 2G' => true,
|
|
'II 2D' => true,
|
|
'IBEx' => true,
|
|
'Includes' => true,
|
|
'With standard' => true,
|
|
'See attached' => true,
|
|
'Testing at' => true,
|
|
);
|
|
|
|
// Check exact matches
|
|
if (isset($knownKeys[$key])) {
|
|
return true;
|
|
}
|
|
|
|
// Check partial matches for common patterns
|
|
$lowerKey = strtolower($key);
|
|
$commonPatterns = array(
|
|
'code',
|
|
'description',
|
|
'type',
|
|
'cable',
|
|
'temperature',
|
|
'pressure',
|
|
'includes',
|
|
'testing',
|
|
);
|
|
|
|
foreach ($commonPatterns as $pattern) {
|
|
if (strpos($lowerKey, $pattern) !== false) {
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Apply italic formatting to specific phrases
|
|
*/
|
|
private static function applyItalics($line) {
|
|
$italicPatterns = array(
|
|
'See attached EC Conformity Declaration for the SE Sensor',
|
|
'If Insulated panels are used',
|
|
);
|
|
|
|
foreach ($italicPatterns as $pattern) {
|
|
if (strpos($line, $pattern) !== false) {
|
|
$escapedPattern = htmlspecialchars($pattern, ENT_QUOTES, 'UTF-8');
|
|
$line = str_replace($escapedPattern, '<em>' . $escapedPattern . '</em>', $line);
|
|
}
|
|
}
|
|
|
|
return $line;
|
|
}
|
|
}
|
|
|
|
?>
|