src/Controller/AppelAProjetController.php line 113

Open in your IDE?
  1. <?php
  2. namespace App\Controller;
  3. use App\Entity\AppelAProjet;
  4. use App\Entity\Project;
  5. use App\Entity\QuestionnaireResponse;
  6. use App\Entity\SignatureCharte;
  7. use App\Entity\User;
  8. use App\Form\AppelAProjetType;
  9. use App\Repository\AppelAProjetRepository;
  10. use App\Repository\ProjectRepository;
  11. use App\Repository\SignatureCharteRepository;
  12. use App\Repository\UserProjectRepository;
  13. use App\Repository\UserRepository;
  14. use App\Service\ProjectNumberService;
  15. use App\Service\ProjectUserService;
  16. use App\Service\QuestionnaireHandlerService;
  17. use Doctrine\Persistence\ManagerRegistry;
  18. use Symfony\Bridge\Twig\Mime\TemplatedEmail;
  19. use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
  20. use Symfony\Component\HttpFoundation\JsonResponse;
  21. use Symfony\Component\HttpFoundation\Request;
  22. use Symfony\Component\HttpFoundation\Response;
  23. use Symfony\Component\HttpFoundation\ResponseHeaderBag;
  24. use Symfony\Component\Mailer\MailerInterface;
  25. use Symfony\Component\Routing\Annotation\Route;
  26. use Symfony\Component\Security\Core\Exception\AccessDeniedException;
  27. use Vich\UploaderBundle\Handler\DownloadHandler;
  28. /**
  29.  * @Route("/appel_a_projet")
  30.  */
  31. class AppelAProjetController extends AbstractController
  32. {
  33.     /**
  34.      * @Route("/", name="appel_a_projet_index", methods={"GET"})
  35.      */
  36.     public function index(AppelAProjetRepository $appelAProjetRepository): Response
  37.     {
  38.         if ($this->isGranted('ROLE_ADMIN_GIRCI')) {
  39.             return $this->render('appel_a_projet/index.html.twig', [
  40.                 'appel_a_projets' => $appelAProjetRepository->findBy([], ['id' => 'DESC']),
  41.             ]);
  42.         } elseif ($this->isGranted('ROLE_COORDONNATEUR') || $this->isGranted('ROLE_METHODO')) {
  43.             return $this->render('appel_a_projet/index.html.twig', [
  44.                 'appel_a_projets' => $appelAProjetRepository->findPublished(),
  45.             ]);
  46. //        } elseif ($this->getUser() === null) {
  47. //            // utilisateur anonyme
  48. //            return $this->render('appel_a_projet/index.html.twig', [
  49. //                'appel_a_projets' => $appelAProjetRepository->findPublishedCurrent(),
  50. //            ]);
  51.         } else {
  52.             $appelAProjets = [];
  53.             if ($this->isGranted('ROLE_PORTEUR') || $this->isGranted('ROLE_DRCI')) {
  54.                 // récupération des appels à projets actifs à venir ou courant
  55.                 $appelAProjets $appelAProjetRepository->findPublishedCurrent();
  56.                 // récupération des appels à projet pour lesquels il a déposé un projet
  57.                 if ($this->isGranted('ROLE_PORTEUR')) {
  58.                     $appelAProjets array_replace($appelAProjets$appelAProjetRepository->findForPorteur($this->getUser()));
  59.                 }
  60.                 if ($this->isGranted('ROLE_DRCI')) {
  61.                     $appelAProjets array_replace($appelAProjets$appelAProjetRepository->findForDrci($this->getUser()));
  62.                 }
  63.             }
  64.             if ($this->isGranted('ROLE_GIRCI_PARTENAIRE')) {
  65.                 $appelAProjets array_replace($appelAProjets$appelAProjetRepository->findForGirci());
  66.             }
  67.             if ($this->isGranted('ROLE_PRE_EVAL') || $this->isGranted('ROLE_THEMA') || $this->isGranted('ROLE_EXPERT') || $this->isGranted('ROLE_RAPPORT') || $this->isGranted('ROLE_EXPERT_3')) {
  68.                 // récupération de tous les appels à projets pour lesquels ils ont des projets associés
  69.                 $appelAProjets array_replace($appelAProjets$appelAProjetRepository->findAssociated($this->getUser()));
  70.             }
  71.             krsort($appelAProjets);
  72.             return $this->render('appel_a_projet/index.html.twig', [
  73.                 'appel_a_projets' => $appelAProjets
  74.             ]);
  75.         }
  76.     }
  77.     /**
  78.      * @Route("/new", name="appel_a_projet_new", methods={"GET","POST"})
  79.      */
  80.     public function new(Request $requestManagerRegistry $doctrine): Response
  81.     {
  82.         $this->denyAccessUnlessGranted('CREATE'AppelAProjet::class);
  83.         $appelAProjet = new AppelAProjet();
  84.         $form $this->createForm(AppelAProjetType::class, $appelAProjet);
  85.         $form->handleRequest($request);
  86.         if ($form->isSubmitted()) {
  87.             if ($form->isValid()) {
  88.                 $entityManager $doctrine->getManager();
  89.                 $entityManager->persist($appelAProjet);
  90.                 $entityManager->flush();
  91.                 $this->addFlash('success''Formulaire soumis avec succès');
  92.                 return $this->redirectToRoute('appel_a_projet_index', [], Response::HTTP_SEE_OTHER);
  93.             }
  94.             $this->addFlash('error''Les données soumises sont invalides');
  95.         }
  96.         return $this->renderForm('appel_a_projet/new.html.twig', [
  97.             'appel_a_projet' => $appelAProjet,
  98.             'form' => $form,
  99.         ]);
  100.     }
  101.     /**
  102.      * @Route("/{id}", name="appel_a_projet_show", methods={"GET"})
  103.      */
  104.     public function show(AppelAProjet $appelAProjet): Response
  105.     {
  106.         return $this->render('appel_a_projet/show.html.twig', [
  107.             'appel_a_projet' => $appelAProjet,
  108.         ]);
  109.     }
  110.     /**
  111.      * @Route("/{id}/edit", name="appel_a_projet_edit", methods={"GET","POST"})
  112.      */
  113.     public function edit(Request $requestAppelAProjet $appelAProjetManagerRegistry $doctrine): Response
  114.     {
  115.         $form $this->createForm(AppelAProjetType::class, $appelAProjet);
  116.         $form->handleRequest($request);
  117.         if ($form->isSubmitted()) {
  118.             if ($form->isValid()) {
  119.                 $doctrine->getManager()->flush();
  120.                 $this->addFlash('success''Formulaire soumis avec succès');
  121.                 return $this->redirectToRoute('appel_a_projet_index', [], Response::HTTP_SEE_OTHER);
  122.             }
  123.             $this->addFlash('error''Les donnes soumises sont invalides');
  124.         }
  125.         return $this->renderForm('appel_a_projet/edit.html.twig', [
  126.             'appel_a_projet' => $appelAProjet,
  127.             'form' => $form,
  128.         ]);
  129.     }
  130.     /**
  131.      * @Route("/{id}/ajout-projet", name="appel_a_projet_add_project", methods={"GET", "POST"})
  132.      * @Route("/{id}/ajout-projet/auto", name="appel_a_projet_add_project_auto", methods={"POST"})
  133.      *
  134.      * @param Request $request
  135.      * @param AppelAProjet $appelAProjet
  136.      * @return Response
  137.      */
  138.     public function addProject(Request $requestAppelAProjet $appelAProjetQuestionnaireHandlerService $questionnaireHandlerServiceProjectNumberService $projectNumberServiceManagerRegistry $doctrine): Response
  139.     {
  140.         $this->denyAccessUnlessGranted('ADD_PROJECT'$appelAProjet);
  141.         if ($appelAProjet->getQuestionnaireLi()) {
  142.             $form $questionnaireHandlerService->createForm($appelAProjet->getQuestionnaireLi());
  143.         } else {
  144.             $form $questionnaireHandlerService->createForm($appelAProjet->getQuestionnaireDc());
  145.         }
  146.         $form->handleRequest($request);
  147.         if ($form->isSubmitted()) {
  148.             $return $questionnaireHandlerService->handleSubmission();
  149.             if ($return instanceof Response) {
  150.                 // cas d'une erreur
  151.                 return $return;
  152.             }
  153.             // cas où ça c'est bien passé
  154.             $questionnaireResponse $questionnaireHandlerService->getQuestionnaireResponse();
  155.             $em $doctrine->getManager();
  156.             /** @var User $user */
  157.             $user $this->getUser();
  158.             if ($appelAProjet->getQuestionnaireLi()) {
  159.                 $questionnaireResponse->setQuestionnaireType(QuestionnaireResponse::QR_TYPE_LI_I);
  160.             } else {
  161.                 $questionnaireResponse->setQuestionnaireType(QuestionnaireResponse::QR_TYPE_DC);
  162.             }
  163.             $project = new Project();
  164.             $project->setAuthor($user)
  165.                 ->setDrci($user->getDrci())
  166.                 ->setStatus(Project::PROJECT_STATUS_BROUILLON)
  167.                 ->setAppelAProjet($appelAProjet)
  168.                 ->setNumber($projectNumberService->generateDraftNumber($project))
  169.                 ->addQuestionnaireResponse($questionnaireResponse)
  170.             ;
  171.             $em->persist($project);
  172.             $em->flush();
  173.             if ($request->attributes->get('_route') == 'appel_a_projet_add_project') {
  174.                 $this->addFlash('success'$return);
  175.                 if ($questionnaireResponse->getStatus() == QuestionnaireResponse::S_STATUS_SUBMIT) {
  176.                     if ($appelAProjet->getQuestionnaireLi()) {
  177.                         $this->addFlash('success''Vous êtes invité à attacher des documents supplémentaires pour terminer le processus de soumission. Merci de bien vouloir préparer les références bibliographiques justifiant l’intérêt du projet (max 5), le tableur des services co-investigateurs, les CV du porteur et du méthodologiste.');
  178.                     }
  179.                     return new JsonResponse(['url' => $this->generateUrl('project_add_files', ['id' => $project->getId()])]);
  180.                 }
  181.                 return new JsonResponse(['url' => $this->generateUrl('project_show', ['id' => $project->getId()])]);
  182.             } else {
  183.                 return new JsonResponse(['url' => $this->generateUrl('questionnaire_display_submission', ['questionnaireResponse' => $questionnaireResponse->getId()])]);
  184.             }
  185.         }
  186.         return $questionnaireHandlerService->renderForm($request);
  187.     }
  188.     /**
  189.      * @Route("/{id}/recap-projets", name="appel_a_projet_recap_project", methods={"GET"})
  190.      */
  191.     public function recapProjet(AppelAProjet $appelAProjetProjectRepository $projectRepositorySignatureCharteRepository $signatureCharteRepository): Response
  192.     {
  193.         // récupération des projets associés à cet aap et à cet utilisateur, en fonction de son rôle
  194.         if ($this->isGranted('ROLE_ADMIN_GIRCI') || $this->isGranted('ROLE_COORDONNATEUR') || $this->isGranted('ROLE_METHODO')) {
  195.             return $this->render('project/index.html.twig', [
  196.                 'appel_a_projet' => $appelAProjet,
  197.                 'projects' => $projectRepository->findByAap($appelAProjet),
  198.             ]);
  199.         } else {
  200.             /** @var User $user */
  201.             $user $this->getUser();
  202.             $projects = [];
  203.             if ($this->isGranted('ROLE_PRE_EVAL') || $this->isGranted('ROLE_RAPPORT')) {
  204.                 if ($appelAProjet->getOuvert() === true) {
  205.                     // todo: accès à tous les projets ? Ou tous les projets pré-évalués dans un premier temps et pour les projets expertisés dans un deuxième ?
  206.                     // reporter la réponse dans le ProjectVoter
  207.                     return $this->render('project/index.html.twig', [
  208.                         'appel_a_projet' => $appelAProjet,
  209.                         'projects' => $projectRepository->findByAap($appelAProjet),
  210.                     ]);
  211.                 }
  212.                 $projects $projectRepository->findByUserProject($appelAProjet$user);
  213.             }
  214.             if ($this->isGranted('ROLE_PORTEUR')) {
  215.                 $projects array_replace($projects$projectRepository->findByPorteur($appelAProjet$user));
  216.             }
  217.             if ($this->isGranted('ROLE_DRCI')) {
  218.                 $projects array_replace($projects$projectRepository->findByDrci($appelAProjet$user));
  219.             }
  220.             if ($this->isGranted('ROLE_THEMA') || $this->isGranted('ROLE_EXPERT') || $this->isGranted('ROLE_EXPERT_3')){
  221.                 $projects array_replace($projects$projectRepository->findByUserProject($appelAProjet$user));
  222.             }
  223.             if ($this->isGranted('ROLE_GIRCI_PARTENAIRE')) {
  224.                 // récupération des tous les appels à projet ayant un userproject associé au girci de l'utilisateur
  225.                 $tmpProjects $projectRepository->findByGirci($appelAProjet$user->getGirci());
  226.                 if (count($tmpProjects) > 0) {
  227.                     // vérification de la signature de la charte (ça ne sert à rien de vérifier la charte si il n'y a pas de projet
  228.                     $signature $signatureCharteRepository->findOneBy(['appelAProjet' => $appelAProjet'user' => $this->getUser(), 'type' => SignatureCharte::CHARTE_TYPE_GIRCI]);
  229.                     if (!$signature) {
  230.                         return $this->redirectToRoute('appel_a_projet_girci_charte', ['id' => $appelAProjet->getId()]);
  231.                     }
  232.                 }
  233.                 $projects array_replace($projects$tmpProjects);
  234.             }
  235.             return $this->render('project/index.html.twig', [
  236.                 'appel_a_projet' => $appelAProjet,
  237.                 'projects' => $projects,
  238.             ]);
  239.         }
  240.     }
  241.     /**
  242.      * @Route("/{id}/girci-charte", name="appel_a_projet_girci_charte", methods={"GET", "POST"})
  243.      *
  244.      * @return Response
  245.      */
  246.     public function girciCharte(AppelAProjet $appelAProjetRequest $requestSignatureCharteRepository $signatureCharteRepositoryManagerRegistry $doctrine): Response
  247.     {
  248.         $this->denyAccessUnlessGranted('ROLE_GIRCI_PARTENAIRE'); // voir si on restraint plus ? Je ne suis pas sûre.
  249.         $signature $signatureCharteRepository->findOneBy(['appelAProjet' => $appelAProjet'user' => $this->getUser(), 'type' => SignatureCharte::CHARTE_TYPE_GIRCI]);
  250.         if ($signature) {
  251.             $this->addFlash('success''Vous avez déjà signé cette charte');
  252.             return $this->redirectToRoute('appel_a_projet_recap_project', ['id' => $appelAProjet->getId()]);
  253.         }
  254.         $form $this->createFormBuilder()
  255.             ->setAction($request->getRequestUri())
  256.             ->setMethod('POST')
  257.             ->getForm()
  258.         ;
  259.         $form->handleRequest($request);
  260.         if ($form->isSubmitted() && $form->isValid()) {
  261.             // enregistrement de la signature
  262.             $signature = (new SignatureCharte())
  263.                 ->setAppelAProjet($appelAProjet)
  264.                 ->setUser($this->getUser())
  265.                 ->setType(SignatureCharte::CHARTE_TYPE_GIRCI)
  266.             ;
  267.             $em $doctrine->getManager();
  268.             $em->persist($signature);
  269.             $em->flush();
  270.             $this->addFlash('success''Charte signée avec succès');
  271.             return $this->redirectToRoute('appel_a_projet_recap_project', ['id' => $appelAProjet->getId()]);
  272.         }
  273.         return $this->render('project/signature_charte.html.twig', [
  274.             'form' => $form->createView(),
  275.             'appelAProjet' => $appelAProjet,
  276.             'type' => 'charteGirci',
  277.         ]);
  278.     }
  279.     /**
  280.      * @Route("/{id}/etat-avancement", name="appel_a_projet_etat_avancement", methods={"GET"})
  281.      *
  282.      * @param AppelAProjet $appelAProjet
  283.      * @param ProjectRepository $projectRepository
  284.      */
  285.     public function etatAvancement(AppelAProjet $appelAProjetProjectRepository $projectRepository): Response
  286.     {
  287.         if ($this->isGranted('ROLE_ADMIN_GIRCI')) {
  288.             $projects $projectRepository->getWithUserProjectWithQestionnaireResponse($appelAProjet);
  289.             return $this->render('appel_a_projet/etat_avancement.html.twig', [
  290.                 'appel_a_projet' => $appelAProjet,
  291.                 'projects' => $projects
  292.             ]);
  293.         }
  294.         if ($this->isGranted('ROLE_COORDONNATEUR')) {
  295.             // récupération de tous les projets et l'éventuel formulaire dont ils sont l'auteur
  296.             $projects $projectRepository->getWithCoordoQR($appelAProjet$this->getUser());
  297.             return $this->render('appel_a_projet/etat_avancement_coordo.html.twig', [
  298.                 'appel_a_projet' => $appelAProjet,
  299.                 'projects' => $projects
  300.             ]);
  301.         }
  302.         if ($this->isGranted('ROLE_METHODO')) {
  303.             $projects $projectRepository->findByAap($appelAProjet);
  304.             return $this->render('appel_a_projet/etat_avancement_methodo.html.twig', [
  305.                 'appel_a_projet' => $appelAProjet,
  306.                 'projects' => $projects
  307.             ]);
  308.         }
  309.         throw $this->createAccessDeniedException();
  310.     }
  311.     /**
  312.      * @Route("/{id}/preeval-envoi-email", name="appel_a_projet_preeval_envoi_email", methods={"GET"})
  313.      * @Route("/{id}/rapport-envoi-email", name="appel_a_projet_rapport_envoi_email", methods={"GET"})
  314.      *
  315.      * @param Request $request
  316.      * @param AppelAProjet $appelAProjet
  317.      * @param UserRepository $userRepository
  318.      * @return Response|AccessDeniedException
  319.      */
  320.     public function sendEmail(Request $requestAppelAProjet $appelAProjetUserRepository $userRepositoryMailerInterface $mailerstring $emailSenderAddress)
  321.     {
  322.         switch ($request->attributes->get('_route')) {
  323.             case 'appel_a_projet_preeval_envoi_email':
  324.                 $this->denyAccessUnlessGranted('PREEVAL_SEND_EMAIL'$appelAProjet);
  325.                 $users $userRepository->getPreEvalByAap($appelAProjet, [QuestionnaireResponse::QR_TYPE_PREEVALQuestionnaireResponse::QR_TYPE_EVAL_THEMA]);
  326.                 $htmlTemplate 'email/info-preeval.html.twig';
  327.                 break;
  328.             case 'appel_a_projet_rapport_envoi_email':
  329.                 $this->denyAccessUnlessGranted('RAPPORT_SEND_EMAIL'$appelAProjet);
  330.                 $users $userRepository->getPreEvalByAap($appelAProjet, [QuestionnaireResponse::QR_TYPE_RAPPORT]);
  331.                 $htmlTemplate 'email/info-rapport.html.twig';
  332.                 break;
  333.             default:
  334.                 return $this->createAccessDeniedException();
  335.         }
  336.         foreach ($users as $user) {
  337.             $email = (new TemplatedEmail())
  338.                 ->from($emailSenderAddress)
  339.                 ->to($user->getEmail())
  340.                 ->subject('Bla bla')
  341.                 ->htmlTemplate($htmlTemplate)
  342.                 ->context([
  343.                     'user' => $user,
  344.                     'aap' => $appelAProjet,
  345.                 ])
  346.             ;
  347.             $mailer->send($email);
  348.         }
  349.         $this->addFlash('success'count($users) . ' messages envoyés avec succès');
  350.         return $this->redirectToRoute('appel_a_projet_recap_project', ['id' => $appelAProjet->getId()]);
  351.     }
  352.     /**
  353.      * @Route("/{id}/generate-experts", name="appel_a_projet_generate_expert", methods={"GET"})
  354.      *
  355.      * @param AppelAProjet $appelAProjet
  356.      * @param UserProjectRepository $userProjectRepository
  357.      * @param ProjectUserService $projectUserService
  358.      * @param ManagerRegistry $doctrine
  359.      * @return Response
  360.      */
  361.     public function generateExperts(AppelAProjet $appelAProjetProjectRepository $projectRepositoryProjectUserService $projectUserServiceManagerRegistry $doctrine): Response
  362.     {
  363.         $this->denyAccessUnlessGranted('GENERATE_EXPERTS'$appelAProjet);
  364.         // récupération de tous les projets
  365.         $projects $projectRepository->findByAppelAProjetExpert($appelAProjet);
  366.         $em $doctrine->getManager();
  367.         $users = [];
  368.         $userProjects = [];
  369.         $existingExperts = [];
  370.         foreach ($projects as $project) {
  371.             foreach ($project->getUserProjects() as $key => $userProject) {
  372.                 if ($userProject->getUser() == null) {
  373.                     if (in_array($project->getNumber() . 'A'$existingExperts)) {
  374.                         $username $project->getNumber() . 'B';
  375.                     } else {
  376.                         $username $project->getNumber() . 'A';
  377.                     }
  378.                     $userProject->setUser($projectUserService->createExpert($userProject->getGirci(), $username));
  379.                     $users[] = $userProject->getUser();
  380.                     $userProjects[] = $userProject;
  381.                     $existingExperts[] = $username;
  382.                 } else {
  383.                     $existingExperts[] = $userProject->getUser()->getUserIdentifier();
  384.                 }
  385.             }
  386.         }
  387.         // je dois générer mon fichier avant d'écrire en base (à cause du erase credential)
  388.         $csv $this->renderView('appel_a_projet/experts.csv.twig', [
  389.             'userProjects' => $userProjects
  390.         ]);
  391.         foreach ($users as $user) {
  392.             $em->persist($user);
  393.         }
  394.         $em->flush();
  395.         $response = new Response($csv);
  396.         $disposition $response->headers->makeDisposition(
  397.             ResponseHeaderBag::DISPOSITION_ATTACHMENT,
  398.             'experts.csv'
  399.         );
  400.         $response->headers->set('Content-Disposition'$disposition);
  401.         return $response;
  402.     }
  403.     /**
  404.      * Deletes a appel à projet entity.
  405.      *
  406.      * @Route("/delete/{id}", name="appel_a_projet_delete_confirm", methods={"GET"})
  407.      *
  408.      * @param AppelAProjet $appelAProjet
  409.      * @return Response
  410.      */
  411.     public function deleteConfirm(AppelAProjet $appelAProjet): Response
  412.     {
  413.         $this->denyAccessUnlessGranted('DELETE'$appelAProjet);
  414.         return $this->render('appel_a_projet/delete.html.twig', [
  415.             'aap' => $appelAProjet,
  416.         ]);
  417.     }
  418.     /**
  419.      * @Route("/{id}/{charte}", name="appel_a_projet_download_charte", methods={"GET"})
  420.      *
  421.      * @param AppelAProjet $appelAProjet
  422.      * @param $charte
  423.      * @param DownloadHandler $downloadHandler
  424.      * @return Response
  425.      */
  426.     public function downloadCharte(AppelAProjet $appelAProjet$charteDownloadHandler $downloadHandler): Response
  427.     {
  428.         switch ($charte) {
  429.             case 'charteGirci':
  430.                 $filename $appelAProjet->getCharteGirci()->getOriginalName();
  431.                 return $downloadHandler->downloadObject($appelAProjet'charteGirciFile'null$filename);
  432.             case 'chartePreeval':
  433.                 $filename $appelAProjet->getChartePreeval()->getOriginalName();
  434.                 return $downloadHandler->downloadObject($appelAProjet'chartePreevalFile'null$filename);
  435.             case 'charteRapport':
  436.                 $filename $appelAProjet->getCharteRapport()->getOriginalName();
  437.                 return $downloadHandler->downloadObject($appelAProjet'charteRapportFile'null$filename);
  438.             case 'charteExpert':
  439.                 $filename $appelAProjet->getCharteExpert()->getOriginalName();
  440.                 return $downloadHandler->downloadObject($appelAProjet'charteExpertFile'null$filename);
  441.             case 'charteExpert3':
  442.                 $filename $appelAProjet->getCharteExpert3()->getOriginalName();
  443.                 return $downloadHandler->downloadObject($appelAProjet'charteExpert3File'null$filename);
  444.             default:
  445.                 throw $this->createNotFoundException();
  446.         }
  447.     }
  448.     /**
  449.      * @Route("/{id}", name="appel_a_projet_delete", methods={"POST"})
  450.      */
  451.     public function delete(Request $requestAppelAProjet $appelAProjetManagerRegistry $doctrineUserProjectRepository $userProjectRepositorySignatureCharteRepository $signatureCharteRepository): Response
  452.     {
  453.         $this->denyAccessUnlessGranted('DELETE'$appelAProjet);
  454.         if ($this->isCsrfTokenValid('delete'.$appelAProjet->getId(), $request->request->get('_token'))) {
  455.             $entityManager $doctrine->getManager();
  456.             // suppression des experts
  457.             // récupération de tous les userProject de type expert de cet appel à projet
  458.             $ups $userProjectRepository->findByAppelAProjetExpertForDelete($appelAProjet);
  459.             foreach ($ups as $up) {
  460.                 $entityManager->remove($up);
  461.                 $entityManager->remove($up->getUser());
  462.             }
  463.             // suppression des signatures de charte
  464.             // récupération de toutes les signatures
  465.             $signatures $signatureCharteRepository->findBy(['appelAProjet' => $appelAProjet]);
  466.             foreach ($signatures as $signature) {
  467.                 $entityManager->remove($signature);
  468.             }
  469.             $entityManager->remove($appelAProjet);
  470.             $entityManager->flush();
  471.         }
  472.         $this->addFlash('success''Appel à projet supprimé avec succès.');
  473.         return $this->redirectToRoute('appel_a_projet_index', [], Response::HTTP_SEE_OTHER);
  474.     }
  475. }