Markus Michalski FAQ

Newsletter Management: Erweiterbarkeit

Newsletter-Plugin für Sylius erweitern - PRE_SUBSCRIBE-Event für Spam-Schutz, Formular-Erweiterung per FormTypeExtension, Template-Overrides und Hinweise zum Ersetzen von Services

English Version

Zurück zur Übersicht

Newsletter Management: Erweiterbarkeit

Diese Dokumentation bezieht sich immer auf die aktuellste veröffentlichte Version.

Das Plugin bietet zwei dokumentierte Erweiterungspunkte für Dritte: das Event PRE_SUBSCRIBE, mit dem ein Listener Anmeldungen ablehnen kann, und das Anmeldeformular NewsletterSignupType, an das sich per FormTypeExtension Felder hängen lassen. Beides nutzt das ALTCHA-Plugin für den Spam-Schutz. Dazu kommen Template-Overrides für das Aussehen.

Das Event PRE_SUBSCRIBE

Eigenschaft Wert
Konstante Mmd\SyliusNewsletterManagementPlugin\Event\NewsletterSubscriptionEvents::PRE_SUBSCRIBE
Event-Name mmd_sylius_newsletter_management_plugin.newsletter_subscription.pre_subscribe
Payload Mmd\SyliusNewsletterManagementPlugin\Event\NewsletterSubscriptionPreSubscribeEvent
Zeitpunkt Bevor etwas gespeichert oder verschickt wird, direkt nach der Prüfung, ob der Newsletter im Channel aktiv ist

Der NewsletterSubscriptionManager löst das Event bei jeder Anmeldung aus, die über ihn läuft: Anmeldeseite (/newsletter), die Anmeldung über die Shop API und die Newsletter-Checkbox bei Registrierung und Profil. Das Footer-Teaser-Formular löst es nicht selbst aus, es leitet nur auf die Anmeldeseite weiter. Abmeldung, Bestätigung und Einstellungen ändern lösen das Event nicht aus.

Der Payload bietet:

Methode Beschreibung
getEmail() Die Adresse, bereits klein geschrieben und getrimmt
getChannel() Der Channel der Anmeldung
getRequest() Der aktuelle Request, etwa für Header, Body-Felder oder die Client-Adresse
getSource() Der Einstiegsweg als NewsletterSubscriptionSource: Storefront, Api, Registration oder Admin
reject(?string $reason = null) Lehnt die Anmeldung ab. $reason ist ein Übersetzungsschlüssel, der dem Kunden angezeigt wird, oder null für den Standardtext
isRejected(), getRejectionReason() Zustand abfragen, etwa für weitere Listener

Eine Ablehnung zeigt im Storefront eine Fehlermeldung (Flash) und beantwortet die Shop-API-Anfrage mit 422.

Beispiel: Listener, der Wegwerf-Domains ablehnt

<?php

declare(strict_types=1);

namespace App\Newsletter;

use Mmd\SyliusNewsletterManagementPlugin\Entity\NewsletterSubscriptionSource;
use Mmd\SyliusNewsletterManagementPlugin\Event\NewsletterSubscriptionEvents;
use Mmd\SyliusNewsletterManagementPlugin\Event\NewsletterSubscriptionPreSubscribeEvent;
use Symfony\Component\EventDispatcher\Attribute\AsEventListener;

#[AsEventListener(event: NewsletterSubscriptionEvents::PRE_SUBSCRIBE)]
final class BlockDisposableDomains
{
    private const BLOCKED = ['mailinator.com', 'trashmail.com'];

    public function __invoke(NewsletterSubscriptionPreSubscribeEvent $event): void
    {
        // Die Registrierung hat ihren eigenen Schutz.
        if ($event->getSource() === NewsletterSubscriptionSource::Registration) {
            return;
        }

        $domain = substr((string) strrchr($event->getEmail(), '@'), 1);
        if (\in_array($domain, self::BLOCKED, true)) {
            $event->reject('app.newsletter.disposable_domain');
        }
    }
}

