CosmoCode ist eine Internetagentur aus Berlin mit Schwerpunkt CMS, Wiki, Web2.0
Great software. Bright people. Happy customers!
Mail info@cosmocode.deTel +49 (30) 814504070
In einem aktuellem Projekt kam ich in die Situation, für spätere Redakteure, das Bilder hochladen erleichtern zu müssen.
Es werden unterschiedliche Bildergröße von ein und demselben Bild gebraucht.
Spezifikation war, dass der Redakteur ein Bild hochläd und die anderen Bilder dann automatisch aus dem großen Bild verkleinert werden.
Das Problem ist leider schlecht dokumentiert (jedenfalls blieben meine Internet Recherchen erfolglos) jedoch ist die Lösung denkbar einfach.
Der Lösungsansatz funktioniert mit kleinen Änderungen auch in Drupal 6, die Mechanik dahinter läuft jedoch anders. :)
Wenn ein Node gespeichert wird (über ein Formular z.B.) dann wird typischerweise die Funktion node_save() benutzt.
Diese Funktion regelt die gesamte Speicherung des Nodes (Insert und Update) und ruft alle nötigen Hooks auf.
Darunter befinden sich auch field_attach_insert() und field_attach_update(), welche für das Erstellen/Updaten unseres Feldes zuständig sind. Diese nehmen das Node, überprüfen die gesetzten Felder und sichern / speichern diese.
Was das praktisch für uns heißt, ist, dass wir bei einem zu speicherndem Node einfach die nötigen Felder setzen müssen und uns der Rest abgenommen wird.
Nachdem das verkleinerte Bild erstellt worden ist, muss Drupal noch bekannt gemacht werden, dass es auf dem Dateisystem eine neue Datei gibt, welche er verwalten soll.
Die von Drupal verwalteten Dateien befinden sich alle in der file_managed Tabelle der Drupal Datenbank.
Glücklicherweise nimmt uns Drupal das manuelle Einfügen der Datei in sämtliche relevanten Datenbank Tabellen ab, in dem es eine File API Funktion namens file_save() anbietet.
Diese API Funktion erwartet ein File Objekt. File Objekte werden in der Datenbank Tabelle file_managed abgelegt, das File Objekt kann man sich als simples mapping der file_managed Felder auf ein Objekt vorstellen.
Da wir keine Methoden benötigen sondern nur die Daten in Form der Tabellenfelder, erstellen wir uns einfach ein neues PHP Objekt vom Typ stdClass (PHP's standard Klasse)
$file = new stdClass(); // eine leere fid (file id) impliziert, dass file_save einen neuen Eintrag für diese Datei anlegen muss $file->fid = ''; $file->uid = $user->uid; $file->status = 1; // sichtbar $file->filename = trim(basename($path), '.'); $file->timestamp = REQUEST_TIME; $file->uri = file_build_uri($path); $file->filesize = filesize($file->uri); $file->filemime = file_get_mimetype($file->uri);
Wichtig ist, dass man file_build_uri() benutzt um die file URI zu erstellen, da Drupal7 ganz auf sog. Streamwrapper1) setzt.
Wir sagen unserem neuem File Objekt jetzt quasi: „Hier, du referenzierst jetzt diese Datei.“ und speichern es dann in die Datenbank - dazu benutzen wir file_save().
file_save() gibt ebenso eines dieser File Objekte zurück, welches dann aber mit den Werten, wie es in der Datenbank steht, gefüllt ist.
Jetzt, wo wir unsere Datei im Drupalsystem haben, müssen wir es noch einem FileField Eintrag zuordnen.
Felder werden nach einem locale, welches die Sprache in der das Feld übersetzt ist darstellt, gespeichert.
Ein typischer FileField Eintrag (nach dem Upload, beim Node speichern) sieht so aus:
Das locale in unserem Falle ist 'de', was das ISO 639-1 Kürzel für Deutschland ist.
[field_picture_example] => Array
(
[de] => Array
(
[0] => Array
(
[alt] =>
[title] =>
[fid] => 6
[display] => 1
[description] =>
[upload_button] => Upload
[remove_button] => Entfernen
[upload] =>
)
)
)
Felder werden als Array erwartet. Da wir in unserem Beispiel aber ein (File) Objekt haben, müssen wir uns die Datenfelder des Objektes noch als Array holen.
Dazu stellt PHP eine Methode namens get_object_vars() welche alle öffentlichen, nicht statischen Felder des Objektes als Array zurückliefert.
global $language; // das globale $language Objekt, das Informationen zur Sprache speichert $node->field_picture_example[$language->language] = array(get_object_vars($file));
Nun muss das Node noch gespeichert werden. Nodes werden über node_save() gespeichert, ob ihr das nun manuell macht oder wie ich den hook_node_presave() Hook benutzt, um die Bilder einfach zum Objekt hinzuzufügen bevor es sowieso gespeichert wird, ist euch überlassen.
Über CosmoCode
Abonnieren