File modules/wikiparser/renderer/XhtmlRenderer.class.php

Last commit: Sun Nov 1 03:08:55 2020 +0100	Jan Dankert	Replaced the calls to "Configuration::rawConfig()" with the OO style calls; Cleanup LoginAction.
1 <?php 2 3 namespace wikiparser\renderer; 4 use cms\base\Configuration; 5 use wikiparser\model\DefinitionItemElement; 6 use DefinitionListEntryElement; 7 use DefinitionListItemElement; 8 use File; 9 use Geshi; 10 use wikiparser\model\LineBreakElement; 11 use wikiparser\model\LinkElement; 12 use logger\Logger; 13 use wikiparser\model\RawElement; 14 use util\Text; 15 use wikiparser\model\TextElement; 16 17 /** 18 * Dokument-Objekt.<br> 19 * Diese Objekt verk�rpert das Root-Objekt in einem DOM-Baum.<br> 20 * <br> 21 * Dieses Objekt kann Text parsen und seine Unterobjekte selbst erzeugen.<br> 22 * 23 * @author Jan Dankert, $Author$ 24 * @version $Revision$ 25 * @package openrat.text 26 */ 27 class XhtmlRenderer 28 { 29 var $linkedObjectIds = array(); 30 var $encodeHtml = false; 31 32 /** 33 * Fu�noten. 34 * 35 * @var Array 36 */ 37 var $footnotes = array(); 38 39 40 /** 41 * Rendert ein Dokument-Element. 42 * 43 * @param Object $child Element 44 * @return String 45 */ 46 function renderElement($child) 47 { 48 $attr = array(); 49 $val = ''; 50 $praefix = ''; 51 $suffix = ''; 52 $empty = false; 53 54 if (count($child->children) > 0) { 55 $subChild1 = $child->children[0]; 56 57 if (!empty($subChild1->class)) 58 $attr['class'] = $subChild1->class; 59 60 if (!empty($subChild1->style)) 61 $attr['style'] = $subChild1->style; 62 63 if (!empty($subChild1->title)) 64 $attr['title'] = $subChild1->title; 65 } 66 67 switch (strtolower(get_class($child))) { 68 case 'tableofcontentelement': 69 $tag = 'p'; 70 foreach ($this->children as $h) { 71 if (strtolower(get_class($h)) == 'headlineelement') { 72 $child->children[] = new RawElement(str_repeat('&nbsp;&nbsp;', $h->level)); 73 $t = new TextElement($h->getText()); 74 $l = new LinkElement(); 75 $l->fragment = $h->getName(); 76 $l->children[] = $t; 77 $child->children[] = $l; 78 $child->children[] = new LineBreakElement(); 79 } 80 } 81 break; 82 83 case 'rawelement': 84 $tag = ''; 85 $val = $child->src; 86 87 break; 88 89 case 'textelement': 90 $tag = ''; 91 // $tag = 'span'; 92 93 $val = $child->text; 94 if ($this->encodeHtml) 95 $val = Text::encodeHtml($val); 96 $val = Text::replaceHtmlChars($val); 97 break; 98 99 case 'footnoteelement': 100 $tag = 'a'; 101 $attr['href'] = '#footnote'; 102 103 $title = ''; 104 foreach ($child->children as $c) 105 $title .= $this->renderElement($c); 106 $attr['title'] = strip_tags($title); 107 108 $nr = 1; 109 foreach ($this->footnotes as $fn) 110 if (strtolower(get_class($fn)) == 'linebreakelement') 111 $nr++; 112 113 $val = $nr; 114 $footnoteConfig = Configuration::subset(['editor','footnote']); 115 if ($footnoteConfig->is('bracket')) 116 $val = '(' . $nr . ')'; 117 if ($footnoteConfig->is('sup')) 118 $val = '<sup><small>' . $nr . '</small></sup>'; 119 120 121 if ($nr == 1) { 122 $this->footnotes[] = new RawElement('&mdash;'); 123 $le = new LinkElement(); 124 $le->name = "footnote"; 125 $this->footnotes[] = $le; 126 $this->footnotes[] = new RawElement('&mdash;'); 127 } 128 $this->footnotes[] = new LineBreakElement(); 129 $this->footnotes[] = new RawElement($val); 130 $this->footnotes[] = new RawElement(' '); 131 foreach ($child->children as $c) 132 $this->footnotes[] = $c; 133 134 $child->children = array(); 135 136 break; 137 138 case 'codeelement': 139 140 if (empty($child->language)) 141 // Wenn keine Sprache verf�gbar, dann ein einfaches PRE-Element erzeugen. 142 $tag = 'pre'; 143 else { 144 // Wenn Sprache verf�gbar, dann den GESHI-Parser bem�hen. 145 $tag = ''; 146 $source = ''; 147 foreach ($child->children as $c) 148 if (strtolower(get_class($c)) == 'textelement') 149 $source .= $c->text . "\n"; 150 $child->children = array(); 151 require_once('./geshi/geshi.php'); 152 $geshi = new Geshi($source, $child->language); 153 $val = $geshi->parse_code(); 154 } 155 break; 156 157 case 'quoteelement': 158 $tag = 'blockquote'; 159 break; 160 161 162 case 'paragraphelement': 163 $tag = 'p'; 164 break; 165 166 case 'speechelement': 167 $tag = 'cite'; 168 169 // Danke an: http://www.apostroph.de/tueddelchen.php 170 //TODO: Abh�ngigkeit von Spracheinstellung implementieren. 171 $language = 'de'; 172 switch ($language) { 173 case 'de': // deutsche Notation 174 $praefix = '&bdquo;'; 175 $suffix = '&ldquo;'; 176 break; 177 case 'fr': 178 $praefix = '&laquo;'; 179 $suffix = '&raquo;'; 180 break; 181 default: // englische Notation 182 $praefix = '&ldquo;'; 183 $suffix = '&rdquo;'; 184 } 185 186 $htmlConfig = Configuration::subset(['editor', 'html']); 187 if ($htmlConfig->is('override_speech')) { 188 $praefix = $htmlConfig->get('override_speech_open'); 189 $suffix = $htmlConfig->get('override_speech_close'); 190 } 191 break; 192 193 case 'linebreakelement': 194 $tag = 'br'; 195 $empty = true; 196 break; 197 198 case 'linkelement': 199 $tag = 'a'; 200 if (!empty($child->name)) 201 $attr['name'] = $child->name; 202 else 203 $attr['href'] = htmlspecialchars($child->getUrl()); 204 205 if (Object::available($child->objectId)) { 206 $file = new File($child->objectId); 207 $file->load(); 208 $attr['title'] = $file->description; 209 unset($file); 210 } 211 break; 212 213 case 'imageelement': 214 $empty = true; 215 $attr['alt'] = ''; 216 217 if (!Object::available($child->objectId)) { 218 $tag = ''; 219 } elseif (empty($attr['title'])) { 220 $tag = 'img'; 221 $attr['src'] = $child->getUrl(); 222 $attr['border'] = '0'; 223 224 // Breite/H�he des Bildes bestimmen. 225 $image = new File($child->objectId); 226 227 $image->load(); 228 $attr['alt'] = $image->name; 229 $attr['title'] = $image->description; 230 231 $image->getImageSize(); 232 $attr['width'] = $image->width; 233 $attr['height'] = $image->height; 234 unset($image); 235 } else { 236 $tag = 'dl'; 237 238 if (empty($attr['class'])) 239 $attr['class'] = "image"; 240 241 $child->children = array(); 242 $dt = new DefinitionListItemElement(); 243 $dt->children[] = new TextElement('(image)'); 244 $dt->children[] = $child; 245 $child->children[] = $dt; 246 247 $dd = new DefinitionListEntryElement(); 248 $dd->children[] = new TextElement('(image)'); 249 $dd->children[] = new TextElement($attr['title']); 250 $child->children[] = $dd; 251 } 252 break; 253 254 case 'strongelement': 255 $tag = 'strong'; 256 break; 257 258 case 'emphaticelement': 259 $tag = 'em'; 260 break; 261 262 case 'insertedelement': 263 $tag = 'ins'; 264 break; 265 266 case 'removedelement': 267 $tag = 'del'; 268 break; 269 270 case 'headlineelement': 271 $tag = 'h' . $child->level; 272 273 $l = new LinkElement(); 274 $l->name = $child->getName(); 275 $child->children[] = $l; 276 277 break; 278 279 case 'tableelement': 280 $tag = 'table'; 281 break; 282 283 case 'tablelineelement': 284 $tag = 'tr'; 285 break; 286 287 case 'definitionlistelement': 288 $items = $child->children; 289 $newChildren = array(); 290 foreach ($items as $item) { 291 $def = new DefinitionItemElement(); 292 $def->key = $item->key; 293 $item->key = ''; 294 $newChildren[] = $def; 295 $newChildren[] = $item; 296 } 297 // Html::debug($newChildren,'Children-neu'); 298 $child->children = $newChildren; 299 $tag = 'dl'; 300 break; 301 302 case 'definitionitemelement': 303 if (!empty($child->key)) { 304 $tag = 'dt'; 305 $val = $child->key; 306 } else { 307 $tag = 'dd'; 308 } 309 break; 310 311 case 'tablecellelement': 312 if ($child->isHeading) 313 $tag = 'th'; else $tag = 'td'; 314 315 if ($child->rowSpan > 1) 316 $attr['rowspan'] = $child->rowSpan; 317 if ($child->colSpan > 1) 318 $attr['colspan'] = $child->colSpan; 319 break; 320 321 case 'listelement': 322 $tag = 'ul'; 323 break; 324 325 case 'teletypeelement': 326 $tag = 'code'; 327 break; 328 329 case 'numberedlistelement': 330 $tag = 'ol'; 331 break; 332 333 case 'listentryelement': 334 $tag = 'li'; 335 break; 336 337 case 'macroelement': 338 339 $className = ucfirst($child->name); 340 $fileName = './dynamicClasses/' . $className . '.class.php'; 341 if (is_file($fileName)) { 342 // Fuer den Fall, dass eine Dynamic-Klasse mehrmals pro Vorlage auftritt 343 if (!class_exists($className)) 344 require($fileName); 345 346 if (class_exists($className)) { 347 $dynEl = new $className; 348 $dynEl->page = &$this->page; 349 350 if (method_exists($dynEl, 'execute')) { 351 $dynEl->objectid = $this->page->objectid; 352 $dynEl->page = &$this->page; 353 354 foreach ($child->attributes as $param_name => $param_value) { 355 if (isset($dynEl->$param_name)) 356 $dynEl->$param_name = $param_value; 357 } 358 359 $dynEl->execute(); 360 $val = $dynEl->getOutput(); 361 } else { 362 Logger::warn('element:' . $this->element->name . ', ' . 363 'class:' . $className . ', no method: execute()'); 364 } 365 } else { 366 Logger::warn('element:' . $this->element->name . ', ' . 367 'class not found:' . $className); 368 } 369 } else { 370 Logger::warn('element:' . $this->element->name . ', ' . 371 'file not found:' . $fileName); 372 } 373 374 // Wenn HTML-Ausgabe, dann Sonderzeichen in HTML �bersetzen 375 if ($this->page->mimeType() == 'text/html') 376 $inhalt = Text::encodeHtmlSpecialChars($inhalt); 377 378 break; 379 380 381 default: 382 383 $tag = 'unknown-element'; 384 $attr['class'] = strtolower(get_class($child)); 385 break; 386 } 387 388 $val .= $praefix; 389 foreach ($child->children as $c) { 390 $val .= $this->renderElement($c); 391 } 392 393 $val .= $suffix; 394 // echo "text:$val"; 395 return $this->renderHtmlElement($tag, $val, $empty, $attr); 396 397 } 398 399 400 /** 401 * Erzeugt ein HTML-Element. 402 * 403 * @param String $tag Name des Tags 404 * @param String $value Inhalt 405 * @param boolean $empty abk�rzen, wenn Inhalt leer ("<... />") 406 * @param Array $attr Attribute als Array<String,String> 407 * @return String 408 */ 409 function renderHtmlElement($tag, $value, $empty, $attr = array()) 410 { 411 if ($tag == '') 412 return $value; 413 414 $val = '<' . $tag; 415 foreach ($attr as $attrName => $attrInhalt) { 416 $val .= ' ' . $attrName . '="' . $attrInhalt . '"'; 417 } 418 419 if ($value == '' && $empty) { 420 // Inhalt ist leer, also Kurzform verwenden. 421 // Die Kurzform ist abh�ngig vom Rendermode. 422 // SGML=<tag> 423 // XML=<tag /> 424 if (Configuration::get(['editor','html','rendermode']) == 'xml') { 425 $val .= ' />'; 426 return $val; 427 } else { 428 $val .= '>'; 429 return $val; 430 } 431 } 432 433 $val .= '>' . $value . '</' . $tag . '>'; 434 return $val; 435 } 436 437 438 /** 439 * Rendering des Dokumentes.<br> 440 * 441 * @return String 442 */ 443 function render() 444 { 445 $this->renderedText = ''; 446 $this->footnotes = array(); 447 448 foreach ($this->children as $child) 449 $this->renderedText .= $this->renderElement($child); 450 451 foreach ($this->footnotes as $child) 452 $this->renderedText .= $this->renderElement($child); 453 454 return $this->renderedText; 455 } 456 } 457 458 ?>
Download modules/wikiparser/renderer/XhtmlRenderer.class.php
History Sun, 1 Nov 2020 03:08:55 +0100 Jan Dankert Replaced the calls to "Configuration::rawConfig()" with the OO style calls; Cleanup LoginAction. Sat, 26 Sep 2020 10:32:02 +0200 Jan Dankert Refactoring: No global $conf array any more. Sun, 23 Feb 2020 00:03:40 +0100 Jan Dankert Refactoring: Namespaces for modules 'logger' and 'language' Sat, 22 Feb 2020 23:58:02 +0100 Jan Dankert Refactoring: Namespacing for module 'util'. Sat, 22 Feb 2020 22:45:05 +0100 Jan Dankert Refactoring: Enable Autoloading, Fix namespace structure. Sat, 16 Dec 2017 23:41:50 +0100 Jan Dankert Der Wikiparser als eigenes Modul (ehem. 'textclasses').