* @copyright 2014 Christian Weiske * @license http://www.gnu.org/licenses/agpl.html GNU AGPL v3 * @link http://cweiske.de/grauphel.htm */ namespace OCA\Grauphel\Lib\Converter; use \XMLReader; /** * Convert Tomboy note XML to HTML * * Tomboy already ships with a converter: * https://git.gnome.org/browse/tomboy/tree/Tomboy/Addins/ExportToHtml/ExportToHtml.xsl * We cannot use it since we want nice callbacks, and we do not want to rely * on the PHP XSL extension, and we have to fix the links. * * @category Tools * @package Grauphel * @author Christian Weiske * @copyright 2014 Christian Weiske * @license http://www.gnu.org/licenses/agpl.html GNU AGPL v3 * @version Release: @package_version@ * @link http://cweiske.de/grauphel.htm */ class Html { protected static $tagMap = array( 'list' => 'ul', 'list-item' => 'li', 'bold' => 'b', 'italic' => 'i', 'monospace' => 'tt', ); protected static $styleClassMap = array( 'strikethrough' => 'strikethrough', 'highlight' => 'highlight', 'size:small' => 'small', 'size:large' => 'large', 'size:huge' => 'huge', ); public $internalLinkHandler; public function __construct() { $this->internalLinkHandler = array($this, 'internalLinkHandler'); } /** * Converts the tomboy note XML into HTML * * @param string $xmlContent Tomboy note content * * @return string HTML */ public function convert($xmlContent) { if (strpos($xmlContent, '') !== false) { $xmlContent = $this->fixNastyLinks($xmlContent); } $html = ''; $reader = new XMLReader(); $reader->xml( '' . "\n" . '' . $xmlContent . '' ); $withinLink = false; $store = &$html; while ($reader->read()) { switch ($reader->nodeType) { case XMLReader::ELEMENT: //echo $reader->name . "\n"; if (isset(static::$tagMap[$reader->name])) { $store .= '<' . static::$tagMap[$reader->name] . '>'; } else if (isset(static::$styleClassMap[$reader->name])) { $store .= ''; } else if (substr($reader->name, 0, 5) == 'link:') { $withinLink = true; $linkText = ''; $store = &$linkText; } break; case XMLReader::END_ELEMENT: if (isset(static::$tagMap[$reader->name])) { $store .= 'name] . '>'; } else if (isset(static::$styleClassMap[$reader->name])) { $store .= ''; } else if (substr($reader->name, 0, 5) == 'link:') { $withinLink = false; $store = &$html; $linkUrl = htmlspecialchars_decode(strip_tags($linkText)); if ($reader->name == 'link:internal') { $linkUrl = call_user_func($this->internalLinkHandler, $linkUrl); } else { $linkUrl = $this->fixLinkUrl($linkUrl); } $store .= '' . $linkText . ''; } break; case XMLReader::TEXT: case XMLReader::SIGNIFICANT_WHITESPACE: $store .= nl2br(htmlspecialchars($reader->value)); break; default: throw new \Exception( 'Unsupported XML node type: ' . $reader->nodeType ); } } $html = str_replace("
\n", "\n", $html); return $html; } /** * Fixes external URLs without a protocol * * @param string $linkUrl URL to fix * * @return string Fixed URL */ protected function fixLinkUrl($linkUrl) { if ($linkUrl{0} == '/') { //Unix file path $linkUrl = 'file://' . $linkUrl; } return $linkUrl; } /** * Dummy internal link handler that simply adds ".htm" to the note title * * @param string $linkUrl Title of page that is linked * * @return string URL to link to */ public function internalLinkHandler($linkUrl) { return $linkUrl . '.htm'; } /** * Re-arranges the XML of formatted links to that clean link tags can * be generated. * * Tomboy 1.15.2 allows link formatting, and the resulting XML is a * mess of multiple(!) link tags that are within or around other formatting * tags. * * This method tries to re-arrange the links so that only a single link tag * appears with all the formatting inside. * * @param string $xmlContent Tomboy note content * * @return string XML content, with re-arranged link tags. */ protected function fixNastyLinks($xmlContent) { preg_match_all( '#(?:<.*>)?.+.+#U', $xmlContent, $matches ); foreach ($matches[0] as $nastyLink) { $cleaner = str_replace('
', '', $nastyLink); $cleaner = preg_replace('#<([a-z]+)><(link:internal)>#U', '<\2><\1>', $cleaner); $cleaner = preg_replace('##U', '', $cleaner); $cleaner = str_replace('', '', $cleaner); $xmlContent = str_replace($nastyLink, $cleaner, $xmlContent); } return $xmlContent; } } ?>