THELIA Forum

Welcome to the THELIA support and discusssion forum

Announcement

Rejoignez la communauté sur le Discord Thelia : https://discord.gg/YgwpYEE3y3

Offline


Bonjour,
je suis depuis plusieurs jours en train d'essayer de faire un truc qui me paraissait simple au départ.
Et la je m'arrache un peu les cheveux et je ne trouve pas que mon code soit très propre ..

Je veux ajouter un champ au form d'inscription (page register), et si ce champ est rempli, on arrète le process d'inscription et on envoie vers une nouvelle url, par exemple, /register-processing, sinon on continue normalement.
Pour ce qui est du champ, pas de probleme, je l'affiche bien via un hook.
Je pensais pouvoir passer uniquement par un listener au départ mais apparemment j'ai besoin d'un controller pour faire ça.
D'ailleurs j'ai trouvé ça dommage de devoir réecrire/recopier certaines méthodes de CustomerController.php dans mon controller

Enfin bref, je n'ai peut être pas fait au plus simple, j'en sais rien ...

En dessous, vous trouverez les codes qui m'affichent bien la page demandée mais l'url ne change pas à la validation du form, elle reste register.

Merci par avance

routing.xml

<?xml version="1.0" encoding="UTF-8" ?>

<routes xmlns="http://symfony.com/schema/routing"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://symfony.com/schema/routing http://symfony.com/schema/routing/routing-1.0.xsd">

        <route id="customer.create.process" path="/register" methods="post">
        <default key="_controller">BestRegister\Controller\BestRegisterController::createAction</default>
        <default key="_view">register-processing</default>
        </route>
</routes>

BestRegisterListener.php

<?php

namespace BestRegister\EventListeners;

use Thelia\Core\Event\TheliaEvents;
use Thelia\Core\Event\TheliaFormEvent;
use Thelia\Core\Event\Customer\CustomerCreateOrUpdateEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\RequestStack;
use Thelia\Core\Translation\Translator;
use Thelia\Tools\URL;
use Thelia\Form\Exception\FormValidationException;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Thelia\Core\HttpKernel\Exception\RedirectException;

use Symfony\Component\HttpFoundation\Request;

class BestRegisterListener implements EventSubscriberInterface
{

    protected $requestStack;

    public function __construct(RequestStack $requestStack)
    {
        $this->requestStack = $requestStack;

    }

    public function addField(TheliaFormEvent $event)
    {
        $event->getForm()->getFormBuilder()->add(
            'secteur_activite',
            TextType::class,
            [
                //'label' => $translator->trans('Industry'),
                'label' => Translator::getInstance()->trans('Industry'),
                'required' => true,
                'label_attr'  => [
                    //'help' => $translator->trans('Choisissez votre secteur d\'activité')
                    'help' => Translator::getInstance()->trans('Choisissez votre secteur d\'activité')
                ]
            ]
        );
    }

    public function createCustomer(CustomerCreateOrUpdateEvent $event)
    {
        $request = $this->requestStack->getCurrentRequest();
        $formData = $request->get('thelia_customer_create', []);

        $secteurActivite = $formData['secteur_activite'];

        if (!empty($secteurActivite)) {
            $request->attributes->set('secteur_activite_filled', true);
            //$event->stopPropagation();
            // throw new RedirectException(URL::getInstance()->absoluteUrl("/register-processing"));
        }
    }
    
    public static function getSubscribedEvents()
    {
        return [
            TheliaEvents::FORM_BEFORE_BUILD . ".thelia_customer_create" => ['addField', 128],
            TheliaEvents::CUSTOMER_CREATEACCOUNT => ['createCustomer', 250],
        ];
    }
}

BestRegisterController.php

<?php

namespace BestRegister\Controller;



use Front\Front;
use Symfony\Component\Form\Extension\Core\Type\FormType;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Symfony\Contracts\EventDispatcher\EventDispatcherInterface;
use Thelia\Controller\Front\BaseFrontController;
use Thelia\Core\Event\Customer\CustomerCreateOrUpdateEvent;
use Thelia\Core\Event\Customer\CustomerLoginEvent;
use Thelia\Core\Event\DefaultActionEvent;
use Thelia\Core\Event\LostPasswordEvent;
use Thelia\Core\Event\Newsletter\NewsletterEvent;
use Thelia\Core\Event\TheliaEvents;
use Thelia\Core\Security\Authentication\CustomerUsernamePasswordFormAuthenticator;
use Thelia\Core\Security\Exception\AuthenticationException;
use Thelia\Core\Security\Exception\CustomerNotConfirmedException;
use Thelia\Core\Security\Exception\UsernameNotFoundException;
use Thelia\Core\Security\Exception\WrongPasswordException;
use Thelia\Form\CustomerLogin;
use Thelia\Form\Definition\FrontForm;
use Thelia\Form\Exception\FormValidationException;
use Thelia\Log\Tlog;
use Thelia\Model\ConfigQuery;
use Thelia\Model\Customer;
use Thelia\Model\CustomerQuery;
use Thelia\Model\Event\CustomerEvent;
use Thelia\Model\Newsletter;
use Thelia\Model\NewsletterQuery;
use Thelia\Tools\RememberMeTrait;
use Thelia\Tools\URL;


