00001 <?php
00002
00013 class WikiParser
00014 {
00015 var $linkedObjectIds = array();
00016
00024 function parse( $text )
00025 {
00026
00027 $zeilen = array();
00028 $nr = 0;
00029
00030 foreach( $text as $t )
00031 {
00032
00033 $zeilen[++$nr] = new Line( rtrim($t) );
00034 }
00035
00036
00037
00038
00039
00040 return $this->parseMultiLineText( $zeilen );
00041 }
00042
00043
00044
00051 function parseMultiLineText( $zeilen )
00052 {
00053 global $conf;
00054
00055 $children = array();
00056 $anzahlZeilen = count( $zeilen );
00057
00058
00059
00060 $zeilen[0] = new Line('');
00061 $zeilen[$anzahlZeilen+1] = new Line('');
00062
00063 for ( $zeileNr=1; $zeileNr<=$anzahlZeilen; $zeileNr++ )
00064 {
00065
00066 $letzteZeile = $zeilen[$zeileNr-1];
00067 $dieseZeile = $zeilen[$zeileNr ];
00068 $naechsteZeile = $zeilen[$zeileNr+1];
00069
00070
00071
00072
00073 if ( $dieseZeile->isEmpty )
00074 {
00075 continue;
00076 }
00077
00078
00079
00080 if ( $dieseZeile->isTableOfContent )
00081 {
00082 $children[] = new TableOfContentElement();
00083 continue;
00084 }
00085
00086
00087
00088
00089 if ( $dieseZeile->isUnparsed )
00090 {
00091 $children[] = new TextElement( $dieseZeile->value );
00092 continue;
00093 }
00094
00095
00096
00097
00098 if ( $naechsteZeile->isHeadlineUnderline )
00099 {
00100 $headline = new HeadlineElement($naechsteZeile->level);
00101 $headline->children = $this->parseSimple( $dieseZeile->value);
00102 $children[] = $headline;
00103 $zeileNr++;
00104 continue;
00105 }
00106
00107
00108
00109
00110 if ( $dieseZeile->isHeadline )
00111 {
00112 $headline = new HeadlineElement($dieseZeile->level);
00113 $headline->children = $this->parseSimple( $dieseZeile->value);
00114 $children[] = $headline;
00115 continue;
00116 }
00117
00118
00119
00120 if ( $dieseZeile->isQuote )
00121 {
00122 $bisZeileNr = $zeileNr+1;
00123 do
00124 {
00125 $bisZeileNr++;
00126 }
00127 while( !$zeilen[$bisZeileNr]->isQuote && $bisZeileNr<=$anzahlZeilen );
00128
00129 $quote = new QuoteElement();
00130 $zeilenAuszug = array();
00131 $nr=0;
00132 for( $zn=$zeileNr+1;$zn<$bisZeileNr;$zn++)
00133 {
00134 $zeilenAuszug[++$nr] = $zeilen[$zn];
00135 }
00136 $quote->children = $this->parseMultiLineText($zeilenAuszug);
00137 $zeileNr = $bisZeileNr+1;
00138 $children[] = $quote;
00139 continue;
00140 }
00141
00142
00143
00144
00145
00146 if ( $dieseZeile->isQuotePraefix )
00147 {
00148 $bisZeileNr = $zeileNr;
00149 while( $bisZeileNr<=$anzahlZeilen && $zeilen[$bisZeileNr]->isQuotePraefix )
00150 $bisZeileNr++;
00151 $bisZeileNr--;
00152
00153 $quote = new QuoteElement();
00154
00155 $zeilenAuszug = $this->getListenAuszug( $zeilen,$zeileNr,$bisZeileNr);
00156
00157
00158 $quote->children = $this->parseMultiLineText($zeilenAuszug);
00159 $zeileNr = $bisZeileNr;
00160 $children[] = $quote;
00161 continue;
00162 }
00163
00164
00165
00166
00167
00168 if ( $dieseZeile->isDefinition )
00169 {
00170 $bisZeileNr = $zeileNr;
00171 while( $bisZeileNr<=$anzahlZeilen && $zeilen[$bisZeileNr]->isDefinition )
00172 $bisZeileNr++;
00173 $bisZeileNr--;
00174
00175 $defList = new DefinitionListElement();
00176
00177 $zeilenAuszug = $this->getListenAuszug( $zeilen,$zeileNr,$bisZeileNr);
00178
00179
00180 foreach( $zeilenAuszug as $zeile )
00181 {
00182 $sep = $conf['editor']['text-markup']['definition-sep'];
00183 list($defKey, $defValue) = explode($sep, $zeile->value);
00184
00185 $defEntry = new DefinitionItemElement();
00186 $defEntry->key = $defKey;
00187 $defEntry->children = $this->parseSimple($defValue);
00188 $defList->children[] = $defEntry;
00189 }
00190 $zeileNr = $bisZeileNr;
00191 $children[] = $defList;
00192 continue;
00193 }
00194
00195
00196
00197
00198 if ( $dieseZeile->isCode)
00199 {
00200 $bisZeileNr = $zeileNr+1;
00201 while( $bisZeileNr<$anzahlZeilen && !$zeilen[$bisZeileNr]->isCode )
00202 $bisZeileNr++;
00203
00204 $code = new CodeElement();
00205 $code->language = trim($dieseZeile->value);
00206
00207 for( $zn=$zeileNr+1;$zn<$bisZeileNr;$zn++)
00208 {
00209 $code->children[] = new TextElement( $zeilen[$zn]->source );
00210
00211 if ( $zn < $bisZeileNr-1 )
00212 $code->children[] = new LineBreakElement();
00213 }
00214 $zeileNr = $bisZeileNr;
00215 $children[] = $code;
00216 continue;
00217 }
00218
00219
00220
00221 if ( $dieseZeile->isTable )
00222 {
00223 $bisZeileNr = $zeileNr;
00224 while( $bisZeileNr<=$anzahlZeilen && $zeilen[$bisZeileNr]->isTable )
00225 $bisZeileNr++;
00226
00227 $tabelle = new TableElement();
00228 $zeilenAuszug = array();
00229 for( $zn=$zeileNr;$zn<=$bisZeileNr;$zn++)
00230 {
00231 $zeilenAuszug[$zn-$zeileNr+1] = $zeilen[$zn];
00232 }
00233 $tabelle->children = $this->parseTable($zeilenAuszug);
00234 $children[] = $tabelle;
00235 $zeileNr = $bisZeileNr+1;
00236 continue;
00237 }
00238
00239
00240
00241 if ( $dieseZeile->isList || $dieseZeile->isNumberedList )
00242 {
00243
00244 $bisZeileNr = $zeileNr;
00245 while( $bisZeileNr<=$anzahlZeilen &&
00246 ($zeilen[$bisZeileNr]->isList || $zeilen[$bisZeileNr]->isNumberedList) )
00247 $bisZeileNr++;
00248 $bisZeileNr--;
00249
00250 if ( $dieseZeile->isList )
00251 $liste = new ListElement();
00252 else
00253 $liste = new NumberedListElement();
00254
00255 $zeilenAuszug = array();
00256 $nr=0;
00257
00258 for( $zn=$zeileNr;$zn<=$bisZeileNr;$zn++)
00259 {
00260 $zeilenAuszug[++$nr] = $zeilen[$zn];
00261 }
00262
00263 $liste->children = $this->parseList($zeilenAuszug,1);
00264 $children[] = $liste;
00265 $zeileNr = $bisZeileNr;
00266 continue;
00267 }
00268
00269
00270
00271 if ( $dieseZeile->isNormal )
00272 {
00273
00274
00275 $bisZeileNr = $zeileNr;
00276 while( $bisZeileNr <= $anzahlZeilen &&
00277 $zeilen[$bisZeileNr ]->isNormal )
00278 {
00279 $bisZeileNr++;
00280 }
00281 $bisZeileNr--;
00282
00283
00284
00285
00286 $para = new ParagraphElement();
00287 for( $zn=$zeileNr;$zn<=$bisZeileNr;$zn++)
00288 {
00289 if ( !$zeilen[$zn]->isNormal )
00290 continue;
00291
00292 if ( $zeilen[$zn]->isUnparsed )
00293 $para->children[] = new TextElement( $zeilen[$zn]->source );
00294
00295 foreach( $this->parseSimple($zeilen[$zn]->value) as $e )
00296 $para->children[] = $e;
00297
00298 if ( $zn < $bisZeileNr )
00299 $para->children[] = new LineBreakElement();
00300 }
00301
00302 $zeileNr = $bisZeileNr;
00303 $children[] = $para;
00304
00305 continue;
00306 }
00307
00308 Html::debug($dieseZeile,"Unbekannte Zeile");
00309 die( 'unknown line: '.$dieseZeile );
00310 }
00311
00312 return $children;
00313 }
00314
00315
00316
00317 function getListenAuszug( $liste, $von, $bis )
00318 {
00319 $auszug = array();
00320 $idx = 0;
00321
00322 for( $j=$von;$j<=$bis;$j++)
00323 {
00324 $auszug[++$idx] = new Line($liste[$j]->value);
00325 }
00326
00327 return $auszug;
00328 }
00329
00330
00334 function parseList( $zeilen,$tiefe )
00335 {
00336 $children = array();
00337 $anzahlZeilen = count( $zeilen );
00338 $entry = null;
00339 for ( $zeileNr=1; $zeileNr<=$anzahlZeilen; $zeileNr++ )
00340 {
00341 $dieseZeile = $zeilen[$zeileNr];
00342
00343
00344 if ( $dieseZeile->indent <= $tiefe )
00345 {
00346 if ( $zeileNr > 1 )
00347 $children[] = $entry;
00348
00349 $entry = new ListEntryElement();
00350 $entry->children = $this->parseSimple( $dieseZeile->value );
00351 }
00352 else
00353 {
00354
00355 if ( $dieseZeile->isList )
00356 $liste = new ListElement();
00357 else
00358 $liste = new NumberedListElement();
00359
00360 $bisZeileNr = $zeileNr;
00361
00362 while( $bisZeileNr<=$anzahlZeilen && $zeilen[$bisZeileNr]->indent != $tiefe )
00363 $bisZeileNr++;
00364 $bisZeileNr--;
00365
00366
00367 $zeilenAuszug = array();
00368 $nr=0;
00369 for( $zn=$zeileNr;$zn<=$bisZeileNr;$zn++)
00370 {
00371 $zeilenAuszug[++$nr] = $zeilen[$zn];
00372 }
00373 $liste->children = $this->parseList($zeilenAuszug,$tiefe+1);
00374 $entry->children[] = $liste;
00375 $zeileNr = $bisZeileNr;
00376 }
00377 }
00378 $children[] = $entry;
00379
00380 return $children;
00381 }
00382
00383
00387 function parseTable( $zeilen )
00388 {
00389 $children = array();
00390 $anzahlZeilen = count( $zeilen );
00391 for ( $zeileNr=1; $zeileNr<=$anzahlZeilen; $zeileNr++ )
00392 {
00393 $dieseZeile = $zeilen[$zeileNr];
00394
00395 $zeile = new TableLineElement();
00396
00397
00398 $zellen = explode('|',$dieseZeile->source);
00399 $colSpan = 1;
00400
00401 foreach( $zellen as $zellenInhalt )
00402 {
00403 if ( $zellenInhalt=='')
00404 {
00405 $colSpan++;
00406 continue;
00407 }
00408
00409 $zelle = new TableCellElement();
00410 $zelle->colSpan = $colSpan;
00411 $colSpan = 1;
00412
00413 if ( substr($zellenInhalt,0,1) == '!' )
00414 {
00415 $zelle->isHeading = true;
00416 $zellenInhalt = substr($zellenInhalt,1);
00417 }
00418
00419 $zelle->children = $this->parseSimple( $zellenInhalt);
00420
00421 $zeile->children[] = $zelle;
00422 }
00423
00424 $children[] = $zeile;
00425 }
00426
00427 return $children;
00428 }
00429
00430
00431
00432 function parseLinks( $text )
00433 {
00434 $conf = Session::getConfig();
00435 $text_markup = $conf['editor']['text-markup'];
00436
00437 $posM = strpos($text,'"'.$text_markup['linkto'].'"');
00438
00439 if ( $posM === false )
00440 return false;
00441
00442 $posL = strpos(substr($text,0,$posM-1),'"');
00443
00444 if ( $posL === false )
00445 return false;
00446
00447 $posR = strpos($text,'"',$posM+4);
00448
00449 if ( $posR === false )
00450 return false;
00451
00452 $parts = array();
00453 $parts[] = substr($text,0 ,$posL );
00454 $parts[] = substr($text,$posL+1,$posM-$posL-1);
00455 $parts[] = substr($text,$posM+4,$posR-$posM-4);
00456 $parts[] = substr($text,$posR+1 );
00457
00458 return $parts;
00459 }
00460
00461
00465 function parseImages( $text )
00466 {
00467 $posM = strpos($text,'image:');
00468
00469 if ( $posM === false )
00470 return false;
00471
00472 $posL = strpos(substr($text,0,$posM-1),'"');
00473
00474 if ( $posL === false )
00475 return false;
00476
00477 $posR = strpos($text,'"',$posM+4);
00478
00479 if ( $posR === false )
00480 return false;
00481
00482 $parts = array();
00483 $parts[] = substr($text,0 ,$posL );
00484 $parts[] = substr($text,$posL+1,$posM-$posL-1);
00485 $parts[] = substr($text,$posM+4,$posR-$posM-4);
00486 $parts[] = substr($text,$posR+1 );
00487
00488 return $parts;
00489 }
00490
00491
00492
00501 function parseSimpleParts( $text,$sepLinks,$sepRechts )
00502 {
00503 $posL = strpos($text,$sepLinks);
00504
00505 if ( $posL === false )
00506 return false;
00507
00508 $posR = strpos($text,$sepRechts,$posL+strlen($sepLinks));
00509
00510 if ( $posR === false )
00511 return false;
00512
00513 $parts = array();
00514 $parts[] = substr($text,0 ,$posL );
00515 $parts[] = substr($text,$posL+strlen($sepLinks),$posR-$posL-strlen($sepLinks));
00516 $parts[] = substr($text,$posR+strlen($sepRechts) );
00517
00518 return $parts;
00519 }
00520
00521
00522
00526 function parseEscapes( $text )
00527 {
00528 $posL = strpos($text,'\\');
00529
00530 if ( $posL === false )
00531 return false;
00532
00533 $parts = array();
00534 $parts[] = substr($text,0 ,$posL );
00535 $parts[] = substr($text,$posL+1,1 );
00536 $parts[] = substr($text,$posL+2 );
00537
00538 return $parts;
00539 }
00540
00541
00542
00552 function parseSimpleElement( $text,$sepL,$sepR,$className )
00553 {
00554 $erg = $this->parseSimpleParts( $text,$sepL,$sepR );
00555 if ( is_array($erg) )
00556 {
00557 $idx = -1;
00558 $elements = array();
00559
00560 $davor = $this->parseSimple($erg[++$idx]);
00561 foreach( $davor as $davorEl )
00562 $elements[] = $davorEl;
00563
00564 $newEl = new $className();
00565 $newEl->children = $this->parseSimple($erg[++$idx]);
00566 $elements[] = $newEl;
00567
00568 $danach = $this->parseSimple($erg[++$idx]);
00569 foreach( $danach as $danachEl )
00570 $elements[] = $danachEl;
00571 return $elements;
00572 }
00573
00574 return false;
00575 }
00576
00577
00578
00585 function fixLinks( $text )
00586 {
00587
00588 $text = ereg_replace( '([A-Za-z0-9._-]+)\->','"\\1"->',$text );
00589
00590
00591 $text = ereg_replace( '\->([A-Za-z0-9\.\:\_\/\,\?\=\&-]+)','->"\\1"',$text );
00592
00593
00594
00595
00596
00597
00598 $text = ereg_replace( '([A-Za-z0-9._-]+@[A-Za-z0-9\.\_\-]+)([^A-Za-z0-9\.\_\-\"])','"\\1"->"mailto:\\1"\\2',$text );
00599
00600
00601 $text = ereg_replace( 'ima?ge?:\/?\/?([A-Za-z0-9\.\:\_\/\,\?\=\&-]+)','{\\1}',$text );
00602
00603 return $text;
00604 }
00605
00606
00607
00614 function parseSimple( $text )
00615 {
00616 $conf = Session::getConfig();
00617 $text_markup = $conf['editor']['text-markup'];
00618
00619 $text = $this->fixLinks($text);
00620 $elements = array();
00621
00622 if ( trim($text) == '' )
00623 return $elements;
00624
00625 $erg = $this->parseLinks( $text );
00626 if ( is_array($erg) )
00627 {
00628 $idx = -1;
00629
00630 $davor = $this->parseSimple($erg[++$idx]);
00631 foreach( $davor as $davorEl )
00632 $elements[] = $davorEl;
00633
00634 $link = new LinkElement();
00635 $link->children = $this->parseSimple($erg[++$idx]);
00636 $link->setTarget( $erg[++$idx] );
00637
00638 if ( $link->objectId != 0 )
00639 $this->linkedObjectIds[] = $link->objectId;
00640 $elements[] = $link;
00641
00642 $danach = $this->parseSimple($erg[++$idx]);
00643 foreach( $danach as $danachEl )
00644 $elements[] = $danachEl;
00645
00646 return $elements;
00647 }
00648
00649
00650 $erg = $this->parseSimpleParts( $text,$text_markup['image-begin'],$text_markup['image-end'] );
00651 if ( is_array($erg) )
00652 {
00653 $idx = -1;
00654
00655 $davor = $this->parseSimple($erg[++$idx]);
00656 foreach( $davor as $davorEl )
00657 $elements[] = $davorEl;
00658
00659 $image = new ImageElement();
00660 $t = new TextElement($erg[++$idx]);
00661 $image->setTarget( intval($t->text) );
00662 $t->text = '';
00663 $image->children[] = $t;
00664
00665 if ( $image->objectId != 0 )
00666 $this->linkedObjectIds[] = $image->objectId;
00667 $elements[] = $image;
00668
00669 $danach = $this->parseSimple($erg[++$idx]);
00670 foreach( $danach as $danachEl )
00671 $elements[] = $danachEl;
00672
00673 return $elements;
00674 }
00675
00676 $erg = $this->parseEscapes( $text );
00677 if ( is_array($erg) )
00678 {
00679 $idx = -1;
00680
00681 $davor = $this->parseSimple($erg[++$idx]);
00682 foreach( $davor as $davorEl )
00683 $elements[] = $davorEl;
00684
00685 $t = new TextElement($erg[++$idx]);
00686 $elements[] = $t;
00687
00688 $danach = $this->parseSimple($erg[++$idx]);
00689 foreach( $danach as $danachEl )
00690 $elements[] = $danachEl;
00691
00692 return $elements;
00693 }
00694
00695 $erg = $this->parseSimpleElement( $text,$text_markup['footnote-begin'],$text_markup['footnote-end'],'FootnoteElement' );
00696 if ( is_array($erg) )
00697 return $erg;
00698
00699 $erg = $this->parseSimpleElement( $text,$text_markup['strong-begin'],$text_markup['strong-end'],'StrongElement' );
00700 if ( is_array($erg) )
00701 return $erg;
00702
00703 $erg = $this->parseSimpleElement( $text,$text_markup['emphatic-begin'],$text_markup['emphatic-end'],'EmphaticElement' );
00704 if ( is_array($erg) )
00705 return $erg;
00706
00707 $erg = $this->parseSimpleElement( $text,$text_markup['code-begin'],$text_markup['code-end'],'TeletypeElement' );
00708 if ( is_array($erg) )
00709 return $erg;
00710
00711 $erg = $this->parseSimpleElement( $text,$text_markup['insert-begin'],$text_markup['insert-end'],'InsertedElement' );
00712 if ( is_array($erg) )
00713 return $erg;
00714
00715 $erg = $this->parseSimpleElement( $text,$text_markup['remove-begin'],$text_markup['remove-end'],'RemovedElement' );
00716 if ( is_array($erg) )
00717 return $erg;
00718
00719 $erg = $this->parseSimpleElement( $text,$text_markup['speech-begin'],$text_markup['speech-end'],'SpeechElement' );
00720 if ( is_array($erg) )
00721 return $erg;
00722
00723
00724 $t = new TextElement($text);
00725 $elements[] = $t;
00726
00727 return $elements;
00728 }
00729 }
00730
00731 ?>