Einführung
Das Besondere an PHP ist, dass man die Ausgabe von Daten, die eigentlich zum User über das Internet gesendet werden sollen, in einen Puffer schreiben kann. Hat man die gesamte Ausgabeseite zwischengepuffert oder aufgefangen, dann kann man mit weiteren PHP Befehlen die Seite verändern und danach dem User übermitteln. Es ist leider so, dass webtodate nicht die Internet-Konventionen von » World Wide Web Consortium einhält. Das sind die Standard, wie HTML und CSS auszusehen hat. Webtodate macht da Fehler beim Generieren der Seiten aus dem CCML Code. Da das aber teilweise im Programm hinterlegt ist, kann man diese Fehler nicht in den CCML-Dateien korrigieren. Dazu dient der Parser. Es macht eine Zwischenspeicherung, dessen was eigentlich als fehlerhafter Code zum Internetbesucher gesendet werden soll, durchsucht die Seite nach Fehlern und korrigiert diese. Natürlich muss man das dem Parser explizit beibringen, was und wie etwas zu korrigieren ist. Von selber weiß der Parser nichts.
Der Parser wird in der Datei navigation.ccml eingebaut und ist damit auf allen Seiten verfügbar. Weil er aber auf allen Seiten ausgegeben wird, sind Änderungen am Parser gut zu testen, d.h. mindestens auf mehreren Seiten zu testen. Denn es wird so sein, dass nicht alle Konstellationen, die der Parser korrigieren oder verändern soll auf allen Seiten auch existieren. Fehlt sozusagen die Ausgangssituation, werden Teile der Parseranweisungen nicht ausgeführt und es ist nicht klar, ob diese Anweisungen auf anderen Seiten korrekt sind.
Der Code
Zum Starten der Puffung wird folgende Zeile eingefügt:
<?php ob_start(); ?>
Sinnvollerweise steht diese Zeile vor "<!DOCTYPE" und bei Shop noch vor "<cc:if cond="&topic.isshop">". Dann wird die gesamte Seite gepuffert und man hat die kompletten Zugriff.
Zum Auslesen und Verarbeiten des Puffers wird am Ende der navigation nach </html> folgt folgender Code eingefügt:
<?php
if (!function_exists("ob_get_clean")) {
function ob_get_clean() {
$ob_contents = ob_get_contents();
ob_end_clean();
return $ob_contents;
}
}
$content=ob_get_clean();
$content=str_replace("<br>","<br />",$content);
.....
echo $content;
?>
Zunächst wird der Buffer ausgelesen mit "ob_get_clean" (den Code davor einfach ignorieren), dabei wird der Puffer in der Variablen "$content" (immer links) gespeichert. In der nächste Zeile werden alle fehlerhaften Anweisung "<br>" zu "<br />" gewandelt, es folgen ggf. weiter Zeilen (hier mit .... angedeutet) und dann mit "echo" die Ausgabe an den User. Hinweis: Die Zeile "....." ist kein PHP Code. Sie muss gelöscht werden oder durch einen korrekten PHP Code ersetzt werden.
Folgender Code wandelt Umlaute in die richtige HTML Notation um:
#C
$content=str_replace('Ä','Ä',$content);
$content=str_replace('ö','ö',$content);
$content=str_replace('Ö','Ö',$content);
$content=str_replace('ü','ü',$content);
$content=str_replace('Ü','Ü',$content);
$content=str_replace('ß','ß',$content);
Sprungmarken auf einen Absatz, die sich in webtodate einfach setzen lassen, sind ebenfalls fehlerhaft, denn diese müssen als erstes Zeichen einen Buchstaben haben und derzeit macht das webtodate nicht. So kann man es korrigieren
#C
$content=str_replace("php#title","php#titletitle",$content);
Regulläre Ausdrücke
Reguläre Ausdrücke sind Möglichkeiten auf unbekanntes zu reagieren: Haben wir irgendeine User-Eingabe aus einer Eingabemaske mit Zahlen und ggf. Leerzeichen und Strichen, will aber nur die Nummern (z.B. einer Telefonnummer) haben (z.B. um abzugleichen ob diese Nummer schon existiert) dann ist dieser Befehl geeignet;
#C
$NurNummern=preg_replace('/[^0-9]/', '', $usereingabe);
Als Reguärer Ausdruck ist er mit "/..../" geklammert.
Dann folgt ein Gruppenanweisung "[.....]", also behandle das Gesuchte (und dann Gefundene) gleichartig.
Es folgt eine Vereinung mit "^" also wir suchen nach "allem außer".
Dann kommt der Buchstabe "0" eine bis-Anweisung mit "-" und der Buchstabe "9".
Ergo: Es wird nach Allem außer "0-9" gesucht und dann durch den zweiten Teil (hier: '') , also durch Nichts ersetzt, was gleichbedeutend ist mit gelöscht.
Es wird in der Usereingabe gesucht und das Ergebnis in $NurNummern gespeichert.
Damit sind alle Sonderzeichen, Leerzeichen, Schrägstriche usw. weg, und nur die Nummern bleiben übrig.
Mit regulären Ausdrücken kann man extrem flexible Dinge machen:
#C
$searchpat="/<form style=\"margin-top:([1-9 ]*)px; margin-bottom:([1-9 ]*)px;\"".
" onsubmit=\"return http\['([a-zA-Z0-9 ]*)'\].submit\(\);\" action=\"([0-9a-z\/\. ]*)\"".
" name=\"([a-z0-9]*)\" method=\"post\">([\n\r.]*)<input type=\"hidden\" name=\"uid\" value=\"([0-9a-z]*)\" \/>".
"([\n\r .]*)<input type=\"([a-z]*)\"/";
$x=preg_match($searchpat,$content,$matchresult,PREG_OFFSET_CAPTURE);
$content=substr($content,0,$x)."<form style=\"margin-top:".$machresult[1]+5."px ....... ".substr($content,$x+strlen($matchresult[0],99999);
Es wird ein Suchmuster (searchpattern) definert: Man sucht nach "<form style="marin-top:"- eine Zahl von 1-9 (wegen "*" auch mehrere Zahlen z.B. zweistellig), dann folgt "px" usw. Irgendwann wird nach (blau) a-z und A-Z und 0-9" gesucht... usw. Wird dieses gesamte Suchmuster gefunden (preg_match) wird in $x in der nächsten Zeile die Position gefunden, also dieses Suchmuster existiert z.B. an der 3243 Stelle des $contents das erste Mal. Die einzelnen Werte werden in $matchresult hinterlegt. Also welcher Wert hatten denn bitte der margin-top? Das steht dann in $matchresult[1]. Der gefundene Text inkl. aller Werte, also der Abschnitt von der 3243. Stelle bis zum Ende des Suchmusters steht in $matchresult[0]. D.h. jede nicht exakte Suchvorgabe, also alles was in Mustern steht und mit (...) ausgezeichnet ist, wird in $matchresult je nach Position abgelegt. Zählt man nach, findet man in $searchpat neun mal eine "(" (einmal entwertet als \(, die dann nicht zählt) und damit wird Matchresult entweder "nichts" enthalten, weil es keinen Treffer gab, oder eine Liste von 9 Einzelwerten. Mit der letzten Zeile setze ich den $content neu zusammen: Nimm alles vor der Funstelle, dann den Text <form style="margin-top und dann das matchresult[1], also die gefundene Pixelzahl, aber nun um 5 pixel erhöht. D.h. wir machen den oberen Rand der Form 5 Pixel höher usw. Und dann hänge an den neuen MIttelteil noch alles nach der Fundstelle an. So könnte ich mit den gefundenen Werten und neuen HTML-Anweisungen diese Stelle komplett neu aufbauen und gleichzeitig flexibel auf die Werte reagieren.
Mit diesem Befehl wird nach Bildbefehlen gesucht: <img title=...... src=.....> und es wird ein alt-Tag eingefügt mit dem gleichen Wert wie der titel und das abschließende </img> Tag wird auch noch eingefügt.
#C
$x=preg_match(/<img title=\"([a-zA-Z0-9]*)\" src=\"([a-zA-Z0-9]*)\">/",$content,$matchresult,PREG_OFFSET_CAPTURE);
$content=substr($content,0,$x)."<img title=\""$matchresult[1]."\" alt=\""$matchresult[1]."\ $matchresult[2]."\"></img>".substr($content,$x+strlen($matchresult[0],99999);
Diese Anweisung muss aber mehrfach in einer Schleife durchlaufen werden, damit man alle Stellen korrigiert. Reguläre Ausdrücke sind eine Wunderwaffe, deren Anwendung extrem koplex und schwierig ist.
Zusammenfassung
Der Parser manipuliert die Seite, bevor der User die Seite zu sehen bekommt. Damit kann man mit PHP auf aktuelle Situationen reagieren: Aktueller Lagerbestand, aktuelles Daten. Der User kann nicht sehen, wie seine empfangenen Daten entstanden sind. Zu große und unnötige Routinen können aber Aufbereitungszeitbenötigen und den User es unbequem machen auf der Seite zu verbleiben. Auch Suchmaschinen bewerten die Antwortszeiten als Kriterium.