Bewertung: 0 / 5

Stern inaktivStern inaktivStern inaktivStern inaktivStern inaktiv
 

Dies ist eine kleine Sammlung von Know-How, Links und Tricks rund um das Thema der Joomla-Manifest-XML-Scripte zur Installation und Konfiguration von Module, Komponenten, Templates und Plugins oder auch Libraries. Es tangiert ebenfalls die Form-Fields die innerhalb von Joomla für die Konfigurationsformulare zur Verfügung stehen. Leider sind manche Dinge nicht so allumfassend dokumentiert oder es bestimmte Situationen in der Entwicklung eigener Erweiterungen für die man Work-Arounds benötigt.

 

Wichtige Links mit Dokumentationen

Hier zunächst eine Linklistenzusammenstellung für wichtige Dokumentationen/Manuals zu dem o.g. Themenbereich:

 

Besondere Feldtypen – Dokumentation

Manche Feldtypen sind in der Joomla-Dokumentation schlecht oder noch nicht beschrieben, z.B. weil diese sehr neu sind. Hier sind für diese weiterführende Links:

  • Feldtyp "customContent"
    • Das ist ein ganz besonderes Feld, welches einen Content-Editor ausgibt. Es ist fast ähnlich wie das Feld „editor“ hat aber spezielle Eigenschaften, z.B: das der Inhalt bei Seitenerzeugung per Content-Plugins vorbereitet werden kann.
    • Die Einbindung erfolgt auch nicht innerhalb der fields-Tags sondern als separater Tag in der Form: <customContent / > auf Rootebene der Manifest-XML-Datei ohne weitere Parameter.
    • Diese Type wird in der o.g. Liste der J!Feldtypen auch nicht beschrieben!
  • Feldtyp "range"
    • gibt einen Slider-Scrollbalken (Schiebe-Button) aus, mit dem Werte in einem Range in Stepweiten eingestellt werden können.
    • Das Objekt scheint aber noch nicht perfekt. Es wird z.B. kein eingestellter Wert angezeigt und nach dem Speichern immer der Standardwert verwendet, statt des Konfigurationswertes.
    • Zum Stand Okt 2018 war dieses Feld in der J!Feld-Doku noch nicht beschrieben.
    • https://forum.joomla.org/viewtopic.php?t=901266
    • Beispiel:
<field
   name="range"
   type="meter"
   color="#ff000055"
   animated="true"
   width="50%"
   active="true"
   label="range"
   step="2"
   min="1"
   max="100"
   default="40"
      />
  • Feldtyp "meter"
    • Bietet einen Fortschrittsbalken (progress-striped, Parameter und Fkt. ähnlich wie range aber ohne Schiebe-Button
    • Besonderheit: Das ist kein eigentliches Input-Feld! Es kreiert wirklich nur einen Fortschrittsbalken. Aber der Wert style=“width:xx%“ kann z.B. per JavaScript/Ajax modifiziert werden.
    • https://docs.joomla.org/Meter_form_field_type
    • Neben den hier beschriebenen Parametern gibt es noch
      • ‚color‘, Farbe des Balkens sollte als RGBA-Wert übergeben werden
      • ‚animated‘, on/true/off/false
      • ‚width‘: horiz. Breite
  • Feldtyp "repeatable"
    • Das ist eine Feldgruppe (fieldset) innerhalb eines Formualar, welches sind wiederholende Unterfelder in belieb erweiterbarer Menge hat. Ideal für Formulareinträge, bei der man eine noch unbekannte Anzahl von Optionen erzeugen lassen will.
    • https://docs.joomla.org/Repeatable_form_field_type/de
    • Die Daten werden im Parent-Feld als JSON-Datenstruktur im value übergeben.
    • Beispiel:
<field name="list_templates"
      type="repeatable"
      icon="list"
      description="PLG_TINY_FIELD_TEMPLATE_FIELD_ELEMENTS_DESC"
      label="PLG_TINY_FIELD_TEMPLATE_FIELD_ELEMENTS_LABEL"
      default='{
          "template":["Layout","Simple snippet"],
      "description":["HTMLLayout","Simple HTML snippet"]}'>
   <fieldset hidden="true" name="list_templates_modal" repeat="true">
      <field name="template"
            label="PLG_TINY_FIELD_TEMPLATE_FIELD_NAME_LABEL"
            size="2"
            type="text" />
      <field name="description"
            label="PLG_TINY_FIELD_TEMPLATE_FIELD_DESCRIPTION_LABEL"
            size="2"
            type="textarea" />
   </fieldset>
