PmWiki 2.x Konfigurationshinweise

Winfried Mueller, www.reintechnisch.de, Start: 18.05.05, Stand: 02.01.14

Vorwort

PmWiki nutze ich seit ungefähr 2003. Ich habe mit der Version 1 begonnen. Damals war die Entwicklung noch sehr dynamisch, weil es ein noch ganz junges Projekt war. 2004 wurde mit der Entwicklung von PmWiki 2.0 begonnen, welches im September 2005 fertiggestellt wurde. Zu dieser Zeit war PmWiki ein ziemlich ausgereiftes System und eine runde Sache. Natürlich gibt es immer tausend Ideen, was man noch verbessern oder dranstricken kann. Doch irgendwie muss man aufpassen, dass aus so einem Projekt eine klar definierte Sache bleibt, die nicht durch alle möglichen Gimicks aufgebläht wird. Denn so enden viele Projekte: Weil sie alles können wollen, werden sie zu einem nur schwer wartbarem System, vor dem jedem Administrator graut.

Seit der Version 2.0 im Jahre 2005 wurde das System zwar kontinuierlich weiter gepflegt, große Veränderungen gab es jedoch nicht mehr. Mich hat das gefreut, weil ich mit dem, was es konnte hinreichend zufrieden war und sich so die Updates von zahlreichen Wikis recht einfach gestaltete. Wer schonmal über 10 Jahre oder länger eine webbasierte Software kontinuierlich lauffähig gehalten, weiß, was das für Arbeit sein kann, die einen da immer wiederkehrend erwartet. Der Umstieg von Version 1.0 auf 2.0 war etwas aufwändiger, weil PmWiki von Grund auf nochmal neu entwickelt wurde und zahlreiche Altlasten ausgeräumt wurden.

Die Version 2.1 kam dann 2006, hier änderte sich nur wenig, so dass ein Update relativ einfach machbar war. Diese Version hatte auch relativ lange Zeit Bestand.

Die Version 2.2 kam erst 2009. Das ist auch die derzeit aktuelle Version Ende 2013, wobei wir mittlerweile bei Version 2.2.58 angekommen sind. Auch dieser lange Zyklus zeigt, dass hauptsächlich ein stabiler Code gepflegt wird, all zu viel Neues ist nicht hinzugekommen. Das Update von 2.1 auf 2.2 gestaltete sich auch relativ einfach.

Die Konfiguration von PmWiki ist unglaublich flexibel. Hierfür hat PmWiki etwa 300 globale Variablen, die bei Initialisierung vorbelegt werden, die man aber über local/config.php überschreiben kann. Hierüber nimmt man größtenteils Einfluss auf die Konfiguration. Weil die Konfigurationsdatei eine PHP-Programmdatei ist, kann man auch beliebigen eigenen PHP-Code hinzufügen oder eigene globale Variablen definieren, die man in Seitentemplates verwendet. Die config.php wird bei jedem Aufruf vom Hauptprogramm pmwiki.php geladen.

PmWiki ist schnell und einfach installiert. Auch die Basiskonfiguration geht recht schnell vonstatten und beinhaltet im Grunde nur das Setzen einiger Variablen. Eine Vorlage für eine config.php wird mitgeliefert (docs/sample-config.php). Ebenso kann man Erweiterungen aus dem Cookbook installieren.

Cookbook-Erweiterungen sind so eine Sache. Man kennt das ja von vielen Projekten: Da wird eine zentrale Codebasis von einem Kernteam entwickelt. Dieser Code ist über Schnittstellen in der Lage, erweitert zu werden. Und die Erweiterungen schreiben dann alle möglichen Leute. Der Vorteil ist, dass so jede Menge Code für Zusatzfunktionen aus dem Boden sprießt. Nach dem Motto, jeder der programmieren kann und eine neue Funktionalität braucht, bastelt mal schnell was zurecht und stellt es für andere Online. Der große Nachteil ist, dass die Qualität solcher Erweiterungen schlecht sein kann und dies zu allen möglichen funktionellen und sicherheitsrelevanten Problemen führt. Es kann auch sehr nervig sein, überhaupt erstmal aus dem Wust von angeboteten Skripten überhaupt erstmal die Spreu vom Weizen zu trennen.

