openrat-cms

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README

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('&nbsp;&nbsp;', $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('&mdash;');
    151 					$le = new LinkElement();
    152 					$le->name = "footnote";
    153 					$this->footnotes[] = $le;
    154 					$this->footnotes[] = new RawElement('&mdash;');
    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 = '&bdquo;';
    206 						$suffix = '&ldquo;';
    207 						break;
    208 					case 'fr':
    209 						$praefix = '&laquo;';
    210 						$suffix = '&raquo;';
    211 						break;
    212 					default: // englische Notation
    213 						$praefix = '&ldquo;';
    214 						$suffix = '&rdquo;';
    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 ?>