</field>
  • Feldtyp „media
    • liefert ein Inputfeld mit Dateiauswahl- und Uplaod-Dialog aber immer nur unterhalb des Pfades ~/images/.
    • Mit preview kann sofort eine Vorschau in der Modulkonfiguration (Backend) angezeigt werden. Die Aktualisierung erfolgt bei Änderungen der Dateiauswahl sofort per Ajax!
    • Die Angaben für preview_width und preview_height erfolgen in Pixel ohne Maßeinheit. Wert wie „auto“ sind nicht zulässig und führen zu Fehlern.
    • Besonderheit 1: Im Verzeichnis libraries/joomla/form gibt es keine media.php, so wie typischerweise für alle anderen Feldtypen!
    • Besonderheit 2: Für dieses Feld ist charakteristisch: Im custom-Modul „Eigenes Modul“ gibt es unter dem Config-Register „Optionen“ eben auch dieses Feld als Hintergrundbild. Das wird erzeugt, obwohl es in der config.xml gar nicht eingebunden ist. Es ist noch nicht klar, wodurch das gesteuert wird.
    • Beispiel:
<field
   name="backgroundimage"
   type="media"
   directory="salesofferimages"
   label="MOD_SALESOFFERIMAGE_FIELD_BACKGROUNDIMAGE_LABEL"
   description="MOD_BACKGROUNDIMAGE_FIELD_LOGO_DESC"
   preview="true"
   preview_width="500"
   preview_height="300"
   />



 

Bei der Installation Dateien in diverse Joomla-Verzeichnisse kopieren

Ich hatte folgende Situation für die ich eine Lösung gesucht habe, die so nicht dokumentiert ist aber doch funktioniert.

Es sollte für ein selbst geschriebenes Modul ein Install-Paket erzeugt werden. In diesem Paket gab es eine Verzeichnis-/Dateistruktur bei der Datein u.a. in das Joomla-Verzeichnis ~/libraries/foomla/form/fields/ aber auch in das Verzeichnis ~/images/meine-neue-erweiterung/ kopiert werden sollten. Über den XML-Knoten <files> kann man prinzipiell nur in das jeweilige Erweiterungsverzeichnis kopieren, als in das Verzeichnis für das Modul, die Komponente etc. nicht aber außerhalb. Der Knoten <media> verwendet als Zielverzeichnis immer das Verzeichnis ~/media/. Leider kann man nicht mehere media-Knoten in die XML-Datei einfügen, jedes weitere würde nämlich ignoriert werden. Jeder dieser Knonten wie files, media, languages ... wird immer nur einmal verarbeitet.

Um hier nun maximale Flexibilität zu erreichen, verwendet man einfach das destination-Attribut im media-Tag und komplette Pfadangaben im filename-Tag, mit der zusätzlichen Besonderheit, dass wir zunächst aus dem Media-Verzeichnis raus müssen, was über die Verzeichnisanweisung "../" erreichen: Am Beispiel wird das glaube ich am besten deutlich:

<media folder="misc" destination="../">
    <filename>images/meine-neue-erweiterung/index.html</filename>
    <filename>images/meine-neue-erweiterung/sample-700x430.jpg</filename>
    <filename>libraries/joomla/form/fields/javascriptexec.php</filename>
</media>