Und dann kommt noch die wichtige Frage auf, wie lange dieser Code auch gepflegt wird. Ein ist sicher: Die zentrale Codebasis wird sich weiter entwickeln, aber wird auch ein verwendetes Cookbook Script weiterentwickelt?

Seien wir ehrlich: Mindestens 80% der Erweiterungen werden über die Jahre verwaisen, da kümmert sich dann keiner mehr drum. Und dann steht man als Admin vor einem echten Problem: Die Benutzer haben sich an bestimmte Funktionalitäten gewöhnt, die nun abgeschaltet werden müssen. Denn um Updates der Codebasis kommt man ja nicht herum, zumindest nicht ewig.

Kurzum, für alles, was langfristig laufen soll, verzichte ich, wo es geht, auf Cookbook-Erweiterungen.

Mit Skins passt man bei PmWiki die Oberfläche an, das Wiki kann so ein völlig anderes Aussehen bekommen, ja man kann es sogar per Klick Live umschalten. Das ist zum Glück recht sauber gelöst - Code und Oberfläche wurden sauber getrennt. Skins gibt es auch vorgefertigt. Hier ist es aber ähnlich, wie mit Cookbook-Skripten: Man weiß nie, wie lange die gepflegt werden. Weil sich aber in der Skin-Schnittstelle nicht so viel tut, ist die Wahrscheinlichkeit groß, dass man hier lange mit dem gleichen Skin arbeiten kann. Und selbst wenn sich mal was ändert, bekommt man das mit etwas HTML-Basiswissen selber hingebastelt.

Wenn man anfängt, eigene Skins zu entwerfen, kann die Sache schon komplizierter werden. Ein Grund, warum ich mich die letzten Tage damit ziemlich abgemüht habe, ist sicherlich etwas fehlende Dokumentation, die die Konzepte und Prinzipien gut erläutert. Ich habe versucht, hier mal einige wichtigen Infos zusammenzutragen, die als Ergänzung zur mitgelieferten Doku dienen sollen.

Wenn man eigene Skins erstellt, sollte man grundsätzlich in HTML und CSS fit sein. Man kommt allerdings auch mit recht wenig Wissen darin weiter, wenn man einen halbwegs passenden Skin auswählt, den man dann hier und dort ein wenig anpasst. Wissen in der Programmiersprache PHP ist immer mal wieder nötig, um Details von PmWiki vestehen zu können oder nicht dokumentierte Funktionalitäten herauszufinden.

Dieses Dokument basiert teilweise noch auf alten Versionen, es kann sich inzwischen manches Detail geändert haben.

Skins

In einem Skin kann man sehr flexibel die Darstellung bzw. das Aussehen des Wikis beeinflussen.

Ein Skin wird grundsätzlich in einem Unterverzeichnis von pub/skins abgelegt, also z.B. pub/skins/myskin. Dort liegen bis zu 3 Dateien, die typisch genauso heißen, wie der Skinname:

  • myskin.tmpl - Hier wird das eigentliche Design in Form einer Vorlage festgelegt. Diese Vorlage ist eine Mischung aus html-Code und Variablen, die später bei der Erzeugung der konkreten HTML-Seite ersetzt werden.
  • myskin.php - Diese Datei legt man wahlweise an, wenn man für den Skin auch php-Code benötigt, der bei der Seitenerzeugung aufgerufen werden soll. Darüber lassen sich z.B. neue Variablen einführen oder globale Variablen neu belegen. Für viele Skins ist diese Datei nicht nötig.
  • myskin.css - Dies ist die css-Datei, die zur Darstellung der Seite verwendet werden soll.

In PmWiki2 ist es nun möglich, für jede Aktion einen eigenen Skin zu erstellen. Sinnvoll ist das z.B. für action=edit. Um mehr Platz für das Editfenster zu bekommen, könnte man in diesem Skin z.B. das Menü ganz weglassen. Wer viel wert auf ein sauberers Design legt, sollte für jede Aktion ein eigenen Skin anlegen.

Hinter dem Skin-Konzept steht eigentlich die Idee, gleiche Funktionalität auf unterschiedliche Weise zu präsentieren. In PmWiki ist es aber gleichzeitig die Stelle, wo man generell die Oberfläche in ihrem Aussehen und ihrer Funktionalität festlegt. Hier kann man also in weiten Grenzen das Aussehen des Wikis festlegen und die (klickbare) Funktionalität, mit der es daher kommt.

