[4074 Aufrufe]

Manager Plugin

In diesem Artikel soll es um die Möglichkeiten des Manager Plugin gehen. Normalerweise werden die Pakete in Symfonyprojekten manuell in die Datei app/AppKernel.php eingetragen. Dies ist für ein CMS wie Contao etwas umständlich. Deshalb kann man in seiner Erweiterung das Manager Plugin benutzen, um die Einstellungen der Erweiterung über der Contao Manager für Symfony bereitzustellen.

Auf die Zusammenhänge der beiden Plugins und die Konfiguration in der composer.json wurde bereits im letzten Artikel eingegangen, weshalb wir hier gleich mit den Möglichkeiten des Manager Plugins beginnen.

BundlePluginInterface

In unserem Bundle nutzen wir das BundlePluginInterface, welches uns erlaubt, unser Bundle zu registrieren. Wie dies geschieht, ist im folgenden Beispiel zu sehen. Wir übergeben der Methode BundleConfig::create() den Namen unseres Bundels. Über die Methode setLoadAfter() können wir noch festlegen, welche Bundles vor unserem geladen werden müssen. Dies funktioniert ähnlich der autoload.ini von Contao 3.

<?php declare(strict_types=1);

namespace Ctocb\Example\Classes\Contao\Manager;

use Contao\ManagerPlugin\Bundle\Config\BundleConfig;
use Contao\ManagerPlugin\Bundle\BundlePluginInterface;
use Contao\ManagerPlugin\Bundle\Parser\ParserInterface;
use Ctocb\Example\CtocbExampleBundle;

class Plugin implements BundlePluginInterface
{
    public function getBundles(ParserInterface $parser): array
    {
        return [
            BundleConfig::create(CtocbExampleBundle::class)->setLoadAfter([ContaoCoreBundle::class])
        ];
    }
}

ConfigPluginInterface

Um unser Bundle zu konfigurieren, nutzen wir das ConfigPluginInterface. Mit diesem können wir zusätzliche YAML-Dateien laden, z. B. für die Konfiguration von Services, oder Listenern.

<?php declare(strict_types=1);

namespace Ctocb\Example\Classes\Contao\Manager;

use Contao\ManagerPlugin\Config\ConfigPluginInterface;
use Symfony\Component\Config\Loader\LoaderInterface;

class Plugin implements ConfigPluginInterface
{

    public function registerContainerConfiguration(LoaderInterface $loader, array $config): void
    {
        $path = '@CtocbExampleBundle/Resources/config/';
        $loader->load("$path/services.yml");
        $loader->load("$path/listener.yml");
    }
}

ExtensionPluginInterface

Das ExtensionPluginInterface kann genutzt werden, um die Konfiguration anderer Bundles zu beeinflussen. Da dies selten nötig, meist keine gute Idee und ganz sicher kein Einsteigerthema ist, werde ich hier nicht weiter darauf eingehen.

DependentPluginInterface

Mit dem DependentPluginInterface können andere Plugins durch den Contao Manager vor dem eigenen geladen werden. Es macht also das gleiche, was die setLoadAfter-Methode für andere Bundles macht, nur halt für Plugins. Da ich dies noch nie benötigt habe, zitiere ich hier das Beispiel aus dem Contao Handbuch:

<?php declare(strict_types=1);

namespace Ctocb\Example\Classes\Contao\Manager;

use Contao\ManagerPlugin\Dependency\DependentPluginInterface;

class Plugin implements DependentPluginInterface
{
    public function getPackageDependencies(): array
    {
        return ['contao/news-bundle'];
    }
}

RoutingPluginInterface

Das RoutingPluginInterface lädt benutzerdefinierte Routen für unser Bundle, dies geht folgendermaßen:

<?php declare(strict_types=1);

namespace Ctocb\Example\Classes\Contao\Manager;

use Contao\ManagerPlugin\Routing\RoutingPluginInterface;
use Symfony\Component\Config\Loader\LoaderResolverInterface;
use Symfony\Component\HttpKernel\KernelInterface;

class Plugin implements RoutingPluginInterface
{
    public function getRouteCollection(LoaderResolverInterface $resolver, KernelInterface $kernel)
    {
        $file = '@CtocbExampleBundle/Resources/config/routing.yml';

        return $resolver->resolve($file)->load($file);
    }
}

Es wird in diesem Beispiel die Datei routing.yml aus dem Verzeichnis Resources/config/ unserer Erweiterung geladen. Diese Datei enthält die Informationen über das Routing, dass wir zur Verfüfung stellen wollen. Ich werden in einem späteren Kapitel daruf eingehen.

Kombination

Selbstverständlich lassen sich die Möglichkeiten auch beliebig kombinieren. Im folgenden Beispiel wird unser Bundle bekannt gegeben, die Konfiguration für Listener und Services, sowie für das Routing geladen.

<?php declare(strict_types = 1);

namespace Ctocb\Example\Classes\Contao\Manager;

use Contao\CoreBundle\ContaoCoreBundle;
use Contao\ManagerPlugin\Bundle\BundlePluginInterface;
use Contao\ManagerPlugin\Bundle\Config\BundleConfig;
use Contao\ManagerPlugin\Bundle\Parser\ParserInterface;
use Contao\ManagerPlugin\Config\ConfigPluginInterface;
use Contao\ManagerPlugin\Routing\RoutingPluginInterface;
use Ctocb\Example\CtocbExampleBundle;
use Symfony\Component\Config\Loader\LoaderInterface;
use Symfony\Component\Config\Loader\LoaderResolverInterface;
use Symfony\Component\HttpKernel\KernelInterface;

class Plugin implements BundlePluginInterface, ConfigPluginInterface, RoutingPluginInterface
{
    protected $path = '@CtocbExampleBundle/Resources/config';

    public function getBundles(ParserInterface $parser): array
    {
        return [BundleConfig::create(CtocbExampleBundle::class)->setLoadAfter([ContaoCoreBundle::class])];
    }

    public function registerContainerConfiguration(LoaderInterface $loader, array $config): void
    {
        $loader->load($this->path . '/services.yml');
        $loader->load($this->path . '/listener.yml');
    }

    public function getRouteCollection(LoaderResolverInterface $resolver, KernelInterface $kernel)
    {
        $file = $this->path . '/routing.yml';

        return $resolver->resolve($file)->load($file);
    }
}

Weitere Informationen

Weitere Informationen findet man im Contao Handbuch unter https://docs.contao.org/dev/framework/manager-plugin/. Die Betreuung wird übrigens von der Contao-Association finanziert und braucht immer Hilfe. An dieser Stelle vielen Dank an Bjarke, Fritz und die vielen weiteren Helfer für Ihre tolle Arbeit.