Wie hier nun zu sehen, holen wir aus dem Archiv-Verzeichnis misc per folder-Attribut-Angabe die Dort liegenden Dateien und Verzeichnisse. Im Joomla-Verzeichnisbaum gehen wir aus dem eigentlichen media-Zielverzeichnis eine Stufe zurück auf das Joomla-Root-Verzeichnis und von dort aus kopieren wir die Datei in die unter filename kompletten Pfadangaben für die einzelnen Dateien.
Wichtig ist noch zu beachten, dass im Installationsarchiv (ZIP-Datei) die vollständigen Pfade so angelegt sein müssen, wie diese im Ziel eingeordnet werden. Also eine Datei, die im Ziel unter images/stories/xyz/ liegen soll, muss auch im Zip-Archiv in einem Pfad images/stories/xyz/ liegen. Nur so funktioniert es wunschgemäß.

 

JavaScript in Erweiterungs-Konfigurationen (Backend) ausführen

Auch diese Problemlösung resultierte aus einer konkrete Erweiterungsprogrammierung, bei dem es das Ziel war ein Feld in einer Modulkonfiguration im Backend durch JavaScript etwas benutzerfreundlicher zu machen. Wenn also das Konfigurationsformular im Backend aufgerufen wird soll dieses JavaScript geladen und ausgeführt werden.

Hierfür gibt es verschiedene Lösungsansätze.

Die schnelle unsaubere Variante (quick-n-dirty):

Siehe hierzu auch folgenden Link: https://stackoverflow.com/questions/26262926/how-do-i-load-a-javascript-call-in-a-joomla-module-backend

Man kann in der Manifest-XML-Datei den Description-Tag dafür nutzen, um JavaScript auszuführen oder zumindest von dort aus eine JavaScript-Funktion aufzurufen, die in einem externen Script deklariert wurde. Das sieht dann z.B: so aus für den Fall von inline-Code:

   <authorUrl>www.media-web.de</authorUrl>
  <version>1.0.0</version>
  <description>
      <![CDATA[
<script type="text/javascript">
    alert('helo');
</script>
]]>
  </description>
...

Ebenso kann man ein externes Script z.B. mymodule.jquery.js erstellen, z.B. in modules/com_mymodule/js und den Aufruf dann so erzeugen:

   <authorUrl>www.media-web.de</authorUrl>
  <version>1.0.0</version>
  <description>
      <![CDATA[
<script
   type="text/javascript"
   src="/modules/mod_mymodule/js/mymodule.jquery.js" >
</script>
]]>
  </description>
...

…Das hat zumindest den Vorteil, dass die Manifest-XML des Moduls weitgehend von JavaScript befreit bleibt, wenn auch nicht vollst.

Nachteile dieser Methode: Es ist eigentlich eine unsaubere Lösung, die zwar in allen Joomlas funktioniert, aber das Feld description mißbraucht und fremdbelegt.

 

Ein saubere Lösung über ein eigenes Form Field

Diese Methode ist sehr elegant, aber vermutlich auch nur eine von evtl. weiteren Möglichkeiten das Ziel zu erreichen. Wir nutzen die Fähigkeit von Joomla aus, dass man recht einfach eigene Formularfeld-Typen durch Programmierung anlegen und dann in den Konfigurationsdialogen verwenden kann. Das nutzend habe ich eine Form-Field-Typ erstellt, welches ein JavaScript benannt bekommt, dann im Konfigurationsformular einbindet und wunschgemäß Aktionen ausführt oder Manipulationen vornimmt. Diese Lösung ist zwar aufwändig aber auch flexibler und läßt sich auch für andere Vorhaben und Projekte portieren.

Zunächst wieder ein Link, wo man zum Thema etwas Basiswissen erlesen kann.: https://docs.joomla.org/Creating_a_custom_form_field_type

Und los gehts: Es wird ein neues Joomla-Form-Field-Script erstellt. Dazu dublizieren wir einfach mal als Lernbeispiel das simple note-Form-Field von libraries/joomla/form/fields/note.php nach z.B. /libraries/joomla/form/fields/javascriptexec.php. Sehr vorteilhaft ist, dass dieses Script nicht zwingend im libraries…fields-Verzeichnis liegen muss. Jede Komponente, jedes Module, Plugin oder Template kann ein solches Fields-Verzeichnis mit eigenen Formfeldern oder Overrides davon haben. Dazu weiter unten mehr. Hier verwenden wir mal zunächst das genannte Zielverzeichnis, auch in dem Wissen, dass das eigentlich ein J!Core-Verzeichnis ist, in dem eigenen Scripte nichts zu suchen haben.

