Added parseAsText to mention parser. Fix multiple email recipients

This commit is contained in:
Julien Nahum
2024-11-06 17:48:10 +01:00
parent ccbf9faa3c
commit ef12c82fe5
5 changed files with 229 additions and 100 deletions

View File

@@ -116,7 +116,7 @@ class PublicFormController extends Controller
return ['id' => $key, 'value' => $value];
})->values()->all();
$redirectUrl = ($form->redirect_url) ? (new MentionParser($form->redirect_url, $formattedData))->parse() : null;
$redirectUrl = ($form->redirect_url) ? (new MentionParser($form->redirect_url, $formattedData))->parseAsText() : null;
if ($redirectUrl && !filter_var($redirectUrl, FILTER_VALIDATE_URL)) {
$redirectUrl = null;

View File

@@ -58,7 +58,7 @@ class EmailIntegration extends AbstractEmailIntegrationHandler
if ($this->form->is_pro) { // For Send to field Mentions are Pro feature
$formatter = (new FormSubmissionFormatter($this->form, $this->submissionData))->outputStringsOnly();
$parser = new MentionParser($this->integrationData?->send_to, $formatter->getFieldsWithValue());
$sendTo = $parser->parse();
$sendTo = $parser->parseAsText();
} else {
$sendTo = $this->integrationData?->send_to;
}
@@ -73,6 +73,7 @@ class EmailIntegration extends AbstractEmailIntegrationHandler
'form_slug' => $this->form->slug,
'mailer' => $this->mailer
]);
$recipients->each(function ($subscriber) {
Notification::route('mail', $subscriber)->notify(
new FormEmailNotification($this->event, $this->integrationData, $this->mailer)

View File

@@ -110,14 +110,14 @@ class FormEmailNotification extends Notification implements ShouldQueue
private function parseReplyTo(string $replyTo): ?string
{
$parser = new MentionParser($replyTo, $this->formatSubmissionData(false));
return $parser->parse();
return $parser->parseAsText();
}
private function getSubject(): string
{
$defaultSubject = 'New form submission';
$parser = new MentionParser($this->integrationData->subject ?? $defaultSubject, $this->formatSubmissionData(false));
return $parser->parse();
return $parser->parseAsText();
}
private function addCustomHeaders(Email $message): void

View File

@@ -62,26 +62,64 @@ class MentionParser
return $result;
}
private function replaceMentions()
public function parseAsText()
{
$pattern = '/<span[^>]*mention-field-id="([^"]*)"[^>]*mention-fallback="([^"]*)"[^>]*>.*?<\/span>/';
return preg_replace_callback($pattern, function ($matches) {
$fieldId = $matches[1];
$fallback = $matches[2];
$value = $this->getData($fieldId);
// First use the existing parse method to handle mentions
$html = $this->parse();
if ($value !== null) {
if (is_array($value)) {
return implode(' ', array_map(function ($v) {
return $v;
}, $value));
}
return $value;
} elseif ($fallback) {
return $fallback;
$doc = new DOMDocument();
$internalErrors = libxml_use_internal_errors(true);
// Wrap in root element
$wrappedContent = '<root>' . $html . '</root>';
$doc->loadHTML(mb_convert_encoding($wrappedContent, 'HTML-ENTITIES', 'UTF-8'), LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD);
libxml_use_internal_errors($internalErrors);
// Convert HTML to plain text with proper line breaks
$text = '';
$this->domToText($doc->getElementsByTagName('root')->item(0), $text);
// Clean up the text:
// 1. Remove escaped newlines
// 2. Replace multiple newlines with single newline
// 3. Trim whitespace
$text = str_replace(['\\n', '\n'], "\n", $text);
$text = preg_replace('/\n+/', "\n", trim($text));
// Ensure each line has exactly one email
$lines = explode("\n", $text);
$lines = array_map('trim', $lines);
$lines = array_filter($lines); // Remove empty lines
return implode("\n", $lines);
}
private function domToText($node, &$text)
{
if ($node->nodeType === XML_TEXT_NODE) {
$text .= $node->nodeValue;
return;
}
$block_elements = ['div', 'p', 'br', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'ul', 'ol', 'li'];
$nodeName = strtolower($node->nodeName);
// Add newline before block elements
if (in_array($nodeName, $block_elements)) {
$text .= "\n";
}
if ($node->hasChildNodes()) {
foreach ($node->childNodes as $child) {
$this->domToText($child, $text);
}
return '';
}, $this->content);
}
// Add newline after block elements
if (in_array($nodeName, $block_elements)) {
$text .= "\n";
}
}
private function getData($fieldId)