Das Thema, was mich persönlich dieses Jahr am meisten genervt hat, ist sicher das Thema Transaktionsemails. So kommt ein ganzer Haufen an Vorlagen mit der Magento-Installation. Noch schlimmer wird es dann, wenn man dann das German-Setup installiert. Insgesamt sicher alles schön und gut - solange man nichts anpassen muss.
Spätestens wenn ein Shop bereits live ist, und man mit zwei verschiedenen Datenbanken arbeitet, kann sich auf doppelte Arbeit einstellen. Dann fängt man an im Testsystem die Mails zu konfigurieren, dann zu testen und später kopiert man den ganzen Inhalt auf das Live-System - im schlimmsten Fall ist noch ein Staging dazwischen. Alles wirklich umständlich und nicht gerade entwicklerfreundlich - schließlich ist es nur eine Frage der Zeit, bis sich die ersten Flüchtigkeitsfehler beim Kopieren einschleichen und man die falsche Vorlage überschreibt oder vergisst. Änderungen können schließlich auch nicht rückgängig gemacht werden.
Genug Einleitung: Genau an dieser Stelle soll mein Beitrag ansetzen. Ziel ist es, die Mails mit in die Versionskontrolle zu bekommen und sich die nervigen Änderungen im Backend sparen zu können. Das schöne ist, dass man diese Änderungen nur einmal machen muss, und sie ab dann in jedem Projekt einfach wieder verwenden kann - ohne Backend und zig tausend Klicks.
Alle Vorteile im Überblick:
- Keine nervigen Änderungen mehr in der Datenbank
- Wir kommen, dank Versionsverwaltung, jederzeit auf einen älteren Stand zurück
- Das Deployment geht super schnell und einfach - und vor allem: Ohne Risiko
- Man genießt die vollen Features der IDE
- Man spart jede Menge Zeit
Wie arbeitet das Mail-Templating
Damit wir aber verstehen, wie die Konfiguration arbeitet, schauen wir uns erstmal ein wenig Code an. Jede Konfiguration eines E-Mail-Templates kann als Standard den Wert „Standard-Vorlage aus der Lokalisierung“ erhalten. Doch was wird dann verwendet? Die Standard-Mail-Vorlagen „aus der Lokalisierung“ findet man (wie der Name schon sagt) unter app/locale/<Sprache>/template/email. Bleibt die Frage, wie Magento die Verbindung zwischen den einzelnen Dateien und der Konfiguration herstellen kann. Alle Mails innerhalb von Magento, werden mit Hilfe der Klasse Mage_Core_Model_Email_Template_Mailer (core/email_template_mailer) aufbereitet, welche das Model Mage_Core_Model_Email_Template zum senden der Mails nutzt. Dieses Model wird mit einer TemplateId aus der Konfiguration gefüttert. Ist diese TemplateId numerisch, wird ein Template aus der Datenbank genutzt - aber davon möchten wir ja weg. Falls wir aber nun den Wert der Konfiguration auf „Standard-Vorlage aus der Lokalisierung“ gesetzt haben, wird statt einer numerischen Id ein String an den Mailer übergeben. Wie das aussieht, können wir sehr schön in der Methode sendTransactional(…) sehen: app/code/core/Mage/Core/Model/Email/Template.php:484if (is_numeric($templateId)) {
$this->load($templateId);
} else {
$localeCode = Mage::getStoreConfig('general/locale/code', $storeId);
$this->loadDefault($templateId, $localeCode);
}
Ein paar Methoden weiter sehen wir, wie die Default-Templates geladen werden. Nämlich über die XML-Konfiguration:
app/code/core/Mage/Core/Model/Email/Template.php:239
static public function getDefaultTemplates()
{
if(is_null(self::$_defaultTemplates)) {
self::$_defaultTemplates = Mage::getConfig()->getNode(self::XML_PATH_TEMPLATE_EMAIL)->asArray();
}
return self::$_defaultTemplates;
}
Es wird also in der Konfiguration nach Einträgen gesucht, welche unter global/template/email im XML zu finden sind. Ein Beispiel dazu, finden wir in der Konfiguration des Adminhtml-Moduls:
app/code/core/Mage/Adminhtml/etc/config.xml:50
<template>
<email>
<admin_emails_forgot_email_template translate="label" module="adminhtml">
<label>Forgot Admin Password</label>
<file>admin_password_reset_confirmation.html</file>
<type>html</type>
</admin_emails_forgot_email_template>
</email>
</template>
Die Templates werden dann einfach per Translator geladen und verspracht, wie man hier sehen kann:
app/code/core/Mage/Core/Model/Email/Template.php:201
$templateText = Mage::app()->getTranslator()->getTemplateFile(
$data['file'], 'email', $locale
);
Wie der Translator arbeitet, wurde übrigens im Türchen 03 von Jan sehr gut erklärt. So weit, so gut. Doch wie ändert man den Pfad der EMails sinnig und sorgt dafür, dass zukünftige Magento-Updates unsere schönen Mailvorlagen nicht wieder überschreiben? Auf dem Weg dahin gibt es wie immer mehrere Möglichkeiten.
Eigene Mail-Templates nutzen
Leider kann man die Mail-Templates nicht einfach in das entsprechende Theme-Verzeichnis legen und dort überschreiben. Magento schaut zuerst nämlich in das app/locale/ Verzeichnis, und wenn das Template da bereits gefunden wurde, wird nicht weiter gesucht. Für mich persönlich ist das aber kein Beinbruch, da es elegantere Wege gibt.1. Pfade der Templates über die Konfiguration ändern.
Nun könnte man die entsprechende Pfade der einzelnen Templates einfach in einer Modul-Konfiguration überschreiben. Dabei ist darauf zu achten, dass die Pfade weiterhin relativ zu app/locale/<template>
<email>
<admin_emails_forgot_email_template>
<file>mytemplate/admin_password_reset_confirmation.html</file>
</admin_emails_forgot_email_template>
</email>
</template>
2. Das Translate-Model überschreiben
Falls man die Dateien wo Ganz anders ablegen möchte (beispielsweise unterhalb des eigenen Moduls), braucht man ein Rewrite für Mage_Core_Model_Translate. Dort könnte man dann einfach andere Pfade zu den Templates zurückgeben. Einstiegspunkt wäre folgende Methode: app/code/core/Mage/Core/Model/Translate.php:460 Rewrites sind natürlich immer weniger elegant. Dieses hätte allerdings den Vorteil, dass wohl die wenigsten Extensions ebenfalls dieses Model überschreiben werden. Dafür hat man aber auch die komplette Freiheit.Alle Mailtemplates auf "Standard" setzen
Nun wäre es natürlich relativ anstrengend, wenn man alle Werte im Admin per Hand durchgehen müsste, um die Mailtemplates auf ihren Standardwert zu setzen. Wenn man sich die Werte in Datenbank genauer anguckt, steht dort genau der Pfad der Konfiguration als Wert - nur dass alle Slashes durch Unterstriche ersetzt werden müssen. Dank dieser Logik kann man ein einfaches SQL-Update schreiben, welches genau diese Aufgabe übernimmt und in Zukunft dann auch in unseren Install-Scripts genutzt werden könnte.UPDATE `core_config_data`
SET `value` = REPLACE(`path`, '/', '_')
WHERE `path` LIKE '%mail%template%'