v1.2.0: Umbenennung, zweizeiliger Erfolgstext, Umlaute

This commit is contained in:
2026-09-21 20:26:47 +02:00
parent eacba9a282
commit 53a6ee2296
@@ -10,9 +10,9 @@ use JTL\Smarty\JTLSmarty;
use Plugin\fp_altcha_spamschutz\src\Service\AltchaService; use Plugin\fp_altcha_spamschutz\src\Service\AltchaService;
/** /**
* Fuegt das ALTCHA-Widget (Container + Skript) in Registrierungs- und Newsletter-Formular ein. * Fügt das ALTCHA-Widget (Container + Skript) in Registrierungs- und Newsletter-Formular ein.
* Wird ueber HOOK_SMARTY_OUTPUTFILTER aufgerufen, also nach dem Rendern der Seite, auf dem * Wird über HOOK_SMARTY_OUTPUTFILTER aufgerufen, also nach dem Rendern der Seite, auf dem
* fertigen HTML-Dokument (phpQuery, jQuery-aehnliche PHP-DOM-API). * fertigen HTML-Dokument (phpQuery, jQuery-ähnliche PHP-DOM-API).
*/ */
class TemplateHandler class TemplateHandler
{ {
@@ -26,11 +26,11 @@ class TemplateHandler
} }
/** /**
* @param array<string, mixed> $args Enthaelt 'smarty' (JTLSmarty) und 'document' (phpQueryObject). * @param array<string, mixed> $args Enthält 'smarty' (JTLSmarty) und 'document' (phpQueryObject).
*/ */
public function generalTemplateIntegration(array $args): void public function generalTemplateIntegration(array $args): void
{ {
// WICHTIG: Dieser Hook laeuft bei JEDEM Seitenaufruf im gesamten Shop. Ein Fehler hier // WICHTIG: Dieser Hook läuft bei JEDEM Seitenaufruf im gesamten Shop. Ein Fehler hier
// darf niemals die Anzeige irgendeiner Shop-Seite verhindern -- deshalb komplett // darf niemals die Anzeige irgendeiner Shop-Seite verhindern -- deshalb komplett
// defensiv mit try/catch umschlossen. Im Zweifel wird einfach kein Widget angezeigt, // defensiv mit try/catch umschlossen. Im Zweifel wird einfach kein Widget angezeigt,
// statt die Seite kaputt zu machen. // statt die Seite kaputt zu machen.
@@ -66,8 +66,8 @@ class TemplateHandler
$newsletterFormCount = 0; $newsletterFormCount = 0;
if ($newsletterEnabled) { if ($newsletterEnabled) {
// JTLs phpQuery-Implementierung kennt kein closest(), daher ueber parents() aufwaerts // JTLs phpQuery-Implementierung kennt kein closest(), daher über parents() aufwärts
// suchen und das naechstgelegene Formular (erster Treffer) nehmen. // suchen und das nächstgelegene Formular (erster Treffer) nehmen.
$newsletterForm = $document->find('input[name="abonnieren"]')->parents('form')->eq(0); $newsletterForm = $document->find('input[name="abonnieren"]')->parents('form')->eq(0);
$newsletterFormCount = \count($newsletterForm); $newsletterFormCount = \count($newsletterForm);
if ($newsletterFormCount > 0) { if ($newsletterFormCount > 0) {
@@ -88,7 +88,7 @@ class TemplateHandler
} }
$this->logDebug($args, \sprintf( $this->logDebug($args, \sprintf(
'Hook ausgefuehrt: register_enabled=%d register_forms_gefunden=%d ' 'Hook ausgeführt: register_enabled=%d register_forms_gefunden=%d '
. 'newsletter_enabled=%d newsletter_forms_gefunden=%d ' . 'newsletter_enabled=%d newsletter_forms_gefunden=%d '
. 'contact_enabled=%d contact_forms_gefunden=%d widget_eingefuegt=%d', . 'contact_enabled=%d contact_forms_gefunden=%d widget_eingefuegt=%d',
$registerEnabled ? 1 : 0, $registerEnabled ? 1 : 0,
@@ -109,7 +109,7 @@ class TemplateHandler
* Schreibt eine Diagnosemeldung, sofern in den Plugin-Einstellungen "Debug-Logging aktivieren" * Schreibt eine Diagnosemeldung, sofern in den Plugin-Einstellungen "Debug-Logging aktivieren"
* eingeschaltet ist. Die Meldung geht sowohl in das PHP-Errorlog des Servers als auch -- damit * eingeschaltet ist. Die Meldung geht sowohl in das PHP-Errorlog des Servers als auch -- damit
* sie auch ohne Serverzugriff einsehbar ist -- als HTML-Kommentar in die ausgelieferte Seite * sie auch ohne Serverzugriff einsehbar ist -- als HTML-Kommentar in die ausgelieferte Seite
* (fuer Besucher unsichtbar, im Seitenquelltext aber direkt sichtbar). * (für Besucher unsichtbar, im Seitenquelltext aber direkt sichtbar).
* *
* @param array<string, mixed> $args * @param array<string, mixed> $args
*/ */
@@ -130,7 +130,7 @@ class TemplateHandler
private function injectWidget(phpQueryObject $document, phpQueryObject $form): void private function injectWidget(phpQueryObject $document, phpQueryObject $form): void
{ {
// Nicht doppelt einfuegen (z. B. wenn die Seite mehrfach gefiltert wird). // Nicht doppelt einfügen (z. B. wenn die Seite mehrfach gefiltert wird).
if (\count($form->find('.fp-altcha')) > 0) { if (\count($form->find('.fp-altcha')) > 0) {
return; return;
} }
@@ -146,13 +146,32 @@ class TemplateHandler
$labelPreparing = $isGerman ? 'Sicherheitsprüfung wird vorbereitet …' : 'Preparing security check …'; $labelPreparing = $isGerman ? 'Sicherheitsprüfung wird vorbereitet …' : 'Preparing security check …';
$labelPreparing = htmlspecialchars($labelPreparing, \ENT_QUOTES, 'UTF-8'); $labelPreparing = htmlspecialchars($labelPreparing, \ENT_QUOTES, 'UTF-8');
$html = '<div class="fp-altcha form-group" data-fp-altcha="' . $challengeJson . '">' // Zweizeilig dargestellt (per <br>, gerendert ueber innerHTML in fp-altcha.js): das
// <br> wird hier als normaler Attributwert htmlspecialchars-kodiert und vom Browser
// beim Auslesen per getAttribute() wieder zu einem echten Zeilenumbruch dekodiert.
$labelVerified = $isGerman ? 'Sicherheitsprüfung<br>bestanden' : 'Security check<br>passed';
$labelVerified = htmlspecialchars($labelVerified, \ENT_QUOTES, 'UTF-8');
$labelFailed = $isGerman
? 'Sicherheitsprüfung fehlgeschlagen. Bitte Seite neu laden.'
: 'Security check failed. Please reload the page.';
$labelFailed = htmlspecialchars($labelFailed, \ENT_QUOTES, 'UTF-8');
$labelWait = $isGerman
? 'Bitte einen Moment warten, die Sicherheitsprüfung läuft noch.'
: 'Please wait a moment, the security check is still running.';
$labelWait = htmlspecialchars($labelWait, \ENT_QUOTES, 'UTF-8');
$html = '<div class="fp-altcha form-group" data-fp-altcha="' . $challengeJson . '"'
. ' data-label-verified="' . $labelVerified . '"'
. ' data-label-failed="' . $labelFailed . '"'
. ' data-label-wait="' . $labelWait . '">'
. '<span class="fp-altcha-status text-muted small"><i class="fa fa-shield" aria-hidden="true"></i> ' . '<span class="fp-altcha-status text-muted small"><i class="fa fa-shield" aria-hidden="true"></i> '
. $labelPreparing . '</span>' . $labelPreparing . '</span>'
. '<input type="hidden" name="altcha" class="fp-altcha-input" value="">' . '<input type="hidden" name="altcha" class="fp-altcha-input" value="">'
. '</div>'; . '</div>';
// Direkt vor dem Absende-Button einfuegen. // Direkt vor dem Absende-Button einfügen.
$submitButton = $form->find('button[type="submit"], input[type="submit"]'); $submitButton = $form->find('button[type="submit"], input[type="submit"]');
if (\count($submitButton) > 0) { if (\count($submitButton) > 0) {
$submitButton->eq(0)->before($html); $submitButton->eq(0)->before($html);
@@ -167,7 +186,7 @@ class TemplateHandler
return; return;
} }
// Bewusst analog zum bewaehrten Muster anderer, quelloffener JTL5-Plugins direkt ueber // Bewusst analog zum bewährten Muster anderer, quelloffener JTL5-Plugins direkt über
// die globale URL_SHOP-Konstante aufgebaut, statt eine Plugin-Pfad-API zu erraten. // die globale URL_SHOP-Konstante aufgebaut, statt eine Plugin-Pfad-API zu erraten.
$assetUrl = \URL_SHOP . '/plugins/fp_altcha_spamschutz/assets/fp-altcha.js'; $assetUrl = \URL_SHOP . '/plugins/fp_altcha_spamschutz/assets/fp-altcha.js';
$assetUrl = htmlspecialchars($assetUrl, \ENT_QUOTES, 'UTF-8'); $assetUrl = htmlspecialchars($assetUrl, \ENT_QUOTES, 'UTF-8');