3 namespace Rapsys\UserBundle\Controller
;
5 use Rapsys\UserBundle\Utils\Slugger
;
6 use Symfony\Bridge\Twig\Mime\TemplatedEmail
;
7 use Symfony\Bundle\FrameworkBundle\Controller\AbstractController
;
8 use Symfony\Component\DependencyInjection\ContainerInterface
;
9 use Symfony\Component\Form\FormError
;
10 use Symfony\Component\HttpFoundation\Request
;
11 use Symfony\Component\Mailer\Exception\TransportExceptionInterface
;
12 use Symfony\Component\Mailer\MailerInterface
;
13 use Symfony\Component\Mime\NamedAddress
;
14 use Symfony\Component\Routing\Generator\UrlGeneratorInterface
;
15 use Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface
;
16 use Symfony\Component\Security\Http\Authentication\AuthenticationUtils
;
17 use Symfony\Component\Translation\TranslatorInterface
;
19 class DefaultController
extends AbstractController
{
24 protected $translator;
26 public function __construct(ContainerInterface
$container, TranslatorInterface
$translator) {
28 $this->config
= $container->getParameter($this->getAlias());
31 $this->translator
= $translator;
34 public function login(Request
$request, AuthenticationUtils
$authenticationUtils) {
35 //Create the LoginType form and give the proper parameters
36 $form = $this->createForm($this->config
['login']['view']['form'], null, [
37 //Set action to login route name and context
38 'action' => $this->generateUrl($this->config
['route']['login']['name'], $this->config
['route']['login']['context']),
42 //Get the login error if there is one
43 if ($error = $authenticationUtils->getLastAuthenticationError()) {
44 //Get translated error
45 $error = $this->translator
->trans($error->getMessageKey());
47 //Add error message to mail field
48 $form->get('mail')->addError(new FormError($error));
51 //Last username entered by the user
52 if ($lastUsername = $authenticationUtils->getLastUsername()) {
53 $form->get('mail')->setData($lastUsername);
59 $this->config
['login']['view']['name'],
61 ['form' => $form->createView(), 'error' => $error]+
$this->config
['login']['view']['context']
65 public function recover(Request
$request, Slugger
$slugger, MailerInterface
$mailer) {
66 //Create the RecoverType form and give the proper parameters
67 $form = $this->createForm($this->config
['recover']['view']['form'], null, array(
68 //Set action to recover route name and context
69 'action' => $this->generateUrl($this->config
['route']['recover']['name'], $this->config
['route']['recover']['context']),
73 if ($request->isMethod('POST')) {
74 //Refill the fields in case the form is not valid.
75 $form->handleRequest($request);
77 if ($form->isValid()) {
79 $doctrine = $this->getDoctrine();
82 $data = $form->getData();
85 if ($user = $doctrine->getRepository($this->config
['class']['user'])->findOneByMail($data['mail'])) {
87 $mail =& $this->config
['recover']['mail'];
89 //Generate each route route
90 foreach($mail['route'] as $route => $tag) {
91 //Only process defined routes
92 if (empty($mail['context'][$tag]) && !empty($this->config
['route'][$route])) {
93 //Process for recover mail url
94 if ($route == 'recover_mail') {
95 //Prepend recover context with tag
96 $this->config
['route'][$route]['context'] = [
97 'recipient' => $slugger->short($user->getMail()),
98 'hash' => $slugger->hash($user->getPassword())
99 ]+
$this->config
['route'][$route]['context'];
101 //Set the url in context
102 $mail['context'][$tag] = $this->get('router')->generate(
103 $this->config
['route'][$route]['name'],
104 $this->config
['route'][$route]['context'],
105 UrlGeneratorInterface
::ABSOLUTE_URL
112 $mail['context']['recipient_mail'] = $data['mail'];
115 $mail['context']['recipient_name'] = trim($user->getForename().' '.$user->getSurname().($user->getPseudonym()?' ('.$user->getPseudonym().')':''));
117 //Init subject context
118 $subjectContext = [];
120 //Process each context pair
121 foreach($mail['context'] as $k => $v) {
122 //Reinsert each context pair with the key surrounded by %
123 $subjectContext['%'.$k.'%'] = $v;
127 $mail['subject'] = ucfirst($this->translator
->trans($mail['subject'], $subjectContext));
130 $message = (new TemplatedEmail())
132 ->from(new NamedAddress($this->config
['contact']['mail'], $this->config
['contact']['name']))
134 //XXX: remove the debug set in vendor/symfony/mime/Address.php +46
135 ->to(new NamedAddress($mail['context']['recipient_mail'], $mail['context']['recipient_name']))
137 ->subject($mail['subject'])
139 //Set path to twig templates
140 ->htmlTemplate($mail['html'])
141 ->textTemplate($mail['text'])
144 ->context(['subject' => $mail['subject']]+
$mail['context']);
146 //Try sending message
147 //XXX: mail delivery may silently fail
150 $mailer->send($message);
152 //Redirect on the same route with sent=1 to cleanup form
153 #return $this->redirectToRoute('rapsys_user_register', array('sent' => 1));
154 return $this->redirectToRoute($request->get('_route'), ['sent' => 1]+
$request->get('_route_params'));
155 //Catch obvious transport exception
156 } catch(TransportExceptionInterface
$e) {
157 //Add error message mail unreachable
158 $form->get('mail')->addError(new FormError($this->translator
->trans('Account found but unable to contact: %mail%', array('%mail%' => $data['mail']))));
162 //Add error message to mail field
163 $form->get('mail')->addError(new FormError($this->translator
->trans('Unable to find account: %mail%', ['%mail%' => $data['mail']])));
169 return $this->render(
171 $this->config
['recover']['view']['name'],
173 ['form' => $form->createView(), 'sent' => $request->query
->get('sent', 0)]+
$this->config
['recover']['view']['context']
177 public function recoverMail(Request
$request, UserPasswordEncoderInterface
$encoder, Slugger
$slugger, MailerInterface
$mailer, $recipient, $hash) {
178 //Create the RecoverType form and give the proper parameters
179 $form = $this->createForm($this->config
['recover_mail']['view']['form'], null, array(
180 //Set action to recover route name and context
181 'action' => $this->generateUrl($this->config
['route']['recover_mail']['name'], ['recipient' => $recipient, 'hash' => $hash]+
$this->config
['route']['recover_mail']['context']),
186 $doctrine = $this->getDoctrine();
192 if (($user = $doctrine->getRepository($this->config
['class']['user'])->findOneByMail($slugger->unshort($recipient))) && $hash == $slugger->hash($user->getPassword())) {
196 if ($request->isMethod('POST')) {
197 //Refill the fields in case the form is not valid.
198 $form->handleRequest($request);
200 if ($form->isValid()) {
202 $data = $form->getData();
204 //set encoded password
205 $encoded = $encoder->encodePassword($user, $data['password']);
208 $user->setPassword($encoded);
211 $manager = $doctrine->getManager();
214 $manager->persist($user);
220 $mail =& $this->config
['recover_mail']['mail'];
223 $hash = $slugger->hash($encoded);
225 //Generate each route route
226 foreach($mail['route'] as $route => $tag) {
227 //Only process defined routes
228 if (empty($mail['context'][$tag]) && !empty($this->config
['route'][$route])) {
229 //Process for recover mail url
230 if ($route == 'recover_mail') {
231 //Prepend recover context with tag
232 $this->config
['route'][$route]['context'] = [
233 'recipient' => $recipient,
235 ]+
$this->config
['route'][$route]['context'];
237 //Set the url in context
238 $mail['context'][$tag] = $this->get('router')->generate(
239 $this->config
['route'][$route]['name'],
240 $this->config
['route'][$route]['context'],
241 UrlGeneratorInterface
::ABSOLUTE_URL
247 $mail['context']['recipient_mail'] = $user->getMail();
250 $mail['context']['recipient_name'] = trim($user->getForename().' '.$user->getSurname().($user->getPseudonym()?' ('.$user->getPseudonym().')':''));
252 //Init subject context
253 $subjectContext = [];
255 //Process each context pair
256 foreach($mail['context'] as $k => $v) {
257 //Reinsert each context pair with the key surrounded by %
258 $subjectContext['%'.$k.'%'] = $v;
262 $mail['subject'] = ucfirst($this->translator
->trans($mail['subject'], $subjectContext));
265 $message = (new TemplatedEmail())
267 ->from(new NamedAddress($this->config
['contact']['mail'], $this->config
['contact']['name']))
269 //XXX: remove the debug set in vendor/symfony/mime/Address.php +46
270 ->to(new NamedAddress($mail['context']['recipient_mail'], $mail['context']['recipient_name']))
272 ->subject($mail['subject'])
274 //Set path to twig templates
275 ->htmlTemplate($mail['html'])
276 ->textTemplate($mail['text'])
279 ->context(['subject' => $mail['subject']]+
$mail['context']);
281 //Try sending message
282 //XXX: mail delivery may silently fail
285 $mailer->send($message);
287 //Redirect on the same route with sent=1 to cleanup form
288 return $this->redirectToRoute($request->get('_route'), ['recipient' => $recipient, 'hash' => $hash, 'sent' => 1]+
$request->get('_route_params'));
289 //Catch obvious transport exception
290 } catch(TransportExceptionInterface
$e) {
291 //Add error message mail unreachable
292 $form->get('mail')->addError(new FormError($this->translator
->trans('Account password updated but unable to contact: %mail%', array('%mail%' => $mail['context']['recipient_mail']))));
298 //Add error message to mail field
299 $form->get('mail')->addError(new FormError($this->translator
->trans('Unable to find account: %mail%', ['%mail%' => $slugger->unshort($recipient)])));
303 return $this->render(
305 $this->config
['recover_mail']['view']['name'],
307 ['form' => $form->createView(), 'sent' => $request->query
->get('sent', 0), 'notfound' => $notfound]+
$this->config
['recover_mail']['view']['context']
311 public function register(Request
$request, UserPasswordEncoderInterface
$encoder, MailerInterface
$mailer) {
312 //Create the RegisterType form and give the proper parameters
313 $form = $this->createForm($this->config
['register']['view']['form'], null, array(
314 'class_title' => $this->config
['class']['title'],
315 //Set action to register route name and context
316 'action' => $this->generateUrl($this->config
['route']['register']['name'], $this->config
['route']['register']['context']),
320 if ($request->isMethod('POST')) {
321 // Refill the fields in case the form is not valid.
322 $form->handleRequest($request);
324 if ($form->isValid()) {
326 $data = $form->getData();
329 $mail =& $this->config
['register']['mail'];
331 //Generate each route route
332 foreach($mail['route'] as $route => $tag) {
333 if (empty($mail['context'][$tag]) && !empty($this->config
['route'][$route])) {
334 $mail['context'][$tag] = $this->get('router')->generate(
335 $this->config
['route'][$route]['name'],
336 $this->config
['route'][$route]['context'],
337 UrlGeneratorInterface
::ABSOLUTE_URL
343 $mail['context']['recipient_mail'] = $data['mail'];
346 $mail['context']['recipient_name'] = trim($data['forename'].' '.$data['surname'].($data['pseudonym']?' ('.$data['pseudonym'].')':''));
348 //Init subject context
349 $subjectContext = [];
351 //Process each context pair
352 foreach($mail['context'] as $k => $v) {
353 //Reinsert each context pair with the key surrounded by %
354 $subjectContext['%'.$k.'%'] = $v;
358 $mail['subject'] = ucfirst($this->translator
->trans($mail['subject'], $subjectContext));
361 $message = (new TemplatedEmail())
363 ->from(new NamedAddress($this->config
['contact']['mail'], $this->config
['contact']['name']))
365 //XXX: remove the debug set in vendor/symfony/mime/Address.php +46
366 ->to(new NamedAddress($mail['context']['recipient_mail'], $mail['context']['recipient_name']))
368 ->subject($mail['subject'])
370 //Set path to twig templates
371 ->htmlTemplate($mail['html'])
372 ->textTemplate($mail['text'])
375 ->context(['subject' => $mail['subject']]+
$mail['context']);
378 $doctrine = $this->getDoctrine();
381 $manager = $doctrine->getManager();
384 $reflection = new \
ReflectionClass($this->config
['class']['user']);
387 $user = $reflection->newInstance();
389 $user->setMail($data['mail']);
390 $user->setPseudonym($data['pseudonym']);
391 $user->setForename($data['forename']);
392 $user->setSurname($data['surname']);
393 $user->setPhone($data['phone']);
394 $user->setPassword($encoder->encodePassword($user, $data['password']));
395 $user->setActive(true);
396 $user->setTitle($data['title']);
398 //XXX: For now there is no point in setting a role at subscription
399 //TODO: see if we can't modify group constructor to set role directly from args
400 //XXX: see vendor/symfony/symfony/src/Symfony/Component/Security/Core/Role/Role.php
401 #$user->addGroup($doctrine->getRepository($this->config['class']['group'])->findOneByRole('ROLE_USER'));
403 $user->setCreated(new \
DateTime('now'));
404 $user->setUpdated(new \
DateTime('now'));
407 $manager->persist($user);
409 //Try saving in database
414 //Try sending message
415 //XXX: mail delivery may silently fail
418 $mailer->send($message);
420 //Redirect on the same route with sent=1 to cleanup form
421 #return $this->redirectToRoute('rapsys_user_register', array('sent' => 1));
422 return $this->redirectToRoute($request->get('_route'), ['sent' => 1]+
$request->get('_route_params'));
423 //Catch obvious transport exception
424 } catch(TransportExceptionInterface
$e) {
425 //Add error message mail unreachable
426 $form->get('mail')->addError(new FormError($this->translator
->trans('Account created but unable to contact: %mail%', array('%mail%' => $data['mail']))));
428 //Catch double subscription
429 } catch (\Doctrine\DBAL\Exception\UniqueConstraintViolationException
$e) {
430 //Add error message mail already exists
431 $form->get('mail')->addError(new FormError($this->translator
->trans('Account already exists: %mail%', ['%mail%' => $data['mail']])));
437 return $this->render(
439 $this->config
['register']['view']['name'],
441 ['form' => $form->createView(), 'sent' => $request->query
->get('sent', 0)]+
$this->config
['register']['view']['context']
448 public function getAlias() {
449 return 'rapsys_user';