src/Controller/Admin/ArticleAdminController.php line 143

Open in your IDE?
  1. <?php
  2. namespace App\Controller\Admin;
  3. use App\Entity\Article;
  4. use App\Entity\MediaAsset;
  5. use App\Form\ArticleType;
  6. use App\Repository\ArticleRepository;
  7. use App\Service\ImageGenerationService;
  8. use App\Service\ModerationService;
  9. use App\Service\SocialPublisherService;
  10. use Doctrine\ORM\EntityManagerInterface;
  11. use Knp\Component\Pager\PaginatorInterface;
  12. use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
  13. use Symfony\Component\HttpFoundation\File\Exception\FileException;
  14. use Symfony\Component\HttpFoundation\JsonResponse;
  15. use Symfony\Component\HttpFoundation\Request;
  16. use Symfony\Component\HttpFoundation\Response;
  17. use Symfony\Component\Routing\Annotation\Route;
  18. use Symfony\Component\String\Slugger\SluggerInterface;
  19. /**
  20.  * @Route("/admin/articles")
  21.  */
  22. class ArticleAdminController extends AbstractController
  23. {
  24.     /**
  25.      * @Route("", name="admin_articles")
  26.      */
  27.     public function index(
  28.         Request $request,
  29.         ArticleRepository $articleRepo,
  30.         PaginatorInterface $paginator
  31.     ): Response {
  32.         $this->denyAccessUnlessGranted('ROLE_ADMIN');
  33.         $status $request->query->get('status''');
  34.         
  35.         $qb $articleRepo->createQueryBuilder('a')
  36.             ->orderBy('a.createdAt''DESC');
  37.         if ($status) {
  38.             $qb->where('a.status = :status')
  39.                 ->setParameter('status'$status);
  40.         }
  41.         $articles $paginator->paginate(
  42.             $qb->getQuery(),
  43.             $request->query->getInt('page'1),
  44.             20
  45.         );
  46.         return $this->render('admin/article/index.html.twig', [
  47.             'articles' => $articles,
  48.             'current_status' => $status,
  49.         ]);
  50.     }
  51.     /**
  52.      * @Route("/new", name="admin_article_new")
  53.      */
  54.     public function new(
  55.         Request $request
  56.         EntityManagerInterface $em,
  57.         SluggerInterface $slugger
  58.     ): Response {
  59.         $this->denyAccessUnlessGranted('ROLE_ADMIN');
  60.         $article = new Article();
  61.         $form $this->createForm(ArticleType::class, $article);
  62.         $form->handleRequest($request);
  63.         if ($form->isSubmitted() && $form->isValid()) {
  64.             $imageFile $form->get('imageFile')->getData();
  65.             
  66.             if ($imageFile) {
  67.                 $mediaAsset $this->handleImageUpload($imageFile$slugger$em);
  68.                 if ($mediaAsset) {
  69.                     $article->setFeaturedImage($mediaAsset);
  70.                 }
  71.             }
  72.             $em->persist($article);
  73.             $em->flush();
  74.             $this->addFlash('success''Article créé avec succès');
  75.             return $this->redirectToRoute('admin_article_edit', ['id' => $article->getId()]);
  76.         }
  77.         return $this->render('admin/article/new.html.twig', [
  78.             'form' => $form->createView(),
  79.         ]);
  80.     }
  81.     /**
  82.      * @Route("/{id}/edit", name="admin_article_edit")
  83.      */
  84.     public function edit(
  85.         Article $article,
  86.         Request $request,
  87.         EntityManagerInterface $em,
  88.         SluggerInterface $slugger
  89.     ): Response {
  90.         $this->denyAccessUnlessGranted('ROLE_ADMIN');
  91.         $form $this->createForm(ArticleType::class, $article);
  92.         $form->handleRequest($request);
  93.         if ($form->isSubmitted() && $form->isValid()) {
  94.             $imageFile $form->get('imageFile')->getData();
  95.             
  96.             if ($imageFile) {
  97.                 $oldImage $article->getFeaturedImage();
  98.                 
  99.                 $mediaAsset $this->handleImageUpload($imageFile$slugger$em);
  100.                 if ($mediaAsset) {
  101.                     $article->setFeaturedImage($mediaAsset);
  102.                     
  103.                     if ($oldImage && $oldImage->getIsAiGenerated()) {
  104.                         $oldPath $this->getParameter('kernel.project_dir') . '/public/' $oldImage->getPath();
  105.                         if (file_exists($oldPath)) {
  106.                             @unlink($oldPath);
  107.                         }
  108.                         $em->remove($oldImage);
  109.                     }
  110.                 }
  111.             }
  112.             $em->flush();
  113.             $this->addFlash('success''Article mis à jour');
  114.             return $this->redirectToRoute('admin_article_edit', ['id' => $article->getId()]);
  115.         }
  116.         return $this->render('admin/article/edit.html.twig', [
  117.             'article' => $article,
  118.             'form' => $form->createView(),
  119.         ]);
  120.     }
  121.     /**
  122.      * @Route("/{id}/publish", name="admin_article_publish", methods={"POST"})
  123.      */
  124.     public function publish(
  125.         Article $article,
  126.         EntityManagerInterface $em,
  127.         SocialPublisherService $socialPublisher
  128.     ): Response {
  129.         $this->denyAccessUnlessGranted('ROLE_ADMIN');
  130.         $article->publish();
  131.         $em->flush();
  132.         $socialPublisher->publishToAllPlatforms($article);
  133.         $this->addFlash('success''Article publié et diffusé sur les réseaux sociaux');
  134.         return $this->redirectToRoute('admin_articles');
  135.     }
  136.     /**
  137.      * @Route("/{id}/validate", name="admin_article_validate", methods={"POST"})
  138.      */
  139.     public function validate(
  140.         Article $article,
  141.         Request $request,
  142.         ModerationService $moderation
  143.     ): Response {
  144.         $this->denyAccessUnlessGranted('ROLE_ADMIN');
  145.         $approved $request->request->get('approved') === '1';
  146.         $notes $request->request->get('notes');
  147.         $moderation->validateManually($article$approved$notes);
  148.         $this->addFlash(
  149.             'success',
  150.             $approved 'Article approuvé' 'Article rejeté'
  151.         );
  152.         return $this->redirectToRoute('admin_articles', ['status' => 'pending']);
  153.     }
  154.     /**
  155.      * @Route("/{id}/delete", name="admin_article_delete", methods={"POST"})
  156.      */
  157.     public function delete(
  158.         Article $article,
  159.         EntityManagerInterface $em
  160.     ): Response {
  161.         $this->denyAccessUnlessGranted('ROLE_ADMIN');
  162.         $em->remove($article);
  163.         $em->flush();
  164.         $this->addFlash('success''Article supprimé');
  165.         return $this->redirectToRoute('admin_articles');
  166.     }
  167.     /**
  168.      * @Route("/{id}/generate-image", name="admin_article_generate_image", methods={"POST"})
  169.      */
  170.     public function generateImage(
  171.         Article $article,
  172.         Request $request,
  173.         ImageGenerationService $imageGenerator,
  174.         EntityManagerInterface $em
  175.     ): JsonResponse {
  176.         $this->denyAccessUnlessGranted('ROLE_ADMIN');
  177.         try {
  178.             $title $request->request->get('title'$article->getTitle());
  179.             $excerpt $request->request->get('excerpt'$article->getExcerpt());
  180.             $mediaAsset $imageGenerator->generateArticleImage($title$excerpt);
  181.             if (!$mediaAsset) {
  182.                 return $this->json([
  183.                     'success' => false,
  184.                     'message' => 'Échec de la génération de l\'image'
  185.                 ], 500);
  186.             }
  187.             $oldImage $article->getFeaturedImage();
  188.             $article->setFeaturedImage($mediaAsset);
  189.             $em->flush();
  190.             if ($oldImage && $oldImage->getIsAiGenerated()) {
  191.                 $oldPath $this->getParameter('kernel.project_dir') . '/public/' $oldImage->getPath();
  192.                 if (file_exists($oldPath)) {
  193.                     @unlink($oldPath);
  194.                 }
  195.                 $em->remove($oldImage);
  196.                 $em->flush();
  197.             }
  198.             return $this->json([
  199.                 'success' => true,
  200.                 'message' => 'Image générée avec succès!',
  201.                 'image_url' => '/' $mediaAsset->getPath(),
  202.                 'media_id' => $mediaAsset->getId(),
  203.             ]);
  204.         } catch (\Exception $e) {
  205.             return $this->json([
  206.                 'success' => false,
  207.                 'message' => 'Erreur: ' $e->getMessage()
  208.             ], 500);
  209.         }
  210.     }
  211.     private function handleImageUpload($imageFileSluggerInterface $sluggerEntityManagerInterface $em): ?MediaAsset
  212.     {
  213.         $originalFilename pathinfo($imageFile->getClientOriginalName(), PATHINFO_FILENAME);
  214.         $safeFilename $slugger->slug($originalFilename);
  215.         $newFilename $safeFilename '-' uniqid() . '.' $imageFile->guessExtension();
  216.         $uploadDir $this->getParameter('kernel.project_dir') . '/public/uploads/media';
  217.         if (!is_dir($uploadDir)) {
  218.             mkdir($uploadDir0777true);
  219.         }
  220.         try {
  221.             $imageFile->move($uploadDir$newFilename);
  222.             $mediaAsset = new MediaAsset();
  223.             $mediaAsset->setType(MediaAsset::TYPE_IMAGE);
  224.             $mediaAsset->setPath('uploads/media/' $newFilename);
  225.             $mediaAsset->setIsAiGenerated(false);
  226.             $mediaAsset->setFileSize(filesize($uploadDir '/' $newFilename));
  227.             $mediaAsset->setMimeType($imageFile->getMimeType());
  228.             $mediaAsset->setTitle($originalFilename);
  229.             $em->persist($mediaAsset);
  230.             $em->flush();
  231.             return $mediaAsset;
  232.         } catch (FileException $e) {
  233.             $this->addFlash('error''Erreur lors de l\'upload de l\'image: ' $e->getMessage());
  234.             return null;
  235.         }
  236.     }
  237. }