Mit dem Attribut #[AsEventListener] und aktiviertem Autoconfigure reicht die Klasse im Projekt. Alternativ registrierst du den Listener per Tag:

services:
    App\Newsletter\BlockDisposableDomains:
        tags:
            - { name: kernel.event_listener, event: 'mmd_sylius_newsletter_management_plugin.newsletter_subscription.pre_subscribe' }

Den Übersetzungsschlüssel aus dem Beispiel legst du in deiner eigenen Übersetzungsdatei an, etwa in translations/flashes.de.yaml. Im Storefront wird der Schlüssel als Flash-Nachricht übersetzt. Gibst du null an, erscheint der Standardtext des Plugins.

Die Newsletter-Checkbox im Sylius-Kern (Registrierung und Profil) löst das Event mit der Quelle Registration aus. Sylius' eigene Shop-API-Registrierung (POST /shop/customers) setzt das Kern-Flag ohne Event und ohne Anmeldung durch das Plugin. Headless-Clients melden sich über POST /shop/newsletter-subscriptions an.

Formular erweitern

Mmd\SyliusNewsletterManagementPlugin\Form\Type\NewsletterSignupType ist bewusst nicht final. Damit kannst du per Symfony FormTypeExtension Felder an das Anmeldeformular hängen. So bindet das ALTCHA-Plugin sein Proof-of-Work-Widget ein, während die serverseitige Prüfung auf PRE_SUBSCRIBE lauscht.

<?php

declare(strict_types=1);

namespace App\Form\Extension;

use Mmd\SyliusNewsletterManagementPlugin\Form\Type\NewsletterSignupType;
use Symfony\Component\Form\AbstractTypeExtension;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\FormBuilderInterface;

final class NewsletterSignupExtension extends AbstractTypeExtension
{
    public static function getExtendedTypes(): iterable
    {
        return [NewsletterSignupType::class];
    }

    public function buildForm(FormBuilderInterface $builder, array $options): void
    {
        $builder->add('companyWebsite', TextType::class, ['mapped' => false, 'required' => false]);
    }
}

Ein nicht gemapptes Feld landet nicht im Datenmodell NewsletterSignup; du liest es in deinem PRE_SUBSCRIBE-Listener aus $event->getRequest().

Die Anmeldeseite rendert nach der Einwilligungs-Checkbox und vor dem Absenden-Button den Twig Hook mmd_altcha.widget.newsletter. Er gehört dem ALTCHA-Plugin und bleibt leer, solange dieses Plugin fehlt oder das Schutzziel nicht aktiviert ist. Wie du das Schutzziel einschaltest, steht unter ALTCHA: Konfiguration.

Templates überschreiben

Das Aussehen von Anmeldeseite, Bestätigung, Einstellungen, Abmeldung, Footer-Teaser und Mails passt du mit dem normalen Sylius-Mechanismus an: Lege ein Template mit demselben Pfad unter templates/bundles/MmdSyliusNewsletterManagementPlugin/ in deinem Projekt oder Theme ab. Welche Templates und Hooks es gibt, steht unter Storefront-Integration. Die Admin-Templates sind Oberflächen-Interna des Plugins und nicht zum Überschreiben gedacht.

Welche Platzhalter Newsletter-Autoren im Editor verwenden dürfen, beschreibt die Seite Newsletter.

Services ersetzen

Die Services des Plugins sind über Interfaces verdrahtet (zum Beispiel NewsletterSubscriptionManagerInterface, NewsletterMailerInterface, NewsletterMailSenderInterface). Du kannst sie mit der normalen Symfony-Service-Dekoration ersetzen oder erweitern.

Technisch ist das möglich, aber nicht als stabile öffentliche API zugesagt. Die dokumentierten Erweiterungspunkte sind PRE_SUBSCRIBE und NewsletterSignupType. Interface-Methoden können sich ändern, prüfe eine Dekoration deshalb bei jedem Update.