J4.x

J4.x: Ein Plugin für Joomla! selbst erstellen

From Joomla! Documentation

This page is a translated version of the page J4.x:Creating a Plugin for Joomla and the translation is 100% complete.

Other languages:
Deutsch • ‎English • ‎español • ‎فارسی • ‎français • ‎Nederlands • ‎русский
Anleitung
Leitfaden um ein Plugin für Joomla! 4 herzustellen
Joomla! 
4.x
series

Die Pluginstruktur für Joomla! 1.5, 2.5 und 3.x war sehr flexibel und mächtig. Plugins können nicht nur verwendet werden um Ereignisse, die durch die Hauptanwendung und durch Erweiterungen ausgelöst wurden, zu verarbeiten, sondern auch um Erweiterungen von Drittanbietern erweiterbar und leistungsfähig zu gestalten. In Joomla! 4.x haben wir eine Menge Code der zugrunde liegenden Prozessverwaltung umgeschrieben, um die Flexibilität zu erhöhen, wenn man die Parameter, die als Ereignisse übergeben werden, verändert, während zeitgleich die Leistungsfähigkeit der Plugins erhöht wurde.

Zweck dieser Anleitung ist es, dich mit den Grundlagen vertraut zu machen, die man wissen muss um ein eigenes Plugin zu entwickeln. Die meisten Plugins bestehen nur aus einer einzigen Code-Datei, um es allerdings richtig zu installieren, muss der Plugin-Code in eine Installationsdatei gepackt werden, die vom Joomla! Installer verarbeitet werden kann.

Die Installationsdatei erstellen

Wie bei allen anderen Erweiterungen von Joomla!, werden Plugins einfach mit einer .zip-Datei installiert (.tar.gz wird auch unterstüzt), allerdings muss eine einwandfreie XML-Datei enthalten sein.
Als ein Beispiel ist hier die XML Installationsdatei für das Plugin des Kategoriensuchwerkzeugs.

<?xml version="1.0" encoding="utf-8"?>
<extension version="3.1" type="plugin" group="search" method="upgrade">
	<name>plg_search_categories</name>
	<author>Joomla! Project</author>
	<creationDate>November 2005</creationDate>
	<copyright>Copyright (C) 2005 - 2018 Open Source Matters. All rights reserved.</copyright>
	<license>GNU General Public License version 2 or later; see LICENSE.txt</license>
	<authorEmail>admin@joomla.org</authorEmail>
	<authorUrl>www.joomla.org</authorUrl>
	<version>3.0.0</version>
	<description>PLG_SEARCH_CATEGORIES_XML_DESCRIPTION</description>
	<files>
		<filename plugin="categories">categories.php</filename>
	</files>
	<languages>
		<language tag="en-GB">en-GB.plg_search_categories.ini</language>
		<language tag="en-GB">en-GB.plg_search_categories.sys.ini</language>
	</languages>
	<config>
		<fields name="params">

			<fieldset name="basic">
				<field
					name="search_limit"
					type="number"
					label="JFIELD_PLG_SEARCH_SEARCHLIMIT_LABEL"
					default="50"
				/>

				<field
					name="search_content"
					type="radio"
					class="switcher"
					label="JFIELD_PLG_SEARCH_ALL_LABEL"
					default="0"
					>
					<option value="1">JYES</option>
					<option value="0">JNO</option>
				</field>

				<field
					name="search_archived"
					type="radio"
					class="switcher"
					label="JFIELD_PLG_SEARCH_ARCHIVED_LABEL"
					default="0"
					>
					<option value="1">JYES</option>
					<option value="0">JNO</option>
				</field>
			</fieldset>

		</fields>
	</config>
</extension>

Wie du sehen kannst, ähnelt der Aufbau anderen Joomla! XML Installationsdateien. Achte nur auf den group="xxx" Eintrag in der <extension> Auszeichnungsmarkierung und die erweiterten Informationen im <filename> Auszeichner. Die Informationen sagen Joomla! in welchen Ordner die Datei kopiert werden soll und zu welcher Gruppe von Plugins es hinzugefügt werden soll.