Ich poste hier einfach mal mein komplettes Script für die Einbindung von JavaScript. Zur Verschlankung habe ich alle Kommentare rausgelöscht, die kann sich jeder selbst in den J!-Core-Scripten im Original anschauen:

<?php

defined('JPATH_PLATFORM') or die;

class MdskFormFieldJavaScriptExec extends JFormField
{
    protected $type = 'JavaScriptExec';

    protected function getLabel()
    {
        if (empty($this->element['label']) && empty($this->element['description']))
        {
            return '';
        }

        $label = (string) $this->element['label'];
        $javascript = (string) $this->element['javascript'];
        $description = (string) $this->element['description'];
        $jQuery = (boolean) $this->element['jQuery'];

        $html = array();

        $html[] = !empty($label) ? '<!-- ' . $label . ' -->' : '';
        $html[] = !empty($description) ? '<!-- ' . $description . ' -->' : '';
        if ($jQuery) JHtml::_('jquery.framework');
        if (!empty($javascript)) {
            JHtml::_('script', JUri::root() . $javascript);
            $html[] = '[js]_mod';
        }

        return implode('', $html);
    }

    protected function getInput()
    {

        $run = (string) $this->element['run'];
        $IdStatus = (string) $this->element['id'];
        $status = (boolean) $this->element['status'];

        $html = array();

        if ($run)
        {
            $run = $run == 'true' ? 'alert' : $run;
            $html[] = '<button type="button" class="run" data-dismiss="' . $run . '">&times;</button>';
        }
        if ($status && !empty($IdStatus)) $html[] = '<ul id="status_'.$IdStatus.'"></ul>';

        return implode('', $html);

    }
}

In der Methode getLabel() werden die Inhalte erzeugt, die als Label für das Formfeld ausgegeben werden. Die Methode getInput() erzeugt das eigentliche FormFeld, also rechts vom Label. Ich nutze hier diesen Bereich, in dem ja keine Inputfeld ausgegeben wird zur Ausgabe von Statusmeldungen und Debug-Infos vom JavaScript.

So, damit haben wir nun unser Script für ein eigenes FormField fertig und müssen dieses nur noch in unserer config.xml oder Erweiterungs-Manifest-XML-Datei einbinden, was dann z.B. so aussieht:

<field
   name="salesofferimagejs"
   type="javascriptexec"
   label="run jQuery salesofferimage"
   javascript="modules/mod_mein-neues-modul/js/mein-neues-formfield.jquery.js"
   jQuery="true"
   />

Kurz die Attribute-Parameter erkärt: name hat eigentlich keine wirkliche Verwendund und dient nur zur sauberen Organisation. Mit dem type-Attribut rufe ich mein neues Formfield aufgerufen. label verwende ich im Script, um im Seitenquellcode einen HTML-Kommentar auszugeben, mit dem für mich sichtbar ist, dass hier ein Form Field arbeitet. Im Produktiv-Modus kann das genaussogut raus, ebenso wie die Kontrollausgabe [js], die mir sichtbar in das Formular anzeigt, das hier mein FormField geladen wurde. Das wichtige Attribut javascript bestimmt per vollst. Pfadangabe welches JavaScript geladen und ausgeführt werden soll. Letztlich wird mit dem Attribut jQuery bestimmt, ob das FormField das jQuery-Framework laden soll. So ließen sich weitere eigene Attribute einfügen, z.B. um andere Frameworks zu laden oder was auch immer gewünscht wird.

 

Eigene Form-Field's aus dem Erweiterungsverzeichnissen nutzen

