toscho.design

WordPress-Tutorial: Ein Framebreaker-Plugin schreiben

Ein Framebreaker ist ein kleines Javascript, das die Website in den Vordergrund hebt, wenn jemand versucht, sie in seinen Frame einzubetten.

In der einfachsten Variante steht das Script im head:

<head>
<script type="text/javascript">
if (self != top) 
{
    top.location.replace(self.location.href); 
}
</script>
</head>

So wird die URL im Verlauf ersetzt und der Zurückbutton funktioniert weiterhin normal.

Nun kann nicht jeder WordPress-Benutzer frei an seinem Theme herumschrauben. Oft wird es aus anderen Quellen aktualisiert, und dann würde der Code überschrieben werden. Ein Plugin löst das Problem, indem es diese Funktionalität vom Theme trennt.

Dateien anlegen

Zuerst erstellen wir ein Verzeichnis framebreaker im Pluginverzeichnis; da legen wir eine PHP-Datei hinein, die wir passenderweise auch framebreaker.php nennen.
Der Dateiname spielt übrigens keine Rolle; er muß nur auf .php enden. Wir achten aber darauf, daß er von anderen leicht als ›Hauptdatei‹ erkannt wird, damit sich jeder schnell zurechtfindet. main.php wäre also auch ein passender Name, code.php eher nicht.
Es ist üblich, bei Datei- und Verzeichnisnamen nur Kleinbuchstaben, Zahlen und Bindestriche zu verwenden.

Wenn das Plugin aus nur einer Datei besteht, braucht es kein eigenes Verzeichnis. Für den Anwender ist es aber übersichtlicher, wenn jedem Plugin ein Verzeichnis entspricht, weil er dann im FTP-Programm nur den Baum aufklappen muß, um alle Plugins zu sehen.
Wollen wir bei einem späteren Update doch weitere Dateien hinzufügen – Icons, Sprachdateien oder eine Optionsseite – müssen wir ohnehin ›umziehen‹.

Metadaten

Der Kopf der Datei sollte so aussehen:

<?php
/*
Plugin Name: Framebreaker
Plugin URI:  http://toscho.de/2010/wordpress-tutorial-framebreaker-plugin/
Description: Baut ein Javascript in den HTML-Kopf, das die Website vor dem Einframen schützt.
Version:     0.1
Author:      Thomas Scholz
Author URI:  http://toscho.de
*/

WordPress genügt der Name; den Rest können wir technisch gesehen weglassen. Aber davon rate ich ab. Die Angaben helfen dem Nutzer, sich für oder gegen das Plugin zu entscheiden. Fehlen sie, sieht es schnell ›verdächtig‹ aus.

Screenshot

Falls wir unser fantastisches Plugin irgendwann auf wordpress.org veröffentlichen wollen, sollten wir jetzt schon nachsehen, ob eines mit diesem Namen existiert.
Die Suche nach ›Framebreaker‹ liefert bis jetzt noch keine Ergebnisse; wir können also weitermachen.

Der Name sollte eher beschreiben als unterhalten, die Hauptfunktion also klar wiedergeben. Wäre ›Framebreaker‹ schon weg, das bestehende Plugin dazu aber nicht so gut, daß wir unsere Arbeit fallen oder dort einfließen lassen wollen, könnten wir noch ›Break Frames‹ oder ›Frame Escape‹ versuchen. ›Luftjucker‹ klänge zwar deutlich amüsanter und ist sicher noch frei, aber danach sucht niemand.

Real gibt es natürlich schon eine Menge Framebreaker (in sehr unterschiedlicher Qualität); unser Plugin brauchen wir dort also nicht anzumelden.

Beim Auslesen der Metadaten wird noch kein Plugin-Code ausgeführt; wir können aber in der Beschreibung ein paar HTML-Elemente verwenden:

  • a[href][title],
  • abbr[title],
  • acronym[title],
  • code,
  • em und
  • strong

Die Beschreibung selbst sollte kurz und knackig sein, kein Roman. Zeilenumbrüche sind nicht erlaubt.

Alle Metadaten zusammen dürfen nicht mehr als 8 KiB beanspruchen.

Guter Stil

Benutze immer <?php, um PHP zu öffnen, niemals Short Open Tags wie <? oder <?=. In manchen Installationen funktioniert nur die ausführliche Schreibweise.

