<?php
namespace App\Controller;
use App\Repository\ReviewFormRepository;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\HttpFoundation\Session\SessionInterface;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\BinaryFileResponse;
use Symfony\Component\HttpFoundation\StreamedResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\PasswordHasher\Hasher\UserPasswordHasherInterface;
use Symfony\Component\Routing\Annotation\Route;
use App\Repository\UsersRepository;
use Doctrine\ORM\EntityManagerInterface;
use DateTime;
use App\Repository\QuestionRepository;
use App\Repository\DimensionRepository;
use App\Repository\EmployeeRepository;
use App\Entity\Users;
use App\Entity\ReviewForm;
use App\Entity\Session;
use App\Entity\Reponse;
use App\Entity\Employee;
class HomeController extends AbstractController
{
public function __construct(
QuestionRepository $questionRepository,
DimensionRepository $dimensionRepository,
ReviewFormRepository $reviewFormRepository,
EmployeeRepository $employeeRepository,
EntityManagerInterface $em
)
{
$this->questionRepository = $questionRepository;
$this->dimensionRepository = $dimensionRepository;
$this->reviewFormRepository = $reviewFormRepository;
$this->employeeRepository = $employeeRepository;
$this->em = $em;
}
// Contrôleur Symfony
#[Route(path: '/', name: 'index')]
public function index(Request $request): Response
{
$lang = $request->query->get('_locale', $request->getSession()->get('_locale', 'fr'));
$request->getSession()->set('_locale', $lang);
$reviewForm = $this->reviewFormRepository->findFormWithDimensionsAndQuestionsByLang('8b6cf598-7f27-11ef-9d7f-1d1f43f3f908', $lang);
return $this->render('index.html.twig', [
'reviewForm' => $reviewForm
]);
}
#[Route('/change-langage/{params}', name: 'change_language')]
public function changeLangage($params, RequestStack $requestStack, SessionInterface $session): Response
{
// Liste des langues valides
$validLocales = ['en', 'fr', 'nl'];
// Vérifier si la langue est valide, sinon utiliser 'en' comme langue par défaut
if (!in_array($params, $validLocales)) {
$params = 'en';
}
// Stocker la langue sélectionnée dans la session
$session->set('_locale', $params);
// Récupérer la requête actuelle
$request = $requestStack->getCurrentRequest();
$previousUrl = $request->headers->get('referer'); // URL du référent (page précédente)
return $this->redirectToRoute('index');
// Ajouter ou mettre à jour le paramètre de langue dans l'URL de la page précédente
$urlComponents = parse_url($previousUrl);
parse_str($urlComponents['query'] ?? '', $query);
$query['_locale'] = $params;
$urlComponents['query'] = http_build_query($query);
// Reconstruire l'URL complète avec le paramètre de langue ajouté
$newUrl = $urlComponents['scheme'] . '://' . $urlComponents['host'] . ($urlComponents['path'] ?? '') . '?' . $urlComponents['query'];
// Rediriger vers l'URL modifiée avec la nouvelle langue
return new RedirectResponse($newUrl);
}
#[Route(path: '/form/{lang}/{formId}', name: 'form')]
public function form($lang, $formId): Response
{
$reviewForm = $this->reviewFormRepository->findFormWithDimensionsAndQuestionsByLang($formId, $lang);
return $this->render('home.html.twig', [
'reviewForm' => $reviewForm
]);
}
#[Route(path: '/send-form', name: 'send_form')]
public function sendForm(Request $request): Response
{
$reviewId = trim((string) $request->get('review', ''));
$lang = strtolower((string) $request->get('lang', 'fr'));
$review = $reviewId !== ''
? $this->reviewFormRepository->findFormWithDimensionsAndQuestionsByLang($reviewId, $lang)
: null;
if (!$review instanceof ReviewForm) {
return new JsonResponse([
'errors' => [
'review' => 'Le formulaire demandé est introuvable.'
]
], 404);
}
$fieldErrors = $this->validateRequiredFields($request);
if (!empty($fieldErrors)) {
return new JsonResponse([
'errors' => $fieldErrors
], 400);
}
$responses = json_decode((string) $request->get('questionData', '[]'), true);
if (!is_array($responses)) {
return new JsonResponse([
'errors' => [
'questionData' => 'Les réponses au questionnaire sont invalides.'
]
], 400);
}
$scoreError = $this->validateScoreConstraints($review, $responses);
if ($scoreError !== null) {
return new JsonResponse([
'errors' => [
'score_rule' => $scoreError
]
], 400);
}
$session = new Session();
$session->setEmployee(null);
$session->setCreatedAt(new \DateTime('now'));
$session->setEmail((string) $request->get('email'));
$fullName = trim(sprintf(
'%s %s',
(string) $request->get('firstName', ''),
(string) $request->get('name', '')
));
$session->setName($fullName !== '' ? $fullName : (string) $request->get('firstName', ''));
$session->setMessage($request->get('message'));
$session->setReviewForm($review);
$session->setLang($lang);
$demographics = [
'region' => $request->get('region'),
'province' => $request->get('province'),
'country' => $request->get('country'),
'gender' => $request->get('gender'),
'age_range' => $request->get('age_range'),
'education_level' => $request->get('education_level'),
'industry' => $request->get('industry'),
'employment_status' => $request->get('employment_status'),
'contract_type' => $request->get('contract_type'),
'working_time' => $request->get('working_time'),
'work_mode' => $request->get('work_mode'),
'commute_time' => $request->get('commute_time'),
'work_language' => $request->get('work_language'),
'management' => $request->get('management'),
'health_status' => $request->get('health_status'),
'job_level' => $request->get('job_level'),
'sector_type' => $request->get('sector_type'),
'org_size' => $request->get('org_size'),
'years_experience' => $request->get('years_experience'),
'tenure' => $request->get('tenure'),
];
$session->setDemographics($demographics);
$employee = $this->employeeRepository->findOneBy(['email' => $request->get('email')]);
if ($employee) {
$session->setEmployee($employee);
}
$responseByQuestionId = [];
foreach ($responses as $response) {
if (!is_array($response) || !isset($response['id'])) {
continue;
}
$responseByQuestionId[(int) $response['id']] = $response;
}
foreach ($review->getDimensions() as $dimension) {
foreach ($dimension->getQuestions() as $question) {
$response = $responseByQuestionId[$question->getId()] ?? null;
if (!$response) {
continue;
}
$reponse = new Reponse();
$reponse->setQuestion($question);
$reponse->setSession($session);
$reponse->setQuantity((int)($response['score'] ?? 0));
$reponse->setMinimalQuantity((int)($response['score_minimal'] ?? 0));
$reponse->setDeleted(false);
$reponse->setComment($response['comment'] ?? null);
$this->em->persist($reponse);
}
}
$session->setStatus(1);
$this->em->persist($session);
$this->em->flush();
return new JsonResponse(['ok' => true]);
}
private function validateRequiredFields(Request $request): array
{
$requiredFields = [
'firstName' => 'Prénom',
'name' => 'Nom',
'email' => 'Email',
'region' => 'Région de résidence',
'gender' => 'Sexe',
'age_range' => 'Âge',
'education_level' => 'Niveau d’études',
'industry' => 'Secteur d’activité',
'employment_status' => 'Statut professionnel actuel',
'job_level' => 'Niveau de fonction',
'sector_type' => 'Secteur d’appartenance',
'org_size' => 'Taille de l’organisation',
'years_experience' => 'Années d’expérience professionnelle',
'tenure' => 'Ancienneté dans l’entreprise actuelle',
'working_time' => 'Temps de travail',
'work_mode' => 'Mode de travail principal',
'commute_time' => 'Temps de trajet quotidien',
'work_language' => 'Langue principale au travail',
'management' => 'Responsabilité hiérarchique',
];
$errors = [];
foreach ($requiredFields as $field => $label) {
$value = trim((string) $request->get($field, ''));
if ($value === '') {
$errors[$field] = sprintf('Le champ « %s » est obligatoire.', $label);
continue;
}
if ($field === 'email' && !filter_var($value, FILTER_VALIDATE_EMAIL)) {
$errors[$field] = 'Veuillez saisir une adresse email valide.';
}
}
return $errors;
}
private function validateScoreConstraints(ReviewForm $review, array $responses): ?string
{
$responseByQuestionId = [];
$responsePositionByQuestionId = [];
foreach ($responses as $position => $response) {
if (!is_array($response) || !isset($response['id'])) {
continue;
}
$questionId = (int) $response['id'];
$responseByQuestionId[$questionId] = $response;
$responsePositionByQuestionId[$questionId] = $position;
}
$dimensions = $review->getDimensions()->toArray();
usort($dimensions, static function ($left, $right) {
return ($left->getSorting() ?? 0) <=> ($right->getSorting() ?? 0);
});
foreach ($dimensions as $dimension) {
$questions = $dimension->getQuestions()->toArray();
$questionCount = count($questions);
if ($questionCount < 3 || $questionCount % 3 !== 0) {
return sprintf('La structure de la dimension "%s" est invalide.', $dimension->getName());
}
usort($questions, static function ($left, $right) use ($responsePositionByQuestionId) {
$leftPosition = $responsePositionByQuestionId[$left->getId()] ?? PHP_INT_MAX;
$rightPosition = $responsePositionByQuestionId[$right->getId()] ?? PHP_INT_MAX;
if ($leftPosition === $rightPosition) {
return ($left->getId() ?? 0) <=> ($right->getId() ?? 0);
}
return $leftPosition <=> $rightPosition;
});
for ($index = 0; $index < $questionCount; $index += 3) {
$groupQuestions = array_slice($questions, $index, 3);
if (count($groupQuestions) < 3) {
return sprintf('Les réponses de la dimension "%s" sont incomplètes.', $dimension->getName());
}
$checks = [
'score' => [
'label' => 'score actuel',
'subScores' => [],
'globalScore' => null,
],
'score_minimal' => [
'label' => 'score souhaité',
'subScores' => [],
'globalScore' => null,
],
];
foreach ($checks as $field => &$check) {
$subScores = [];
$globalScore = null;
foreach ($groupQuestions as $groupIndex => $question) {
$response = $responseByQuestionId[$question->getId()] ?? null;
$value = is_array($response) ? ($response[$field] ?? null) : null;
if ($value === null || $value === '') {
return sprintf('Les réponses de la dimension "%s" sont incomplètes.', $dimension->getName());
}
$score = (int) $value;
if ($groupIndex < 2) {
$subScores[] = $score;
} else {
$globalScore = $score;
}
}
if (count($subScores) < 2 || $globalScore === null) {
return sprintf('Les réponses de la dimension "%s" sont incomplètes.', $dimension->getName());
}
$min = min($subScores);
$max = max($subScores);
if (($min === $max && $globalScore !== $min) || ($min !== $max && ($globalScore < $min || $globalScore > $max))) {
if ($min === $max) {
return sprintf(
'Le %s de la dimension "%s" doit être égal à %d.',
$check['label'],
$dimension->getName(),
$min
);
}
return sprintf(
'Le %s de la dimension "%s" doit être compris entre %d et %d.',
$check['label'],
$dimension->getName(),
$min,
$max
);
}
}
unset($check);
}
}
return null;
}
}