Custom Meta Box mit Galerie

Es gibt so manche Funktionen, die scheint es nur in Plugins zu geben und werden auch nirgendwo angesprochen. Eine Meta Box Galerie ist eine davon. Von meiner Seite aus oft gefragt und vielfach verlangt, ist die Lösung laut Web meist nur „dafür gibt es doch ein Plugin“. Für mich als Programmierer sind solche Aussagen nicht wirklich hilfreich, fordern aber meinen Kopf nach einer eigenen Lösung. die „eigene Lösung“ ist in diesem Fall ein zusammensuchen von Ideen und Denkansätzen aus dem Netz. Leider sind dies viel zu viele, und ich konnte mir auch nicht jede Seite merken, wo ich einen Hinweis für dieses Puzzle bekommen habe. Doch möchte ich das Ergebnis niemanden vorenthalten – auch wenn dieses eher ein Prototyp ist. Vielleicht hilft jemanden diese Funktion zur Erzeugung einer Meta Box mit einer Galerie.

[EDIT]20.09.2018 – Es gibt einen kleinen Bug mit Galerie in Kombination mit dem eigentlichen Beitragsbild von WordPress[/EDIT]

Die Galerie in einer Custom Meta Box hat viele Vorteile; ob als festdefinierten Zusatz im Beitrag, zur Veranschaulichung von Produkten, oder als Bild Slider. Die Verwendungen können je nach Nutzer individuell und ausgefallen sein. Es gibt zwar diverse Plugins, die sich diesem Thema annehmen und dem Benutzer eine zusätzliche Galerie bieten, jedoch kommen Plugins auch mit Nachteilen: Kompatibilität, Sicherheit und Performance. Diese Probleme gibt es auch in den eigenen Programmierungen, dort kann man aber flexibler eingreifen und anpassen.

Anpassen ist hier auch das nächste Stichwort. Wenn ich in meinen eigenen Skripten anpasse, brauche ich keine Angast haben, dass die mit dem nächsten Update verloren gehen. Eventuell muss man kurze Änderungen bei der Kompatibilität für WordPress/PHP vornehmen, diese lassen sich jedoch recht fix ersuchen und ändern.

Zurück zur Galerie. Diese benötigte ich für diverse kleinere Projekte. Kunden wollten für Seiten einen eigenen Bild Slider haben oder brauchten eine Produktansicht, welche immer identisch sein soll (Aufbau und Positionierung). Da die reguläre Galerie in WordPress in den Content eingefügt wird, ist die exakte Position nicht immer gegeben. Es wäre natürlich möglich über Reguläre Ausdrücke und Hooks den Content zu identifizieren und anzupassen, aber die Fehlerquelle ist zu groß, als dass sich dies lohnen würde.

Irgendwann habe ich mir aus diversen Skripten ein Lösung gebastelt. Diese funktionierte und war sogar recht einfach zu bedienen. Der Code war Lang und verursachte hier und da kleinere Probleme, alles aber noch im Rahmen des möglichen. Im Groben konnte man beliebig viele Bilder (nacheinander, nicht zeitgleich) Laden, und diese per „Drag and Drop“ sortieren. Im Frontend habe ich dann das Array aufgerufen und die Bilder entsprechend ausgegeben. Es gab hier immer noch den Neid bei der richtigen Galerie Funktion von WordPress. Diese war bekannt und intuitiv zu bedienen. Nach gefühlten Ewigkeiten habe ich es endlich geschafft, diese Funktion in die Tat umzusetzen. Dies möchte ich hier mit Euch teilen!

Skript für die Meta Box: functions.php