Falls man ein Plugin kreiert, das auf bestehende Kernereignisse reagiert, würde sich das group="xxx" Attribut ändern, um die Bezeichnung des bestehenden Pluginordners für den Ereignistypen, den man zu verbessern wünscht, wiederzugeben. Beispielsweise group="Authentifizierung" oder group="User". Beachte auch Plugin/Ereignisse für eine vollständige Liste von bestehenden Kernereigniskategorien. Bei der Gestaltung eines neuen Plugins, welches auf Kernereignisse reagiert, ist es wesentlich, dass dein Pluginname eindeutig ist und nicht mit irgendeinem der anderen Plugins kollidiert, die ebenfalls auf das Kernereignis reagieren können, von dem du auch profitieren willst.

Falls man jedoch ein Plugin entwirft, das auf keine Kernsystemereignisse reagiert, sollte sich die Wahl der group="xxx" Auszeichnungsmarkierung von jedweder der bestehenden Kernkategorien unterscheiden.

Tipp: Wird das attribute method="upgrade" dem Tag, also der Auszeichnungsmarkierung, hinzugefügt, kann dieses Plugin installiert werden, ohne eine vorherige Version entfernen zu müssen. Alle bestehenden Dateien werden überschrieben, aber alte Dateien werden nicht gelöscht.

Das Plugin erstellen

Die objekt-orientierte Vorgehensweise Plugins zu schreiben bedingt das Verfassen einer Unterklasse unter CMSPlugin, eine Grundlagenklasse, welche die grundlegenden Eigenschaften von Plugins umsetzt. In deinen Verfahren sind die folgenden Eigenschaften verfügbar:

  • $this->params: der parameters-Satz für dieses Plugin vom Administrator
  • $this->_name: der Name des Plugins
  • $this->_type: die Gruppe (Art) des Plugins
  • $this->db: das Datenbankobjekt
  • $this->app: das Anwendungsobjekt

Tipp: Um $this->db und $this->app zu verwenden, testet CMSPlugin, ob das Objekt existiert und nicht privat ist. Falls gewünscht wird, das Standardobjekt zu verwenden, erstelle unkonkrete Eigenschaften in der Plugin Objektklasse (dass heißt protected $db; protected $app; ist im selben Bereich wie protected $autoloadLanguage = true;). Die Eigenschaften werden nicht bestehen, es sei denn ausdrücklich erstellt.

Im folgenden Programmkodebeispiel, vertritt <PluginGroup> die Gruppe (Typ) des Plugins, und <PluginName> stellt den Namen dar. Beachte das Klassen- und Funktionsnamen in PHP nicht zwischen Groß- und Kleinbuchstaben unterscheidet.

Wir haben hier auch das SubscriberInterface implementiert, welches den größten Umbruch seit Joomla! 1.5-3.x darstellt. Anstatt den Funktionsnamen, der auch dem Ereignisnamen entspricht, automatisch aufspüren zu lassen, erlaubt dies angepasste Funktionsnamen zu verwenden. Daher sind wir in der Lage mitzuteilen, welche Plugins welche Funktionen implementieren und da die Syntaxprüfung öffentlicher Methoden im PGP-Kode langsam ist, ergibt das einen gewaltigen Leistungsschub.

Beachte, dass es über die ganze Joomla! 4 Programmreihe eine veraltete Schicht gibt, die Plugins betrifft, die die alte Namensstrategie von Pluginnamen, die mit Ereignisnamen übereinstimmen, falls das SubscriberInterface nicht implementiert ist.

<?php
// no direct access
defined( '_JEXEC' ) or die;

use Joomla\CMS\Plugin\CMSPlugin;
use Joomla\CMS\Event\Event;
use Joomla\Event\SubscriberInterface;

class Plg<PluginGroup><PluginName> extends CMSPlugin implements SubscriberInterface
{
	/**
	 * Load the language file on instantiation
	 *
	 * @var    boolean
	 * @since  3.1
	 */
	protected $autoloadLanguage = true;

	/**
	 * Returns an array of events this subscriber will listen to.
	 *
	 * @return  array
	 */
	public static function getSubscribedEvents(): array
	{
		return [
			'<EventName>' => 'myFunctionName',
		];
	}

	/**
	 * Plugin method is the array value in the getSubscribedEvents method
	 * The plugin then modifies the Event object (if it's not immutable)
	 */
	 public function myFunctionName(Event $event)
	 {
		/*
		 * Plugin code goes here.
		 * You can access parameters via $this->params
		 */
		return true;
	}
}
?>

