diff --git a/htdocs/core/class/HtmlToOdtConverter.class.php b/htdocs/core/class/HtmlToOdtConverter.class.php index 3df9d3cb3af..ff8e90ccfb0 100644 --- a/htdocs/core/class/HtmlToOdtConverter.class.php +++ b/htdocs/core/class/HtmlToOdtConverter.class.php @@ -1,7 +1,7 @@ )|(?:>(.*)<\/\1>))/'); +// Learn more about this regex pattern: https://regexr.com/4vi60 +define('HTML_REGEX_PATTERN', '/<([A-Za-z]+)(?:\s([A-Za-z]+(?:\-[A-Za-z]+)?(?:=(?:".*?")|(?:[0-9]+))))*(?:(?:\s\/>)|(?:>(.*)<\/\1>))/'); class HtmlToOdtConverter { @@ -41,7 +41,7 @@ class HtmlToOdtConverter { '' ); - $odtText = self::replaceHtmlWithOdtTag(self::getDataFromHtml($htmlText), $customStyles); + $odtText = self::replaceHtmlWithOdtTag(self::getDataFromHtml($htmlText), $customStyles, $fontDeclarations); foreach ($customStyles as $key => $value) { array_push($automaticStyles, '' . $value . ''); @@ -49,7 +49,8 @@ class HtmlToOdtConverter { return array( 'automaticStyles' => $automaticStyles, - 'content' => $odtText + 'content' => $odtText, + 'fonts' => $fontDeclarations ); } @@ -58,8 +59,9 @@ class HtmlToOdtConverter { * @param array $tags An array with html tags generated by the getDataFromHtml() function * @param array $customStyles An array of style defenitions that should be included inside the odt file */ - private static function replaceHtmlWithOdtTag($tags, &$customStyles) { + private static function replaceHtmlWithOdtTag($tags, &$customStyles, &$fontDeclarations) { if ($customStyles == null) $customStyles = array(); + if ($fontDeclarations == null) $fontDeclarations = array(); $odtResult = ''; @@ -74,23 +76,23 @@ class HtmlToOdtConverter { break; case 'strong': case 'b': - $odtResult .= '' . ($tag['children'] != null ? self::replaceHtmlWithOdtTag($tag['children'], $customStyles) : $tag['innerText']) . ''; + $odtResult .= '' . ($tag['children'] != null ? self::replaceHtmlWithOdtTag($tag['children'], $customStyles, $fontDeclarations) : $tag['innerText']) . ''; break; case 'i': case 'em': - $odtResult .= '' . ($tag['children'] != null ? self::replaceHtmlWithOdtTag($tag['children'], $customStyles) : $tag['innerText']) . ''; + $odtResult .= '' . ($tag['children'] != null ? self::replaceHtmlWithOdtTag($tag['children'], $customStyles, $fontDeclarations) : $tag['innerText']) . ''; break; case 'u': - $odtResult .= '' . ($tag['children'] != null ? self::replaceHtmlWithOdtTag($tag['children'], $customStyles) : $tag['innerText']) . ''; + $odtResult .= '' . ($tag['children'] != null ? self::replaceHtmlWithOdtTag($tag['children'], $customStyles, $fontDeclarations) : $tag['innerText']) . ''; break; case 's': - $odtResult .= '' . ($tag['children'] != null ? self::replaceHtmlWithOdtTag($tag['children'], $customStyles) : $tag['innerText']) . ''; + $odtResult .= '' . ($tag['children'] != null ? self::replaceHtmlWithOdtTag($tag['children'], $customStyles, $fontDeclarations) : $tag['innerText']) . ''; break; case 'sub': - $odtResult .= '' . ($tag['children'] != null ? self::replaceHtmlWithOdtTag($tag['children'], $customStyles) : $tag['innerText']) . ''; + $odtResult .= '' . ($tag['children'] != null ? self::replaceHtmlWithOdtTag($tag['children'], $customStyles, $fontDeclarations) : $tag['innerText']) . ''; break; case 'sup': - $odtResult .= '' . ($tag['children'] != null ? self::replaceHtmlWithOdtTag($tag['children'], $customStyles) : $tag['innerText']) . ''; + $odtResult .= '' . ($tag['children'] != null ? self::replaceHtmlWithOdtTag($tag['children'], $customStyles, $fontDeclarations) : $tag['innerText']) . ''; break; case 'span': if (isset($tag['attributes']['style'])) { @@ -98,7 +100,14 @@ class HtmlToOdtConverter { foreach ($tag['attributes']['style'] as $styleName => $styleValue) { switch ($styleName) { case 'font-family': - $odtStyles .= ''; + $fontName = $styleValue; + if (strpos($fontName, ',') !== false) { + $fontName = explode(',', $fontName)[0]; + } + if (!in_array($fontName, $fontDeclarations)) { + array_push($fontDeclarations, $fontName); + } + $odtStyles .= ''; break; case 'font-size': if (preg_match('/([0-9]+)\s?(px|pt)/', $styleValue, $matches)) { @@ -117,14 +126,14 @@ class HtmlToOdtConverter { } } if (strlen($odtStyles) > 0) { - $key = microtime(); + $key = floatval(str_replace('.', '', microtime(true)))+rand(0, 10); $customStyles[$key] = $odtStyles; - $odtResult .= '' . ($tag['children'] != null ? self::replaceHtmlWithOdtTag($tag['children'], $customStyles) : $tag['innerText']) . ''; + $odtResult .= '' . ($tag['children'] != null ? self::replaceHtmlWithOdtTag($tag['children'], $customStyles, $fontDeclarations) : $tag['innerText']) . ''; } } break; default: - $odtResult .= self::replaceHtmlWithOdtTag($tag['children'], $customStyles); + $odtResult .= self::replaceHtmlWithOdtTag($tag['children'], $customStyles, $fontDeclarations); break; } } @@ -171,7 +180,8 @@ class HtmlToOdtConverter { $tempHtml = substr($tempHtml, $tagOffset); } // Extract the attribute data from the html tag - $explodedAttributes = strlen($matches[2][0]) > 0 ? explode(' ', $matches[2][0]) : array(); + preg_match_all('/([0-9A-Za-z]+(?:="[0-9A-Za-z\:\-\s]*")?)+/', $matches[2][0], $explodedAttributes); + $explodedAttributes = array_filter($explodedAttributes[0]); $attributes = array(); // Store each attribute with its name in the $attributes array for ($i=0; $icontentXml = str_replace('', $styles . '', $this->contentXml); + // Join the font declarations and add them to the content xml + $fonts = ''; + foreach ($result['fonts'] as $font) { + if (strpos($this->contentXml, 'style:name="' . $font . '"') === false) { + $fonts .= ''; + } + } + $this->contentXml = str_replace('', $fonts . '', $this->contentXml); // Set the var to the converted odt value $this->vars[$tag] = $result['content']; }