Skins können auch in Unterverzeichnissen von pub/skins/myskin liegen. Das bietet sich an, wenn man für seinen Skins für spezielle Aktionen Extra-Skins anlegt, also z.B. so:

 
  pub/skins/myskin: 
    myskin.tmpl
    myskin.css
  pub/skins/myskin/print: 
    print.tmpl
    print.css
  pub/skins/myskin/edit:
    edit.tmpl
    print.css
  pub/skins/myskin/diff:
    diff.tmpl
    diff.css

Eingebunden werden solche Skins in der local.cfg so:

 
$Skin = "myskin";
$ActionSkin['edit']  = 'myskin/edit';
$ActionSkin['print'] = 'myskin/print';
$ActionSkin['diff']  = 'myskin/diff';

Wird kein eigener print-Skin eingebunden, greift PmWiki auf pub/skins/print zurück. Bindet man kein diff und edit ein, wird ein Standardverhalten erzeugt, was allerdings hart codiert in irgendwelchen php-Skripten liegt.

Aufbau der Vorlagen-Datei (*.tmpl)

Bei der Erzeugung einer konkreten Wikiseite dient diese Datei also Vorlage. Die Datei wird geparst und es passieren folgende Dinge:

  • Variablen, wie $SkinDirUrl werden durch den aktuellen Wert dieser globalen Wikivariablen ersetzt. Globale Wikivariablen beginnen immer mit einem großen Buchstaben und natürlich dem $Zeichen, womit ja alle Variablen in php beginnen.
  • Internationalisierungsstrings (I18N) wie SearchWiki werden durch den Wert ersetzt, wie er in der XLPage-Wikiseite der aktuellen Gruppe zu finden ist. Sie beginnen mit einem Dollarzeichen und in eckige Klammern sind ein oder mehrere Wörter eingeschlossen. Findet PmWiki in der XLPage diese Wortgruppe auf der linken Seite der Zuweisung in XLPage, wird es durch den Wert der rechten Seite ersetzt. Mit 'SearchWiki' => 'Suchen' wird SearchWiki durch 'Suchen' ersetzt. Der Mechanismus ist so flexibel, dass man sich komplett eigene Internationalisierungsstrings ausdenken kann, man sollte sich jedoch an die bisher definierten halten. Wer einen Skin erstellt, welcher nur in einer Sprache genutzt wird, kann alle I18N Strings durch feste Werte ersetzen. Der Verweis auf die aktuelle XLPage macht man übrigens in der config.php über die Funktion XLPage(), also z.B. XLPage('de','PmWikiDe.XLPage') oder XLPage('de', 'Site.XLPage'). Auf welche Seite man hier verweist, ist eigentlich egal, PmWiki muss an diesem Ort nur eine Seite finden, die die Internationalisierungsstrings enthält.
  • Marker in der Form <!--Markername--> werden durch bestimmte Inhalte ersetzt. So wird z.B. der Marker <!--PageText--> durch den Seitentext ersetzt, den PmWiki erzeugt. Das ist eigentlich das zentrale Element des Ersetzungsvorganges. Weil der HTML-Parser dies als Kommentar sieht, stören solche Ersetzungsmarkierungen bei der Erstellung des Designs nicht. Diese Marker bleiben auch nach dem Ersetzen erhalten, sind also noch in der ausgelieferten HTML-Seite vorhanden, direkt dahinter steht dann der eingefügte Inhalt, der zu dem Marker gehört. Das macht das Debugging leichter.
  • Marker in der Form <!--Markername-->...<!--/Markername--> verhalten sind anders. Sie markieren einen Bereich, der nach bestimmten Bedingungen ein- oder ausgeblendet wird. So legt z.B. <!--PageHeaderFmt-->..<!--/PageHeaderFmt--> den Kopfbereich fest, der immer dann ausgeblendet wird, wenn auf der Wikiseite die Anweisung (:noheader:) eingefügt wird. Allerdings muss man hier aufpassen: Bereiche lassen sich nicht verschachteln. Hat man z.B. im Header den Titel eingebaut, so wäre PageTitleFmt in PageHeader geschachtelt, was nicht funktioniert. Weiterhin wird durch diese Bereiche die PHP-Variable $<Markername> definiert. Der Inhalt zwischen den Tags wandert also in die gleichnamige globale PHP-Variable.
  • Marker der Form <!--wiki:Main.SomePage--> werden durch den Inhalt dieser Wikiseite ersetzt, wenn diese vorhanden ist. Darüber funktioniert z.B. die Einblendung des Menüs (Main.SideBar) oder anderer Fenster oder Bereiche, welche unabhängig vom eigentlichen Hauptinhalt angezeigt werden sollen.
  • Marker der Form <!--function:SomeFunction arguments--> werden durch den Rückgabewert der aufgerufenen php-Funktion ersetzt.
  • Variablen in der Form {$variablename} sind keine globalen PHP-Variablen, sondern sogenannte "Page specific variables", ein PmWiki-Konzept. Solche Variablen können auch innerhalb des Markups auf einer Seite benutzt werden. Siehe hierzu: http://www.pmwiki.org/wiki/PmWiki/PageVariables

