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