Das Skript sieht auf den ersten Blick recht umfangreich aus. Dies liegt daran, dass dies ein Ausschnitt von einem etwas größerem Teil ist; beibehalten ist soweit alles relevante für die Galerie und ein wenig mehr.

  1. class galerieMetabox {
  2. private $screen = array (
  3. 'post',
  4. 'page',
  5. );
  6. private $meta_fields = array (
  7. array (
  8. 'label' => 'Galerie',
  9. 'id' => 'galerie_97142',
  10. 'type' => 'gallery',
  11. ),
  12. );
  13. public function __construct () {
  14. add_action ('add_meta_boxes', array ($this, 'add_meta_boxes'));
  15. add_action ('save_post', array ($this, 'save_fields'));
  16. }
  17. public function add_meta_boxes () {
  18. foreach ($this->screen as $single_screen) {
  19. add_meta_box (
  20. 'galerie',
  21. 'Galerie',
  22. array ($this, 'meta_box_callback'),
  23. $single_screen,
  24. 'normal',
  25. 'default'
  26. );
  27. }
  28. }
  29. public function meta_box_callback ($post) {
  30. wp_nonce_field ('galerie_data', 'galerie_nonce');
  31. $this->field_generator ($post);
  32. }
  33. public function field_generator ($post) {
  34. $output = '';
  35. $outputGallery = '';
  36. $script = '';
  37. foreach ($this->meta_fields as $meta_field) {
  38. $label = '<label for="'. $meta_field['id'] .'">'. $meta_field['label'] .'</label>';
  39. $meta_value = get_post_meta ($post->ID, $meta_field['id'], true);
  40. if (empty ($meta_value)) {
  41. $meta_value = $meta_field['default'];
  42. }
  43. switch ($meta_field['type']) {
  44. case "gallery":
  45. $input .= sprintf (
  46. '<button class="%s button-primary" id="%s" name="%s" value="Browse" type="button"><span class="dashicons dashicons-slides"></span>%s</button>',
  47. $meta_field['id'] .'_button',
  48. $meta_field['id'] .'_button',
  49. $meta_field['id'] .'_button',
  50. $meta_field['label']
  51. );
  52. $input .= sprintf (
  53. '<input %s id="%s" name="%s" type="%s" value="%s" />',
  54. $meta_field['type'] !== 'color' ? 'style="width: 100%"' : '',
  55. $meta_field['id'],
  56. $meta_field['id'],
  57. 'hidden',
  58. $meta_value
  59. );
  60. $input .= sprintf (
  61. '<input %s id="%s" name="%s" type="%s" value="%s" disabled />',
  62. $meta_field['type'] !== 'color' ? 'style="width: 100%"' : '',
  63. $meta_field['id'] .'_nonsens',
  64. $meta_field['id'] .'_nonsens',
  65. 'text',
  66. $meta_value
  67. );
  68. $script .= sprintf (
  69. "<script>\n".
  70. "jQuery (\"#galerie .hndle\").each (function (e) {\n".
  71. "jQuery (this).attr(\"class\", \"no-position\");\n".
  72. "});\n".
  73. "(function ($) {\n".
  74. "$('.%s').click (function (event) {\n".
  75. "var gallery = wp.media.gallery;\n".
  76. "var ids = $('#%s').val(); // your current attachment ids\n".
  77. "var frame = gallery.edit('
  78. [gallery' + ( ids.length ? ' ids=\"' + ids + '\"' : '' ) + ']
  79. ');\n".
  80. "frame.state ('gallery-edit').on ('update', function (attachments) {\n".
  81. "// `attachments` is an array of attachment objects\n".
  82. "console.log (attachments);\n".
  83. "// get all the attachment ids this way\n".
  84. "var ids = attachments.pluck ('id');\n".
  85. "$('#%s').attr('value', ids);\n".
  86. "$('#%s').attr('value', ids);\n".
  87. "});\n".
  88. "frame.on ('close', function () {\n".
  89. "frame.detach();\n".
  90. "});\n".
  91. "})\n".
  92. "}) (jQuery);\n".
  93. "</script>",
  94. $meta_field['id'] .'_button',
  95. $meta_field['id'],
  96. $meta_field['id'],
  97. $meta_field['id'] .'_nonsens'
  98. );
  99. $image_ids = explode (',', get_post_meta ($post->ID, $meta_field['id'], true));
  100. $outputGallery .= sprintf (
  101. '<div class="image-holder %s">',
  102. $meta_field['id'] .'_button'
  103. );
  104. foreach ($image_ids as $image_id) {
  105. $outputGallery .= wp_get_attachment_image ($image_id);
  106. }
  107. $outputGallery .= '</div>';
  108. break;
  109. default:
  110. }
  111. $output .= ''. $label .''. $input .'';
  112. echo $this->style().''. $output .''. $outputGallery .''. $script;
  113. }
  114. }
  115. public function format_rows ($label, $input) {
  116. return ''. $label .''. $input .'';
  117. }
  118. public function style () {
  119. return '<style></style>';
  120. }
  121. public function script () {
  122. return $script;
  123. }
  124. public function save_fields ($post_id) {
  125. if (!isset ($_POST['galerie_nonce'])) {
  126. return $post_id;
  127. }
  128. $nonce = $_POST['galerie_nonce'];
  129. if (!wp_verify_nonce ($nonce, 'galerie_data')) {
  130. return $post_id;
  131. }
  132. if (defined ('DOING_AUTOSAVE') AND DOING_AUTOSAVE) {
  133. return $post_id;
  134. }
  135. foreach ($this->meta_fields as $meta_field) {
  136. if (isset ($_POST[$meta_field['id']])) {
  137. switch ($meta_field['type']) {
  138. case 'email':
  139. $_POST[$meta_field['id']] = sanitize_email ($_POST[$meta_field['id']]);
  140. break;
  141. case 'text':
  142. $_POST[$meta_field['id']] = sanitize_text_field ($_POST[$meta_field['id']]);
  143. break;
  144. }
  145. update_post_meta ($post_id, $meta_field['id'], $_POST[$meta_field['id']]);
  146. } elseif ($meta_field['type'] === 'checkbox') {
  147. update_post_meta ($post_id, $meta_field['id'], '0');
  148. }
  149. }
  150. }
  151. }
  152. if (class_exists('galerieMetabox')) {
  153. new galerieMetabox;
  154. };

Erklärung des Skriptes

  • 2–5: Sichtbarkeit der Meta Box; Aktuell in Beiträgen (post) und Seiten (page); kann erweitert werden, zum Beispiel mit Custom Post Types
  • 8–14: Angaben zur Meta Box: Die Beschriftung (label), die Identifikation (id) und die Art der Eingabe (gallery)
  • 20–31: Erzeugen der Meta Box mit den vordefinierten Variablen $screen und $meta_fields;
  • 43–119: Erzeugen der Eingabefelder über eine Schleife um ggf. mehrere Eingabearten abzudecken (nicht im Beispiel)
    • 44: Definition der Beschriftung (label)
    • 45: Übergabe von vorhandenen Werten
    • 47–49: Verhalten bei nicht vorhandenen Werten
    • 51–113: Switch Abfrage für mehrere Eingabearten (nicht im beispiel)
      • 51–57: Erzeugen des Buttons mit den Variablen aus 7–13
      • 59–66: Erzeugen von verstecktem Eingabefeld für die Variablenübergabe zum Speichern und weiterverarbeiten
      • 67–74: Erzeugen von deaktiviertem Eingabefeld für die Anzeige der Variable (ohne außenstehende Manipulation; nur für Testzwecke, kann später gelöscht werden)
      • 76–102: Erzeugen des JQuery-Skript für die Funktion der Galerie (öffnen, ändern, speichern), auf Basis der Vordefinierten Variablen aus 7–13
        • 77–79: „Drag and Drop“ der Meta Box verhindern (Umgehen von Formatierungsproblemen)
      • 104–110: Bilder der Galerie in Variable speichern zur Ausgabe im Backend (nach dem Speichern werden diese Änderungen übernommen und angezeigt)
    • 118: Ausgabe der kompletten Meta Box inklusive Aufruf für Style-Angabe (noch ungenutzt)
  • 122–124: Funktion zur Formatierung (im Beispiel ungenutzt)
  • 126–128: Funktion zur Gestaltung (im Beispiel ungenutzt; wird aufgerufen)
  • 134–157: Speichern der Meta Box
  • 159–161: Aufruf der Klasse zur Erzeugung der Meta Box

Die Erzeugung ist noch recht primitiv. Einige Variablen und Funktionen scheinen in diesem Fall ungenutzt oder unsinnig zu sein. Der Grund des Vorhandenseins liegt darin, dass ich dies aus einem Skript genommen habe, wo es mehr als nur um die Galerie Meta Box geht. Das Ursprüngliche Skript wurde über Hasty erzeugt und an deren Code-Vorlage angepasst um dies im Ablauf besser integrieren zu können. Derzeit gibt es bei deren Generatore (noch) nicht die Möglichkeit eine Galerie mit einzubinden, deswegen habe ich selbst einen ersten Ansatz geschrieben, in der Hoffnung, dass dies irgendwann mal als Funktion mit übernommen wird.

Wie man im Skript sieht, ist die Variable der Galerie lediglich die Aufzählung der IDs von den Bildern, welche in WordPress verwaltet werden (Zu erkennen im Backend beim Erzeugen der Galerie im deaktiviertem Eingabefeld). Der Grund hierfür ist recht Simpel: Der Einfachheit halber. Da auch WordPress mit der kompletten Zeichenkette im Shorcode Arbeitet und man die IDs einfach über explode () in PHP trennen kann, habe ich mich für diesen Weg entschieden.

Aufruf im Frontend

Um die IDs der Bilder im Frontend zu nutzen, kann man folgenden Befehl verwenden. Der übergebene Wert ist eine Zeichenkette, welche lediglich aufgetrennt werden muss um an die einzelnen Bilder zu kommen. Dies dürfte ab hier kein Problem mehr sein.

<?php $galleryImageIDs = get_post_meta (get_the_ID(), 'gallerie_97142', true); ?>

Fehler/Bugs

  • Wenn ein Beitragsbild definiert ist, wird dieses als Standard in die Galerie geladen, jedoch nicht ausgewählt.

Aktuell sind mir keine Fehler bekannt. Das Skript sieht derzeit im Backend nicht sonderlich schön aus, da es für die reine Funktion entworfen wurde. Hier kann man selbst noch anpassen. Wenn dieser Projektteil effektiv in die Nutzung einfließt, werde ich dies hier auch noch bearbeiten. Allein schon wegen der Code-Darstellung wird dieser Beitrag bald bearbeitet werden.

Auch ist es noch unschön. dass die Vorschau der Bilder bei der Änderungen der Meta Box erst mit dem Aktualisieren/Speichern/Veröffentlichen des Beitrages im Frontend erscheinen. Hier wird über JavaScript/JQuery nachgerüstet!


Noch kein Kommentar zu “Custom Meta Box mit Galerie”


Kommentar hinterlassen

Diese HTML-TAGS stehen dir zur Verfügung:
<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>