Laß das schließende ?> am Ende der PHP-Datei weg, damit sich keine Leerzeilen oder -zeichen einschleichen, die das berüchtigte Headers already sent auslösen.

Benenne deine Klassen und Funktionen stets so, daß sie wahrscheinlich nicht mit anderen Plugins oder gar dem Core kollidieren. Benutze im Zweifel function_exists() und class_exists().

Stelle niemals, wirklich nie, Variablen in den globalen Namensraum!

Schreib alles in UTF-8. Mit jeder anderen Zeichenkodierung wirst du ganz sicher Probleme bekommen.

Kommentiere ausführlich und benutze PHPDoc, aus dem man automatisch eine ordentliche Dokumentation erstellen kann.

Grundfunktion

Bisher kann man das Plugin nur aktivieren; es tut noch nichts.
Also brauchen wir zwei weitere Abschnitte: Eine Funktion, die den Javascriptcode ausgibt, und eine Angabe dazu, wo und wann sie ausgeführt werden soll.

Die Funktion ist einfach:

if ( ! function_exists('toscho_write_framebreaker') )
{
    /**
     * Inserts a javascript frame buster.
     * @return void
     */
    function toscho_write_framebreaker()
    {
?>
<script type="text/javascript">
if (self != top) 
{
    top.location.replace(self.location.href); 
}
</script>
<?php
        return;
    }
}

Wir wollen das Script in den Kopf des HTML-Codes schreiben; dort wartet in WordPress schon die Funktion wp_head() auf uns. Die steht in jedem ordentlichen Theme, meistens in der Datei header.php:

<head>
<!-- allerhand Code -->
<?php
wp_head();
?>
</head>

Wir finden die Funktion in der Datei wp-includes/general-template.php:

/**
 * Fire the wp_head action
 *
 * @since 1.2.0
 * @uses do_action() Calls 'wp_head' hook.
 */
function wp_head() {
    do_action('wp_head');
}

Zu Deutsch: Die Funktion löst einfach die gleichnamige Aktion aus.

Filter und Aktionen

Hier kommen wir zu den beiden einfachsten Schnittstellen (Hooks) für Pluginautoren. Eine Aktion (action) wird zu einem bestimmten Zeitpunkt in der Verarbeitung ausgelöst, ähnlich dem Onclick-Event in Javascript. Manchmal, aber nicht immer, werden noch Variablen übergeben.

Ein Filter (filter) übergibt immer mindestens eine Variable – und er erwartet, daß die Filterfunktion sie nach dem Bearbeiten wieder zurückliefert.

Weit mehr als 1000 solcher Hooks bietet WordPress derzeit an; Adam R. Brown hält eine aktuelle Liste vor: WordPress Hook Database.

Wir können auch eigene Filter und Aktionen bereitstellen, damit andere Autoren in ihren Plugins und Themes unserem Code nicht hilflos ausgeliefert sind.
Wenn wir etwas direkt ausgeben, dann sollten wir immer einen Filter anbieten. Deshalb schreiben wir unsere Funktion jetzt ein bißchen um:

if ( ! function_exists('toscho_write_framebreaker') )
{
    /**
     * Inserts a javascript frame buster.
     * @return void
     */
    function toscho_write_framebreaker()
    { 
        $script = '
<script type="text/javascript">
if (self != top) 
{
    top.location.replace(self.location.href); 
}
</script>';
        /**
         * To alter the script output just use 
         * add_filter('toscho_write_framebreaker', 'your_function');
         */
        $script = apply_filters('toscho_write_framebreaker', $script);
        
        echo $script;
        
        return;
    }
}

Beim Aufruf der Funktion apply_filters() sieht WordPress nach, ob jemand einen Filter für den ersten Parameter definiert hat. Wenn ja, dann wird er ausgeführt, ehe wir weiterarbeiten. Dieses elegante und mächtige Werkzeug ermöglicht eine reibungsarme Kommunikation zwischen Themes, Plugins und dem Core.

Den Framebreaker an eine Aktion binden

Jetzt bringen wir unser Plugin zum Arbeiten, mit nur einer Zeile nach der Funktion:

add_action('wp_head', 'toscho_write_framebreaker');