Wichtige I18N Strings:

 
$[Author]                 Autorfeld im Editmodus
$[Edit Page]              Ändern Link der Seite
$[Go]                     Suche Button               
$[Page History]           Link Aufruf Seitenhistorie
$[Powered by]             Powered by PmWiki 
$[Preview]                Button Vorschau im Editmodus   
$[Printable View]         Link Druckansicht
$[Recent Changes]         Link Letzte Änderungen Seite
$[Reset]                  Button Reset im Editmodus
$[Save]                   Button Save im Editmodus
$[SearchWiki]             Link Suchefenster
$[This is a minor edit]   Kleine Änderung Text im Editmodus

Weitere I18N Strings findet man auf der passenden XLPage, die man sich von pmwiki.org herunterladen kann.

Wichtige globale PmWiki-Variablen:

 
$Action              aktuelle Aktion (print, edit...)
$Author              Autor der Seite
$DiffClassMinor      ?
$EditBaseTime        aktueller Zeitpunkt für Editier-Fenster
$EditMessageFmt      ?
$EditText            Seitenquelltext für Editier-Fenster
$FullName            Gruppe.Wikiseite
$Group               Gruppenname
$Groupspaced         Gruppenname WikiWord separiert
$LastModified        Datumsstring der letzten Änderung
$Name                Name des Authors
$PageLogoUrl         Url des Logos
$PageUrl             Seiten-Url
$PubDirUrl           Url des pub-Verzeichnisses
$ScriptUrl           Url von pmwiki.php
$SkinDirUrl          Skin Basisverzeichnis, normal pub/skins
$Title               Titel der Seite
$Titlespaced         Titel der Seite, WikiWord mit Space getrennt
$WikiTitle           Wikititel, in config.php festgelegt 

Wichtige Marker:

 
<!--HTMLHeader-->  html-<head> Einfügemarke. Für alles, was in den 
                   <head> soll. Z.B. wird hier $HTMLHeaderFmt 
                   eingesetzt.

<!--PageText-->    Inhalt der Wikiseite

<!--PageHeaderFmt-->  Bereich, der den Kopf der Seite 
                      definiert (Logo...)
<!--/PageHeaderFmt-->

<!--PageTitleFmt-->  Seitentitel, der im html angezeigt wird
<!--/PageTitleFmt-->


<!--PageLeftFmt-->  Sidebar links
<!--/PageLeftFmt-->


<!--PageRightFmt--> Sidebar rechts
<!--/PageRightFmt-->

<!--PageFooterFmt-->  Start des Footers, (wird $PageFooterFmt 
                      gespeichert)
<!--/PageFooterFmt--> Ende des Footers

<!--PageEditFmt-->    Editseite

<!--wiki:Main.SomePage-->  Inhalt einer andere Wikiseite ins Layout 
                           einbauen (für Menüs oder Sidebars)
                           auch <!--wiki:$Group.SomePage--> 
                           funktioniert

<!--function:SomeFunction ''arguments''--> Call a php Function

<!--HTMLFooter-->     Am Schluß des Bodys für Ausgabe unterhalb von PageText


Konsequent Templates einsetzen

