<?php
namespace App\Controller;
use App\Entity\Contenu;
use App\Entity\Niveau;
use App\Entity\Profil;
use App\Entity\Univers;
use App\Entity\User;
use App\Form\LoginType;
use App\Repository\ContenuRepository;
use App\Service\Email;
use App\Service\NiveauService;
use App\Service\Search;
use Doctrine\ORM\EntityManagerInterface;
use Exception;
use Knp\Component\Pager\PaginatorInterface;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Form\Extension\Core\Type\EmailType;
use Symfony\Component\Form\Extension\Core\Type\TextareaType;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\Session\SessionInterface;
use Symfony\Component\RateLimiter\RateLimiterFactory;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
use Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface;
use Symfony\Component\Security\Http\Authentication\AuthenticationUtils;
use Symfony\Component\Security\Http\Event\InteractiveLoginEvent;
use Symfony\Contracts\Translation\TranslatorInterface;
class HomeController extends AbstractController
{
/**
* @Route("/", name="home")
* @param SessionInterface $session
* @param ContenuRepository $contenuRepository
* @return Response
*/
public function index(SessionInterface $session, ContenuRepository $contenuRepository)
{
$user = $this->getUser();
$profil = ($user instanceof User) ? $session->get('profil', $user->getProfil()) : null;
$em = $this->getDoctrine()->getManager();
$contenusALaUne = $em->getRepository(Contenu::class)->getPin($user);
$videoALaUne = $em->getRepository(Contenu::class)->getPinVideo($user);
$derniersContenus = $contenuRepository->getByProfilNiveau($user, null, 10, null, false, true, 'article', $contenusALaUne);
$nextContenus = $contenuRepository->getByProfilNiveau($user, null, 10, 10);
$hasMore = count($nextContenus) > 0;
$urlBarVideo = $em->getRepository(Niveau::class)->findOneBy(['name' => 'Bar à vidéos', 'type' => 'video']);
return $this->render('home/index.html.twig', [
'pin' => $contenusALaUne,
'pin2' => $videoALaUne ? $videoALaUne[0] : null,
'derniers_contenus' => $derniersContenus,
'home' => true,
'has_more' => $hasMore,
'niveauBarVideo' => $urlBarVideo
]);
}
/**
* @param SessionInterface $session
* @param NiveauService $niveauService
* @return Response
*/
public function navbar(SessionInterface $session, NiveauService $niveauService)
{
$em = $this->getDoctrine()->getManager();
$stack = $this->get('request_stack');
$masterRequest = $stack->getMasterRequest();
$user = $this->getUser();
//$profil = ($user instanceof User) ? $session->get('profil', $user->getProfil()) : null;
$em->getConfiguration()->addCustomHydrationMode('tree', 'Gedmo\Tree\Hydrator\ORM\TreeObjectHydrator');
$niveaux = $em->getRepository(Niveau::class)->createQueryBuilder('n')
->select('n')
->leftJoin('n.univers', 'u')
->andWhere('u.id = :uid')
->setParameter('uid', $this->getUser()->getUnivers())
->addOrderBy('n.root, n.lft', 'ASC')
->andWhere('n.root = 1')
->andWhere('n.parent IS NOT NULL')
->getQuery()
->setHint(\Doctrine\ORM\Query::HINT_INCLUDE_META_COLUMNS, true)
->getResult('tree');
$path = $masterRequest->getPathInfo();
//$path = str_replace(['article', 'produit', 'formation'], '', $path);
$path = trim($path, '/');
return $this->render('navbar.html.twig', [
'niveaux' => $niveaux,
'path' => $path,
'empty' => $niveauService->getNiveaux($this->getUser(), $niveaux)
]);
}
/**
* @Route("/login", name="login", methods="GET|POST")
* @param AuthenticationUtils $authenticationUtils
* @return Response
*/
public function login(AuthenticationUtils $authenticationUtils, ParameterBagInterface $parameterBag)
{
$form = $this->createForm(LoginType::class);
$error = $authenticationUtils->getLastAuthenticationError();
$lastUsername = $authenticationUtils->getLastUsername();
return $this->render('home/login.html.twig', [
'form' => $form->createView(),
'last_username' => $lastUsername,
'error' => $error,
'urlSaml' => 'https://' . $parameterBag->get('SAML_AUTH_HOST') . '/saml/login'
]);
}
/**
* @Route("/premiere-connexion/{hash}", name="first_login", methods="GET")
* @param Request $request
* @param SessionInterface $session
* @param TokenStorageInterface $tokenStorage
* @param EventDispatcherInterface $eventDispatcher
* @param string $hash
* @return \Symfony\Component\HttpFoundation\RedirectResponse
*/
public function first_login(Request $request, SessionInterface $session, TokenStorageInterface $tokenStorage, EventDispatcherInterface $eventDispatcher, string $hash)
{
$user = $this->getDoctrine()->getManager()->getRepository(User::class)->findOneBy([
'password' => '$argon2i' . base64_decode($hash),
]);
if ($user) {
$token = new UsernamePasswordToken($user, null, 'main', $user->getRoles());
$tokenStorage->setToken($token);
$session->set('_security_main', serialize($token));
$event = new InteractiveLoginEvent($request, $token);
$eventDispatcher->dispatch($event, 'security.interactive_login');
}
return $this->redirectToRoute('home');
}
/**
* @Route("/sso/{hash}", name="sso", methods="GET")
* @param Request $request
* @param SessionInterface $session
* @param TokenStorageInterface $tokenStorage
* @param EventDispatcherInterface $eventDispatcher
* @param string $hash
* @return \Symfony\Component\HttpFoundation\RedirectResponse
* @throws \Doctrine\ORM\NonUniqueResultException
*/
public function sso(Request $request, SessionInterface $session, TokenStorageInterface $tokenStorage, EventDispatcherInterface $eventDispatcher, string $hash)
{
$user = $this->getDoctrine()->getManager()->getRepository(User::class)->createQueryBuilder('u')
->andWhere('SHA2(u.email, 256) = :hash')
->andWhere('u.isActive = 1')
->setParameter('hash', $hash)
->getQuery()
->getOneOrNullResult();
if ($user) {
$token = new UsernamePasswordToken($user, null, 'main', $user->getRoles());
$tokenStorage->setToken($token);
$session->set('_security_main', serialize($token));
$event = new InteractiveLoginEvent($request, $token);
$eventDispatcher->dispatch($event, 'security.interactive_login');
}
return $this->redirectToRoute('home');
}
/**
* @Route("/deconnexion", name="logout")
* @return Response
*/
public function logout()
{
return $this->render('home/login.html.twig');
}
/**
* @Route("/recherche", name="search", methods={"GET"})
* @param Request $request
* @param Search $searchService
* @param PaginatorInterface $paginator
* @return Response
* @throws Exception
*/
public function search(Request $request, Search $searchService, PaginatorInterface $paginator)
{
$keywordSearch = $request->query->get('search', null);
$resultats = $searchService->getResultats($this->getUser(), $keywordSearch, $request->getLocale());
$qty = $request->query->getInt('qty', 10);
$paginatorArticle = $paginator->paginate($resultats['contenu']['articles'], $request->query->getInt('page_article', 1), $qty, ['pageParameterName' => 'page_article']);
$paginatorProduct = $paginator->paginate($resultats['contenu']['products'], $request->query->getInt('page_produit', 1), $qty, ['pageParameterName' => 'page_produit']);
$paginatorVideo = $paginator->paginate($resultats['contenu']['videos'], $request->query->getInt('page_video', 1), $qty, ['pageParameterName' => 'page_video']);
$paginatorArticle->setCustomParameters(['align' => 'center']);
$paginatorProduct->setCustomParameters(['align' => 'center']);
$paginatorVideo->setCustomParameters(['align' => 'center']);
$paginatorArticle->setParam('active', 'nav-article-tab');
$paginatorProduct->setParam('active', 'nav-product-tab');
$paginatorVideo->setParam('active', 'nav-video-tab');
return $this->render('search/search.html.twig', [
'paginatorArticle' => $paginatorArticle,
'paginatorProduct' => $paginatorProduct,
'paginatorVideo' => $paginatorVideo,
'qty' => $qty,
'search' => $keywordSearch,
'resultats' => $resultats
]);
}
/**
* @Route("/switch-role", name="switch_profil", methods={"GET","POST"})
* @param Request $request
* @param SessionInterface $session
* @return Response
*/
public function switchRole(Request $request, SessionInterface $session, EntityManagerInterface $em)
{
/** @var User $user */
$user = $this->getUser();
$univers = $em->getRepository(Univers::class)->findAll();
$form = $this->createFormBuilder($user, ['action' => $this->generateUrl('switch_profil'),])
->add('univers', EntityType::class, [
'class' => Univers::class,
'choices' => [
$univers[2],
$univers[1],
$univers[4],
$univers[3],
$univers[5],
$univers[0]
],
'data' => $user->getUnivers() ?? $user->getPreferedUnivers(),
// 'placeholder' => 'all.univers',
'expanded' => false,
'multiple' => false,
'attr' => [
'class' => 'select2',
'data-parent' => '',
]
])->getForm();;
$form->handleRequest($request);
if ($form->isSubmitted()) {
if ($user->getProfil()->getEntite()->getCanSwitch()) {
$univers = $form->get('univers')->getData();
$user->setUnivers($univers);
$em->persist($user);
$em->flush();
}
return $this->redirect($request->headers->get('referer', $this->generateUrl('home')));
}
return $this->render('user/switch_role.html.twig', [
'user' => $user,
'form' => $form->createView(),
]);
}
/**
* @Route("/mot-de-passe-oublie", name="forgot_password")
* @param Request $request
* @param UserPasswordEncoderInterface $passwordEncoder
* @param TranslatorInterface $translator
* @param Email $emailService
* @return \Symfony\Component\HttpFoundation\RedirectResponse|Response
*/
public function forgotPassword(Request $request, UserPasswordEncoderInterface $passwordEncoder, TranslatorInterface $translator, Email $emailService)
{
$form = $this->createFormBuilder(null, [
'action' => $this->generateUrl('forgot_password')
])
->add('email', EmailType::class, [
'required' => true
])
->getForm();
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$em = $this->getDoctrine()->getManager();
$user = $em->getRepository(User::class)->findOneBy(['email' => $form->getData()['email']]);
if ($user) {
$tempPassword = User::generatePassword();
$password = $passwordEncoder->encodePassword($user, $tempPassword);
$user->setPassword($password);
$user->setIsTemporaryPassword(true);
$em->persist($user);
$em->flush();
$subject = $translator->trans('email.forgot_password.subject');
$template = $this->getParameter('MC_TEMPLATE_LOST_PASSWORD');
$emailService->send($subject, [
'USER_FIRSTNAME' => $user->getFirstname(),
'USER_LASTNAME' => $user->getLastname(),
'USER_LOGIN' => $tempPassword,
'USER_EMAIL' => $user->getEmail(),
'URL_LOGIN' => $this->generateUrl('login', [], UrlGeneratorInterface::ABSOLUTE_URL),
'URL' => $this->generateUrl('login', [], UrlGeneratorInterface::ABSOLUTE_URL)
], $user, $template);
$this->addFlash('success', 'flash.login.password_sent');
} else {
$this->addFlash('danger', 'flash.user.not_found');
}
return $this->redirectToRoute('home');
}
return $this->render('home/forgot_password.html.twig', ['form' => $form->createView()]);
}
/**
* @Route("/assistance", name="help_customer", methods={"GET", "POST"})
* @param Request $request
* @param Email $emailService
* @param TranslatorInterface $translator
* @return Response
*/
public function assistance(
Request $request,
Email $emailService,
TranslatorInterface $translator,
RateLimiterFactory $assistanceFormSubmitLimiter
) {
$user = $this->getUser();
$typeAssist = (!$user) ? [
'assistance.metier' => 'M',
'assistance.technique' => 'T'
] : [
'assistance.metier' => 'M',
'assistance.technique' => 'T',
];
$form = $this->createFormBuilder(null, [
'action' => $this->generateUrl('help_customer'),
'label' => false
])->getForm();
if (!$user) {
$form->add('email', EmailType::class, [
'required' => true,
'label' => 'user.email'
]);
}
$form->add('type', ChoiceType::class, [
'label' => 'assistance.type',
'choices' => $typeAssist,
'required' => true
])
->add('question', TextareaType::class, [
'required' => true,
'label' => 'assistance.question',
]);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
// Rate limiter pour l'assistance
$limiter = $assistanceFormSubmitLimiter->create($request->getClientIp());
if (false === $limiter->consume()->isAccepted()) {
// On fait semblant que ça a marché pour qu'un attaquant potentiel soit content de lui
$this->addFlash('success', $translator->trans('flash.assistance.sent'));
$referer = $request->headers->get('referer');
return $this->redirect($referer);
}
$ask_type = $form->get('type')->getData();
$ask_question = $form->get('question')->getData();
$ask_email = $this->getUser() ? $this->getUser()->getEmail() : $form->get('email')->getData();
if ($ask_type == 'M' && ($emailAdress = $this->getParameter('EMAIL_ASSISTANCE_METIER')) && ($template = $this->getParameter('MC_TEMPLATE_ASSISTANCE_METIER'))) {
// Mail assistance métier
$subject = $translator->trans('email.assistance_metier.subject');
$vars = [
'USER_FIRSTNAME' => $user ? $user->getFirstName() : 'Inconnu',
'USER_LASTNAME' => $user ? $user->getLastName() : ' ',
'USER_TEXT' => $ask_question,
'USER_EMAIL' => $ask_email,
];
if ($emailService->send($subject, $vars, $emailAdress, $template)) {
$this->addFlash('success', $translator->trans('flash.assistance.sent'));
}
} elseif ($ask_type == 'F' && ($emailAdress = $this->getParameter('EMAIL_ASSISTANCE_FINANCIERE')) && ($template = $this->getParameter('MC_TEMPLATE_ASSISTANCE_FINANCIERE'))) {
// Mail assistance financière
$subject = $translator->trans('email.assistance_financiere.subject');
$vars = [
'USER_FIRSTNAME' => $user ? $user->getFirstName() : 'Inconnu',
'USER_LASTNAME' => $user ? $user->getLastName() : ' ',
'USER_TEXT' => $ask_question,
'USER_EMAIL' => $ask_email,
];
if ($emailService->send($subject, $vars, $emailAdress, $template)) {
$this->addFlash('success', $translator->trans('flash.assistance.sent'));
}
} elseif ($emailAdress = $this->getParameter('EMAIL_ASSISTANCE_TECHNIQUE')) {
$subject = $translator->trans('email.assistance_technique.subject');
if ($emailService->send($subject, [], $emailAdress, null, $ask_email . ' demande : ' . "\r\n" . $ask_question)) {
$this->addFlash('success', $translator->trans('flash.assistance.sent'));
}
}
$referer = $request->headers->get('referer');
return $this->redirect($referer);
}
return $this->render('home/help_customer.html.twig', ['form' => $form->createView()]);
}
/**
* @Route("/load/home/articles/{page}", name="load_article", defaults={"page" : 1})
* @param Request $request
* @param SessionInterface $session
* @param ContenuRepository $contenuRepository
* @param int $page
* @return Response
*/
public function load(Request $request, SessionInterface $session, ContenuRepository $contenuRepository, $page = 1)
{
/** @param Profil $profil */
$profil = $session->get('profil', $this->getUser()->getProfil());
$next = $contenuRepository->getByProfilNiveau($this->getUser(), null, 10, 10 * ($page - 1), false, true, 'article');
$nextContenus = $contenuRepository->getByProfilNiveau($this->getUser(), null, 10, 10 * $page, false, true, 'article');
$hasMore = count($nextContenus) > 0;
return $this->render('home/next_contenus.html.twig', [
'derniers_contenus' => $next,
'home' => true,
'page' => $page,
'sum' => $request->get('sum', 0),
'has_more' => $hasMore,
]);
}
/**
* @Route("/change_locale/{locale}", name="change_locale")
*/
public function changeLocale($locale, Request $request)
{
// On stocke la langue dans la session
$request->getSession()->set('_locale', $locale);
// On revient sur la page précédente
return $this->redirect($request->get('referer'));
}
}