Contao 4 erweitern

Services in Hooks

Fragments

Symfony-Routen im Backend

Contao 4 erweitern

Wie man die Managed-Edition anpasst

Individuelle Anpassung oder frei verfügbares Bundle?

Individuelle Anpassung

Ordnerstruktur

managed-edition/
    app/
    assets/
    files/
    src/
    system/
    templates/
    vendor/
    web/

app/

app/
    config/
        config.yml
        parameters.yml
    Resources/
        contao/
            config/
            dca/
            languages/
            templates/

src/

src/
    AppBundle/
        Controller/
        ...
<?php

namespace AppBundle\Controller;

class MyController
{
}

src/

In Symfony 4 entfällt der Ordner AppBundle (bundle-less application):

src/
    Controller/
    ...
<?php

namespace App\Controller;

class MyController
{
}

Namespace Best Practice

Namespace Ressource Elternklasse
App/ContentElement Inhaltselemente extends Contao\ContentElement
App/DataContainer DCA-Callbacks -
App/Model Models extends Contao\Model
App/FrontendModule Frontend-Module extends Contao\Module
App/Widget Widgets extends Contao\Widget

Manager-Plugin

app/
    ContaoManagerPlugin.php

Damit der Autoloader die Klasse findet, muss sie registriert werden:

"autoload": {
    "classmap": [
        "app/ContaoManagerPlugin.php"
    ]
}

Bundles registrieren

<?php

use Contao\ManagerPlugin\Bundle\Config\BundleConfig;
use Contao\ManagerPlugin\Bundle\BundlePluginInterface;
use Contao\ManagerPlugin\Bundle\Parser\ParserInterface;
use Knp\Bundle\MenuBundle\KnpMenuBundle;

class ContaoManagerPlugin implements BundlePluginInterface
{
    public function getBundles(ParserInterface $parser)
    {
        return [
            BundleConfig::create(KnpMenuBundle::class),
        ];
    }
}

Container konfigurieren

<?php

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

class ContaoManagerPlugin implements ConfigPluginInterface
{
    public function registerContainerConfiguration(LoaderInterface $loader, array $config)
    {
        $loader->load(__DIR__.'/config/custom.yml');
    }
}

Routen laden

<?php

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

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

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

Dependencies angeben

<?php

use Contao\ManagerPlugin\Dependency\DependentPluginInterface;

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

Frei verfügbares Bundle

Zielsetzung

  • Pflege des Codes in einem Git-Repository
  • Einbindung des Bundles in die Managed-Edition über die composer.json
  • Änderungen werden im vendor/-Ordner der Managed-Edition gemacht und anschließend nach origin gepusht
  • Löschen des vendor/-Ordners soll nicht das Git-Repository löschen

GitHub

Das Repository liegt bei GitHub (oder GitLab etc.) und ist bei Packagist registriert:

"require": {
    "vendor/package": "dev-master"
},
"config": {
    "preferred-install": {
        "vendor/": "source",
        "*": "dist"
    }
}

Lokal

Das Repository liegt auf dem lokalen Rechner:

"require": {
    "vendor/package": "dev-master"
},
"repositories": [
    {
        "type": "vcs",
        "path": "/pfad/zum/repo"
    }
],
"config": {
    "preferred-install": {
        "vendor/": "source",
        "*": "dist"
    }
}

Getting started

Services in Hooks

Service-IDs anstelle von Klassen verwenden

Bisher

<?php

$GLOBALS['TL_HOOKS']['replaceInsertTags'][] = array(
    'ModuleFaq',
    'replaceInsertTags'
);
<?php

$GLOBALS['TL_DCA']['tl_faq'] = array(
    'config' => array(
        'onload_callback' => array(
            array('tl_faq', 'checkPermission')
        )
    )
)

Bisher

<?php

$GLOBALS['TL_HOOKS']['replaceInsertTags'][] = array(
    'contao_faq.listener.insert_tags',
    'onReplaceInsertTags'
);
<?php

$GLOBALS['TL_DCA']['tl_faq'] = array(
    'config' => array(
        'onload_callback' => array(
            array('contao_faq.security.permission_checker', 'onCheckFaq')
        )
    )
)

Hooks taggen

Listener

services:
    contao_faq.listener.insert_tags:
        class: Contao\FaqBundle\Listener\InsertTagsListener
        tags:
            - { name: contao.hook, hook: replaceInsertTags }
  • Ruft die Methode onReplaceInsertTags() auf
  • Die Methode kann mittels method: foo explizit definiert werden
  • Die Priorität kann mittels priority: 64 angegeben werden

Fragments

Inhaltselemente und Module als Fragments

Bisher

$GLOBALS['FE_MOD']['navigationMenu']['fastnav'] = 'ModuleFastnav';
class ModuleNavigation extends Module
{
    protected $strTemplate = 'mod_fastnav';

    public function generate()
    {
    }

    protected function compile()
    {
    }
}

Neu

services:
    app.module.fastnav_controller:
        class: App\Controller\Module\FastnavController
        tags:
            - { name: contao.frontend_module, category: navigationMenu }
  • Der Key für tl_module.type, $GLOBALS['TL_LANG'] etc. sowie der Name des Templates werden aus dem Klassennamen generiert: fastnav, MOD.fastnav, mod_fastnav.html5
  • Der Type kann mittels type: foo explizit definiert werden: MOD.foo, mod_foo.html5

Neu

<?php

namespace App\Controller\Module;

use Contao\CoreBundle\Controller\AbstractFrontendModuleController
use Contao\Model;
use Contao\Template;
use Symfony\Component\HttpFoundation\Request;

class FastnavController extends AbstractFrontendModuleController
{
    protected function getResponse(Template $template, Model $model, Request $request)
    {
        return $template->getResponse();
    }
}

Symfony-Routen im Backend

Symfony-Routen aufrufen und die Ausgabe im Backend anzeigen

Zielsetzung

  • Erstellung einer Symfony-Route
  • Verwendung von Twig
  • Ausgabe im Contao-Backend
  • Hinzufügen eines eigenen Menüpunktes

Erstellung einer Symfony-Route

Verwendung von Twig

Hinzufügen eines eigenen Menüpunktes

Ausgabe im Contao-Backend

Noch Fragen?

Vielen Dank für die Aufmerksamkeit