src/Controller/Admin/ForumReponseCrudController.php line 237

Open in your IDE?
  1. <?php
  2. namespace App\Controller\Admin;
  3. use App\Controller\Trait\ForumAccessTrait;
  4. use App\Entity\ForumReponse;
  5. use App\Entity\Sujetforum;
  6. use App\Entity\User;
  7. use App\Form\CommentResponseForumType;
  8. use App\Repository\ForumReponseRepository;
  9. use App\Service\NotificationManager;
  10. use Doctrine\ORM\EntityManagerInterface;
  11. use EasyCorp\Bundle\EasyAdminBundle\Config\Crud;
  12. use EasyCorp\Bundle\EasyAdminBundle\Config\Action;
  13. use EasyCorp\Bundle\EasyAdminBundle\Config\KeyValueStore;
  14. use EasyCorp\Bundle\EasyAdminBundle\Context\AdminContext;
  15. use EasyCorp\Bundle\EasyAdminBundle\Event\AfterCrudActionEvent;
  16. use EasyCorp\Bundle\EasyAdminBundle\Event\AfterEntityPersistedEvent;
  17. use EasyCorp\Bundle\EasyAdminBundle\Event\BeforeCrudActionEvent;
  18. use EasyCorp\Bundle\EasyAdminBundle\Event\BeforeEntityPersistedEvent;
  19. use EasyCorp\Bundle\EasyAdminBundle\Exception\ForbiddenActionException;
  20. use EasyCorp\Bundle\EasyAdminBundle\Exception\InsufficientEntityPermissionException;
  21. use EasyCorp\Bundle\EasyAdminBundle\Factory\EntityFactory;
  22. use EasyCorp\Bundle\EasyAdminBundle\Field\IdField;
  23. use EasyCorp\Bundle\EasyAdminBundle\Config\Actions;
  24. use EasyCorp\Bundle\EasyAdminBundle\Field\DateField;
  25. use EasyCorp\Bundle\EasyAdminBundle\Field\TextField;
  26. use EasyCorp\Bundle\EasyAdminBundle\Field\BooleanField;
  27. use EasyCorp\Bundle\EasyAdminBundle\Field\TextareaField;
  28. use EasyCorp\Bundle\EasyAdminBundle\Field\AssociationField;
  29. use EasyCorp\Bundle\EasyAdminBundle\Controller\AbstractCrudController;
  30. use EasyCorp\Bundle\EasyAdminBundle\Router\AdminUrlGenerator;
  31. use EasyCorp\Bundle\EasyAdminBundle\Security\Permission;
  32. use Symfony\Component\HttpFoundation\Request;
  33. use Symfony\Component\HttpFoundation\Response;
  34. use Symfony\Component\Routing\Annotation\Route;
  35. use Knp\Component\Pager\PaginatorInterface;
  36. use Symfony\Component\Security\Core\Security;
  37. use Symfony\Component\HttpFoundation\JsonResponse;
  38. use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
  39. use Symfony\Component\Validator\Constraints\DateTime;
  40. use EasyCorp\Bundle\EasyAdminBundle\Field\FormField;
  41. use EasyCorp\Bundle\EasyAdminBundle\Field\CollectionField;
  42. use EasyCorp\Bundle\EasyAdminBundle\Dto\EntityDto;
  43. use EasyCorp\Bundle\EasyAdminBundle\Dto\SearchDto;
  44. use EasyCorp\Bundle\EasyAdminBundle\Collection\FieldCollection;
  45. use EasyCorp\Bundle\EasyAdminBundle\Collection\FilterCollection;
  46. use Doctrine\ORM\QueryBuilder;
  47. class ForumReponseCrudController extends AbstractBaseCrudController
  48. {
  49.     use ForumAccessTrait;
  50.     private $tokenStorage;
  51.     private $adminUrlGenerator;
  52.     private $notificationManager;
  53.         public function __construct(TokenStorageInterface $tokenStorage,
  54.         AdminUrlGenerator $adminUrlGeneratorNotificationManager $notificationManager)
  55.         {
  56.             $this->tokenStorage $tokenStorage;
  57.             $this->adminUrlGenerator $adminUrlGenerator;
  58.             $this->notificationManager $notificationManager;
  59.         }
  60.     public static function getEntityFqcn(): string
  61.     {
  62.         return ForumReponse::class;
  63.     }
  64.     public function configureCrud(Crud $crud): Crud
  65.     {
  66.         return $crud ->setPageTitle('index''Liste des Réponses')
  67.             ->setPageTitle('detail''Détails des Réponses')
  68.             ->setPageTitle('new''Créer une réponse');
  69.     }
  70.     public function configureActions(Actions $actions): Actions
  71.     {
  72.         $actions->add(Crud::PAGE_INDEXAction::DETAIL)
  73.         ->update(Crud::PAGE_INDEX,Action::NEW, function (Action $action) {
  74.             return $action->setLabel('Créer une reponse');
  75.         })
  76.         ->update(Crud::PAGE_NEWAction::SAVE_AND_RETURN, function (Action $action) {
  77.             return $action->setLabel('Enregistrer');
  78.         })
  79.         ->remove(Crud::PAGE_INDEXAction::DETAIL)
  80.         // ->remove(Crud::PAGE_INDEX, Action::NEW)
  81.         //->remove(Crud::PAGE_DETAIL, Action::EDIT)
  82.         ;
  83.         return $actions;
  84.     }
  85.     /**
  86.      * @param SearchDto $searchDto
  87.      * @param EntityDto $entityDto
  88.      * @param FieldCollection $fields
  89.      * @param FilterCollection $filters
  90.      * @return QueryBuilder
  91.      */
  92.     public function createIndexQueryBuilder(SearchDto $searchDtoEntityDto $entityDtoFieldCollection $fieldsFilterCollection $filters): QueryBuilder
  93.     {
  94.         $response parent::createIndexQueryBuilder($searchDto$entityDto$fields$filters); // TODO: Change the autogenerated stub
  95.         $response->andWhere('entity.parent IS NULL ');
  96.         $response->andWhere('entity.reponse IS NOT  NULL ');
  97.         $response->andWhere('entity.user IS NOT  NULL ');
  98.         return $response;
  99.     }
  100.     public function configureFields(string $pageName): iterable
  101.     {
  102.         return [
  103.             FormField::addTab('Détail Réponse')
  104.             ->setIcon('map')->addCssClass('optional'),
  105.             IdField::new('id')->hideOnForm(),
  106.             //TextField::new('nom','Nom')->formatValue(function ($value) { return $value ; }),
  107.             DateField::new('date''Date de la réponse')->formatValue(function ($value) {
  108.                 return $value ;
  109.             })->hideOnForm(),
  110.             AssociationField::new('user''utilisateur')->hideOnForm(),
  111.             AssociationField::new('sujetforum''Sujet'),
  112.             TextareaField::new('reponse''Réponse')->formatValue(function ($value) {
  113.                 return $value ;
  114.             }),
  115.      
  116.                
  117.             BooleanField::new('etat''Publier ?')
  118.                 // ->onlyOnForms() // Ne s'affiche que dans le formulaire
  119.                 ->setFormTypeOption('attr', ['class' => 'enable-in-form'])->setDisabled$pageName == Crud::PAGE_INDEX,true), // Ajout d'une classe CSS personnalisée
  120.   
  121.              FormField::addTab('Commentaires')
  122.              ->setIcon('map')->addCssClass('optional'),
  123.     
  124.              CollectionField::new('children')
  125.              ->allowAdd(true)
  126.              ->allowDelete(true)
  127.              ->setEntryIsComplex(true)
  128.              ->setLabel('comment')
  129.              ->setEntryType(CommentResponseForumType::class)
  130.             
  131.             
  132.              ->setFormTypeOptions(
  133.                  [
  134.                      'allow_add' => true,
  135.                      'allow_delete' => true,
  136.                      'form_attr' => 'ok',
  137.                      'label' => false,
  138.                      'auto_initialize' => false,
  139.                      'block_name' => null,
  140.                      'compound' => true,
  141.                      'by_reference' => false,
  142.              ]
  143.              )->hideOnIndex(false)->setLabel('Liste Commentaire')
  144.         
  145.         ];
  146.         DateField::new('date''Date de la réponse')->formatValue(function ($value) {
  147.             return $value ;
  148.         })->hideOnForm();
  149.     }
  150.     public function persistEntity(EntityManagerInterface $entityManager$entityInstance): void
  151.     {
  152.         $user $this->tokenStorage->getToken()->getUser();
  153.         $entityInstance->setUser($user);
  154.         $entityInstance->setDate(new \DateTime());
  155.         if ($entityInstance->getChildren()) {
  156.             foreach ($entityInstance->getChildren() as $child) {
  157.                 $child->setUser($user);
  158.                 $child->setDate(new \DateTime());
  159.                 $child->setEtat(true);
  160.                 $child->setParent($entityInstance);
  161.                 // Les commentaires (enfants) héritaient rarement du sujet → null à la publication
  162.                 if (!$child->getSujetforum() && $entityInstance->getSujetforum()) {
  163.                     $child->setSujetforum($entityInstance->getSujetforum());
  164.                 }
  165.                 $entityManager->persist($child);
  166.             }
  167.         }
  168.         $entityManager->persist($entityInstance);
  169.         $entityManager->flush();
  170.     }
  171.     public function updateEntity(EntityManagerInterface $entityManager$entityInstance): void
  172.     {
  173.         $conn $entityManager->getConnection();
  174.         $currentUser $this->tokenStorage->getToken()->getUser();
  175.         $oldChildren = [];
  176.         $parentSujet $entityInstance->getSujetforum();
  177.         $pendingNotifications = [];
  178.         /** check if children was updated */
  179.         foreach ($entityInstance->getChildren()->getSnapshot() as $child) {
  180.             /** check if there are children was removed */
  181.             if (!$entityInstance->getChildren()->contains($child)) {
  182.                 $entityManager->remove($child);
  183.                 continue;
  184.             }
  185.             if (!$child->getId()) {
  186.                 continue;
  187.             }
  188.             $sql 'SELECT * FROM forum_reponse f WHERE f.id = :id';
  189.             $resultSet $conn->executeQuery($sql, ['id' => $child->getId()]);
  190.             $oldChildren[$child->getId()] = $resultSet->fetchAssociative();
  191.         }
  192.         foreach ($entityInstance->getChildren() as $child) {
  193.             $child->setParent($entityInstance);
  194.             // Toujours rattacher le sujet du parent (sinon crash getSujetforum()->getId())
  195.             if (!$child->getSujetforum() && $parentSujet) {
  196.                 $child->setSujetforum($parentSujet);
  197.             }
  198.             if ($child->getId() && array_key_exists($child->getId(), $oldChildren) && $oldChildren[$child->getId()]) {
  199.                 $previous $oldChildren[$child->getId()];
  200.                 if (!empty($previous['user_id'])) {
  201.                     $child->setUser($entityManager->getRepository(User::class)->find($previous['user_id']));
  202.                 }
  203.                 if (!empty($previous['date'])) {
  204.                     $child->setDate(new \DateTime($previous['date']));
  205.                 }
  206.             } else {
  207.                 if (!$child->getUser()) {
  208.                     $child->setUser($currentUser);
  209.                 }
  210.             }
  211.             // date est NOT NULL en base : toujours garantir une valeur avant flush
  212.             if (!$child->getDate()) {
  213.                 $child->setDate(new \DateTime());
  214.             }
  215.             $entityManager->persist($child);
  216.             if ($child->isEtat()) {
  217.                 $pendingNotifications[] = [
  218.                     'reponse' => $child,
  219.                     'title' => 'Votre commentaire a été validé !',
  220.                     'message' => 'Votre commentaire a été validé ! ',
  221.                 ];
  222.             }
  223.         }
  224.         if ($entityInstance->isEtat()) {
  225.             $pendingNotifications[] = [
  226.                 'reponse' => $entityInstance,
  227.                 'title' => 'Votre réponse/commentaire a été validé !',
  228.                 'message' => 'Votre réponse/commentaire a été validé ! ',
  229.             ];
  230.         }
  231.         // Flush d'abord les réponses/commentaires, puis les notifications
  232.         // (évite qu'un flush dans NotificationManager persiste une date null)
  233.         $entityManager->flush();
  234.         foreach ($pendingNotifications as $notif) {
  235.             $this->notifyForumPublication(
  236.                 $entityManager,
  237.                 $notif['reponse'],
  238.                 $notif['title'],
  239.                 $notif['message']
  240.             );
  241.         }
  242.     }
  243.     /**
  244.      * Notifie l'auteur qu'une réponse/commentaire a été publié.
  245.      * Ne plante jamais si sujet ou utilisateur est absent.
  246.      */
  247.     private function notifyForumPublication(
  248.         EntityManagerInterface $entityManager,
  249.         ForumReponse $reponse,
  250.         string $title,
  251.         string $message
  252.     ): void {
  253.         $sujet $reponse->getSujetforum();
  254.         if (!$sujet && $reponse->getParent()) {
  255.             $sujet $reponse->getParent()->getSujetforum();
  256.             if ($sujet) {
  257.                 $reponse->setSujetforum($sujet);
  258.             }
  259.         }
  260.         $auteur $reponse->getUser();
  261.         if (!$sujet || !$auteur) {
  262.             return;
  263.         }
  264.         $urlSujet '/show/forum/detail/' $sujet->getId();
  265.         $this->notificationManager->pushMessage($title$message$auteur$urlSujet);
  266.     }
  267.     #[Route('/show/forum/detail/{id}'name'show_forum_detail')]
  268.     public function listServices(Sujetforum $sujetRequest $requestEntityManagerInterface $entityManagerPaginatorInterface $paginatorSecurity $security): Response
  269.     {
  270.         if ($security->getUser()) {
  271.             $donnees $entityManager->getRepository(ForumReponse::class)->finResponsesdWithUser($sujet->getId(), 0$security->getUser()->getId());
  272.         } else {
  273.             
  274.             $donnees $entityManager->getRepository(ForumReponse::class)->finResponsesdWithUser($sujet->getId(), 0);
  275.         }
  276.         $reponseForums $donnees;
  277.         return $this->render('forum/detail.html.twig', [
  278.              'sujetForum'=>$sujet,
  279.              'reponsesForums'=>$reponseForums
  280.           
  281.          ]);
  282.     }
  283.     
  284.     #[Route('/make/forum/response/{id}'name'make_forum_response'methods: ['POST'])]
  285.     public function responseForum(Sujetforum $sujetRequest $request,
  286.      EntityManagerInterface $entityManagerSecurity $security,
  287.      NotificationManager $notificationManager
  288.      ): Response
  289.     
  290.         $this->validateRequestCsrfToken($request'forum');
  291.         $this->denyAccessUnlessGranted('IS_AUTHENTICATED_FULLY');
  292.         $reponse= new ForumReponse();
  293.         $reponse->setReponse($request->request->get('message'));
  294.         $reponse->setUser($security->getUser());
  295.         $reponse->setDate(new \DateTime());
  296.         $reponse->setEtat(false);
  297.         $reponse->setSujetforum($sujet);
  298.         $entityManager->persist($reponse);
  299.         $entityManager->flush();
  300.            // Send Comment
  301.            $edit_demande_url =  $this->adminUrlGenerator
  302.            ->setController(ForumReponseCrudController::class)
  303.            ->setAction(Action::EDIT)
  304.            ->setEntityId($reponse->getId())
  305.            ->generateUrl();
  306.            $notification_message 'Nouvelle Réponse au Sujet ! ';
  307.            $admins $entityManager->getRepository(User::class)->findByRole('ROLE_ADMIN');
  308.            foreach($admins as $admin){
  309.                $notificationManager->pushMessage('Nouvelle Réponse au Sujet ! '$notification_message$admin$edit_demande_url);
  310.            }
  311.            // End send comment
  312.             return $this->redirectToRoute('show_forum_detail', ['id' => $sujet->getId()]);
  313.     }
  314.     #[Route('/delete/forum/reponse/{id}'name'delete_forum_response'methods: ['POST'])]
  315.     public function deleteResponseForum(ForumReponse $reponseRequest $requestEntityManagerInterface $entityManagerSecurity $security): JsonResponse
  316.     {
  317.         $this->validateRequestCsrfToken($request'ajax');
  318.         $this->denyUnlessForumReponseOwner($reponse);
  319.         $entityManager->remove($reponse);
  320.         $entityManager->flush();
  321.         return new JsonResponse(['data' => 'done'], Response::HTTP_OK, ['Content-Type''application/json']);
  322.     }
  323.     #[Route('/make/forum/comment/{id}/{repid}'name'make_forum_comment'methods: ['POST'])]
  324.     public function responseComment(Sujetforum $sujetint $repidRequest $requestEntityManagerInterface $entityManagerSecurity $security NotificationManager $notificationManager): Response
  325.     {
  326.         $this->validateRequestCsrfToken($request'forum');
  327.         $this->denyAccessUnlessGranted('IS_AUTHENTICATED_FULLY');
  328.         $parent $entityManager->getRepository(ForumReponse::class)->find($repid);
  329.         if (null === $parent || null === $parent->getSujetforum() || $parent->getSujetforum()->getId() !== $sujet->getId()) {
  330.             throw $this->createNotFoundException('Réponse introuvable.');
  331.         }
  332.         $reponse= new ForumReponse();
  333.         $reponse->setReponse($request->request->get('message'));
  334.         $reponse->setUser($security->getUser());
  335.         $reponse->setDate(new \DateTime());
  336.         $reponse->setEtat(false);
  337.         $reponse->setSujetforum($sujet);
  338.         $reponse->setParent($parent);
  339.         $entityManager->persist($reponse);
  340.         $entityManager->flush();
  341.         $edit_demande_url =  $this->adminUrlGenerator
  342.         ->setController(ForumReponseCrudController::class)
  343.         ->setAction(Action::EDIT)
  344.         ->setEntityId($repid)
  345.         ->generateUrl();
  346.         $notification_message 'Nouveau Commentaire  ! ';
  347.         $admins $entityManager->getRepository(User::class)->findByRole('ROLE_ADMIN');
  348.         foreach($admins as $admin){
  349.             $notificationManager->pushMessage('Nouveau Commentaire ! '$notification_message$admin$edit_demande_url);
  350.         }
  351.         return $this->redirectToRoute('show_forum_detail', ['id' => $sujet->getId()]);
  352.     }
  353.     #[Route('/update/forum/response/{id}'name'update_forum_response'methods: ['POST'])]
  354.     public function updateResponseForum(ForumReponse $reponseRequest $requestEntityManagerInterface $entityManager): Response
  355.     {
  356.         $this->validateRequestCsrfToken($request'forum');
  357.         $this->denyUnlessForumReponseOwner($reponse);
  358.         $reponse->setReponse($request->request->get('message'));
  359.         $reponse->setDate(new \DateTime());
  360.         $entityManager->persist($reponse);
  361.         $entityManager->flush();
  362.         return $this->redirectToRoute('show_forum_detail', ['id' => $reponse->getSujetforum()->getId()]);
  363.     }
  364.     #[Route('/ajax/get/ReponseForum/{id}'name'show_forum_ReponseForum')]
  365.     public function ReponseForum(Sujetforum $sujetRequest $requestEntityManagerInterface $entityManagerPaginatorInterface $paginatorSecurity $security): JsonResponse
  366.     {
  367.         $offset = (int)$request->query->get('offset');
  368.       
  369.         if ($security->getUser()) {
  370.             $donnees $entityManager->getRepository(ForumReponse::class)->finResponsesdWithUser($sujet->getId(), $offset$security->getUser()->getId());
  371.         } else {
  372.             
  373.             $donnees $entityManager->getRepository(ForumReponse::class)->finResponsesdWithUser($sujet->getId(), $offset);
  374.         }
  375.         $reponseForums $donnees;
  376.         foreach ($donnees as $key => $obj) {
  377.             $childrenData = [];
  378.             foreach ($obj->getChildren() as $child) {
  379.                 $childrenData[] = [
  380.                     'id' => $child->getId(),
  381.                     'date' => $child->getDate()->format('d/m/Y'),
  382.                     'userName' => $child->getUser()->getUsername(),
  383.                     'reponse' => $child->getReponse(),
  384.                     'userId' => $child->getUser()->getId(),
  385.                     'etat' => $child->isEtat(),
  386.                 ];
  387.             }
  388.         
  389.             $result[$key] = [
  390.                 'id' => $obj->getId(),
  391.                 'date' => $obj->getDate()->format('d/m/Y'),
  392.                 'userName' => $obj->getUser()->getUsername(),
  393.                 'userId' => $obj->getUser()->getId(),
  394.                 'reponse' => $obj->getReponse(),
  395.                 'etat' => $obj->isEtat(),
  396.                 'childs' => $childrenData,
  397.             ];
  398.         }
  399.         
  400.         return new JsonResponse([
  401.             'result'=>$result,
  402.             'reponsesForums'=>$reponseForums
  403.          
  404.         ], Response::HTTP_OK, ['Content-Type''application/json']);
  405.     }
  406. }