1 <?php
declare(strict_types
=1);
4 * This file is part of the Rapsys UserBundle package.
6 * (c) Raphaël Gertz <symfony@rapsys.eu>
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
12 namespace Rapsys\UserBundle\Controller
;
14 use Doctrine\DBAL\Exception\UniqueConstraintViolationException
;
15 use Symfony\Bridge\Twig\Mime\TemplatedEmail
;
16 use Symfony\Component\Form\FormError
;
17 use Symfony\Component\HttpFoundation\Request
;
18 use Symfony\Component\HttpFoundation\Response
;
19 use Symfony\Component\HttpKernel\Exception\BadRequestHttpException
;
20 use Symfony\Component\Mailer\Exception\TransportExceptionInterface
;
21 use Symfony\Component\Mime\Address
;
22 use Symfony\Component\Routing\Generator\UrlGeneratorInterface
;
23 use Symfony\Component\Security\Http\Authentication\AuthenticationUtils
;
28 class DefaultController
extends AbstractController
{
30 * Confirm account from mail link
32 * @param Request $request The request
33 * @param string $mail The shorted mail address
34 * @param string $hash The hashed password
35 * @return Response The response
37 public function confirm(Request
$request, $mail, $hash): Response
{
39 if ($hash != $this->slugger
->hash($mail)) {
41 throw new BadRequestHttpException($this->translator
->trans('Invalid %field% field: %value%', ['%field%' => 'hash', '%value%' => $hash]));
45 $mail = $this->slugger
->unshort($smail = $mail);
48 if (filter_var($mail, FILTER_VALIDATE_EMAIL
) === false) {
50 //XXX: prevent slugger reverse engineering by not displaying decoded mail
51 throw new BadRequestHttpException($this->translator
->trans('Invalid %field% field: %value%', ['%field%' => 'mail', '%value%' => $smail]));
54 //Without existing registrant
55 if (!($user = $this->doctrine
->getRepository($this->config
['class']['user'])->findOneByMail($mail))) {
56 //Add error message mail already exists
57 //XXX: prevent slugger reverse engineering by not displaying decoded mail
58 $this->addFlash('error', $this->translator
->trans('Account %mail% do not exists', ['%mail%' => $smail]));
60 //Redirect to register view
61 return $this->redirectToRoute($this->config
['route']['register']['name'], ['mail' => $smail, 'field' => $sfield = $this->slugger
->serialize([]), 'hash' => $this->slugger
->hash($smail.$sfield)]+
$this->config
['route']['register']['context']);
65 $user->setActive(true);
68 $this->manager
->persist($user);
71 $this->manager
->flush();
73 //Add error message mail already exists
74 $this->addFlash('notice', $this->translator
->trans('Your account has been activated'));
76 //Redirect to user view
77 return $this->redirectToRoute($this->config
['route']['edit']['name'], ['mail' => $smail, 'hash' => $this->slugger
->hash($smail)]+
$this->config
['route']['edit']['context']);
81 * Edit account by shorted mail
83 * @param Request $request The request
84 * @param string $mail The shorted mail address
85 * @param string $hash The hashed password
86 * @return Response The response
88 public function edit(Request
$request, $mail, $hash): Response
{
90 if ($hash != $this->slugger
->hash($mail)) {
92 throw new BadRequestHttpException($this->translator
->trans('Invalid %field% field: %value%', ['%field%' => 'hash', '%value%' => $hash]));
96 $mail = $this->slugger
->unshort($smail = $mail);
98 //With existing subscriber
99 if (empty($user = $this->doctrine
->getRepository($this->config
['class']['user'])->findOneByMail($mail))) {
101 //XXX: prevent slugger reverse engineering by not displaying decoded mail
102 throw $this->createNotFoundException($this->translator
->trans('Unable to find account %mail%', ['%mail%' => $smail]));
105 //Prevent access when not admin, user is not guest and not currently logged user
106 if (!$this->isGranted('ROLE_ADMIN') && $user != $this->getUser() || !$this->isGranted('IS_AUTHENTICATED_FULLY')) {
107 //Throw access denied
108 //XXX: prevent slugger reverse engineering by not displaying decoded mail
109 throw $this->createAccessDeniedException($this->translator
->trans('Unable to access user: %mail%', ['%mail%' => $smail]));
112 //Create the RegisterType form and give the proper parameters
113 $edit = $this->createForm($this->config
['edit']['view']['edit'], $user, [
114 //Set action to register route name and context
115 'action' => $this->generateUrl($this->config
['route']['edit']['name'], ['mail' => $smail, 'hash' => $this->slugger
->hash($smail)]+
$this->config
['route']['edit']['context']),
117 'civility_class' => $this->config
['class']['civility'],
118 //Set civility default
119 'civility_default' => $this->doctrine
->getRepository($this->config
['class']['civility'])->findOneByTitle($this->config
['default']['civility']),
121 'mail' => $this->isGranted('ROLE_ADMIN'),
126 ]+
$this->config
['edit']['field']);
129 if ($this->isGranted('ROLE_ADMIN')) {
130 //Create the LoginType form and give the proper parameters
131 $reset = $this->createForm($this->config
['edit']['view']['reset'], $user, [
132 //Set action to register route name and context
133 'action' => $this->generateUrl($this->config
['route']['edit']['name'], ['mail' => $smail, 'hash' => $this->slugger
->hash($smail)]+
$this->config
['route']['edit']['context']),
141 if ($request->isMethod('POST')) {
142 //Refill the fields in case the form is not valid.
143 $reset->handleRequest($request);
145 //With reset submitted and valid
146 if ($reset->isSubmitted() && $reset->isValid()) {
148 $data = $reset->getData();
151 $data->setPassword($this->hasher
->encodePassword($data, $data->getPassword()));
154 $this->manager
->persist($data);
156 //Flush to get the ids
157 $this->manager
->flush();
160 $this->addFlash('notice', $this->translator
->trans('Account %mail% password updated', ['%mail%' => $mail = $data->getMail()]));
162 //Redirect to cleanup the form
163 return $this->redirectToRoute($this->config
['route']['edit']['name'], ['mail' => $smail = $this->slugger
->short($mail), 'hash' => $this->slugger
->hash($smail)]+
$this->config
['route']['edit']['context']);
168 $this->config
['edit']['view']['context']['reset'] = $reset->createView();
172 if ($request->isMethod('POST')) {
173 //Refill the fields in case the form is not valid.
174 $edit->handleRequest($request);
176 //With edit submitted and valid
177 if ($edit->isSubmitted() && $edit->isValid()) {
179 $data = $edit->getData();
182 $this->manager
->persist($data);
184 //Try saving in database
186 //Flush to get the ids
187 $this->manager
->flush();
190 $this->addFlash('notice', $this->translator
->trans('Account %mail% updated', ['%mail%' => $mail = $data->getMail()]));
192 //Redirect to cleanup the form
193 return $this->redirectToRoute($this->config
['route']['edit']['name'], ['mail' => $smail = $this->slugger
->short($mail), 'hash' => $this->slugger
->hash($smail)]+
$this->config
['route']['edit']['context']);
194 //Catch double slug or mail
195 } catch (UniqueConstraintViolationException
$e) {
196 //Add error message mail already exists
197 $this->addFlash('error', $this->translator
->trans('Account %mail% already exists', ['%mail%' => $data->getMail()]));
201 //XXX: prefer a reset on login to force user unspam action
202 } elseif (!$this->isGranted('ROLE_ADMIN')) {
204 $this->addFlash('notice', $this->translator
->trans('To change your password login with your mail and any password then follow the procedure'));
208 return $this->render(
210 $this->config
['edit']['view']['name'],
212 ['edit' => $edit->createView(), 'sent' => $request->query
->get('sent', 0)]+
$this->config
['edit']['view']['context']
219 * @param Request $request The request
220 * @param AuthenticationUtils $authenticationUtils The authentication utils
221 * @param string $mail The shorted mail address
222 * @param string $hash The hashed password
223 * @return Response The response
225 public function login(Request
$request, AuthenticationUtils
$authenticationUtils, $mail, $hash): Response
{
226 //Create the LoginType form and give the proper parameters
227 $login = $this->createForm($this->config
['login']['view']['form'], null, [
228 //Set action to login route name and context
229 'action' => $this->generateUrl($this->config
['route']['login']['name'], $this->config
['route']['login']['context']),
230 //Disable repeated password
231 'password_repeated' => false,
240 if (!empty($mail) && !empty($hash)) {
242 if ($hash != $this->slugger
->hash($mail)) {
244 throw new BadRequestHttpException($this->translator
->trans('Invalid %field% field: %value%', ['%field%' => 'hash', '%value%' => $hash]));
248 $mail = $this->slugger
->unshort($smail = $mail);
251 if (filter_var($mail, FILTER_VALIDATE_EMAIL
) === false) {
253 throw new BadRequestHttpException($this->translator
->trans('Invalid %field% field: %value%', ['%field%' => 'mail', '%value%' => $smail]));
257 $login->get('mail')->setData($mail);
258 //Last username entered by the user
259 } elseif ($lastUsername = $authenticationUtils->getLastUsername()) {
260 $login->get('mail')->setData($lastUsername);
263 //Get the login error if there is one
264 if ($error = $authenticationUtils->getLastAuthenticationError()) {
265 //Get translated error
266 $error = $this->translator
->trans($error->getMessageKey());
268 //Add error message to mail field
269 $login->get('mail')->addError(new FormError($error));
271 //Create the LoginType form and give the proper parameters
272 $recover = $this->createForm($this->config
['recover']['view']['form'], null, [
273 //Set action to recover route name and context
274 'action' => $this->generateUrl($this->config
['route']['recover']['name'], $this->config
['route']['recover']['context']),
281 //Get recover mail entity
282 $recover->get('mail')
283 //Set mail from login form
284 ->setData($login->get('mail')->getData())
286 ->addError(new FormError($this->translator
->trans('Use this form to recover your account')));
288 //Add recover form to context
289 $context['recover'] = $recover->createView();
292 $this->addFlash('notice', $this->translator
->trans('To change your password login with your mail and any password then follow the procedure'));
296 return $this->render(
298 $this->config
['login']['view']['name'],
300 ['login' => $login->createView()]+
$context+
$this->config
['login']['view']['context']
307 * @param Request $request The request
308 * @param string $mail The shorted mail address
309 * @param string $pass The shorted password
310 * @param string $hash The hashed password
311 * @return Response The response
313 public function recover(Request
$request, $mail, $pass, $hash): Response
{
314 //Without mail, pass and hash
315 if (empty($mail) && empty($pass) && empty($hash)) {
316 //Create the LoginType form and give the proper parameters
317 $form = $this->createForm($this->config
['recover']['view']['form'], null, [
318 //Set action to recover route name and context
319 'action' => $this->generateUrl($this->config
['route']['recover']['name'], $this->config
['route']['recover']['context']),
326 if ($request->isMethod('POST')) {
327 //Refill the fields in case the form is not valid.
328 $form->handleRequest($request);
330 if ($form->isValid()) {
332 $data = $form->getData();
334 //Find user by data mail
335 if ($user = $this->doctrine
->getRepository($this->config
['class']['user'])->findOneByMail($data['mail'])) {
337 $recoverMail =& $this->config
['recover']['mail'];
340 $mail = $this->slugger
->short($user->getMail());
343 $pass = $this->slugger
->hash($user->getPassword());
345 //Generate each route route
346 foreach($this->config
['recover']['route'] as $route => $tag) {
347 //Only process defined routes
348 if (!empty($this->config
['route'][$route])) {
349 //Process for recover mail url
350 if ($route == 'recover') {
351 //Set the url in context
352 $recoverMail['context'][$tag] = $this->router
->generate(
353 $this->config
['route'][$route]['name'],
354 //Prepend recover context with tag
358 'hash' => $this->slugger
->hash($mail.$pass)
359 ]+
$this->config
['route'][$route]['context'],
360 UrlGeneratorInterface
::ABSOLUTE_URL
367 $recoverMail['context']['recipient_mail'] = $user->getMail();
370 $recoverMail['context']['recipient_name'] = $user->getRecipientName();
372 //Init subject context
373 $subjectContext = $this->slugger
->flatten(array_replace_recursive($this->config
['recover']['view']['context'], $recoverMail['context']), null, '.', '%', '%');
376 $recoverMail['subject'] = ucfirst($this->translator
->trans($recoverMail['subject'], $subjectContext));
379 $message = (new TemplatedEmail())
381 ->from(new Address($this->config
['contact']['mail'], $this->config
['contact']['title']))
383 //XXX: remove the debug set in vendor/symfony/mime/Address.php +46
384 ->to(new Address($recoverMail['context']['recipient_mail'], $recoverMail['context']['recipient_name']))
386 ->subject($recoverMail['subject'])
388 //Set path to twig templates
389 ->htmlTemplate($recoverMail['html'])
390 ->textTemplate($recoverMail['text'])
393 //XXX: require recursive merge to avoid loosing subkeys
394 //['subject' => $recoverMail['subject']]+$recoverMail['context']+$this->config['recover']['view']['context']
395 ->context(array_replace_recursive($this->config
['recover']['view']['context'], $recoverMail['context'], ['subject' => $recoverMail['subject']]));
397 //Try sending message
398 //XXX: mail delivery may silently fail
401 $this->mailer
->send($message);
403 //Redirect on the same route with sent=1 to cleanup form
404 return $this->redirectToRoute($request->get('_route'), ['sent' => 1]+
$request->get('_route_params'));
405 //Catch obvious transport exception
406 } catch(TransportExceptionInterface
$e) {
407 //Add error message mail unreachable
408 $form->get('mail')->addError(new FormError($this->translator
->trans('Account found but unable to contact: %mail%', array('%mail%' => $data['mail']))));
412 //Add error message to mail field
413 $form->get('mail')->addError(new FormError($this->translator
->trans('Unable to find account %mail%', ['%mail%' => $data['mail']])));
419 return $this->render(
421 $this->config
['recover']['view']['name'],
423 ['form' => $form->createView(), 'sent' => $request->query
->get('sent', 0)]+
$this->config
['recover']['view']['context']
428 if ($hash != $this->slugger
->hash($mail.$pass)) {
430 throw new BadRequestHttpException($this->translator
->trans('Invalid %field% field: %value%', ['%field%' => 'hash', '%value%' => $hash]));
434 $mail = $this->slugger
->unshort($smail = $mail);
437 if (filter_var($mail, FILTER_VALIDATE_EMAIL
) === false) {
439 //XXX: prevent slugger reverse engineering by not displaying decoded mail
440 throw new BadRequestHttpException($this->translator
->trans('Invalid %field% field: %value%', ['%field%' => 'mail', '%value%' => $smail]));
443 //With existing subscriber
444 if (empty($user = $this->doctrine
->getRepository($this->config
['class']['user'])->findOneByMail($mail))) {
446 //XXX: prevent slugger reverse engineering by not displaying decoded mail
447 throw $this->createNotFoundException($this->translator
->trans('Unable to find account %mail%', ['%mail%' => $smail]));
450 //With unmatched pass
451 if ($pass != $this->slugger
->hash($user->getPassword())) {
453 //XXX: prevent use of outdated recover link
454 throw $this->createNotFoundException($this->translator
->trans('Outdated recover link'));
457 //Create the LoginType form and give the proper parameters
458 $form = $this->createForm($this->config
['recover']['view']['form'], $user, [
459 //Set action to recover route name and context
460 'action' => $this->generateUrl($this->config
['route']['recover']['name'], ['mail' => $smail, 'pass' => $pass, 'hash' => $hash]+
$this->config
['route']['recover']['context']),
467 if ($request->isMethod('POST')) {
468 //Refill the fields in case the form is not valid.
469 $form->handleRequest($request);
471 if ($form->isValid()) {
473 $data = $form->getData();
475 //Set encoded password
476 $encoded = $this->hasher
->encodePassword($user, $user->getPassword());
479 $pass = $this->slugger
->hash($encoded);
482 $user->setPassword($encoded);
485 $this->manager
->persist($user);
488 $this->manager
->flush();
491 $this->addFlash('notice', $this->translator
->trans('Account %mail% password updated', ['%mail%' => $mail]));
493 //Redirect to user login
494 return $this->redirectToRoute($this->config
['route']['login']['name'], ['mail' => $smail, 'hash' => $this->slugger
->hash($smail)]+
$this->config
['route']['login']['context']);
499 return $this->render(
501 $this->config
['recover']['view']['name'],
503 ['form' => $form->createView(), 'sent' => $request->query
->get('sent', 0)]+
$this->config
['recover']['view']['context']
508 * Register an account
510 * @param Request $request The request
511 * @param string $mail The shorted mail address
512 * @param string $field The serialized then shorted form field array
513 * @param string $hash The hashed serialized field array
514 * @return Response The response
516 public function register(Request
$request, $mail, $field, $hash): Response
{
518 if (!empty($_POST['register']['mail'])) {
520 $this->logger
->emergency(
521 $this->translator
->trans(
522 'register: mail=%mail% locale=%locale% confirm=%confirm%',
524 '%mail%' => $postMail = $_POST['register']['mail'],
525 '%locale%' => $request->getLocale(),
526 '%confirm%' => $this->router
->generate(
527 $this->config
['route']['confirm']['name'],
528 //Prepend subscribe context with tag
530 'mail' => $postSmail = $this->slugger
->short($postMail),
531 'hash' => $this->slugger
->hash($postSmail)
532 ]+
$this->config
['route']['confirm']['context'],
533 UrlGeneratorInterface
::ABSOLUTE_URL
540 //With mail and field
541 if (!empty($field) && !empty($hash)) {
543 if ($hash != $this->slugger
->hash($mail.$field)) {
545 throw new BadRequestHttpException($this->translator
->trans('Invalid %field% field: %value%', ['%field%' => 'hash', '%value%' => $hash]));
551 $mail = $this->slugger
->unshort($smail = $mail);
554 if (filter_var($mail, FILTER_VALIDATE_EMAIL
) === false) {
556 //XXX: prevent slugger reverse engineering by not displaying decoded mail
557 throw new BadRequestHttpException($this->translator
->trans('Invalid %field% field: %value%', ['%field%' => 'mail', '%value%' => $smail]));
560 //With existing registrant
561 if ($existing = $this->doctrine
->getRepository($this->config
['class']['user'])->findOneByMail($mail)) {
562 //With disabled existing
563 if ($existing->isDisabled()) {
565 $response = $this->render(
567 $this->config
['register']['view']['name'],
569 ['title' => $this->translator
->trans('Access denied'), 'disabled' => 1]+
$this->config
['register']['view']['context']
573 $response->setStatusCode(403);
577 //With unactivated existing
578 } elseif (!$existing->isActivated()) {
580 $activateMail =& $this->config
['register']['mail'];
582 //Generate each route route
583 foreach($this->config
['register']['route'] as $route => $tag) {
584 //Only process defined routes
585 if (!empty($this->config
['route'][$route])) {
586 //Process for confirm url
587 if ($route == 'confirm') {
588 //Set the url in context
589 $activateMail['context'][$tag] = $this->router
->generate(
590 $this->config
['route'][$route]['name'],
591 //Prepend subscribe context with tag
593 'mail' => $smail = $this->slugger
->short($existing->getMail()),
594 'hash' => $this->slugger
->hash($smail)
595 ]+
$this->config
['route'][$route]['context'],
596 UrlGeneratorInterface
::ABSOLUTE_URL
603 $activateMail['context']['recipient_mail'] = $existing->getMail();
606 $activateMail['context']['recipient_name'] = $existing->getRecipientName();
608 //Init subject context
609 $subjectContext = $this->slugger
->flatten(array_replace_recursive($this->config
['register']['view']['context'], $activateMail['context']), null, '.', '%', '%');
612 $activateMail['subject'] = ucfirst($this->translator
->trans($activateMail['subject'], $subjectContext));
615 $message = (new TemplatedEmail())
617 ->from(new Address($this->config
['contact']['mail'], $this->config
['contact']['title']))
619 //XXX: remove the debug set in vendor/symfony/mime/Address.php +46
620 ->to(new Address($activateMail['context']['recipient_mail'], $activateMail['context']['recipient_name']))
622 ->subject($activateMail['subject'])
624 //Set path to twig templates
625 ->htmlTemplate($activateMail['html'])
626 ->textTemplate($activateMail['text'])
629 ->context(['subject' => $activateMail['subject']]+
$activateMail['context']);
631 //Try sending message
632 //XXX: mail delivery may silently fail
635 $this->mailer
->send($message);
636 //Catch obvious transport exception
637 } catch(TransportExceptionInterface
$e) {
638 //Add error message mail unreachable
639 $this->addFlash('error', $this->translator
->trans('Account %mail% tried activate but unable to contact', ['%mail%' => $existing->getMail()]));
643 $routeParams = $request->get('_route_params');
645 //Remove mail, field and hash from route params
646 unset($routeParams['mail'], $routeParams['field'], $routeParams['hash']);
648 //Redirect on the same route with sent=1 to cleanup form
649 return $this->redirectToRoute($request->get('_route'), ['sent' => 1]+
$routeParams);
652 //Add error message mail already exists
653 $this->addFlash('warning', $this->translator
->trans('Account %mail% already exists', ['%mail%' => $existing->getMail()]));
655 //Redirect to user view
656 return $this->redirectToRoute(
657 $this->config
['route']['edit']['name'],
659 'mail' => $smail = $this->slugger
->short($existing->getMail()),
660 'hash' => $this->slugger
->hash($smail)
661 ]+
$this->config
['route']['edit']['context']
672 //Unshort then unserialize field
673 $field = $this->slugger
->unserialize($sfield = $field);
675 } catch (\Error
|\Exception
$e) {
677 throw new BadRequestHttpException($this->translator
->trans('Invalid %field% field: %value%', ['%field%' => 'field', '%value%' => $field]), $e);
680 //With non array field
681 if (!is_array($field)) {
683 throw new BadRequestHttpException($this->translator
->trans('Invalid %field% field: %value%', ['%field%' => 'field', '%value%' => $field]));
685 //Without field and hash
698 $reflection = new \
ReflectionClass($this->config
['class']['user']);
701 $user = $reflection->newInstance(strval($mail));
703 //Create the RegisterType form and give the proper parameters
704 $form = $this->createForm($this->config
['register']['view']['form'], $user, $field+
[
705 //Set action to register route name and context
706 'action' => $this->generateUrl($this->config
['route']['register']['name'], ['mail' => $smail, 'field' => $sfield, 'hash' => $hash]+
$this->config
['route']['register']['context']),
708 'civility_class' => $this->config
['class']['civility'],
709 //Set civility default
710 'civility_default' => $this->doctrine
->getRepository($this->config
['class']['civility'])->findOneByTitle($this->config
['default']['civility']),
715 ]+
$this->config
['register']['field']);
717 if ($request->isMethod('POST')) {
718 //Refill the fields in case the form is not valid.
719 $form->handleRequest($request);
721 if ($form->isValid()) {
723 $data = $form->getData();
725 //With existing registrant
726 if ($this->doctrine
->getRepository($this->config
['class']['user'])->findOneByMail($mail = $data->getMail())) {
727 //Add error message mail already exists
728 $this->addFlash('warning', $this->translator
->trans('Account %mail% already exists', ['%mail%' => $mail]));
730 //Redirect to user view
731 return $this->redirectToRoute(
732 $this->config
['route']['edit']['name'],
734 'mail' => $smail = $this->slugger
->short($mail),
735 'hash' => $this->slugger
->hash($smail)
736 ]+
$this->config
['route']['edit']['context']
741 $registerMail =& $this->config
['register']['mail'];
744 $user->setPassword($this->hasher
->encodePassword($user, $user->getPassword()));
747 $this->manager
->persist($user);
749 //Iterate on default group
750 foreach($this->config
['default']['group'] as $i => $groupTitle) {
752 if (($group = $this->doctrine
->getRepository($this->config
['class']['group'])->findOneByTitle($groupTitle))) {
754 //XXX: see vendor/symfony/security-core/Role/Role.php
755 $user->addGroup($group);
759 //XXX: consider missing group as fatal
760 throw new \
Exception(sprintf('Group from rapsys_user.default.group[%d] not found by title: %s', $i, $groupTitle));
764 //Generate each route route
765 foreach($this->config
['register']['route'] as $route => $tag) {
766 //Only process defined routes
767 if (!empty($this->config
['route'][$route])) {
768 //Process for confirm url
769 if ($route == 'confirm') {
770 //Set the url in context
771 $registerMail['context'][$tag] = $this->router
->generate(
772 $this->config
['route'][$route]['name'],
773 //Prepend subscribe context with tag
775 'mail' => $smail = $this->slugger
->short($data->getMail()),
776 'hash' => $this->slugger
->hash($smail)
777 ]+
$this->config
['route'][$route]['context'],
778 UrlGeneratorInterface
::ABSOLUTE_URL
785 $registerMail['context']['recipient_mail'] = $data->getMail();
788 $registerMail['context']['recipient_name'] = $data->getRecipientName();
790 //Init subject context
791 $subjectContext = $this->slugger
->flatten(array_replace_recursive($this->config
['register']['view']['context'], $registerMail['context']), null, '.', '%', '%');
794 $registerMail['subject'] = ucfirst($this->translator
->trans($registerMail['subject'], $subjectContext));
797 $message = (new TemplatedEmail())
799 ->from(new Address($this->config
['contact']['mail'], $this->config
['contact']['title']))
801 //XXX: remove the debug set in vendor/symfony/mime/Address.php +46
802 ->to(new Address($registerMail['context']['recipient_mail'], $registerMail['context']['recipient_name']))
804 ->subject($registerMail['subject'])
806 //Set path to twig templates
807 ->htmlTemplate($registerMail['html'])
808 ->textTemplate($registerMail['text'])
811 ->context(['subject' => $registerMail['subject']]+
$registerMail['context']);
813 //Try saving in database
816 $this->manager
->flush();
818 //Add error message mail already exists
819 $this->addFlash('notice', $this->translator
->trans('Your account has been created'));
821 //Try sending message
822 //XXX: mail delivery may silently fail
825 $this->mailer
->send($message);
827 //Redirect on the same route with sent=1 to cleanup form
828 return $this->redirectToRoute($request->get('_route'), ['sent' => 1]+
$request->get('_route_params'));
829 //Catch obvious transport exception
830 } catch(TransportExceptionInterface
$e) {
831 //Add error message mail unreachable
832 $form->get('mail')->addError(new FormError($this->translator
->trans('Account %mail% tried subscribe but unable to contact', ['%mail%' => $data->getMail()])));
834 //Catch double subscription
835 } catch (UniqueConstraintViolationException
$e) {
836 //Add error message mail already exists
837 $this->addFlash('error', $this->translator
->trans('Account %mail% already exists', ['%mail%' => $mail]));
843 return $this->render(
845 $this->config
['register']['view']['name'],
847 ['form' => $form->createView(), 'sent' => $request->query
->get('sent', 0)]+
$this->config
['register']['view']['context']