Was mir an PmWiki nicht gefällt, ist, dass immer noch nicht konsequent auf Templates gesetzt wird. Manche HTML oder CSS-Vorlage schwirrt noch direkt im PHP-Code rum. So eine Vermischung verheißt oft nichts Gutes. Vieles davon lässt sich aber abschalten und über Templates verwalten.

Im Template des eigenen Skins kann man z.B. den Abschnitt <!--PageEditFmt--> mit hinzunehmen. Das Template für die Editseite fliegt nämlich normal in pmwiki.php rum und kann dann über die Neubelegung einer globalen Variable verändert werden. Wenn man dagegen diesen Abschnitt in die Template-Datei packt, dann wird die Variable mit diesem gefüllt. Ausgegeben wird der Abschnitt dann nur, wenn man wirklich die Edit-Aktion ausführt. Man hat sozusagen ein gemischtes Template für alles, wo je nach Bedingung bestimmte Teile ein- oder ausgeblendet werden.

Eleganter finde ich jedoch die Methode, für jede Aktion ein separates Template anzulegen. Dieses Konzept ist flexibler und übersichtlicher, bedeutet aber etwas mehr Arbeit.

CSS-Stylesheets

Modernes Webdesign versucht, alles, was die Darstellung angeht, in CSS-Dateien auszulagern. So sollte man das bei seinem Skin auch versuchen. Man kann darüber saubere und im Code übersichtliche Webseiten gestalten, die auch sehr flexibel sind. PmWiki bringt viel Unterstützung mit, damit man über CSS ordentlich arbeiten kann.

CSS-Styles werden im Code über die Variable $HTMLHeaderFmt['styles'] eingefügt. Will man alles sauber in eine CSS-Datei auslagern, setzt man über die config.php auf eine leeres Array:

 
# includierte Styles ausschalten
$HTMLHeaderFmt['styles'] = array();

Wenn man nun die Seitenhistorie einer Seite aufruft, sieht man, dass da tatsächlich was fehlt. Hier werden nämlich einige CSS-Einstellungen gebraucht, die PmWiki über obige Variable in den HTML-Header normal einfügt. Diese hab ich dann in die CSS-Datei meines Skins übernommen. Konkret sind es diese:

 
.diffbox { 
  border:1px #999999 solid; 
  margin-top:1.33em; 
}

.diffauthor { 
  font-weight:bold; 
}

.diffchangesum { 
  font-weight:bold; 
}

.difftime { 
  font-size:66%; 
  background-color:#dddddd; 
}

.difftype { 
  clear:both; 
  font-size:66%; 
  font-weight:bold; 
}

.diffadd { 
  border-left:5px #99ff99 solid; 
  padding-left:5px; 
}

.diffdel { 
  border-left:5px #ffff99 solid; 
  padding-left:5px; 
}

.diffrestore { 
  clear:both; 
  font-size:66%; 
  margin:1.5em 0px; 
}


.indent { 
  margin-left:40px; 
}

.outdent {
  margin-left:40px; 
  text-indent:-40px;
}

.vspace {
  margin-top: 1.33em;
}

.note { 
  color:green; 
  font-style:italic; 
}

.editconflict { 
  color:green; 
  font-style:italic; 
  margin-top:1.33em; 
  margin-bottom:1.33em; 
}

Man kann die natürlich auch nach eigenen Bedürfnissen anpassen. In einigen Skripts von PmWiki findet man weitere CSS-Styles, die man hier übernehmen muss. Man findet sie in den Zuweisungen zur Variablen $HTMLStylesFmt[]. Alles, was dieser Variablen (Array) zugewiesen wird, taucht über $HTMLHeaderFmt['styles'] wieder auf. Man sollte also einfach mal ein grep auf $HTMLStylesFmt[] machen.

Für die Druckausgabe braucht es oft kein Extra-Template. Man kann nämlich entweder eine Druck-CSS-Datei anlegen, die dann eine druckangepasste Ausgabe steuert. Oder man schreibt in der Standard-CSS Datei einen Abschnitt, der die Druckausgabe steuert. Dies sollte bei allen Browsern ab Version 5 funktionieren. Beispiel:

 
@media print {
  #leftbox {
    display: none;
  }
  #head {
    display:none;
  }

  #rightbox {
    margin-left: 0px;
    width:98%;
  }

  #content {
    border:0;  
  }

  #footerright {
    display:none;
  }

  #footerleft {
    color: #000;
  }

  h1, h2, h3, h4 {
    color: #000;
    font-weight: bold;
  }

  a {
    color: #aaaaaa;
  }

  pre {
    border: 1px dashed #000000;
    font-size: 9pt;
    padding: 8px;
  }
}