Oben hatten wir zunächst vorgeschlagen, für das neue Form Field das Joomla-Core-Verzeichnis libraries/joomla/form/fields/ zu nutzen. Wir brauchen bei einem eigenen Script zwar nicht befürchten, dass dieses dort überschrieben werden würde, aber es gehört dort trotzdem nicht hin. Außerdem hat es an dieser Stelle den Nachteil, dass wir für unsere Erweiterung uns zu sehr im Joomla-Verzeichnis-Wald verteilen und auch die Installation per Manifest-Datei komplizierter wird. Deshalb ist es sinnvoll dieses Formfeldscript mit in das Verzeichnis für unsere neuen Erweiterung zu legen. Am Beispiel eine neuen Moduls würde man das wie folgend erklärt erreichen.

Dazu vielen Dank an Volkmar Volli Schlothauer, der in Joomla-Forum dazu dankenswerterweise eine Tipp gepostet hatte: https://forum.joomla.de/thread/6513-modul-mit-eigenem-form-field-per-manifest-installieren/?postID=44952#post44953. dieser Beitrag sollte zum Verständnis meiner Ausführungen ergänzend gelesen werden, weil ich hier nur kurz die Lösung beschreibe. Ebenfalls nützlich in diesem Zusammenhang sein Post zum Thema Joomla-Namespacing (Namensumgebung-Konflikte), welches auch hierbei Berücksichtigung finden sollte.

Verwendet wird dazu das Attribut addfieldpath welches z.B. in einem fieldset-Knoten oder anderen Knoten eingebaut werden kann. Am Beispiel könnte das so aussehen:

 <config>
        <fields name="params">
            <fieldset name="basic" addrulepath="modules/mod_mein-neues-module/rules" addfieldpath="modules/mod_mein-neues-module/formfields/">
                <field
                    name="mein-neues-formfield"
                    type="mein-neues-formfield"
                    label="run jQuery mein-neues-formfield"
                    javascript="modules/mod_mein-neues-formfield/js/mein-neues-formfield.jquery.js"
                    jQuery="true"
                    />
...



 

Prüfung von Formulareingaben backend-seitig per PHP

Ganz oben hatte ich beschrieben, z.B. JavaScript im Formular zu integrieren, um dieses komfortabler zu machen. Ebenso wäre damit möglich vor dem Absenden von Formulardaten Eingabeprüfungen/Validierungen vorzunehmen. Dies per JavaScript zu tun ist neben der Verwendung der Joomla-Core-Formularfeld-Filter eine weitere Möglichkeit. Aber man kann dazu auch eigene Prüfungscripte per PHP einbinden - unter Nutzung der dafür vorgesehenen Joomla-Mittel. Vorteil, hier kann man recht indiv. für die eigene Joomla-Erweiterung eigenen Prüfungen hinterlegen. Das erfolgt wie hier beschrieben:

Zu empfehlen sei folgender Link zum Thema: https://joomla.stackexchange.com/questions/314/module-params-custom-validation-is-possible

Besser ist die Möglichkeit per custom-rules, wie folgend beschrieben. Ein Beispiel im Joomla-Core findet man in der Komponente com_contact (s. components/com_contact/models/forms/contact.xml) oder in com_users. Hier mal die mögliche Umsetzung

  1. In das zutreffende fieldset der Module-Manifest-XML-Datei wird ein Attribute addrulepath in dieser Form eingefügt, was den Pfad zum Rule-Verzeichnis definiert welches neben den Joomla-Core-Rules-Verzeichnis nach Prüfregeln durch unsere Erweiterung durchsucht wird:
<fieldset name="basic" addrulepath="modules/mod_mein-neues-module/rules">
  1. Als nächstes wird in das zutreffende Feld die Regel als attribute eingebunden. Dazu wird das Attribute validate genutzt, was z.B. so erfolgt und womit das zu erstellende Script angesprochen wird, welches ausgeführt werden soll – in diesem Bsp. testinput.php:
<field
   name="xyz"
   type="myinput"
   label="COM_MYINPUT"
   description="COM_MYINPUT_DESC"
   id="myinput"
   validate="testinput"