Wenn die Funktion do_action() mit einem Parameter aufgerufen wird, sieht WordPress wiederum nach, ob für diesen Parameter Aktionen angeboten werden. Wir könnten unser Plugin noch um eine eigene Aktion erweitern:

add_action('framebreak', 'toscho_write_framebreaker');

Dann könnte ein Theme-Autor in seine Vorlage schreiben:

do_action('framebreak');

Wird das Plugin deaktiviert, passiert dann einfach nichts. Ist es aber aktiv, wird der Javascript-Code ausgegeben.

Manche Plugin-Autoren stellen Ausgaben zur Verfügung, die man an beliebiger Stelle im Theme aufrufen kann. Genau dafür existieren eigene Aktionen.
Schlampig hingegen wäre dies:

if ( function_exists('meine_plugin_funktion')
{
    meine_plugin_funktion();
}

Das komplette Plugin

Im Ganzen sieht das Plugin – ergänzt um eine Lizenzangabe – jetzt so aus:

<?php
/*
Plugin Name: Framebreaker
Plugin URI:  http://toscho.de/2010/wordpress-tutorial-framebreaker-plugin/
Description: Baut ein Javascript in den HTML-Kopf, das die Website vor dem Einframen schützt.
Version:     0.1
Author:      Thomas Scholz
Author URI:  http://toscho.de
License:     GPL
*/

/*  
Copyright 2010  Thomas Scholz  (email: info@toscho.de)

This program is free software; you can redistribute it and/or 
modify it under the terms of the GNU General Public License, 
version 2, as published by the Free Software Foundation.

This program is distributed in the hope that it will be useful, 
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
GNU General Public License for more details.

You should have received a copy of the GNU General Public 
License along with this program; if not, write to the Free 
Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, 
MA  02110-1301  USA
*/

if ( ! function_exists('toscho_write_framebreaker') )
{
    /**
     * Inserts a javascript frame buster.
     * @return void
     */
    function toscho_write_framebreaker()
    { 
        $script = '
<script type="text/javascript">
if (self != top) 
{
    top.location.replace(self.location.href); 
}
</script>';
        /**
         * To alter the script output just use 
         * add_filter('toscho_write_framebreaker', 'your_function');
         */
        $script = apply_filters('toscho_write_framebreaker', $script);
        
        echo $script;
        
        return;
    }
}

add_action('wp_head', 'toscho_write_framebreaker');

Testen

Jetzt aktivieren wir das Plugin. Wenn sich ein Fehler eingeschlichen hat, verweigert WordPress die Aktivierung, und wir sehen (meistens) die passende PHP-Fehlermeldung am Anfang der Plugin-Verwaltungsseite.

Wenn kein Fehler auftritt, laden wir jetzt unsere Startseite neu und sehen in den Quellcode: Richtig, da steht der Framebreaker.

Unser erstes Plugin ist fertig.

Naja … Software ist niemals ›fertig‹. Wir könnten beispielsweise noch Ausnahmen einbauen, die bestimmte Frames zulassen. Dank des Filters kann das zwar jetzt schon jeder tun, aber eine kleine Optionsseite dafür wäre handlicher. Vielleicht im nächsten Teil?

Lektüre

15 Kommentare

  1. Patrick am 01.03.2010 · 09:46

    Hi Thomas,

    vielen Dank fuer dieses kleine Tutorial. Wollte mich schon des laengeren mit der Thematik beschaeftigen und mir scheint's, dass die Basics gar nicht so schwer sind.

    Greetings

  2. David am 01.03.2010 · 10:13

    Kannst Du diesen Absatz noch mal genauer erläutern, bitte:

    Manche Plugin-Autoren stellen Ausgaben zur Verfügung, die man an beliebiger Stelle im Theme aufrufen kann. Genau dafür existieren eigene Aktionen.
    Schlampig hingegen wäre dies:

    Wenn ich in einem Plugin themplate-Funktionen definiere ist das schlampig? Sollte ich statt dessen eher actions definieren, die dann im Template mit do_action eingebunden werden?

  3. Thomas Scholz am 01.03.2010 · 10:21

    @David: Ja, genau. Das Template muß auch dann funktionieren, wenn das Plugin abgeschaltet wird, und die eleganteste Umsetzung hierfür ist do_action().

  4. David am 01.03.2010 · 13:24

    Danach habe ich gesucht, danke. Mir war bisher nicht bewusst, dass mit add_action auch eigene Aktionen definiert werden können.

    Diese Lizenzgeschichte finde ich nervig. Für ein paar Codeschnipsel müsste man sich theoretisch durch die ganzen Lizenztexte GPL1, 2 etc. wühlen.
    Sind die Garantie-gibt's-nicht-Erklärungen denn nötig, bzw. im Ernstfall überhaupt rechtsgültig?

  5. Thomas Scholz am 01.03.2010 · 13:37

    @David: Du kannst die Lizenzangaben auch weglassen. Folgt man Matts Argumenten zu Themes, so stehen auch Plugins automatisch unter der GPL. Die gilt auch in Deutschland.

    Ich sehe zwei Vorteile darin, diesen Punkt explizit herauszustellen: Der Empfänger muß nicht nachfragen, und der Autor bleibt sich der Tatsache bewußt, daß nicht nur er den Code lesen und verstehen muß.
    Zugegebenermaßen handhabe ich das nicht immer so sauber, wie ich es hier dargestellt habe …

  6. Dieter am 02.03.2010 · 23:16

    Schöne Idee mit dem Framebreaker-Plugin und sehr anschaulich erklärt. Danke!

    Da ich an dem Header des Themes rumschrauben kann, werde ich erst einfach mal nur das JavaScript testen. ;-)

    Sollte ich mal das Bedürfnis bekommen, in das Schreiben von Plugins einzusteigen, kenne ich jetzt einen hilfreichen Artikel dafür. :-)

  7. Sergej Müller am 03.03.2010 · 15:06

    Schön zusammengefasst.

    In der Praxis versuche ich Plugins ebenfalls mit Actions zu versehen. Je nach Plugin-Größe bin ich dann aber zu faul eine extra Action zu deklarieren. Muss mich überwinden ;)

  8. Dirk am 08.03.2010 · 15:03

    Danke für die hilfreiche Zusammenfassung. Ich bin ein Anfänger und habe vor allem in Bezug auf die Lizenzfragen Probleme. Aber spätestens aus den Kommentaren ist mir klar geworden, dass alles garnicht so schwer ist, wie es auf den ersten Blick erscheint. Vielen Dank dafür.

  9. Egon am 10.12.2010 · 12:22

    Hab jetzt schon länger bei G* nach einer vernünftigen Anleitung gesucht. Es ist gar nicht so einfach die Zusammenhänge zu verstehen, wenn man nicht so in php fit ist. Aber das ist doch auch für Anfänger einigermaßen umsetzbar

  10. Patrick am 06.01.2011 · 21:13

    Und wie veröffentliche ich mein Plugin jetzt auf wordpress.Org, ich finde nirgends eine gute Anleitung

  11. Thomas Scholz am 06.01.2011 · 21:32

    @Patrick: Du beschaffst dir da ein Konto und meldest dein Plugin an. Dann bekommst du irgendwann die Zugangsdaten für das SVN-Repository. Jetzt installierst du dir einen lokalen SVN-Klienten, unter Windows beispielsweise TortoiseSVN, und mit dem lädst du dann dein Plugin hoch. Es gibt eine Kurzanleitung.

  12. Patrick am 07.01.2011 · 01:25

    Weißt du da verzweifelt man und mir ist nach genauen lesen auch aufgefallen das ich immer noch keine zugangsdaten erhaltenhabe. Wie lange dauert das denn? Habe gegen Nachmittag mein Plugin angemeldet. Habe mittlerweile eine wnglische genau Anleitung gefunden:) und dabei ist mir aufgefallen, dass ich noch keinverzeihniss bekommenhabe. :/

  13. Thomas Scholz am 07.01.2011 · 01:39

    @Patrick: Das kann ein paar Tage dauern. Geduld.

  14. Lea am 07.02.2011 · 17:04

    Wie lange ungefähr? Bei mir ist es jetzt eine Woche her und hab noch nichts bekommen :(

  15. Thomas Scholz am 07.02.2011 · 20:20

    @Lea: Das ist ungewöhnlich lange. Versuche doch mal, das Plugin noch einmal einzureichen.