]> Raphaƫl G. Git Repositories - userbundle/blob - Controller/DefaultController.php
Fix requirement
[userbundle] / Controller / DefaultController.php
1 <?php
2
3 namespace Rapsys\UserBundle\Controller;
4
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;
18
19 class DefaultController extends AbstractController {
20 //Config array
21 protected $config;
22
23 //Translator instance
24 protected $translator;
25
26 public function __construct(ContainerInterface $container, TranslatorInterface $translator) {
27 //Retrieve config
28 $this->config = $container->getParameter($this->getAlias());
29
30 //Set the translator
31 $this->translator = $translator;
32 }
33
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']),
39 'method' => 'POST'
40 ]);
41
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());
46
47 //Add error message to mail field
48 $form->get('mail')->addError(new FormError($error));
49 }
50
51 //Last username entered by the user
52 if ($lastUsername = $authenticationUtils->getLastUsername()) {
53 $form->get('mail')->setData($lastUsername);
54 }
55
56 //Render view
57 return $this->render(
58 //Template
59 $this->config['login']['view']['name'],
60 //Context
61 ['form' => $form->createView(), 'error' => $error]+$this->config['login']['view']['context']
62 );
63 }
64
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']),
70 'method' => 'POST'
71 ));
72
73 if ($request->isMethod('POST')) {
74 //Refill the fields in case the form is not valid.
75 $form->handleRequest($request);
76
77 if ($form->isValid()) {
78 //Get doctrine
79 $doctrine = $this->getDoctrine();
80
81 //Set data
82 $data = $form->getData();
83
84 //Try to find user
85 if ($user = $doctrine->getRepository($this->config['class']['user'])->findOneByMail($data['mail'])) {
86 //Set mail shortcut
87 $mail =& $this->config['recover']['mail'];
88
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'];
100 }
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
106 );
107
108 }
109 }
110
111 //Set recipient_name
112 $mail['context']['recipient_mail'] = $data['mail'];
113
114 //Set recipient_name
115 $mail['context']['recipient_name'] = trim($user->getForename().' '.$user->getSurname().($user->getPseudonym()?' ('.$user->getPseudonym().')':''));
116
117 //Init subject context
118 $subjectContext = [];
119
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;
124 }
125
126 //Translate subject
127 $mail['subject'] = ucfirst($this->translator->trans($mail['subject'], $subjectContext));
128
129 //Create message
130 $message = (new TemplatedEmail())
131 //Set sender
132 ->from(new NamedAddress($this->config['contact']['mail'], $this->config['contact']['name']))
133 //Set recipient
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']))
136 //Set subject
137 ->subject($mail['subject'])
138
139 //Set path to twig templates
140 ->htmlTemplate($mail['html'])
141 ->textTemplate($mail['text'])
142
143 //Set context
144 ->context(['subject' => $mail['subject']]+$mail['context']);
145
146 //Try sending message
147 //XXX: mail delivery may silently fail
148 try {
149 //Send message
150 $mailer->send($message);
151
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']))));
159 }
160 //Accout not found
161 } else {
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']])));
164 }
165 }
166 }
167
168 //Render view
169 return $this->render(
170 //Template
171 $this->config['recover']['view']['name'],
172 //Context
173 ['form' => $form->createView(), 'sent' => $request->query->get('sent', 0)]+$this->config['recover']['view']['context']
174 );
175 }
176
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']),
182 'method' => 'POST'
183 ));
184
185 //Get doctrine
186 $doctrine = $this->getDoctrine();
187
188 //Init not found
189 $notfound = 1;
190
191 //Retrieve user
192 if (($user = $doctrine->getRepository($this->config['class']['user'])->findOneByMail($slugger->unshort($recipient))) && $hash == $slugger->hash($user->getPassword())) {
193 //User was found
194 $notfound = 0;
195
196 if ($request->isMethod('POST')) {
197 //Refill the fields in case the form is not valid.
198 $form->handleRequest($request);
199
200 if ($form->isValid()) {
201 //Set data
202 $data = $form->getData();
203
204 //set encoded password
205 $encoded = $encoder->encodePassword($user, $data['password']);
206
207 //Set user password
208 $user->setPassword($encoded);
209
210 //Get manager
211 $manager = $doctrine->getManager();
212
213 //Persist user
214 $manager->persist($user);
215
216 //Send to database
217 $manager->flush();
218
219 //Set mail shortcut
220 $mail =& $this->config['recover_mail']['mail'];
221
222 //Regen hash
223 $hash = $slugger->hash($encoded);
224
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,
234 'hash' => $hash
235 ]+$this->config['route'][$route]['context'];
236 }
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
242 );
243 }
244 }
245
246 //Set recipient_name
247 $mail['context']['recipient_mail'] = $user->getMail();
248
249 //Set recipient_name
250 $mail['context']['recipient_name'] = trim($user->getForename().' '.$user->getSurname().($user->getPseudonym()?' ('.$user->getPseudonym().')':''));
251
252 //Init subject context
253 $subjectContext = [];
254
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;
259 }
260
261 //Translate subject
262 $mail['subject'] = ucfirst($this->translator->trans($mail['subject'], $subjectContext));
263
264 //Create message
265 $message = (new TemplatedEmail())
266 //Set sender
267 ->from(new NamedAddress($this->config['contact']['mail'], $this->config['contact']['name']))
268 //Set recipient
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']))
271 //Set subject
272 ->subject($mail['subject'])
273
274 //Set path to twig templates
275 ->htmlTemplate($mail['html'])
276 ->textTemplate($mail['text'])
277
278 //Set context
279 ->context(['subject' => $mail['subject']]+$mail['context']);
280
281 //Try sending message
282 //XXX: mail delivery may silently fail
283 try {
284 //Send message
285 $mailer->send($message);
286
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']))));
293 }
294 }
295 }
296 //Accout not found
297 } else {
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)])));
300 }
301
302 //Render view
303 return $this->render(
304 //Template
305 $this->config['recover_mail']['view']['name'],
306 //Context
307 ['form' => $form->createView(), 'sent' => $request->query->get('sent', 0), 'notfound' => $notfound]+$this->config['recover_mail']['view']['context']
308 );
309 }
310
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']),
317 'method' => 'POST'
318 ));
319
320 if ($request->isMethod('POST')) {
321 // Refill the fields in case the form is not valid.
322 $form->handleRequest($request);
323
324 if ($form->isValid()) {
325 //Set data
326 $data = $form->getData();
327
328 //Set mail shortcut
329 $mail =& $this->config['register']['mail'];
330
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
338 );
339 }
340 }
341
342 //Set recipient_name
343 $mail['context']['recipient_mail'] = $data['mail'];
344
345 //Set recipient_name
346 $mail['context']['recipient_name'] = trim($data['forename'].' '.$data['surname'].($data['pseudonym']?' ('.$data['pseudonym'].')':''));
347
348 //Init subject context
349 $subjectContext = [];
350
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;
355 }
356
357 //Translate subject
358 $mail['subject'] = ucfirst($this->translator->trans($mail['subject'], $subjectContext));
359
360 //Create message
361 $message = (new TemplatedEmail())
362 //Set sender
363 ->from(new NamedAddress($this->config['contact']['mail'], $this->config['contact']['name']))
364 //Set recipient
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']))
367 //Set subject
368 ->subject($mail['subject'])
369
370 //Set path to twig templates
371 ->htmlTemplate($mail['html'])
372 ->textTemplate($mail['text'])
373
374 //Set context
375 ->context(['subject' => $mail['subject']]+$mail['context']);
376
377 //Get doctrine
378 $doctrine = $this->getDoctrine();
379
380 //Get manager
381 $manager = $doctrine->getManager();
382
383 //Init reflection
384 $reflection = new \ReflectionClass($this->config['class']['user']);
385
386 //Create new user
387 $user = $reflection->newInstance();
388
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']);
397
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'));
402
403 $user->setCreated(new \DateTime('now'));
404 $user->setUpdated(new \DateTime('now'));
405
406 //Persist user
407 $manager->persist($user);
408
409 //Try saving in database
410 try {
411 //Send to database
412 $manager->flush();
413
414 //Try sending message
415 //XXX: mail delivery may silently fail
416 try {
417 //Send message
418 $mailer->send($message);
419
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']))));
427 }
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']])));
432 }
433 }
434 }
435
436 //Render view
437 return $this->render(
438 //Template
439 $this->config['register']['view']['name'],
440 //Context
441 ['form' => $form->createView(), 'sent' => $request->query->get('sent', 0)]+$this->config['register']['view']['context']
442 );
443 }
444
445 /**
446 * {@inheritdoc}
447 */
448 public function getAlias() {
449 return 'rapsys_user';
450 }
451 }