content = $content;
$this->data = $data;
}
public function parse()
{
$doc = new DOMDocument();
// Disable libxml errors and use internal errors
$internalErrors = libxml_use_internal_errors(true);
// Wrap the content in a root element to ensure it's valid XML
$wrappedContent = '' . $this->content . '';
// Load HTML, using UTF-8 encoding
$doc->loadHTML(mb_convert_encoding($wrappedContent, 'HTML-ENTITIES', 'UTF-8'), LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD);
// Restore libxml error handling
libxml_use_internal_errors($internalErrors);
$xpath = new DOMXPath($doc);
$mentionElements = $xpath->query("//span[@mention]");
foreach ($mentionElements as $element) {
$fieldId = $element->getAttribute('mention-field-id');
$fallback = $element->getAttribute('mention-fallback');
$value = $this->getData($fieldId);
if ($value !== null) {
$textNode = $doc->createTextNode(is_array($value) ? implode(', ', $value) : $value);
$element->parentNode->replaceChild($textNode, $element);
} elseif ($fallback) {
$textNode = $doc->createTextNode($fallback);
$element->parentNode->replaceChild($textNode, $element);
} else {
$element->parentNode->removeChild($element);
}
}
// Extract and return the processed HTML content
$result = $doc->saveHTML($doc->getElementsByTagName('root')->item(0));
// Remove the root tags we added
$result = preg_replace('/<\/?root>/', '', $result);
// Trim whitespace and convert HTML entities back to UTF-8 characters
$result = trim(html_entity_decode($result, ENT_QUOTES | ENT_HTML5, 'UTF-8'));
return $result;
}
private function replaceMentions()
{
$pattern = '/]*mention-field-id="([^"]*)"[^>]*mention-fallback="([^"]*)"[^>]*>.*?<\/span>/';
return preg_replace_callback($pattern, function ($matches) {
$fieldId = $matches[1];
$fallback = $matches[2];
$value = $this->getData($fieldId);
if ($value !== null) {
if (is_array($value)) {
return implode(' ', array_map(function ($v) {
return $v;
}, $value));
}
return $value;
} elseif ($fallback) {
return $fallback;
}
return '';
}, $this->content);
}
private function getData($fieldId)
{
$value = collect($this->data)->firstWhere('id', $fieldId)['value'] ?? null;
if (is_object($value)) {
return (array) $value;
}
return $value;
}
}