Per AJAX auf Newsletter-Controller zugreifen

Hallo,

ich würde gerne per AJAX auf den Newsletter Controller zugreifen, ohne dass der User direkt auf die Newsletter-Seite weitergeleitet wird. Ich möchte damit ermöglichen, dass sich User ohne die Newsletter-Seite und ohne zusätzliches Laden der kompletten Seite registrieren können.

Meine Idee war folgende:

Ich schreibe einen Plugin mit einem Controller der in etwa wie folgt aussieht:

Front()->Plugins()->ViewRenderer()->setNoRender();

        // Hier möchte ich den Aufruf zur Registrierung direkt an den Newsletter-Controller 
        // weiterleiten, so das ich nur im Ergebnis ($result) schauen muss, ob die Registrierung 
        // erfolgreich ist oder nicht
        $result = $this->forward('index', 'newsletter', 'frontend', $this->Request()->getParams());

        //bei $result erhalte ich leider nur NULL als Ausgabe
        echo '';
        var_dump($result);
        echo '';
        die();

        // Hier will ich das ergebnis per JSON zurückgeben um später eine Bestätigung anzeigen zu 
        // können, ob die Registrierung erfolgreich war oder nicht
        $this->Response()->setBody(
            json_encode(
                [
                    //Hier das Ergebnis ob die Registierung erfolgreich war oder nicht
                    'info1' => 123,
                    'info2' => 333
                ]
            )
        );
    }
}
  1. Warum funktioniert mit $this->forward so scheinbar nicht?

  2. Was haltet ihr von diesem Weg, was wäre aus eurer Sicht die bessere Alternative?

Das ist eine schöne Idee. ich kann dir nicht genaueres zum newsletter controller sagen, aber vll helfen dir ein paar infos.

  • Ich würde aber erstmal bei den params checken ob es X und Y parameter sind und nicht jeden durchlassen.
  • Anschliessend den newsletter Controller anrufen
  • Ich glaub norender muss nicht sein wenn keine themedatei vorhanden ist juckts nicht.
  • und zum schluss echo json_encode(array(“info1” => 123. “info2” => 333)); statt $this->…
  • das die() kommt dann ganz zum schluss. sonst wird ja das json_encode nicht ausgeführt
1 „Gefällt mir“

Danke für deine Antwort.

  • Ich würde aber erstmal bei den params checken ob es X und Y parameter sind und nicht jeden durchlassen.
    • Das sollte nur für ein schnelles Ergebnis sorgen, du hast recht, in der Endform werde ich da nur das nötigste durchlassen
  • Anschliessend den newsletter Controller anrufen
    • Hier habe ich meine Probleme. Wie funktioniert das? mein $this->forward(…) liefert leider nur NULL, woran kann das liegen? Wie würdest du den einen anderen Controller aufrufen?
  • Ich glaub norender muss nicht sein wenn keine themedatei vorhanden ist juckts nicht.
  • und zum schluss echo json_encode(array(“info1” => 123. “info2” => 333)); statt $this->…
  • das die() kommt dann ganz zum schluss. sonst wird ja das json_encode nicht ausgeführt
    • Das die() war nur dafür da, dass ich erstmal sehe, was ich im $result habe und leider steht da nur “null” drin. Ich würde das die() auch ungern drin lassen, das sollte auch kein Problem sein

Ich habe gerade festgestellt das $this->forward(…) gar keinen return Wert zurück gibt. Daher ist ja klar, dass ich keine Antwort auf die Eintragung erhalte. Wenn ich keine Bestätigung habe, kann ich dem User leider nicht sagen, dass er erfolgreich eingetragen wurde.

Frageg ist wie eine Alternative aussieht?

Ich habe mich jetzt gegen einen eigenen Controller entschieden und werde mit einem Event vom Newsletter-Controller arbeiten.

Wenn der Controller mit seiner Arbeit durch ist, sag ich ihm dass er die View nicht rendern und stattdessen JSON ausgeben soll. 

