Die “Smarty-Tags” in xt:Commerce-Templates geben einen teilweise ziemlich umfangreichen HTML-Code aus. Das ist einerseits praktisch, da das Schreiben von Templates auf diese Weise ein bisschen übersichtlicher wird, andererseits kann das auch einige Einschränkungen bedeuten, weil einem so auch ein guter Teil der Gestaltung “aus der Hand genommen” wird.

Mit den Standard-”Modifiern” sind jedoch ein paar Anpassungen recht leicht zu erledigen - Diese reichen allerdings nicht immer für das aus, was man erreichen möchte. Es ist aber möglich, “eigene Modifier” zu schreiben, die man speziell in seinem Template einsetzen kann. In diesem Beitrag also eine Einsatzbeispiel der Standard-Funktionen und eine Anleitung, wie man individuelle Änderungen übersichtlich einbauen kann.

 

Wozu “Modifier”?

Nicht immer gibt xt:Commerce genau das aus, was man gerne hätte.

Ein Beispiel dafür wären die {$PRODUCTS_IMAGE}-Anweisungen. Allen gemein ist, dass sie ein Artikelbild anzeigen. Und allen gemein ist, dass man nicht bestimmen kann, ob’s das “kleine”, “große” oder “mittlere” Produktbild sein soll. Und gemein an allen ist, dass man nicht ohne “traditionelles Gebastel” an den zuständigen PHP-Dateien auskommt, wenn man eine andere Abbildungsgröße in seinem Template haben möchte.

Bei den “Boxes” müssten dazu auch keine System-Dateien bearbeitet werden, die entsprechenden PHP-Files sind ja im Template hinterlegt. Anders sieht’s allerdings bei Produkt-Auflistungen jeglicher Art oder den “Einzel-Ansichten” von Produkten aus.

Wenn dort andere Bilder angezeigt werden sollen, geht das auch ohne viel “Gefummel” - und zwar mit “Modifiern”. Hier würde ich “replace” empfehlen, und dann ist es ganz einfach: Mit einem kleinen Zusatz …

{$PRODUCTS_IMAGE|replace:"info_images":"thumbnail_images"}

… würde man dafür sorgen, dass statt des “mittleren” das “kleinste” Artikelfoto angezeigt wird. Der “Modifier” verändert (in diesem Fall mit “Ersetze info_images durch thumbnail_images”) die HTML-Ausgabe, so dass durch den damit veränderten Datei-Pfad das “kleinere Bild” gewählt wird.

Smarty hat quasi “ab Werk” schon etliche “Modifier” mit auf den Weg bekommen, viele davon sind auch als gleich oder sehr ähnlich benannte PHP-Funktionen bekannt. Und damit kann man schon so Einiges anstellen.

 

Wozu “eigene Modifier?”

Weil die “mitgelieferten” nicht immer ausreichen.

Dafür wieder ein Beispiel: Angenommen, die “Versandkosten-Info” soll nicht mehr in einem PopUp-Fenster geöffnet werden. Solche Aufgaben sind mit den Standard-Smarty-Funktionen kaum zu bewältigen.

Sehr vielseitig einsetzbar ist zwar der “regex_replace”-Modifier, eine weitere Ersetzungs-Funktion, die aber im Gegensatz zum einfachen “replace” auch reguläre Ausdrücke als “Suchmuster” akzeptiert - Aber ich denke, man kann sich gut vorstellen, wie unübersichtlich eine Template-Datei mit der Zeit werden kann, die mit lauter “regulären Ausdrücken” vollgeschrieben ist.

Die Versandkosten-PopUps sind ziemlich tief im System “verankert” - all diese Konstruktionen zu finden und anzupassen ist a) ein Haufen Arbeit und bedeutet b) etliche Änderungen an etlichen System-Dateien, die man sich auch sparen kann. Natürlich könnte man (um die System-Dateien unangetastet zu lassen) den Versandkosten-Link auch mit der üblichen xtc_hreflink-Konstruktion nachbauen:

<a href="{php} echo xtc_href_link(BEISPIEL, 'coID=xyz'); {/php}">Versandkosten</a>

… das ist allerdings wieder eine Menge Code für ein bisschen Link. Außerdem müsste man sich bei mehrsprachigen Shops wieder etwas anderes (komplizierteres) einfallen lassen. Einfacher wäre es, solche “Spezialitäten” in eigene Funktionen “auszulagern” (beispielsweise “noPopUp”, o.ä.) - und diese eben als normalen “Modifier” einsetzen zu können.

Ziel: Ein “PopUp freier” Versandkosten-Link könnte dann meinetwegen so aussehen:

{$SHIPPING_LINK|noPopUp}

Dafür müsste man also einen “noPopUp”-Modifier programmieren, der den Link aus der PopUp-Anweisung (inklusive Session-ID) extrahiert und einen “ganz normalen” Link mit dem vorgegebenen Text daraus macht.

Das ist gar nicht so schwer - Hier also eine kleine Anleitung …

 

Vorüberlegung: Template spezifische Modifier