class BestRegisterController extends BaseFrontController
{
   
   
public function createAction(EventDispatcherInterface $eventDispatcher, Request $request)
{
    if ($request->attributes->get('secteur_activite_filled')) {
        
        return $this->render('register-processing.html');
//return $this->generateUrl('register-processing');
//return $this->generateRedirectFromRoute('register-processing');

    } else {

        $customerCreation = $this->createForm(FrontForm::CUSTOMER_CREATE);

        try {
            $form = $this->validateForm($customerCreation, 'post');

            $customerCreateEvent = $this->createEventInstance($form->getData());

            $eventDispatcher->dispatch($customerCreateEvent, TheliaEvents::CUSTOMER_CREATEACCOUNT);

            $newCustomer = $customerCreateEvent->getCustomer();

            // Newsletter
            if (true === $form->get('newsletter')->getData()) {
                $newsletterEmail = $newCustomer->getEmail();
                $nlEvent = new NewsletterEvent(
                    $newsletterEmail,
                    $this->getRequest()->getSession()->getLang()->getLocale()
                );
                $nlEvent->setFirstname($newCustomer->getFirstname());
                $nlEvent->setLastname($newCustomer->getLastname());

                // Security : Check if this new Email address already exists
                if (null !== $newsletter = NewsletterQuery::create()->findOneByEmail($newsletterEmail)) {
                    $nlEvent->setId($newsletter->getId());
                    $eventDispatcher->dispatch($nlEvent, TheliaEvents::NEWSLETTER_UPDATE);
                } else {
                    $eventDispatcher->dispatch($nlEvent, TheliaEvents::NEWSLETTER_SUBSCRIBE);
                }
            }

            if (ConfigQuery::isCustomerEmailConfirmationEnable() && !$newCustomer->getEnable()) {
                $response = $this->generateRedirectFromRoute('customer.login.view');
            } else {
                $this->processLogin($eventDispatcher, $customerCreateEvent->getCustomer());

                $cart = $this->getSession()->getSessionCart($eventDispatcher);
                if ($cart->getCartItems()->count() > 0) {
                    $response = $this->generateRedirectFromRoute('cart.view');
                } else {
                    $response = $this->generateSuccessRedirect($customerCreation);
                }

                return $response;
            }
        } catch (FormValidationException $e) {
            $message = $this->getTranslator()->trans(
                'Please check your input: %s',
                [
                    '%s' => $e->getMessage(),
                ],
                Front::MESSAGE_DOMAIN
            );
        } catch (\Exception $e) {
            $message = $this->getTranslator()->trans(
                'Sorry, an error occurred: %s',
                [
                    '%s' => $e->getMessage(),
                ],
                Front::MESSAGE_DOMAIN
            );
        }

        Tlog::getInstance()->error(
            sprintf(
                'Error during customer creation process: %s. Exception was %s',
                $message,
                $e->getMessage()
            )
        );

        $customerCreation->setErrorMessage($message);

        $this->getParserContext()
            ->addForm($customerCreation)
            ->setGeneralError($message)
        ;

        // Redirect to error URL if defined
        if ($customerCreation->hasErrorUrl()) {
            return $this->generateErrorRedirect($customerCreation);
        }
    */}
}

    /**
     * Dispatch event for customer login action.
     */
    protected function processLogin(EventDispatcherInterface $eventDispatcher, Customer $customer): void
    {
        $eventDispatcher->dispatch(new CustomerLoginEvent($customer), TheliaEvents::CUSTOMER_LOGIN);
    }

    /**
     * @return \Thelia\Core\Event\Customer\CustomerCreateOrUpdateEvent
     */
 