if($this->isAjaxRequest($request)) {

$controller->Front()->Plugins()->ViewRenderer()->setNoRender();

 

Über die $args des Events kann ich mir 1. ausgeben lassen ob die Anmeldung des Users erfolgreich war und 2. ob es sich um einen „ajaxRequest“ handelt. So kann ich das View-Rendern nur dann deaktivieren wenn es wirklich einen ajax-Aufruf gab. In das Form habe ich mir dafür ein hidden input-Field gepackt mit dem namen „ajax-newsletter“.

 

Mein Problem war bis eben noch, dass ich kein Captcha habe. Dafür habe ich mir diesen Block aus der newsletter.tpl kopiert:

{* Captcha *}
                            {block name="frontend_newsletter_form_captcha"}
                                {if !({config name=noCaptchaAfterLogin} && $sUserLoggedIn)}
                                    {$newsletterCaptchaName = {config name=newsletterCaptcha}}
                                    
                                        {if $newsletterCaptchaName === 'legacy'}
                                            

                                                {* Deferred loading of the captcha image *}
                                                {block name='frontend_newsletter_form_captcha_placeholder'}
                                                    
                                                    
                                                {/block}

                                                {block name='frontend_newsletter_form_captcha_label'}
                                                    {s name="SupportLabelCaptcha" namespace="frontend/forms/elements"}{/s}
                                                {/block}

                                                {block name='frontend_newsletter_form_captcha_code'}
                                                    
                                                        
                                                    
                                                {/block}
                                            
                                        {else}
                                            {$captchaName = $newsletterCaptchaName}
                                            {$captchaHasError = isset($sErrorFlag) && count($sErrorFlag) > 0}
                                            {include file="widgets/captcha/custom_captcha.tpl" captchaName=$captchaName captchaHasError=$captchaHasError}
                                        {/if}
                                    
                                {/if}
                            {/block}

 

Wenn ich jetzt mit einem Form-Data-Faker arbeite und ihn automatisch die Daten ausfüllen lasse, dann trifft er auf den konfigurierten Honeypot und wird aussortiert.

 

Wenn ich mir das so korrekt denke, dann sollten doch alle anderen Plugins etc. kein Problem mit meinem Newsletter-Plugin haben oder? Ich habe mir extra das ‚Enlight_Controller_Action_PostDispatchSecure_Frontend_Newsletter‘ Event geschnappt und verändere nur die view.

 

Was sagt ihr dazu?

Jetzt habe ich leider ein anderes Problem.

Wenn ich den Newsletter-Endpoint anspreche, dann hat dieser angeblich keine Werte erhalten. Im Request-Objekt sind alle Daten enthalten die ich geschickt habe. In der Newsletter.php werden die Daten aber wie folgt z.B. ausgelesen:

        if (!isset(Shopware()->System()->_POST['newsletter'])) {
            return;
        }

        if (Shopware()->System()->_POST['subscribeToNewsletter'] != 1) {
            // Unsubscribe user
            $this->View()->assign('sStatus', Shopware()->Modules()->Admin()->sNewsletterSubscription(Shopware()->System()->_POST['newsletter'], true));

            $session = $this->container->get('session');
            if ($session->offsetExists('sNewsletter')) {
                $session->offsetSet('sNewsletter', false);
            }

            return;
        }

Leider ist die Variable: Shopware()->System()->_POST leer. Bei einem normalen Aufruf der Seite und das anmelden über die Standard /newsletter - Seite, sind diese Variablen befüllt.

Warum sind diesen Variablen leer?

 

Ich habe dafür einen „fix“ in mein Plugin aufgenommen wo ich mit einem PreDispatch_Frontend_Newsletter folgende Variablen setze:

$existingPostVars = Shopware()->System()->_POST->toArray();

            $params = [
                'subscribeToNewsletter' => $request->getParam('subscribeToNewsletter'),
                'newsletter' => $request->getParam('newsletter'),
                'ajax-request' => $request->getParam('ajax-request'),
                'first_name_confirmation' => $request->getParam('first_name_confirmation'),
                'captchaName' => $request->getParam('captchaName'),
                '__csrf_token' => $request->getParam('__csrf_token'),
                'module' => $request->getParam('module'),
                'controller' => $request->getParam('controller'),
                'action' => $request->getParam('action'),
            ];

            $params = array_merge($params, $existingPostVars);

            Shopware()->System()->__set('_POST', $params);

Das fühlt sich wie ein hack und etwas dirty an… Auf jeden Fall habe ich jetzt eine „Newsletter-Api“

 

Was sagt ihr zu dem Fix und wisst ihr warum keine Daten aus ‚Shopware()->System()->_POST->toArray()‘ kommen, wenn ich diese per Rest-Client aufrufe?