/>
  1. Nun erstellen wir im genannten Verzeichnis, hier am Bsp. unseres Moduls (~/modules/mod_mein-neues-modul/rules/) dieses neue Prüfscript. Das Script muss exact so heißen wie in validate angegeben, also z.B. testinput.php. In diesem Script muss es eine Methode test() geben die autom. für die Prüfung aufgerufen wird.
  2. Der Inhalt könnte so aussehen. Am Beispiel der im Joomla-Core schon existierenden Filter-Regeln kann man sich Know-How erlesen:
<?php

defined('_JEXEC') or die;

use Joomla\Registry\Registry;

class JFormRuleSalesOfferImage extends JFormRule
{
    public function test(SimpleXMLElement $element, $value, $group = null, Registry $input = null, JForm $form = null)
    {
    // die('<pre>'.print_r($element,1).'</pre>'.$value);

        $imagepath = $value;

        $allowedMediaTypes = array('jpg','png','jpeg');

        if (!empty($imagepath))
        {
            $path_parts = pathinfo($imagepath);
            if (in_array($path_parts['extension'],$allowedMediaTypes)) return true;
        }

        return false;
    }
}

Auch in diesem Scriptbeispiel habe ich wieder alle inline-Kommentare entfernt.

 

Nützliche kleine Features in Form-Fields

Hier will ich kurz ein paar Features vorstellen, die ganz nützlich sein könnten und nich jedem bekannt sind.

Formfield-Debugging

Jedes form field kennt auch ein Attritbut debug. Wenn dieses mit dem value=1 oder "true" übergeben wird, dann erfolgen oberhalb das Formulars diverse Debug-Ausgaben. Diese sind unterschiedlich je form field in welches das Debug-Attribut platziert wurde.

Formfield-Abhängigkeiten

Damit ist gemeint, dass man Formfelder auch voneinander abhängig anzeigen lassen kann. Also z.B. dass Formfeld X nur angezeigt wird, wenn Formfeld A einen bestimmten Wert hat. Auch mehrere Feldabhängigkeiten können definiert werden. Dazu sollten Sie den J!Dok-Beitrag zum Thema Showon lesen: https://docs.joomla.org/Form_field#Common_attributes

So sieht dann beispielsweise ein Showon-Abhängigkeitsabfrage in eine showon-FormFieldAttribut aus: showon="myFormFldA:1[AND]myFormFldB!:". Dieses Codebeispiel erstellt die Regel: Zeige myFormFldX nur an wenn der Inhalt von myFormFldA 1 ist und der Inhalt von myFormFldB nicht leer ist.

Zeilenumbrüche in Form-Field-Descriptions

Mitunter ist es wünschenswert Zeilenumbrüche in Beschreibungstexten der Forumlarfelder einzufügen, z.B. um die Lesbarkeit zuverbessern oder die Hilfetext in den Tooltipps optisch zu strukturieren. Das ist jedoch nicht so einfach möglich eine <br /> für prompt zu einem gravierenden Fehler im Backend. Auch mit eine \n kommt man nicht ans Ziel. Die Lösung sieht so aus: Fügen Sie statt des <br /> diese Schreibweise in den Descriptiontext: &lt;br /&gt;.

 

Ausführen von PHP-Code in einem Modul-Backend-Formular

Wenn man PHP-Code in einem Module im Backend ausführen will, kann man das über ein Plugin erreichen, in dem man den event-trigger onBeforeSave einbindet. Dort kann jede beliebige Prüfung eingebaut werden.

Hier kann man sich dazu KnowHow anlesen: https://stackoverflow.com/questions/23266011/run-custom-php-code-in-joomla-module-backend-page

 

 

Kommentare (0)

Bisher wurden hier noch keine Kommentare veröffentlicht

Einen Kommentar verfassen

  1. Kommentar als Gast veröffentlichen. Registriere Dich oder melde Dich zu Deinem Benutzerkonto an.
0 Zeichen
Anhänge (0 / 3)
Deinen Standort teilen
Gib den Text aus dem Bild ein. Nicht zu erkennen?