Um ein Silverstripe-Modul zu entwicklen, gibt es zwei Herangehensweisen:
Das Modul silverstripe-sendy dient als Schnittstelle zwischen dem Silverstripe-basierten CMS und dem Newsletterdienst Sendy. Im CMS kann mithilfe von Elemental-Blöcken eine Mail zusammengestellt und dann in Sendy exportiert werden.
Für das Rendern des übergeordneten Bodies, der die Blöcke umgibt, kann aktuell nur ein Template verwendet werden. Um ein anderes Template zu verwenden, muss man die Template-Datei ersetzen. Bei regelmässigen Wechseln ist dies mühsam und fehleranfällig.
Das Modul soll also so weiterentwickelt werden, dass in der Konfiguration mehrere Templates definiert und im CMS ausgesucht werden können. Das streamlined den Prozess erheblich.
In einem zweiten Schritt wird ein zweites Problem angegangen: Da man sich in E-Mails bestenfalls ausschliesslich auf Inline-CSS verlassen sollte, muss auch das Styling für die Elemental-Blöcke modifiziert werden. Statt externe Stylesheets zu laden, sollen auch die Blöcke auf Templates zurückgreifen, die nach Vorgabe benannt und abgelegt wurden.
Das Modul silverstripe-sendy enthält eine Klasse SendyCampaign, zu der unter anderem die Elemental Area für die Inhaltsblöcke gehört und die anhand eines Templates gerendert wird.
Nach aktuellem Stand verwendet die Render-Methode starr ein Template, dessen Name dem Klassennamen entspricht - also SendyCampaign.ss, falls keine Extension vorliegt. Die entsprechende Methode im Code der Klasse:
// SendyCampaign.php
public function getHTMLNewsletter()
{
$template = SSViewer::create(self::class);
// [...]
return $this->renderWith($template);
}
Um die Verwendung verschiedener Styles zu ermöglichen, gehen wir folgendermassen vor:
Das Datenbankfeld für Schritt 1 ist schnell hinzugefügt:
// SendyCampaign.php
/**
* Database fields
* @config
* @var array
*/
private static $db = [
'Title' => 'Varchar',
'FromName' => 'Varchar',
'FromEmail' => 'Varchar',
'ReplyToEmail' => 'Varchar',
'Subject' => 'Varchar',
'IsTransferred' => 'Varchar',
'Style' => 'Varchar' // neuer Eintrag
];
Die Schritte 2 & 3 lösen wir gemeinsam.
Eine SilverStripe-Config wird im YAML-Format geschrieben. Hier lagern wir unter dem Key styles eine Liste von key-value-Paaren. Der Key verweist auf den Dateinamen des Styles, der Wert repräsentiert den front-facing name für das CMS. Testweise sieht das so aus:
# app.yml
Syntro\SilverStripeSendy\Model\SendyCampaign:
styles:
red: Red Style
blue: Blue Style
Weiters legen wir eine statische Variable styles an, welche die ausgelesenen Styles beinhaltet. Um sicherzustellen, dass wir beim Aufrufen der Bearbeitung im CMS auf dem neusten Stand sind, rufen wir die Config innerhalb der getCMSFields()-Methode auf und befüllen mit ihr die styles-Variable.
Anschliessend prüfen wir, ob überhaupt styles konfiguriert sind. Falls ja, wird ein Dropdown-Feld zur Auswahl eingeblendet. Die Auswahl wird dann in das DB-Feld Style geschrieben. Ausserdem konfigurieren wir einen "empty default" und stellen sicher, dass kein Feld angezeigt wird, wenn nichts konfiguriert ist. Der user facing-String für den "empty default" wird mit einer hier nicht näher zu erklärenden Übersetzungslösung angezeigt.
// SendyCampaign.php
/**
* Holds styles (format: <template name> => <human name>)
*
* @config
* @var array
*/
private static $styles = [];
// [...]
public function getCMSFields()
{
// [...]
$styles = $this->config()->get('styles');
if (count($styles) > 0) {
$fields->addFieldToTab(
'Root.Main',
$styleDropdownField = DropdownField::create('Style', 'Style', $styles),
'ElementalArea'
);
$styleDropdownField->setHasEmptyDefault(true);
$styleDropdownField->setEmptyString(_t("DNADesign\\Elemental\\Models\\BaseElement".'.CUSTOM_STYLES', 'Select a style..'));
} else {
$fields->removeByName('Style');
}
}
Nun müssen wir den Rendering-Code anpassen.
Wir ergänzen zuerst die Klasse um eine Methode getStyles(). Sie soll uns anhand des DB-Feldes Style einen Array zurückgeben, den wir wiederum als Argument an SSViewer::create verwenden können. Wir stellen dabei sicher, dass der Output bei nicht gesetzem DB-Feld dem üblichen Output entspricht. Beim gesetzten Feld hingegen stellen wir den gewählten Style an die erste Stelle des Arrays. Darauf folgt, um einen Fallback zu implementieren, der übliche Style als zweite Wahl.
Schliesslich müssen wir die neue Methode in der getHTMLNewsletter()-Methode einbauen.
Das Ergebnis: Wir können an der gewohnten Stelle (/app/templates/Syntro/SilverStripeSendy/Model/) Styles im Format SendyCampaign_<style>.ss lagern. Sind sie korrekt konfiguriert, können sie im CMS ausgewählt werden und werden dann geladen. Bei Konfigurationsfehlern oder nicht entsprechend abgelegtem Style wird auf den Default SendyCampaign.ss zurückgegriffen.
// SendyCampaign.php
/**
* If no entry in Style field, return default style
* If there is entry in Style field, return that with default fallback
*
* @return array
*/
public function getStyles()
{
$styles = [];
if (!($this->Style)) {
array_push($styles, self::class);
} else {
array_push(
$styles,
self::class."_".$this->Style,
self::class
);
}
return $styles;
}
// [...]
/**
* getHTMLNewsletter - returns the HTML render of the Newsletter
*
* @return DBHTMLText
*/
public function getHTMLNewsletter()
{
$template = SSViewer::create($this->getStyles());
$template->includeRequirements(false);
return $this->renderWith($template);
}