Wenn man sich in einer Shopware 6 SaaS Umgebung und Apps bewegt, hat man nicht mehr die Möglichkeit Rules im PageLoader zu prüfen und ein bool-Value rein zu reichen, weil man nun alles via Twig machen muss. Entweder im Template oder in den App Scripts, die die PageLoader-Events ersetzt haben.
Geht zum Glück an ganz einfach auch wenn es kein array_intersect gibt.
{% set hideBuyButton = false %}
{% set checkRuleIds = config('MyApp.config.checkRules') %}
{% set intersect = checkRuleIds|filter((rule) => rule in context.context.ruleIds) %}
{% if intersect|length > 0 %}
{% set hideBuyButton = true %}
{% endif %}
Wenn man den Lieferschein erzeugt, fällt manchmal auf dass das eine Datum sich im Format stark unterscheidet. Es wäre so als würde es eine andere Locale als die anderen benutzen.. oder gar keine.
Der Fehler liegt direkt in der delivery_note.html.twig:
% block document_side_info_contents %}
{{ parent() }}
<tr><td>{% trans with {'%deliveryDate%': config.custom.deliveryDate|format_date('medium', locale=order.language.locale.code)} %}document.deliveryDate{% endtrans %}</td></tr>
{% endblock %}
[code]
Wenn man sich die anderen Datum-Formate in der base oder letter_header Datei anguckt fällt auf, dass hier das Locale nicht aus der Order stammt bzw nicht daraus gelesen wird. Korrekt wäre hier also:
[code]
% block document_side_info_contents %}
{{ parent() }}
<tr><td>{% trans with {'%deliveryDate%': config.custom.deliveryDate|format_date('medium', locale=locale)} %}document.deliveryDate{% endtrans %}</td></tr>
{% endblock %}
Aus Shopware kennt man das Prinzip, dass man beim Erweitern von Templates einfach "parent:" angeben muss und es wird immer das vorher gehende Template mit dem selben Pfad erweitert. So kann man ein Template mehrmals durch eine unbekannte Anzahl von Plugins erweitern lassen. Twig will aber immer einen Namespace haben. Also muss man heraus finden, mit welchen Plugin man anfängt und welches Plugin dann auf das aktuelle folgt oder man auf das Basis-Template gehen muss. Ich hab mich von der Shopware 6 Implementierung inspirieren lassen und ein kleines Beispiel gebaut, bei dem man die ein Template erweitern kann und die Plugin-Namespaces immer dynamisch ergänzt werden.
Die Verzeichnisstruktur des Beispiels ist sehr einfach:
Die Basislogik habe ich in einer einfachen Function zusammen gefasst. Hier wird entweder das Plugin heraus gesucht mit dem angefangen werden muss oder das Plugin, das auf das aktuelle folgt und auch dieses Template mitbringt.
function findNewBase($template, $list = [], $currentBase = null) {
$result = 'base';
$found = $currentBase == null; //if null, took the first one
foreach($list as $key => $path) {
if($key == $currentBase) {
$found = true;
}
else if ($found && file_exists($path . '/' . $template)) {
$result = $key;
break;
}
}
return $result;
}
Die Integration wird über ein Token-Parser implementiert.
final class ExtTokenParser extends AbstractTokenParser {
/**
* @var Parser
*/
protected $parser;
private $list = [];
public function __construct(array $list)
{
$this->list = $list;
}
public function getTag(): string
{
return 'base_extends';
}
/**
* @return Node
*/
public function parse(Token $token)
{
$stream = $this->parser->getStream();
$source = $stream->getSourceContext()->getName();
$template = $stream->next()->getValue();
$stream->injectTokens([
new Token(Token::BLOCK_START_TYPE, '', 2),
new Token(Token::NAME_TYPE, 'extends', 2),
new Token(Token::STRING_TYPE, $parent, 2),
new Token(Token::BLOCK_END_TYPE, '', 2),
]);
Jetzt fehlt nur noch eine passende include-Funktion und man kann sich selbst ein System bauen, desen Templates sich über Plugins ohne Probleme erweitern lassen. Ich arbeite daran....
Edit: Die vollständige Implementierung mit extends und include ist jetzt auf GitHub zu finden.
Nach vielen vielen Monden habe ich es am Ende doch mal fertig gebracht mein altes Zeiterfassung-Projekt bei Github hoch zu laden. Wobei das komplizierteste noch war das Framework "hübsch" zu machen. Das Modul ist jetzt auch mehrsprachig.
Zum 10. Geburtstag meines PHP-Frameworks wird sich da viel ändern und es damit dann wieder etwas mehr zu anderen Frameworks aufschließen können.
Mein eigener Class-Loader fliegt raus und es wird noch der ClassLoader vom Composer verwendet. Meiner kann zwar auch mit PSR4 umgehen, aber nach dem Umstieg muss ich dann auch alles darauf umstellen und habe keine Ausrede mehr, weil die Kompatibilität weg fällt.
Es gibt nun ein public-Verzeichnis so dass alle Config-Dateien und Classes außerhalb des Bereiches liegen, auf dem Benutzer zugreifen können. Das sorgt für mehr Sicherheit, macht das Laden von CSS und Bildern aus dem Theme-Verzeichnis aber komplizierter. Ich überlege hier auf Assetic umzusteigen. Momentan läuft meine Lösung aber sehr gut.
Und das Beste und wichtigste was aber auch am meisten Arbeit machen wird (darum habe ich ganz viele alte Module erst einmal gelöscht und lasse auch die alten PHP-Pages drin) ist, dass Module-Pages nun wirklich mit Controller und Twig-Template gerendert werden. Die Twig-Templates könenn vom Theme und von eigenes Templates in der Instance überschrieben werden und so kann man nun endlich das Aussehen der Module leicht und schnell anpassen.
Smarty war schon länger drin, wurde aber nie benutzt und ist jetzt raus geflogen.
Mein erstes Projekt damit wird sein, die Zeiterfassung für Kunden-Projekte neu zu schreiben und für alle brauchbar zu machen. Das wird wohl am Ende nur 1-2 Tage dauern. Also nichts im Vergleich zum Umbau des Frameworks.
Man kann sehr einfach mit CSS auch die Reihenfolge von Elementen ändern. Damit kann man allein schon mit CSS viel an Templates anpassen ohne gleich Twig oder Smarty bemühen zu müssen.