    private function createEventInstance($data)
    {
        $customerCreateEvent = new CustomerCreateOrUpdateEvent(
            $data['title'] ?? null,
            $data['firstname'] ?? null,
            $data['lastname'] ?? null,
            $data['address1'] ?? null,
            $data['address2'] ?? null,
            $data['address3'] ?? null,
            $data['phone'] ?? null,
            $data['cellphone'] ?? null,
            $data['zipcode'] ?? null,
            $data['city'] ?? null,
            $data['country'] ?? null,
            $data['email'] ?? null,
            $data['password'] ?? null,
            $data['lang_id'] ?? $this->getSession()->getLang()->getId(),
            $data['reseller'] ?? null,
            $data['sponsor'] ?? null,
            $data['discount'] ?? null,
            $data['company'] ?? null,
            null,
            $data['state'] ?? null
        );

        return $customerCreateEvent;
    }


}

Last edited by vz777 (04-11-2023 02:26:42)

Offline


Bon j'étais fatigué et j'ai une fois de plus poster n'importe quoi l'autre soir .. Désolé

Je suis reparti de 0.

Voila la methode de mon controller

    public function createAction(EventDispatcherInterface $eventDispatcher, Request $request)
    {
        
    $formData = $request->get('thelia_customer_create', []);
    $secteurActiviteFilled = !empty($formData['secteur_activite']);

        if (!$this->getSecurityContext()->hasCustomerUser()) {
            $customerCreation = $this->createForm(FrontForm::CUSTOMER_CREATE);

            try {
                $form = $this->validateForm($customerCreation, 'post');

                if ($secteurActiviteFilled)   
                return $this->render('register-processing');

                $customerCreateEvent = $this->createEventInstance($form->getData());

                $eventDispatcher->dispatch($customerCreateEvent, TheliaEvents::CUSTOMER_CREATEACCOUNT);

                $newCustomer = $customerCreateEvent->getCustomer();

               ...

et celles de mon listener

    protected $requestStack;

    public function __construct(RequestStack $requestStack)
    {
        $this->requestStack = $requestStack;
    }
    
    public function addField(TheliaFormEvent $event)
    {
        $event->getForm()->getFormBuilder()->add(
            'secteur_activite',
            TextType::class,
            [
                'label' => Translator::getInstance()->trans('Industry'),
                'required' => false,
                'label_attr' => array(
                'for' => 'industry'
                 )
            ]
        );
    }
    
    public function createCustomer(CustomerCreateOrUpdateEvent $event)
    {
        $request = $this->requestStack->getCurrentRequest();
        $formData = $request->get('thelia_customer_create', []);

        $secteurActivite = $formData['secteur_activite'];
        if (!empty($secteurActivite)) {
            $request->attributes->set('secteur_activite_filled', true);
            // throw new RedirectException(URL::getInstance()->absoluteUrl("/register-processing"));
        }
    }
    
    public static function getSubscribedEvents()
    {
        return [
            TheliaEvents::FORM_BEFORE_BUILD . ".thelia_customer_create" => ['addField', 255],
            TheliaEvents::CUSTOMER_CREATEACCOUNT => ['createCustomer', 250],
        ];
    }

Je ne m'explique pas pourquoi avec juste throw new RedirectException dans le listener cela ne suffit pas.

Je n'arrive pas à créer une nouvelle url, peut être qu'il faut la déclarer quelque part, mais bon je vais laisser tomber ça, le comportement attendu est la.


Le truc qui me préoccupe un peu, c'est comme je touche au formulaire d'inscription, est-ce que je ne m'expose pas à des problèmes de sécurité en fonctionnant ainsi ?
Je ne vois pas pourquoi mais bon, j'aime mieux demander.

Offline


Bon ça me parait overkill un controller pour faire çe que je veux faire.
J'ai donc gardé uniquement mon listener.

Le seul truc que j'arrive à faire ici c'est une FormValidationException,
pourquoi je n'arrive pas à faire une RedirectException ?

D'après le forum, ça à bien l'air d'être une RedirectException qu'il faut faire.

Quand je met une RedirectException, les logs ne sont pas très explicite

1: ERROR [CustomerController.php:createAction()] {218} 2023-11-11 19:43:25:Error during customer creation process : Désolé. Une erreur s'est produite : . Exception was 
use Thelia\Core\HttpKernel\Exception\RedirectException;


    public function createCustomer(CustomerCreateOrUpdateEvent $event)
    {
        
        $request = $this->requestStack->getCurrentRequest();

        $formData = $request->get('thelia_customer_create', []);

        $secteurActiviteFilled = $formData['secteur_activite'];

        if (!empty($secteurActiviteFilled)) {

                $event->stopPropagation();
                throw new FormValidationException('Register on progress');
                //throw new RedirectException(URL::getInstance()->absoluteUrl("/register-processing"));

        }
    }