Plugins im eigenen Kode verwenden

Falls ein Plugin für eine neues, den Kern nicht betreffendes Ereignis, erschaffen wird, entsinne dich daran, dein Plugin nach der Installation zu aktivieren. Stelle jeden Bezug auf dein neues Plugin mit dem JPluginHelper::importPlugin()-Befehl voran.

Jetz, wo du ein eigenes Plugin erstellt hast, wirst du es wahrscheinlich in deinem Programmkode aufrufen wollen. Was du nicht tun solltest: der Joomla! Kern hat eine Vielzahl von eingebauten Ereignisse, bei denen du eventuell willst, dass dein Pluginkode davon erfasst wird (und in diesem Fall kannst du den folgenden Abschnitt ignorieren).

Das neue Joomla! 4 Verfahren

Die neue Verfahrensweise in Joomla! 4 ist es, den Dispatcher zu holen und ein benanntes Ereignis zu verteilen.

use Joomla\CMS\Event\AbstractEvent;
use Joomla\CMS\Factory;

$dispatcher = Factory::getApplication()->getDispatcher();

// Here we create an event however as long as you implement EventInterface you can create your own 
// custom classes
$event = AbstractEvent::create(
	'<EventName>',
	[
		'name' => $value,
	]
);

$eventResult = $dispatcher->dispatch('<EventName>', $event);

Falls der Benutzer die Erlaubnis erhält, Werte zu verändern, kann man das Ergebnis des Ereingisses verwenden und Ergebnisse daraus zurückgewinnen. Du kannst folgendes anschauen:

defined('_JEXEC') or die;

use BadMethodCallException;
use Joomla\CMS\Event\AbstractImmutableEvent;
use Joomla\CMS\Table\TableInterface;

/**
 * Event class for an event
 */
class MyCustomEvent extends AbstractImmutableEvent
{
	/**
	 * Constructor.
	 *
	 * @param   string  $name       The event name.
	 * @param   array   $arguments  The event arguments.
	 *
	 * @throws  BadMethodCallException
	 */
	public function __construct($name, array $arguments = array())
	{
		if (!array_key_exists('myProperty', $arguments))
		{
			throw new BadMethodCallException("Argument 'myProperty' is required for event $name");
		}

		parent::__construct($name, $arguments);
	}

	/**
	 * Setter for the myProperty argument
	 *
	 * @param   mixed  $value  The value to set
	 *
	 * @return  mixed
	 *
	 * @throws  BadMethodCallException  if the argument is not of the expected type
	 */
	protected function setMyProperty($value)
	{
		if (!empty($value) && !is_object($value) && !is_array($value))
		{
			throw new BadMethodCallException("Argument 'src' of event {$this->name} must be empty, object or array");
		}

		return $value;
	}
}

Warum haben wir diese Namensklasse über Parametern eingeführt? Nun, es macht es einfacher angepasste setters und getters für die Eigenschaften einzuführen - momentan kann ein Plugin entweder eine Eigenschaft komplett verändern wie es will - für einen Verfasser gibt es keinen Weg ihm Grenzen aufzusetzen.

Wie die maximale Kompatibiltät mit Joomla! 3 erreicht wird

Falls man ein Ereignis auf eine ähnliche Weise wie im entfernten J3.x JEventDispatcher auslösen will, verwende Kode wie diesen:

$results = \Joomla\CMS\Factory::getApplication()->triggerEvent( '<EventName>', <ParameterArray> );

Es ist wichtig darauf hinzuweisen, dass sich die Parameter in einer Matrix befinden müssen. Die Funktion des Plugins selbst wird die Parameter als Ereignisobjekt erhalten, falls das SubscriberInterface implementiert und als einzelne Werte, falls nicht. Trotzdem wird diese Vorgehensweise immer ein Datenfeld ausgeben, dass das Plugin zurückgibt.

Beachte, dass falls JEDWEDES Plugin in einer Gruppe das SubscriberInterface nicht implementiert, wird die Ergebniseigenschaft (als sowohl ein benannter Parameter und als Ergebnis von einem Plugin) als eine spezielle Eigenschaft verwendet und ist somit nutzlos.