Da man derlei Änderungen am ausgegebenen HTML-Quellcode meistens für ein konkretes Projekt und ein konkretes Template braucht, sollte man versuchen, die eigenen “Smarty-PlugIns” auch immer mit dem jeweiligen Template zusammen zu verwalten. Denn so hat man keine Probleme, wenn “meinBeispielModifier” in Template A eine andere Aufgabe bekommen soll, als “meinBeispielModifier” in Template B.

Smarty ist da sehr flexibel. In der Konfigurations-Datei ist natürlich zunächst bloß der “übliche” PlugIn Ordner angegeben, aus dem sich das Smarty-System seine “Erweiterungen” holt. Man kann jedoch zusätzlich noch weitere Ordner bestimmen - und dazu legen wir einfach mal einen Ordner “smarty” innerhalb unseres Templates an und ändern die Smarty-Konfiguration dahingehend ab, dass “PlugIns” immer zusätzlich im Ordner “smarty” des jeweils aktiven Templates gesucht werden.

Das kann man “allgemeingültig” machen, damit man nicht für jedes neue Template die Smarty-Kofiguration ändern muss.

Eigene Smarty-PlugIns für xt:Commerce
Die “betroffenen” Dateien - Beispiel aus xt:Commerce 3.04 SP2.1

 

1) Template-Ordner “smarty” als PlugIn-Ordner

Eine xt:Commerce-Datei muss geändert werden, aber alle folgenden Erweiterungen spielen sich ausschließlich innerhalb des Templates ab. Allerdings handelt es sich dabei nicht um eine “echte” System-Datei, sondern nur um die Konfiguraion von Smarty innerhalb des Shops.

1a) Pfad zum Template

In der Datei “Smarty.class.php” verweisen wir auf unseren neuen “smarty”-Ordner in unseren Template. Dazu müssen wir dem System “beibringen”, wo genau immer das jeweils aktive Template zu finden ist. Wir definieren also zunächst einmal den “neuen PlugIn-Ordner” und fügen den Pfad nach den anderen Definitionen ein (etwa Zeile 55)


define('SMARTY_PHP_PASSTHRU',   0);
define('SMARTY_PHP_QUOTE',      1);
define('SMARTY_PHP_REMOVE',     2);
define('SMARTY_PHP_ALLOW',      3);

//NEU: Pfad zum PlugIn-Ordner im aktiven Template!
define('MY_TEMPLATE_PLUGINS', DIR_FS_CATALOG.'templates/'.CURRENT_TEMPLATE.'/smarty');
	

 

1b) Definition als zusätzlicher PlugIn-Ordner

Jetzt muss Smarty diesen Pfad zusätzlich zum “normalen” PlugIn-Ordner erkennen. Da man mehrere Ordner festlegen kann und diese sich auch nicht zwingend innerhalb des Smarty-Ordners befinden müssen, ist das kein Problem. Das Array $plugins_dir braucht nur noch einen entsprechenden weiteren Eintrag (etwa ab Zeile 95):


    /**
     * An array of directories searched for plugins.
     *
     * @var array
     */
    //ALT: Nur ein PlugIn-Verzeichnis
    //var $plugins_dir     =  array('plugins');
    //NEU: Jetzt wird zusätzlich im Template nach PlugIns gesucht.
    var $plugins_dir     =  array('plugins',MY_TEMPLATE_PLUGINS);
	

 

2) “Eigene Modifier” im Template - Ausprobieren

Nun können wir unsere eigenen “Funktionen” schreiben, mit denen wir den HTML-Code von xt:Commerce nach unseren Wünschen anpassen können. Die Benennung der Dateien und darin enthaltenen “Haupt-Funktion” muss einigen Regeln entsprechen, damit auch alles korrekt erkannt wird.

2a) Übungsbeispiel: Modifier ohne Parameter

Ein einfaches (wenn auch nicht besonders sinnvolles) Beispiel für einen “Modifier” wäre die Funktion “SmartyTest”. Im neuen “smarty”-Ordner unseres Templates legen wir eine PHP-Datei an - der Name dieser Datei muss entsprechend “modifier.SmartyTest.php”, damit die Funktion “SmartyTest” auch als Modifier erkannt wird.


<?php

function smarty_modifier_SmartyTest($Input) {

	return 'Ein Test: '.$Input.' Test bestanden';

} 

?>
	

Damit kann “SmartyTest” im Template eingesetzt werden.

Zum Ausprobieren einfach mal die “index.html” öffnen und {$NAVTRAIL} mit der neuen Funktion “nachbearbeiten” {$NAVTRAIL|SmartyTest} - Wenn alles geklapt hat ist die Breadcrumb-Navigation um ein wenig zusätzlichen Text “bereichert.”

2b) Übungsbeispiel: Modifier mit Parameter

Es ist auch möglich, “Parameter” an die Modifier weiterzugeben, so dass sich die Ausgabe nach unterschiedlichen Anforderungen anpassen lässt. Die Vorgehensweise ist ähnlich, die Modifier-Funktion wird dabei wie von anderen PHP-Funktionen gewohnt angelegt:


function smarty_modifier_NochEinTest($Input, $Anzahl = 1) {

	$Anzahl = intval($Anzahl);
	return str_repeat('#', $Anzahl).$Input.str_repeat('#', $Anzahl); 

}
	

Eventuelle Fehlermeldungen werden dadurch abgefangen, dass für den Parameter “Anzahl” eine Eins “voreingestellt” ist - und aus $Anzahl vor der Weiterverarbeitung immer ein ganzzahliger Wert gemacht wird.

Diese Funktion muss analog zum ersten Beispiel in wieder in einer eigenen Datei gespeichert werden, der Name diesmal entsprechend “modifier.NochEinTest.php”

Ausprobieren: Bleiben wir gleich bei der “index.html” aus unserem Template - und schreiben für {$NAVTRAIL} diesmal {$NAVTRAIL|NochEinTest} - In diesem Fall haben wir keinen Wert als Parameter übergeben, daher wird die Voreinstellung “1″ vorausgesetzt.

Um beispielsweise das “#” in fünffacher Ausführung vor und hinter die Breadcrumb-Navigation zu setzen, geben wir {$NAVTRAIL|NochEinTest:5} ein, und das “#” wird jeweils fünf mal wiederholt.

 

3) “Eigene Modifier” - Beispiel “noPopUp”

Zugegeben, die Übungs-Beispiele sind für den praktischen Einsatz in einem xt:Commerce-Template eigentlich nicht zu gebrauchen und waren nur zur Veranschaulichung gedacht.

Eingangs hatte ich ja vorgeschlagen, die Versandkosten-PopUps durch normale Verlinkungen zu ersetzen. Und das ist mit einem eigenen Modifier sehr viel leichter zu erreichen als mit dem Bearbeiten von lauter System-Dateien. Ein solcher “noPopUp”-Modifier könnte zum Beispiel (getestet mit SP2.1) so aussehen:


<?php

function smarty_modifier_noPopUp($Input) {

	if (preg_match("/window.open/", strtolower($Input))) {
		$Link = stripcslashes($Input);
		$Link = preg_replace("/.*window.open[^']*'([^']*).*/",'$1',$Link);
	} else {
		$Link = preg_replace("/.*href=\"([^\"]*)\".*/",'$1',$Input);
	}
	$Link = str_replace('popup_content','shop_content',$Link);

	$Output = SHIPPING_EXCL.' <a href="'.$Link.'">'.SHIPPING_COSTS.'</a>';
	return $Output;

} ?>
	

Abzuspeichern wäre dieses Script unter dem Namen “modifier.noPopUp.php” im “smarty”-Ordner des Templates.

Danach ist es fertig zum Einsatz: Wenn man anstelle der üblichen Versandkosten-Links {$SHIPPING_LINK|noPopUp} schreibt, wird der “Original Shipping-Link” daraufhin untersucht, ob eine typische window.open-Anweisung enthalten ist - und der ursprüngliche Link “xtrahiert”. Der strtolower-Befehl, damit die Sache auch dann funktioniert, wenn Großbuchstaben verwendet worden sein sollten.

Wird keine “window.open”-Anweisung gefunden, liegt im Regelfall auch kein PopUp-Link vor, so dass die Link-Adresse mit dem zweiten preg_replace isoliert werden kann.

Anschließend wird dafür gesorgt, dass der verlinkte Inhalt innerhalb des Shops und nicht innerhalb eines PopUp-Fensters angezeigt wird. Und am Ende wird wieder alles “zusammengesetzt”.

Die zusätzlichen Smarty-Modifier können dabei (wie im Beispiel zu sehen) auf die in den Sprach-Dateien hinterlegten Daten zugreifen, so dass man sich in diesem Fall nicht auch noch darum kümmern muss, den Text “vor” und “innerhalb des Links” zu erhalten.

 

Zusammenfassung:

Mit selbst geschriebenen “Modifiern” kann man also viele Bereiche in seinem xt:Commerce-Template nach Wunsch anpassen und umgestalten - ohne dabei ins System eingreifen zu müssen. Und diese Erweiterungen lassen sich bequem mit den jeweiligen Templates zusammen verwalten.

Kurz-Anleitung:

  1. In der Datei “Smarty.class.php” einen zusätzlichen PlugIn-Ordner definieren. Vorschlag: Ordner “smarty” innerhalb des Templates
  2. Benennungsregel 1: Die Modifier-Datei muss heißen “modifier.MeineFunktion.php”
  3. Benennungsregel 2: Die Modifier-Funktion muss heißen: “smarty_modifier_MeineFunktion”
  4. Abspeichern der neuen Modifier im “smarty”-Ordner des Templates
  5. Die Modifier-Funktion braucht mindestens einen Parameter, an den ersten wird immer der usprüngliche Inhalt des Smarty-Tags übergeben - Rückgabe als “return”
  6. Einsatz im Template: {$BEISPIEL|MeineFunktion}