Pitfalls, Tipps und Tricks

  • Ich hatte den Fall, dass beim Aufruf der Edit-Seiten-Funktion keine Seite ausgeliefert wurde. Dieser Fehler war sehr hartnäckig und ich suchte Stunden im Code. Irgendwann hatte ich eine Zeile gefunden, an dem das Skript hängenblieb. Es hatte was mit der Sessionverwaltung zu tun. Die Sessionverwaltung speichert Informationen im Temp-Verzeichnis des Hosts. Und da scheint wohl in sehr seltenen Fällen was schief zu gehen. Nachdem ich dort alle alten sess_* Dateien gelöscht hatte, funktionierte alles wieder.
  • Manchmal gab es Probleme mit der .flock Datei im Verzeichnis wiki.d. Nachdem ich die von Hand löschte, funktionierte alles wieder.
  • Man muss auf die richtigen Rechte des wiki.d Verzeichnisse achten. Oft reicht 775 aus, manche Internetrechner haben jedoch eine ungünstige Konfiguration, so dass man 777er Rechte dafür braucht. Gleiches gilt für die Seitendateien im wiki.d Verzeichnis, welche normal mit 660 konfiguriert sind, manchmal jedoch 666 brauchen.
  • Man sollte darauf achten, die .htaccess Dateien in den entsprechenden Verzeichnissen nicht zu löschen, weil sonst Sicherheitsprobleme auftreten.
  • Beim Aufbau meines separaten Edit-Skins erschien die Seitenvorschau zweimal. Erst durch "SetTmplDisplay('PagePreviewFmt',0);" in der local.php konnte ich das unterdrücken. Ich glaub, das ist noch ein Bug in PmWiki (Beta 2.0.39)
  • Webdesign nach modernen XHTML/CSS Richtlinien (tabellenloses Design) ist grundsätzlich möglich, ab Browsern der Version 5. Allerdings gibt es eine Menge Bugs in diversen Browsern und so sind von den vielen CSS-Möglichkeiten nur ganz wenige Wege wirklich gangbar. Man kann sehr viel Zeit damit verbringen, herauszufinden, welche Designmöglichkeiten wo überall richtig funktionieren. Wer diese nicht investieren will, orientiere sich besser an Musterlösungen, wie man sie vielerorts im Internet findet. Auch kann man sich diverse fertige Skins anschauen und davon lernen. Beim Testen der Darstellung sollte man mindestens Internet-Explorer, Opera und Mozilla/Firefox verwenden. Weil der Internet-Explorer nur einmal installiert sein kann, braucht man mehrere Rechner, um sowohl mit Version 5, wie auch mit Version 6 testen zu können.

Weblog

19.03.2008 :: Division by Zero Error

Auf manchen Installationen kommt es bei der Benutzung der Wiki-Suche zu einem "Division by Zero Error". In diesem Fall sollte man dies hier lesen: http://www.pmwiki.org/wiki/PITS/00830

Die Eingabe von:

$TableRowIndexMax = 1;

in der config.php hat geholfen.

26.07.2005 :: Externe Links immer im neuen Fenster

Es gibt einige Für und Wider, wie externe Links geöffnet werden sollen. Ich finde es besser, wenn externe Links immer in einem neuen Fenster geöffnet werden. Einerseits erkennt der Besucher so, dass es sich um ein Angebot jenseits meiner Homepage handelt, andererseits verliere ich den Kontakt mit ihm durch einen externen Link nicht.

Mir war es mit der Zeit zu lästig, immer wieder %newwin% für jeden externen Link zu schreiben. Umstellen lässt sich das in PmWiki ganz einfach, so dass dann jeder Link in neuem Fenster erscheint. Einfach in die local.php folgendes einfügen:

 
$UrlLinkFmt = 
  "<a class='urllink' href='\$LinkUrl' target='_blank'>\$LinkText</a>";

Weblinks