Drupal Module programmieren - Autotag Teil 3 (Das Modul)

Was wir zuerst brauchen ist ein Taxonomie-Vokabular, in dem unsere Tags gespeichert werden können. Also einfach eins anlegen unter admin/content/taxonomy. Name, Beschreibung, Inhaltstypen sind alle egal. Stellt es so ein, wie ihr es braucht. Unter Einstellungen macht einen Haken bei Tags und Mehrfachauswahl und lasst Erforderlich frei. Wir wollen den Benutzer ja nicht zwingen etwas einzugeben, sondern wollen automatisch Tags hinzufügen, wenn er es nicht tun will oder vergisst. Das neu erstellte Vokabular ist jetzt angelegt und hat dafür gesorgt, dass bei den abgehakten Inhaltstypen unter "Inhalt erstellen" jetzt ein Eingabefenster erscheint, in das man Tags eingeben kann. Außerdem hat das Vokabular natürlich auch eine ID bekommen. Die findet ihr am einfachsten heraus, indem ihr unter admin/content/taxonomy beim neu angelegten Vokabular  auf Vokabular bearbeiten klickt. Wenn ihr euch jetzt den Pfad oben betrachtet steht da soetwas wie admin/content/taxonomy/edit/vocabulary/7. Die 7 am Ende ist die ID des Vokabulars. Die brauchen wir noch später.

Wir gehen jetzt also in unsere autotag.module Datei, wo wir bereits den hook_menu() implementiert haben und fügen eine weitere Funktion hinzu, die wir benutzen um uns in die Node API von Drupal einzuhaken:

/**
 * Implementation of hook_nodeapi().
 */
function autotag_nodeapi($node, $op)
{
  if ($op == 'validate') {
    if (module_exists('token') && $node->taxonomy['tags'][7] == '') {
      $node->taxonomy['tags'][7] = token_replace(variable_get('token_autotag_pattern', '[month], [language], autotag'), 'node', $node);
    }
  }
}

Warum machen wir das? Ganz einfach: Unsere Aktion soll ja stattfinden, wenn eine neue Node erstellt wird. Und zwar genau dann, wenn jemand eine Node erstellt hat, auf Speichern klickt, aber keine Tags eingegeben hat. Wir müssen uns also in die Geschehnisse einhaken, die stattfinden, wenn jemand bei einer Node auf Speichern klickt. Und das geht über die Node API.

Im Gegensatz zum hook_menu() erwartet hook_nodeapi diesmal auch einige Parameter. Einmal die Node selber um die es hier geht (die ist immer im Objekt $node gespeichert) und den Status der derzeitigen Node-Verarbeitung (auch Operation genannt und in der Variable $op gespeichert). Welche Werte $op haben kann, findet ihr hier heraus:

http://api.drupal.org/api/function/hook_nodeapi

Wenn ihr euch die Liste durchlest, werdet ihr zwei Werte finden, die unserem Bedürfnis entsprechen: validate und presave. Beide sollten funktionieren, ich hab mich für validate entschieden. Da wir uns in die Node-Ereignisse eingehakt haben, werden bei jeder Node-bezogenen Aktion alle Module nach hook_nodeapi() durchsucht und, falls gefunden, ausgeführt. Im Grunde wird unsere Funktion also bei jedem Klick in einem Node-Fenster ausgeführt. Das ist natürlich nicht Sinn der Sache, wir wollen unsere Funktion ja nur nutzen wenn jemand im Bearbeiten-Modus einer Node auf Speichern klickt. Kurz: wenn $op auf "validate" oder "presave" steht.

Wir nutzen also eine If-Schleife um sicherzustellen, dass unser Code auch nur in diesem Moment ausgeführt wird und nutzen dann eine weitere If-Schleife um sicherzustellen, dass unser Code auch nur ausgeführt wird, wenn das Tag-Feld leergelassen wurde. Hierfür brauchen wir dann auch die Id des entsprechenden Vokabulars.

Die Funktion token_replace wird ebenfalls vom Token-Modul zur Verfügung gestellt und erwartet als Parameter zuerst den String der die zu ersetzenden Tokens enthält, als zweites eine Angabe welche Ersetzungsklasse genutzt werden soll und als drittes das Objekt, in dem der Austausch stattfinden soll. Wenn man als drittes ein Objekt übergibt, sollte der zweite Parameter ebenfalls die Art des Objektes darstellen. In diesem Fall übergeben wir ein $node Objekt, also übergeben wir als zweiten Parameter 'node'. Andere Möglichkeiten wären z.B. 'comment' oder 'user', wenn wir ein $comment oder $user Objekt übergeben würden.

Und das war's schon. Das Modul ist fertig, funktioniert und kann über den Admin-Bereich konfiguriert werden.