src/Controller/CustomerController.php line 592

Open in your IDE?
  1. <?php
  2. namespace App\Controller;
  3. use App\Entity\Country;
  4. use App\Entity\Customer;
  5. use App\Entity\User;
  6. use App\Service\Mailer;
  7. use App\Service\StripeClient;
  8. use Stripe\Exception\ApiErrorException;
  9. use Symfony\Bridge\Doctrine\Form\Type\EntityType;
  10. use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
  11. use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
  12. use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
  13. use Symfony\Component\Form\Extension\Core\Type\EmailType;
  14. use Symfony\Component\Form\Extension\Core\Type\HiddenType;
  15. use Symfony\Component\Form\Extension\Core\Type\PasswordType;
  16. use Symfony\Component\Form\Extension\Core\Type\RepeatedType;
  17. use Symfony\Component\Form\Extension\Core\Type\SubmitType;
  18. use Symfony\Component\Form\Extension\Core\Type\TextType;
  19. use Symfony\Component\Form\FormError;
  20. use Symfony\Component\HttpFoundation\Request;
  21. use Symfony\Component\HttpFoundation\Session\SessionInterface;
  22. use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
  23. use Symfony\Component\Routing\Annotation\Route;
  24. use Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface;
  25. use Symfony\Component\Security\Core\User\UserInterface;
  26. use Symfony\Component\Security\Core\Validator\Constraints\UserPassword;
  27. use Symfony\Component\Security\Csrf\TokenGenerator\UriSafeTokenGenerator;
  28. use Symfony\Component\Validator\Constraints\Date;
  29. use Symfony\Component\Validator\Constraints\Email;
  30. use Symfony\Component\Validator\Constraints\EqualTo;
  31. use Symfony\Component\Validator\Constraints\IsTrue;
  32. use Symfony\Component\Validator\Constraints\Length;
  33. use Symfony\Component\Validator\Constraints\NotBlank;
  34. class CustomerController extends AbstractController
  35. {
  36.     /**
  37.      * @Route("/portal/registrierung", name="customer_registration")
  38.      *
  39.      * @param \Symfony\Component\HttpFoundation\Session\SessionInterface $session
  40.      * @param \Symfony\Component\HttpFoundation\Request $request
  41.      * @param \Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface $passwordEncoder
  42.      * @param \App\Service\Mailer $mailer
  43.      * @param \Symfony\Component\Security\Core\User\UserInterface|null $user
  44.      *
  45.      * @return \Symfony\Component\HttpFoundation\Response
  46.      * @throws \Twig_Error_Loader
  47.      * @throws \Twig_Error_Runtime
  48.      * @throws \Twig_Error_Syntax
  49.      */
  50.     public function registration(
  51.         SessionInterface $session,
  52.         Request $request,
  53.         UserPasswordEncoderInterface $passwordEncoder,
  54.         Mailer $mailer,
  55.         UserInterface $user null
  56.     ) {
  57.         if ($request->get('utm_campaign') === 'rabattcode-register') {
  58.             $session->set('riser-discount'true);
  59.         }
  60.         if ($user !== null) {
  61.             if ($this->isGranted('ROLE_CUSTOMER')) {
  62.                 return $this->redirectToRoute('portal');
  63.             }
  64.             if ($this->isGranted('ROLE_ADMIN')) {
  65.                 return $this->redirectToRoute('dashboard');
  66.             }
  67.         }
  68.         $customer = new Customer();
  69.         /** @var \App\Repository\CountryRepository $countryRepo */
  70.         $countryRepo $this->getDoctrine()->getRepository(Country::class);
  71.         $formBuilder $this->createFormBuilder($customer);
  72.         $formBuilder
  73.             ->add('gender'ChoiceType::class, [
  74.                 'label'    => 'Anrede',
  75.                 'expanded' => true,
  76.                 'choices'  => [
  77.                     'Herr'         => 'm',
  78.                     'Frau'         => 'f',
  79.                     'Keine Angabe' => 'u',
  80.                 ],
  81.             ])
  82.             ->add('firstName'TextType::class, ['label' => 'Vorname'])
  83.             ->add('lastName'TextType::class, ['label' => 'Nachname'])
  84.             ->add('company'TextType::class, ['label' => 'Firma''required' => false])
  85.             ->add('street'TextType::class, ['label' => 'Straße / Hausnr.'])
  86.             ->add('city'TextType::class, ['label' => 'Stadt'])
  87.             ->add('zip'TextType::class, ['label' => 'PLZ'])
  88.             ->add('country'EntityType::class, [
  89.                 'class'             => Country::class,
  90.                 'choice_label'      => 'name',
  91.                 'label'             => 'Land',
  92.                 'choices'           => $countryRepo->getChoices(),
  93.                 'preferred_choices' => $countryRepo->getPreferredCountryChoices(),
  94.             ])
  95.             ->add('email'EmailType::class, [
  96.                 'label'       => 'E-Mail-Adresse',
  97.                 'mapped'      => false,
  98.                 'constraints' => [
  99.                     new NotBlank([
  100.                         'message' => 'E-Mail-Adresse darf nicht leer sein',
  101.                     ]),
  102.                     new Email([
  103.                         'message' => 'Dies ist keine gültige E-Mail-Adresse',
  104.                     ]),
  105.                 ],
  106.             ])
  107.             ->add('confirmEmail'EmailType::class, [
  108.                 'label'       => 'E-Mail-Adresse bestätigen',
  109.                 'mapped'      => false,
  110.                 'required'    => false,
  111.                 'constraints' => [
  112.                     new Email([
  113.                         'message' => 'Dies ist keine gültige E-Mail-Adresse',
  114.                     ]),
  115.                 ],
  116.             ])
  117.             ->add('phone'TextType::class, ['label' => 'Telefonnummer''required' => false])
  118.             ->add('password'RepeatedType::class, [
  119.                 'type'            => PasswordType::class,
  120.                 'invalid_message' => 'Die Passwörter stimmen nicht überein',
  121.                 'first_options'   => ['label' => 'Passwort wählen'],
  122.                 'second_options'  => ['label' => 'Passwort wiederholen'],
  123.                 'mapped'          => false,
  124.                 'constraints'     => [
  125.                     new NotBlank([
  126.                         'message' => 'Bitte geben Sie ein Passwort ein',
  127.                     ]),
  128.                     new Length([
  129.                         'min'        => 6,
  130.                         'minMessage' => 'Das Passwort muss mindestens {{ limit }} Zeichen lang sein',
  131.                         'maxMessage' => 'Das Passwort überschreitet die zugelassene Länge von {{ limit }} Zeichen',
  132.                         'max'        => 4096,
  133.                     ]),
  134.                 ],
  135.             ]);
  136.         if ($session->get('riser-discount') === true) {
  137.             $formBuilder->add('riserCode'TextType::class, [
  138.                 'label'       => 'Rabatt-Code',
  139.                 'required'    => false,
  140.                 'mapped'      => false,
  141.                 'constraints' => [
  142.                     new EqualTo([
  143.                         'value'   => getenv('PORTAL_RISER_CUSTOMER_CODE'),
  144.                         'message' => 'Der eingegebene Rabatt-Code ist nicht gültig',
  145.                     ]),
  146.                 ],
  147.             ]);
  148.         }
  149.         $form $formBuilder
  150.             ->add('terms'CheckboxType::class, [
  151.                 'label'       => 'Die Datenschutzerklärung und AGB habe ich zur Kenntnis genommen.',
  152.                 'required'    => true,
  153.                 'mapped'      => false,
  154.                 'constraints' => [
  155.                     new IsTrue([
  156.                         'message' => 'Bitte bestätigen Sie die Datenschutzerklärung und AGB',
  157.                     ]),
  158.                 ],
  159.             ])
  160.             ->add('save'SubmitType::class, ['label' => 'Registrieren'])
  161.             ->getForm();
  162.         $form->handleRequest($request);
  163.         if ($form->isSubmitted() && $form->isValid()) {
  164.             /* Honey-pot. Hopefully bots will fill out this field and get redirected to the success page without an actual registration */
  165.             $confirmEmail $form->get('confirmEmail')->getData();
  166.             if (!empty($confirmEmail)) {
  167.                 return $this->redirectToRoute('customer_registration_success');
  168.             }
  169.             $email $form->get('email')->getData();
  170.             if (empty($this->getDoctrine()->getRepository(User::class)->findBy(['email' => $email]))) {
  171.                 /** @var \App\Entity\Customer $customer */
  172.                 $customer $form->getData();
  173.                 $customer->setCreationDate(new \DateTime());
  174.                 $user = new User();
  175.                 if ($form->has('riserCode') && ! empty($form->get('riserCode')->getData())) {
  176.                     $customer->setIsRiserCustomer(true);
  177.                 }
  178.                 $user->setEmail($form->get('email')->getData());
  179.                 $user->setRoles(['ROLE_CUSTOMER']);
  180.                 $user->setPassword(
  181.                     $passwordEncoder->encodePassword(
  182.                         $user,
  183.                         $form->get('password')->getData()
  184.                     )
  185.                 );
  186.                 $user->setCustomer($customer);
  187.                 // generate confirmation token
  188.                 $tokenGenerator = new UriSafeTokenGenerator();
  189.                 $user->setConfirmationKey($tokenGenerator->generateToken());
  190.                 $user->setConfirmationType(User::CONFIRMATION_TYPE_REGISTRATION);
  191.                 $entityManager $this->getDoctrine()->getManager();
  192.                 $entityManager->persist($user);
  193.                 $entityManager->flush();
  194.                 // send confirmation mail
  195.                 $mailer->sendPortalRegistrationEmail($user);
  196.                 $session->remove('riser-discount');
  197.                 return $this->redirectToRoute('customer_registration_success');
  198.             }
  199.             $form->get('email')->addError(new FormError('Die angegebene E-Mail-Adresse existiert bereits'));
  200.         }
  201.         return $this->render('portal/customer/registration.html.twig', [
  202.             'form'          => $form->createView(),
  203.             'riserDiscount' => $session->get('riser-discount') === true,
  204.         ]);
  205.     }
  206.     /**
  207.      * @Route("/portal/registrierung-erfolgreich", name="customer_registration_success")
  208.      */
  209.     public function registrationSuccess()
  210.     {
  211.         return $this->render('portal/customer/registration_success.html.twig');
  212.     }
  213.     /**
  214.      * @Route("/portal/registrierung-abschliessen/{token}", name="customer_registration_confirmation")
  215.      *
  216.      * @param string $token
  217.      *
  218.      * @return \Symfony\Component\HttpFoundation\Response
  219.      */
  220.     public function registrationConfirmation($token)
  221.     {
  222.         /** @var \App\Entity\User[] $users */
  223.         $users $this->getDoctrine()->getRepository(User::class)->findBy(['confirmationKey' => $token'confirmationType' => User::CONFIRMATION_TYPE_REGISTRATION]);
  224.         if (empty($users)) {
  225.             $success false;
  226.             $this->addFlash('error''Der Bestätigungscode ist ungültig oder wurde bereits verwendet');
  227.         } else {
  228.             $success true;
  229.             $user $users[0];
  230.             $user->setConfirmationKey(null)->setConfirmationType(null)->setIsActive(true);
  231.             $entityManager $this->getDoctrine()->getManager();
  232.             $entityManager->persist($user);
  233.             $entityManager->flush();
  234.         }
  235.         return $this->render('portal/customer/registration_confirmation.html.twig', [
  236.             'success' => $success,
  237.         ]);
  238.     }
  239.     /**
  240.      * @Route("/portal/profil/", name="customer_profile")
  241.      *
  242.      * @return \Symfony\Component\HttpFoundation\Response
  243.      */
  244.     public function profile()
  245.     {
  246.         return $this->render('portal/customer/profile/index.html.twig');
  247.     }
  248.     /**
  249.      * @Route("/portal/profil/persoenliche-daten/", name="customer_profile_data")
  250.      *
  251.      * @param \Symfony\Component\Security\Core\User\UserInterface $user
  252.      * @param \Symfony\Component\HttpFoundation\Request $request
  253.      *
  254.      * @return \Symfony\Component\HttpFoundation\Response
  255.      */
  256.     public function profilePersonalData(UserInterface $userRequest $request)
  257.     {
  258.         /** @var User $user */
  259.         /** @var \App\Repository\CountryRepository $countryRepo */
  260.         $countryRepo $this->getDoctrine()->getRepository(Country::class);
  261.         $formBuilder $this->createFormBuilder($user->getCustomer());
  262.         $form        $formBuilder
  263.             ->add('gender'ChoiceType::class, [
  264.                 'label'    => 'Anrede',
  265.                 'expanded' => true,
  266.                 'choices'  => [
  267.                     'Herr'         => 'm',
  268.                     'Frau'         => 'f',
  269.                     'Keine Angabe' => 'u',
  270.                 ],
  271.             ])
  272.             ->add('firstName'TextType::class, ['label' => 'Vorname'])
  273.             ->add('lastName'TextType::class, ['label' => 'Nachname'])
  274.             ->add('company'TextType::class, ['label' => 'Firma''required' => false])
  275.             ->add('street'TextType::class, ['label' => 'Straße / Hausnr.'])
  276.             ->add('city'TextType::class, ['label' => 'Stadt'])
  277.             ->add('zip'TextType::class, ['label' => 'PLZ'])
  278.             ->add('country'EntityType::class, [
  279.                 'class'             => Country::class,
  280.                 'choice_label'      => 'name',
  281.                 'label'             => 'Land',
  282.                 'choices'           => $countryRepo->getChoices(),
  283.                 'preferred_choices' => $countryRepo->getPreferredCountryChoices(),
  284.             ])
  285.             ->add('phone'TextType::class, ['label' => 'Telefonnummer''required' => false])
  286.             ->add('save'SubmitType::class, ['label' => 'Änderungen speichern'])
  287.             ->getForm();
  288.         $form->handleRequest($request);
  289.         if ($form->isSubmitted() && $form->isValid()) {
  290.             $customer $form->getData();
  291.             $entityManager $this->getDoctrine()->getManager();
  292.             $entityManager->persist($customer);
  293.             $entityManager->flush();
  294.             return $this->redirectToRoute('customer_profile');
  295.         }
  296.         return $this->render('portal/customer/profile/personal_data.html.twig', [
  297.             'form' => $form->createView(),
  298.         ]);
  299.     }
  300.     /**
  301.      * @Route("/portal/profil/zahldaten/", name="customer_profile_payment_data")
  302.      *
  303.      * @param \Symfony\Component\Security\Core\User\UserInterface $user
  304.      * @param \Symfony\Component\HttpFoundation\Request $request
  305.      * @param \App\Service\StripeClient $stripeClient
  306.      *
  307.      * @return \Symfony\Component\HttpFoundation\Response
  308.      *
  309.      * @throws \Stripe\Exception\ApiErrorException
  310.      */
  311.     public function profilePaymentData(UserInterface $userRequest $requestStripeClient $stripeClient)
  312.     {
  313.         /** @var User $user */
  314.         $stripeCustomerId $user->getCustomer()->getStripeCustomer();
  315.         if ($stripeCustomerId !== null) {
  316. //            $stripeCustomer        = $stripeClient->getCustomer($stripeCustomerId);
  317. //            $stripeCustomerSources = $stripeCustomer->sources->data;
  318.             $stripeCustomerSources $stripeClient->getCardsByCustomer($stripeCustomerId);
  319.         } else {
  320. //            $stripeCustomer        = null;
  321.             $stripeCustomerSources = [];
  322.         }
  323.         $formBuilder $this->createFormBuilder();
  324.         $form        $formBuilder
  325.             ->add('type'ChoiceType::class, [
  326.                 'label'       => 'Zahlungsart wählen',
  327.                 'expanded'    => true,
  328.                 'choices'     => [
  329.                     'Kreditkarte' => 'card',
  330. //                    'Lastschrift' => 'sepa',
  331.                 ],
  332.                 'choice_attr' => function ($choiceValue$key$value) {
  333.                     return ['class' => 'payment_type_' strtolower($key)];
  334.                 },
  335.             ])
  336. //            ->add('stripeSource', HiddenType::class)
  337.             ->add('save'SubmitType::class, ['label' => 'Hinzufügen'])
  338.             ->getForm();
  339.         $form->handleRequest($request);
  340.         if ($form->isSubmitted() && $form->isValid()) {
  341. /*
  342.             $stripeSource = $form->get('stripeSource')->getData();
  343.             try {
  344.                 $stripeClient->getSource($stripeSource);
  345.             } catch (\Exception $e) {
  346.                 $this->addFlash('error', 'Ein Fehler ist aufgetreten.');
  347.                 return $this->redirectToRoute('customer_profile_payment_data');
  348.             }
  349. */
  350.             if ($stripeCustomerId === null) {
  351.                 $stripeCustomer $stripeClient->createCustomer($user->getEmail());
  352.                 $stripeCustomerId $stripeCustomer->id;
  353.                 $user->getCustomer()->setStripeCustomer($stripeCustomerId);
  354.                 $entityManager $this->getDoctrine()->getManager();
  355.                 $entityManager->persist($user);
  356.                 $entityManager->flush();
  357.             }
  358.             $setupIntent $stripeClient->createSetupIntent($stripeCustomerId);
  359. /*
  360.             try {
  361.                 $stripeCustomer->sources->create(['source' => $stripeSource]);
  362.             } catch (\Exception $e) {
  363.                 if ($e->getMessage() === 'Your card\'s security code is incorrect.') {
  364.                     $this->addFlash('error', 'Der Sicherheitscode ist nicht korrekt.');
  365.                 } elseif ($e->getMessage() === 'Your card was declined.') {
  366.                     $this->addFlash('error', 'Ihre Karte wurde abgelehnt.');
  367.                 } else {
  368.                     $this->addFlash('error', 'Ein Fehler ist aufgetreten. Bitte prüfen Sie Ihre Eingaben.');
  369.                 }
  370.             }
  371. */
  372.             return $this->redirectToRoute('customer_profile_add_card', [
  373.                 'setupIntentId' => $setupIntent->id,
  374.             ]);
  375.         }
  376.         $sepaSources array_filter($stripeCustomerSources, function ($el) {
  377.             return $el->type === 'sepa_debit';
  378.         });
  379.         $cardSources array_filter($stripeCustomerSources, function ($el) {
  380.             return $el->type === 'card';
  381.         });
  382.         return $this->render('portal/customer/profile/payment_data.html.twig', [
  383.             'form'        => $form->createView(),
  384.             'sepaSources' => $sepaSources,
  385.             'cardSources' => $cardSources,
  386.         ]);
  387.     }
  388.     /**
  389.      * @Route("/portal/profil/zahldaten/kreditkarte-hinzufuegen/{setupIntentId}", name="customer_profile_add_card")
  390.      *
  391.      * @param \Symfony\Component\Security\Core\User\UserInterface $user
  392.      * @param \Symfony\Component\HttpFoundation\Request $request
  393.      * @param \App\Service\StripeClient $stripeClient
  394.      *
  395.      * @param string $setupIntentId
  396.      *
  397.      * @return \Symfony\Component\HttpFoundation\Response
  398.      */
  399.     public function addCard(UserInterface $userRequest $requestStripeClient $stripeClientstring $setupIntentId)
  400.     {
  401.         /** @var User $user */
  402.         if (empty($setupIntentId)) {
  403.             $this->addFlash('error''Ein Fehler ist aufgetreten.');
  404.             return $this->redirectToRoute('customer_profile_payment_data');
  405.         }
  406.         try {
  407.             $setupIntent $stripeClient->getSetupIntent($setupIntentId);
  408.         } catch (ApiErrorException $e) {
  409.             $this->addFlash('error''Ein Fehler ist aufgetreten.');
  410.             return $this->redirectToRoute('customer_profile_payment_data');
  411.         }
  412.         return $this->render('portal/customer/profile/payment_data_add_card.html.twig', [
  413.             'clientSecret' => $setupIntent->client_secret,
  414.         ]);
  415.     }
  416.     /**
  417.      * @Route("/portal/profil/zahldaten/{sourceId}/entfernen/", name="customer_profile_remove_payment_source")
  418.      *
  419.      * @param \Symfony\Component\Security\Core\User\UserInterface $user
  420.      * @param \App\Service\StripeClient $stripeClient
  421.      * @param string $sourceId
  422.      *
  423.      * @return \Symfony\Component\HttpFoundation\RedirectResponse
  424.      */
  425.     public function removePaymentSource(UserInterface $userStripeClient $stripeClientstring $sourceId)
  426.     {
  427.         /** @var User $user */
  428.         $stripeCustomerId $user->getCustomer()->getStripeCustomer();
  429.         if ($stripeCustomerId === null) {
  430.             $this->addFlash('error''Fehler: Zahlungsmethode nicht vorhanden');
  431.             return $this->redirectToRoute('customer_profile_payment_data');
  432.         }
  433.         try {
  434. //            $stripeCustomer = $stripeClient->getCustomer($stripeCustomerId);
  435. //            $stripeCustomer->sources->retrieve($sourceId)->detach();
  436.             $stripeClient->getPaymentMethod($sourceId)->detach();
  437.             $this->addFlash('notice''Zahlungsmethode erfolgreich entfernt');
  438.         } catch (ApiErrorException $e) {
  439.             $this->addFlash('error''Fehler: Zahlungsmethode nicht vorhanden');
  440.         }
  441.         return $this->redirectToRoute('customer_profile_payment_data');
  442.     }
  443.     /**
  444.      * @Route("/portal/profil/passwort/", name="customer_profile_password")
  445.      *
  446.      * @param \Symfony\Component\Security\Core\User\UserInterface $user
  447.      * @param \Symfony\Component\HttpFoundation\Request $request
  448.      * @param \Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface $passwordEncoder
  449.      *
  450.      * @return \Symfony\Component\HttpFoundation\Response
  451.      */
  452.     public function profilePassword(
  453.         UserInterface $user,
  454.         Request $request,
  455.         UserPasswordEncoderInterface $passwordEncoder
  456.     ) {
  457.         /** @var User $user */
  458.         $formBuilder $this->createFormBuilder($user);
  459.         $form        $formBuilder
  460.             ->add('old_password'PasswordType::class, [
  461.                 'mapped' => false,
  462.                 'label'  => 'aktuelles Passwort',
  463.                 'constraints' => [
  464.                     new UserPassword([
  465.                         'message' => 'Das Passwort ist nicht korrekt'
  466.                     ])
  467.                 ]
  468.             ])
  469.             ->add('password'RepeatedType::class, [
  470.                 'type'            => PasswordType::class,
  471.                 'invalid_message' => 'Die Passwörter stimmen nicht überein',
  472.                 'first_options'   => ['label' => 'Neues Passwort wählen'],
  473.                 'second_options'  => ['label' => 'Neues Passwort wiederholen'],
  474.                 'mapped'          => false,
  475.                 'constraints'     => [
  476.                     new NotBlank([
  477.                         'message' => 'Bitte geben Sie ein Passwort ein',
  478.                     ]),
  479.                     new Length([
  480.                         'min'        => 6,
  481.                         'minMessage' => 'Das Passwort muss mindestens {{ limit }} Zeichen lang sein',
  482.                         'maxMessage' => 'Das Passwort überschreitet die zugelassene Länge von {{ limit }} Zeichen',
  483.                         'max'        => 4096,
  484.                     ]),
  485.                 ],
  486.             ])
  487.             ->add('save'SubmitType::class, ['label' => 'Änderungen speichern'])
  488.             ->getForm();
  489.         $form->handleRequest($request);
  490.         if ($form->isSubmitted() && $form->isValid()) {
  491.             $user->setPassword(
  492.                 $passwordEncoder->encodePassword(
  493.                     $user,
  494.                     $form->get('password')->getData()
  495.                 )
  496.             );
  497.             $entityManager $this->getDoctrine()->getManager();
  498.             $entityManager->persist($user);
  499.             $entityManager->flush();
  500.             return $this->redirectToRoute('customer_profile');
  501.         }
  502.         return $this->render('portal/customer/profile/password.html.twig', [
  503.             'form' => $form->createView(),
  504.         ]);
  505.     }
  506.     /**
  507.      * @Route("/portal/passwort-vergessen/", name="customer_forgot_password")
  508.      *
  509.      * @param \Symfony\Component\HttpFoundation\Request $request
  510.      * @param \Symfony\Component\HttpFoundation\Session\Session $session
  511.      * @param \App\Service\Mailer $mailer
  512.      *
  513.      * @return \Symfony\Component\HttpFoundation\Response
  514.      * @throws \Twig_Error_Loader
  515.      * @throws \Twig_Error_Runtime
  516.      * @throws \Twig_Error_Syntax
  517.      */
  518.     public function forgotPassword(Request $request, \Symfony\Component\HttpFoundation\Session\Session $sessionMailer $mailer)
  519.     {
  520.         if ($this->isGranted('ROLE_CUSTOMER')) {
  521.             $session->getFlashBag()->clear();
  522.             return $this->redirectToRoute('portal');
  523.         }
  524.         if ($this->isGranted('ROLE_ADMIN')) {
  525.             $session->getFlashBag()->clear();
  526.             return $this->redirectToRoute('dashboard');
  527.         }
  528.         if (!empty($session->getFlashBag()->peekAll())) {
  529.             return $this->render('portal/customer/forgot-password.html.twig', [
  530.                 'step' => 2,
  531.             ]);
  532.         }
  533.         $formBuilder $this->createFormBuilder();
  534.         $form        $formBuilder
  535.             ->add('email'EmailType::class, [
  536.                 'label'       => 'Ihre E-Mail-Adresse',
  537.                 'constraints' => [
  538.                     new NotBlank([
  539.                         'message' => 'E-Mail-Adresse darf nicht leer sein',
  540.                     ]),
  541.                     new Email([
  542.                         'message' => 'Dies ist keine gültige E-Mail-Adresse',
  543.                     ]),
  544.                 ],
  545.             ])
  546.             ->add('save'SubmitType::class, ['label' => 'Passwort zurücksetzen'])
  547.             ->getForm();
  548.         $form->handleRequest($request);
  549.         if ($form->isSubmitted() && $form->isValid()) {
  550.             /** @var User[] $result */$session->getFlashBag()->clear();
  551.             $result $this->getDoctrine()->getRepository(User::class)->findBy(['email' => $form->get('email')->getData()]);
  552.             if ( ! empty($result)) {
  553.                 $user $result[0];
  554.                 if ( ! $user->getIsActive()) {
  555.                     $this->addFlash('error',
  556.                         'Dieses Konto ist nicht aktiv. Fall Sie sich neu registriert haben, schauen Sie bitte in Ihrem E-Mail-Postfach nach einer Bestätigungsmail für Ihre Registrierung und klicken Sie auf den Bestätigungslink. Bei Fragen oder Problemen stehen wir Ihnen gerne per E-Mail zur Verfügung: <a href="mailto:support@adressermittlung.de">support@adressermittlung.de</a>');
  557.                 } else {
  558.                     if ($user->getConfirmationType() === null || $user->getConfirmationType() === User::CONFIRMATION_TYPE_PASSWORD_RESET) {
  559.                         // generate confirmation token
  560.                         $tokenGenerator = new UriSafeTokenGenerator();
  561.                         $user->setConfirmationKey($tokenGenerator->generateToken());
  562.                         $user->setConfirmationType(User::CONFIRMATION_TYPE_PASSWORD_RESET);
  563.                         $entityManager $this->getDoctrine()->getManager();
  564.                         $entityManager->persist($user);
  565.                         $entityManager->flush();
  566.                         $mailer->sendPortalResetPasswordEmail($user);
  567.                     }
  568.                     $this->addFlash('notice','Eine E-Mail mit Anweisungen zum Zurücksetzen Ihres Passworts wurde an die von Ihnen angegebene E-Mail-Adresse versandt. Bitte prüfen Sie Ihr Postfach.');
  569.                 }
  570.             } else {
  571.                 $this->addFlash('notice','Eine E-Mail mit Anweisungen zum Zurücksetzen Ihres Passworts wurde an die von Ihnen angegebene E-Mail-Adresse versandt. Bitte prüfen Sie Ihr Postfach.');
  572.             }
  573.             return $this->redirectToRoute('customer_forgot_password');
  574.         }
  575.         return $this->render('portal/customer/forgot-password.html.twig', [
  576.             'form' => $form->createView(),
  577.             'step' => 1,
  578.         ]);
  579.     }
  580.     /**
  581.      * @Route("/portal/passwort-aendern/{token}", name="customer_reset_password")
  582.      *
  583.      * @param \Symfony\Component\HttpFoundation\Request $request
  584.      * @param \Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface $passwordEncoder
  585.      * @param string $token
  586.      *
  587.      * @return \Symfony\Component\HttpFoundation\Response
  588.      */
  589.     public function resetPassword(Request $requestUserPasswordEncoderInterface $passwordEncoder$token)
  590.     {
  591.         if ($this->isGranted('ROLE_CUSTOMER')) {
  592.             return $this->redirectToRoute('portal');
  593.         }
  594.         if ($this->isGranted('ROLE_ADMIN')) {
  595.             return $this->redirectToRoute('dashboard');
  596.         }
  597.         /** @var \App\Entity\User[] $users */
  598.         $users $this->getDoctrine()->getRepository(User::class)->findBy(['confirmationKey' => $token'confirmationType' => User::CONFIRMATION_TYPE_PASSWORD_RESET]);
  599.         $viewParams = [];
  600.         if (empty($users)) {
  601.             $viewParams['success'] = false;
  602.             $this->addFlash('error''Der Sicherheitscode ist ungültig oder wurde bereits verwendet');
  603.         } else {
  604.             $viewParams['success'] = true;
  605.             $formBuilder $this->createFormBuilder();
  606.             $form $formBuilder->add('password'RepeatedType::class, [
  607.                 'type'            => PasswordType::class,
  608.                 'invalid_message' => 'Die Passwörter stimmen nicht überein',
  609.                 'first_options'   => ['label' => 'Passwort wählen'],
  610.                 'second_options'  => ['label' => 'Passwort wiederholen'],
  611.                 'constraints'     => [
  612.                     new NotBlank([
  613.                         'message' => 'Bitte geben Sie ein Passwort ein',
  614.                     ]),
  615.                     new Length([
  616.                         'min'        => 6,
  617.                         'minMessage' => 'Das Passwort muss mindestens {{ limit }} Zeichen lang sein',
  618.                         'maxMessage' => 'Das Passwort überschreitet die zugelassene Länge von {{ limit }} Zeichen',
  619.                         'max'        => 4096,
  620.                     ]),
  621.                 ],
  622.             ])
  623.             ->add('save'SubmitType::class, ['label' => 'Passwort ändern'])
  624.             ->getForm();
  625.             $form->handleRequest($request);
  626.             if ($form->isSubmitted() && $form->isValid()) {
  627.                 $user $users[0];
  628.                 $user->setPassword(
  629.                     $passwordEncoder->encodePassword(
  630.                         $user,
  631.                         $form->get('password')->getData()
  632.                     )
  633.                 );
  634.                 $user->setConfirmationKey(null)->setConfirmationType(null)->setIsActive(true);
  635.                 $entityManager $this->getDoctrine()->getManager();
  636.                 $entityManager->persist($user);
  637.                 $entityManager->flush();
  638.                 $this->addFlash('notice''Ihr Passwort wurde erfolgreich geändert. Sie können sich nun mit Ihrem neuen Passwort einloggen.');
  639.                 return $this->redirectToRoute('app_login');
  640.             }
  641.             $viewParams['form'] = $form->createView();
  642.         }
  643.         return $this->render('portal/customer/reset_password.html.twig'$viewParams);
  644.     }
  645. }