src/Controller/Admin/BlogPostCrudController.php line 314

Open in your IDE?
  1. <?php
  2. namespace App\Controller\Admin;
  3. use Throwable;
  4. use App\Entity\User;
  5. use App\Entity\Media;
  6. use App\Service\Role;
  7. use App\Entity\BlogPost;
  8. use App\Service\Helpers;
  9. use App\Service\Position;
  10. use App\Service\CsvExporter;
  11. use App\Admin\Field\SeoField;
  12. use App\Service\DuplicatePost;
  13. use Doctrine\ORM\QueryBuilder;
  14. use App\Admin\Action\CsvAction;
  15. use App\Admin\Field\MediaField;
  16. use App\Entity\BlogPostHistoryUpdate;
  17. use App\Repository\BlogPostRepository;
  18. use App\Admin\Field\NotificationField;
  19. use App\Admin\Field\TextareaField;
  20. use App\Entity\BlogPostCategory;
  21. use App\Entity\ScoringQuiz;
  22. use Doctrine\ORM\EntityManagerInterface;
  23. use App\Service\BlogPost as BlogPostService;
  24. use App\Repository\BlogPostCategoryRepository;
  25. use App\Repository\Criteria1Repository;
  26. use App\Repository\Criteria2Repository;
  27. use App\Repository\Criteria3Repository;
  28. use App\Repository\ScoringQuizRepository;
  29. use App\Service\SiteConfig;
  30. use Symfony\Component\HttpFoundation\Response;
  31. use EasyCorp\Bundle\EasyAdminBundle\Config\Crud;
  32. use EasyCorp\Bundle\EasyAdminBundle\Config\Action;
  33. use EasyCorp\Bundle\EasyAdminBundle\Config\Assets;
  34. use EasyCorp\Bundle\EasyAdminBundle\Dto\EntityDto;
  35. use EasyCorp\Bundle\EasyAdminBundle\Dto\SearchDto;
  36. use EasyCorp\Bundle\EasyAdminBundle\Config\Actions;
  37. use EasyCorp\Bundle\EasyAdminBundle\Config\Filters;
  38. use EasyCorp\Bundle\EasyAdminBundle\Field\FormField;
  39. use EasyCorp\Bundle\EasyAdminBundle\Field\TextField;
  40. use EasyCorp\Bundle\EasyAdminBundle\Field\ImageField;
  41. use EasyCorp\Bundle\EasyAdminBundle\Field\ChoiceField;
  42. use Symfony\Component\HttpFoundation\RedirectResponse;
  43. use Symfony\Component\HttpFoundation\StreamedResponse;
  44. use Symfony\Contracts\Translation\TranslatorInterface;
  45. use EasyCorp\Bundle\EasyAdminBundle\Field\BooleanField;
  46. use EasyCorp\Bundle\EasyAdminBundle\Field\IntegerField;
  47. use EasyCorp\Bundle\EasyAdminBundle\Field\DateTimeField;
  48. use EasyCorp\Bundle\EasyAdminBundle\Filter\EntityFilter;
  49. use Symfony\Component\Form\Extension\Core\Type\TextType;
  50. use EasyCorp\Bundle\EasyAdminBundle\Config\KeyValueStore;
  51. use EasyCorp\Bundle\EasyAdminBundle\Context\AdminContext;
  52. use EasyCorp\Bundle\EasyAdminBundle\Filter\BooleanFilter;
  53. use EasyCorp\Bundle\EasyAdminBundle\Field\AssociationField;
  54. use Symfony\Component\Form\Extension\Core\Type\TextareaType;
  55. use EasyCorp\Bundle\EasyAdminBundle\Router\AdminUrlGenerator;
  56. use EasyCorp\Bundle\EasyAdminBundle\Collection\FieldCollection;
  57. use EasyCorp\Bundle\EasyAdminBundle\Collection\FilterCollection;
  58. use EasyCorp\Bundle\EasyAdminBundle\Provider\AdminContextProvider;
  59. use EasyCorp\Bundle\EasyAdminBundle\Controller\AbstractCrudController;
  60. use DateInterval;
  61. use DateTime;
  62. use Doctrine\Common\Collections\Collection;
  63. use Symfony\Component\HttpFoundation\RequestStack;
  64. class BlogPostCrudController extends AbstractCrudController
  65. {
  66.     public function __construct(
  67.         private Helpers $helpers,
  68.         private BlogPostRepository $blogPostRepository,
  69.         private BlogPostCategoryRepository $blogPostCategoryRepository,
  70.         private Position $position,
  71.         private TranslatorInterface $translator,
  72.         private AdminUrlGenerator $adminUrlGenerator,
  73.         private Role $role,
  74.         private EntityManagerInterface $em,
  75.         private BlogPostService $blogPostService,
  76.         private CsvExporter $csvExporter,
  77.         private AdminContextProvider $adminContextProvider,
  78.         private SiteConfig $serviceSiteConfig,
  79.         private Criteria1Repository $criteria1Repository,
  80.         private Criteria2Repository $criteria2Repository,
  81.         private Criteria3Repository $criteria3Repository,
  82.         private RequestStack $requestStack,
  83.         private ScoringQuizRepository $scoringQuizRepository,
  84.     ) {}
  85.     public static function getEntityFqcn(): string
  86.     {
  87.         return BlogPost::class;
  88.     }
  89.     public function createIndexQueryBuilder(SearchDto $searchDtoEntityDto $entityDtoFieldCollection $fieldsFilterCollection $filters): QueryBuilder
  90.     {
  91.         $qb parent::createIndexQueryBuilder($searchDto$entityDto$fields$filters);
  92.         // Get only owned Post for ROLE_REDACTEUR
  93.         if (array_search(User::ROLE_REDACTEUR$this->getUser()->getRoles())) {
  94.             $qb->where("entity.author = :user")
  95.                 ->setParameter("user"$this->getUser());
  96.         } else if (array_search(User::ROLE_CHEF_RUBRIQUE$this->getUser()->getRoles())) {
  97.             // Get only Posts for the assigned categories of the current user
  98.             $qb->join('entity.blogPostCategory''bpc')
  99.                 ->join('bpc.users''user')
  100.                 ->andWhere("user.id = :userId")
  101.                 ->setParameter("userId"$this->getUser()->getId());
  102.         }
  103.         $qb->leftJoin('entity.scoringQuiz''sq')
  104.         ->leftJoin('entity.identityForm''if');
  105.         return $qb;
  106.     }
  107.     /**
  108.      * @param Crud $crud
  109.      * @return Crud
  110.      */
  111.     public function configureCrud(Crud $crud): Crud
  112.     {
  113.         $this->blogPostRepository->checkPositions();
  114.         return $crud
  115.             // the labels used to refer to this entity in titles, buttons, etc.
  116.             ->setPageTitle(Crud::PAGE_INDEX'bo.blog-post.title-plural')
  117.             ->setEntityLabelInSingular('bo.blog-post.title')
  118.             ->setEntityLabelInPlural('bo.blog-post.title-plural')
  119.             ->overrideTemplates([
  120.                 'crud/index' => 'admin/sortable-list-index.html.twig',
  121.                 'crud/edit' => 'admin/blog-post-edit.html.twig',
  122.             ])
  123.             ->setSearchFields(['title''description'])
  124.             ->setDefaultSort(['position' => 'asc'])
  125.             ->setFormThemes([
  126.                 '@EasyAdmin/crud/form_theme.html.twig',
  127.                 '@A2lixTranslationForm/bootstrap_5_layout.html.twig',
  128.                 'admin/forms/contributor.html.twig',
  129.             ]);
  130.     }
  131.     public function configureAssets(Assets $assets): Assets
  132.     {
  133.         return $assets
  134.             ->addJsFile('assets/admin/js/blog.js')
  135.             ->addJsFile('assets/admin/js/access-rights.js')
  136.             ->addJsFile('https://scribens.fr/API/tinymce.plugin.js');
  137.     }
  138.     private function redirectToIndex(): RedirectResponse
  139.     {
  140.         $url $this->get(AdminUrlGenerator::class)->setAction(Action::INDEX)->generateUrl();
  141.         if ($this->isFromFiltersCategory()) {
  142.             $categoryId $this->requestStack->getMainRequest()->get('filters')['blogPostCategory']['value'];
  143.             $url $this->get(AdminUrlGenerator::class)
  144.                 ->setAction(Action::INDEX)
  145.                 ->set('filters[blogPostCategory][value]'$categoryId)
  146.                 ->set('filters[blogPostCategory][comparison]''=')
  147.                 ->generateUrl();
  148.         }
  149.         return new RedirectResponse($url);
  150.     }
  151.     /**
  152.      * @throws Throwable
  153.      */
  154.     public function dropBlogPost(AdminContext $context): RedirectResponse
  155.     {
  156.         $categoryId null;
  157.         if ($this->isFromFiltersCategory()) {
  158.             $categoryId $this->requestStack->getMainRequest()->get('filters')['blogPostCategory']['value'];
  159.         }
  160.         $blogPost $context->getEntity()->getInstance();
  161.         $this->blogPostRepository->moveBlogPostDown($blogPost$categoryId);
  162.         return $this->redirectToIndex();
  163.     }
  164.     /**
  165.      * @throws Throwable
  166.      */
  167.     public function raiseBlogPost(AdminContext $context): RedirectResponse
  168.     {
  169.         $categoryId null;
  170.         if ($this->isFromFiltersCategory()) {
  171.             $categoryId $this->requestStack->getMainRequest()->get('filters')['blogPostCategory']['value'];
  172.         }
  173.         $blogPost $context->getEntity()->getInstance();
  174.         $this->blogPostRepository->moveBlogPostUp($blogPost$categoryId);
  175.         return $this->redirectToIndex();
  176.     }
  177.     private function isFromCategory(): bool
  178.     {
  179.         return $this->requestStack->getMainRequest()->get('category') !== null;
  180.     }
  181.     private function isFromListProgram(): bool
  182.     {
  183.         $filters $this->requestStack->getMainRequest()->get('filters');
  184.         if (is_array($filters) && array_key_exists('isScheduled'$filters)) {
  185.             return $this->requestStack->getMainRequest()->get('filters')['isScheduled'] !== null;
  186.         }
  187.         return false;
  188.     }
  189.     private function isFromFiltersCategory(): bool
  190.     {
  191.         $filters $this->requestStack->getMainRequest()->get('filters');
  192.         if (is_array($filters) && array_key_exists('blogPostCategory'$filters)) {
  193.             return $this->requestStack->getMainRequest()->get('filters')['blogPostCategory'] !== null;
  194.         }
  195.         return false;
  196.     }
  197.     public function createEntity(string $entityFqcn)
  198.     {
  199.         /** @var BlogPost $entity */
  200.         $entity = new $entityFqcn();
  201.         if ($this->isFromFiltersCategory()) {
  202.             $categoryId $this->requestStack->getMainRequest()->get('filters')['blogPostCategory']['value'];
  203.             $categoryIds is_array($categoryId) ? $categoryId : [$categoryId];
  204.             foreach ($categoryIds as $id) {
  205.                 $category $this->blogPostCategoryRepository->find($id);
  206.                 $entity->setBlogPostCategory($category);
  207.             }
  208.         }
  209.         return $entity;
  210.     }
  211.     public function persistEntity(EntityManagerInterface $entityManager$entityInstance): void
  212.     {
  213.         $entityInstance->setAuthor($this->GetUser());
  214.         // Set the position of the new Blog Post to 0
  215.         $entityInstance->SetPosition(0);
  216.         // Increase the positions of the all the BlogPost in the Categoriy
  217.         $blogPosts $entityInstance->getBlogPostCategory()->getBlogPosts();
  218.         foreach ($blogPosts as $blogPost) {
  219.             $blogPost->setPosition($blogPost->getPosition() + 1);
  220.             // dd($blogPost);
  221.             $this->em->persist($blogPost);
  222.         }
  223.         // Load the criterias from the category
  224.         $this->blogPostService->loadCategory($entityInstance);
  225.         $entityManager->flush();
  226.         parent::persistEntity($entityManager$entityInstance);
  227.     }
  228.     public function updateEntity(EntityManagerInterface $entityManager$entityInstance): void
  229.     {
  230.         // Update the updatedAt field of the current entity
  231.         $entityInstance->setUpdatedAt(new \DateTime());
  232.         // Set the Blog Post at first position
  233.         $this->blogPostService->movePositionTop($entityInstance);
  234.         // Create History
  235.         $user $this->getUser();
  236.         $historyUpdate = new BlogPostHistoryUpdate();
  237.         $historyUpdate->setBlogPost($entityInstance);
  238.         $historyUpdate->setUser($user);
  239.         $historyUpdate->setUpdatedAt(new \DateTime());
  240.         $entityManager->persist($historyUpdate);
  241.         parent::updateEntity($entityManager$entityInstance);
  242.     }
  243.     public function configureActions(Actions $actions): Actions
  244.     {
  245.         $dropBlogPost Action::new('dropBlogPost'false'fas fa-chevron-down')
  246.             ->displayAsLink()
  247.             ->linkToCrudAction('dropBlogPost')
  248.             ->addCssClass('btn')
  249.             ->setTemplatePath('admin/block-position-action.html.twig');
  250.         $raiseBlogPost Action::new('raiseBlogPost'false'fas fa-chevron-up')
  251.             ->displayAsLink()
  252.             ->linkToCrudAction('raiseBlogPost')
  253.             ->addCssClass('btn m-1')
  254.             ->setTemplatePath('admin/block-position-action.html.twig');
  255.         $loadCategory Action::new('loadCategory'"Charger la rubrique""fa fa-arrow-right")
  256.             ->linkToCrudAction('loadCategoryAction')
  257.             ->addCssClass('btn btn-secondary mx-2');
  258.         $viewScoringQuiz Action::new('scoringQuizAction''bo.cms.view_blog_post_scoring_quiz''fa fa-list')
  259.             ->linkToCrudAction("scoringQuizAction");
  260.         $viewIdentityForm Action::new('identityFormAction''Formulaire d\'identité''fa fa-file')
  261.             ->linkToCrudAction("identityFormAction");
  262.         $viewBlocks Action::new('viewBlocks''bo.cms.view_blog_post_blocks''fa fa-th-large')
  263.             ->addCssClass('btn btn-secondary')
  264.             ->linkToUrl(function (BlogPost $entity) {
  265.                 return $this->get(AdminUrlGenerator::class)
  266.                     ->setAction(Action::INDEX)
  267.                     ->setController(BlogPostGalleryCrudController::class)
  268.                     ->setEntityId(null)
  269.                     ->set('free_page_id'$entity->getId())
  270.                     ->generateUrl();
  271.             });
  272.         $viewEntity Action::new('viewEntity''bo.blog-post.link'"fa fa-eye")
  273.             ->setCssClass('btn btn-secondary')
  274.             ->setHtmlAttributes(["target" => "_blank"])
  275.             ->linkToRoute('podcast', function (BlogPost $entity) {
  276.                 $blogPost $this->blogPostRepository->findOneBy(['id' => $entity->getId()]);
  277.                 return [
  278.                     'slug' => $blogPost->getSlug(),
  279.                 ];
  280.             });
  281.         $downloadQRCode Action::new('downloadQRCode''bo.download-qr-code')
  282.             ->displayAsLink()
  283.             ->setHtmlAttributes(["download" => ""])
  284.             ->linkToUrl(function (BlogPost $entity) {
  285.                 return $this->get('parameter_bag')->get('app.url.qrcode') . '/' $entity->getQrCode();
  286.             });
  287.         $Duplicate Action::new('Duplicate''bo.duplicate')
  288.             ->linkToCrudAction('duplicateAction')->addCssClass('btn-duplicate');
  289.         $DuplicateEdit Action::new('Duplicate''bo.duplicate'"fa fa-clone")
  290.             ->linkToCrudAction('duplicateAction');
  291.         $deleteMedia Action::new('deleteMedia'false)
  292.             ->addCssClass('d-none')
  293.             ->linkToCrudAction('deleteMedia');
  294.         $deleteImagePreviewMedia Action::new('deleteImagePreviewMedia'false)
  295.             ->addCssClass('d-none')
  296.             ->linkToCrudAction('deleteImagePreviewMedia');
  297.         $deleteFeaturingImageMedia Action::new('deleteFeaturingImageMedia'false)
  298.             ->addCssClass('d-none')
  299.             ->linkToCrudAction('deleteFeaturingImageMedia');
  300.         $deletePreviewVideo Action::new('deletePreviewVideo'false)
  301.             ->addCssClass('d-none')
  302.             ->linkToCrudAction('deletePreviewVideo');
  303.         $programAction Action::new('listProgram''bo.action.list-program')
  304.             ->createAsGlobalAction()
  305.             ->linkToCrudAction('listProgram');
  306.         if ($this->isFromCategory()) {
  307.             $actions
  308.                 ->add(Crud::PAGE_INDEXCsvAction::new())
  309.                 ->add(Crud::PAGE_INDEX$programAction)
  310.                 ->remove(Crud::PAGE_INDEXAction::NEW)
  311.                 ->remove(Crud::PAGE_INDEXAction::EDIT)
  312.                 ->remove(Crud::PAGE_INDEXAction::DELETE)
  313.                 ->remove(Crud::PAGE_INDEXAction::DETAIL);
  314.         }
  315.         return $actions
  316.             ->remove(Crud::PAGE_NEWAction::SAVE_AND_ADD_ANOTHER)
  317.             ->add(Crud::PAGE_INDEXCsvAction::new())
  318.             ->add(Crud::PAGE_INDEX$programAction)
  319.             ->add(Crud::PAGE_DETAIL$viewEntity)
  320.             ->add(Crud::PAGE_INDEX$downloadQRCode)
  321.             ->add(Crud::PAGE_INDEX$Duplicate)
  322.             ->add(Crud::PAGE_INDEX$dropBlogPost)
  323.             ->add(Crud::PAGE_INDEX$raiseBlogPost)
  324.             ->add(Crud::PAGE_EDIT$viewEntity)
  325.             ->add(Crud::PAGE_EDIT$DuplicateEdit)
  326.             ->add(Crud::PAGE_EDIT$viewScoringQuiz)
  327.             ->add(Crud::PAGE_EDIT$viewIdentityForm)
  328.             ->add(Crud::PAGE_EDIT$viewBlocks)
  329.             ->add(Crud::PAGE_EDIT$deleteMedia)
  330.             ->add(Crud::PAGE_EDIT$deleteImagePreviewMedia)
  331.             ->add(Crud::PAGE_EDIT$deleteFeaturingImageMedia)
  332.             ->add(Crud::PAGE_EDIT$deletePreviewVideo)
  333.             ->add(Crud::PAGE_NEWAction::SAVE_AND_CONTINUE)
  334.             ->add(Crud::PAGE_EDIT$loadCategory);
  335.     }
  336.     public function scoringQuizAction(AdminContext $context)
  337.     {
  338.         $this->em->clear();
  339.         $entityId $context->getRequest()->query->get('entityId');
  340.         // Use the repository directly
  341.         $blogPostRepository $this->em->getRepository(BlogPost::class);
  342.         
  343.         /** @var BlogPost $instance */
  344.         $instance $blogPostRepository->findWithRelationships($entityId);
  345.         if (!$instance) {
  346.             throw $this->createNotFoundException('Blog post not found');
  347.         }
  348.         $scoringQuiz $instance->getScoringQuiz();
  349.         if ($scoringQuiz) {
  350.             $url $this->adminUrlGenerator->setAction(Action::EDIT)
  351.                 ->set("blogPostId"$instance->getId())
  352.                 ->setEntityId($scoringQuiz->getId())
  353.                 ->setController(ScoringQuizCrudController::class)
  354.                 ->generateUrl();
  355.         } else {
  356.             $url $this->adminUrlGenerator->setAction(Action::NEW)
  357.                 ->set("blogPostId"$instance->getId())
  358.                 ->setEntityId(null)
  359.                 ->setController(ScoringQuizCrudController::class)
  360.                 ->generateUrl();
  361.         }
  362.         return $this->redirect($url);
  363.     }
  364.     public function identityFormAction(AdminContext $context)
  365.     {
  366.         /** @var BlogPost $instance */
  367.         $instance $context->getEntity()->getInstance();
  368.         $identityForm $instance->getIdentityForm();
  369.         if ($identityForm) {
  370.             $url $this->adminUrlGenerator->setAction(Action::EDIT)
  371.                 ->set("blogPostId"$instance->getId())
  372.                 ->setEntityId($identityForm->getId())
  373.                 ->setController(IdentityFormCrudController::class)
  374.                 ->generateUrl();
  375.         } else {
  376.             $url $this->adminUrlGenerator->setAction(Action::NEW)
  377.                 ->set("blogPostId"$instance->getId())
  378.                 ->setEntityId(null)
  379.                 ->setController(IdentityFormCrudController::class)
  380.                 ->generateUrl();
  381.         }
  382.         return $this->redirect($url);
  383.     }
  384.     public function loadCategoryAction(AdminContext $context): Response
  385.     {
  386.         /** @var BlogPost $instance */
  387.         $instance $context->getEntity()->getInstance();
  388.         $this->blogPostService->loadCategory($instance);
  389.         return $this->redirectToItem($instance);
  390.     }
  391.     public function duplicateAction(DuplicatePost $duplicatePostEntityManagerInterface $entityManagerAdminContext $context)
  392.     {
  393.         $clonedEntity $duplicatePost->createClonedEntity($context);
  394.         $this->blogPostService->movePositionTop($clonedEntity);
  395.         $url $this->adminUrlGenerator->setAction(Action::EDIT)
  396.             ->setEntityId($clonedEntity->getId())
  397.             ->generateUrl();
  398.         return $this->redirect($url);
  399.     }
  400.     public function configureResponseParameters(KeyValueStore $responseParameters): KeyValueStore
  401.     {
  402.         if ($responseParameters->get('pageName') === Crud::PAGE_EDIT) {
  403.             /** @var BlogPost $entity */
  404.             $entity $this->getContext()->getEntity()->getInstance();
  405.             $responseParameters->set('mediaMime'$entity->getMedia()?->getFile()?->getMimeType());
  406.         }
  407.         if ($responseParameters->get('pageName') == Crud::PAGE_INDEX) {
  408.             // get the current selected category
  409.             if ($this->isFromFiltersCategory()) {
  410.                 $categoryId $this->requestStack->getMainRequest()->get('filters')['blogPostCategory']['value'];
  411.                 if ($categoryId) {
  412.                     $category $this->blogPostCategoryRepository->find($categoryId);
  413.                     $blogPostPositions $category->getBlogPosts()->map(fn(BlogPost $bp) => $bp->getPosition())->toArray();
  414.                 }
  415.             } else {
  416.                 $blogPosts $this->blogPostRepository->findAll();
  417.                 $blogPostPositions array_map(fn(BlogPost $bp) => $bp->getPosition(), $blogPosts);
  418.             }
  419.             if ($blogPostPositions) {
  420.                 $min min($blogPostPositions);
  421.                 $max max($blogPostPositions);
  422.             } else {
  423.                 $min = -1;
  424.                 $max = -1;
  425.             }
  426.             $responseParameters->set('minPos'$min);
  427.             $responseParameters->set('maxPos'$max);
  428.         }
  429.         return $responseParameters;
  430.     }
  431.     public function configureFilters(Filters $filters): Filters
  432.     {
  433.         if (!$this->isFromCategory()) {
  434.             $filters
  435.                 ->add(EntityFilter::new('criteria1Items'$this->criteria1Repository->findOneBy([])->getName()))
  436.                 ->add(EntityFilter::new('criteria2Items'$this->criteria2Repository->findOneBy([])->getName()))
  437.                 ->add(EntityFilter::new('criteria3Items'$this->criteria3Repository->findOneBy([])->getName()))
  438.                 ->add(EntityFilter::new('blogPostCategory''bo.blog-post-category.title')
  439.                     ->setFormTypeOption('value_type_options.placeholder''Seléctionner une rubrique')
  440.                     ->setFormTypeOption('value_type_options.empty_data'null)
  441.                 )
  442.                 ->add(BooleanFilter::new('isScheduled''bo.blog-post.field.is-scheduled')->setFormTypeOption('expanded'true))
  443.                 ->add(BooleanFilter::new('isActivated''bo.blog-post.field.is-activated')->setFormTypeOption('expanded'true));
  444.         }
  445.     
  446.         return $filters;
  447.     }
  448.     public function deleteMedia(AdminContext $context): Response
  449.     {
  450.         /** @var BlogPost $entity */
  451.         $entity $context->getEntity()->getInstance();
  452.         $this->em->remove($entity->getMedia());
  453.         $entity->setMedia(null);
  454.         $this->em->persist($entity);
  455.         $this->em->flush();
  456.         return $this->redirectToItem($entity);
  457.     }
  458.     public function deleteImagePreviewMedia(AdminContext $context): Response
  459.     {
  460.         /** @var BlogPost $entity */
  461.         $entity $context->getEntity()->getInstance();
  462.         $this->em->remove($entity->getImagePreviewMedia());
  463.         $entity->setImagePreviewMedia(null);
  464.         $this->em->persist($entity);
  465.         $this->em->flush();
  466.         return $this->redirectToItem($entity);
  467.     }
  468.     public function deletePreviewVideo(AdminContext $context)
  469.     {
  470.         /** @var BlogPost $entity */
  471.         $entity $context->getEntity()->getInstance();
  472.         $this->em->remove($entity->getPreviewVideo());
  473.         $entity->setPreviewVideo(null);
  474.         $this->em->persist($entity);
  475.         $this->em->flush();
  476.         return $this->redirectToItem($entity);
  477.     }
  478.     public function deleteFeaturingImageMedia(AdminContext $context)
  479.     {
  480.         /** @var BlogPost $entity */
  481.         $entity $context->getEntity()->getInstance();
  482.         $this->em->remove($entity->getFeaturingImageMedia());
  483.         $entity->setFeaturingImageMedia(null);
  484.         $this->em->persist($entity);
  485.         $this->em->flush();
  486.         return $this->redirectToItem($entity);
  487.     }
  488.     private function redirectToItem(BlogPost $item): Response
  489.     {
  490.         return $this->redirect(
  491.             $this->adminUrlGenerator->setAction(Action::EDIT)
  492.                 ->setEntityId($item->getId())
  493.                 ->generateUrl()
  494.         );
  495.     }
  496.     public function listProgram(AdminContext $context): RedirectResponse
  497.     {
  498.         $url $this->get(AdminUrlGenerator::class)
  499.             ->setAction(Action::INDEX)
  500.             ->set('filters[isScheduled][value]'true)
  501.             ->generateUrl();
  502.         return new RedirectResponse($url);
  503.     }
  504.     public function csvExport(AdminContext $context): StreamedResponse
  505.     {
  506.         $entityClass $this->getEntityFqcn();
  507.         $qb $this->em->createQueryBuilder()
  508.             ->from($entityClass'n')
  509.             ->addSelect('n')
  510.             ->orderBy('n.createdAt');
  511.         if ($this->isFromListProgram()) {
  512.             $qb->andWhere('n.isScheduled = :type')
  513.                 ->setParameter('type'true);
  514.         }
  515.         if ($this->isFromFiltersCategory()) {
  516.             $categoryId $this->requestStack->getMainRequest()->get('filters')['blogPostCategory']['value'];
  517.             $qb->innerJoin('n.blogPostCategory''bpc')
  518.                 ->andWhere('bpc IN (:cat)')
  519.                 ->setParameter('cat'$categoryId);;
  520.         }
  521.         $fileName sprintf('Contenu-%s.csv'date('d-M-Y_H-i'));
  522.         $res $this->csvExporter->getResponseFromQueryBuilder($qb$entityClass$fileName);
  523.         return $res;
  524.     }
  525.     /**
  526.      * @param string $pageName
  527.      * @return iterable
  528.      */
  529.     public function configureFields(string $pageName): iterable
  530.     {
  531.         /** @var BlogPost $instance */
  532.         $instance $this->adminContextProvider->getContext()->getEntity()->getInstance();
  533.         if ($instance) {
  534.             /** @var BlogPostCategory $category */
  535.             $category $instance->getBlogPostCategory();
  536.         }
  537.         $fieldRoleDisabled = isset($category) ? !$category->getIsPublic() : false;
  538.         $fieldCriteria1Disabled = isset($category) ? !$category->isHasAllCriteria1() : false;
  539.         $fieldCriteria2Disabled = isset($category) ? !$category->isHasAllCriteria2() : false;
  540.         $fieldCriteria3Disabled = isset($category) ? !$category->isHasAllCriteria3() : false;
  541.         if ($pageName === Crud::PAGE_NEW) {
  542.             $instance->setIsPublic(true);
  543.             $instance->setHasAllCriteria1(true);
  544.             $instance->setHasAllCriteria2(true);
  545.             $instance->setHasAllCriteria3(true);
  546.             // Set the default desactivation date
  547.             $defaultLifeTime $this->serviceSiteConfig->isBlogPostLifeTime();
  548.             if ($defaultLifeTime) {
  549.                 $defaultLifeTimeDays $this->serviceSiteConfig->getBlogPostLifeTimeDays();
  550.                 $interval DateInterval::createFromDateString(strval($defaultLifeTimeDays ?? 0) . ' days');
  551.                 $instance->setActivationDate(new DateTime());
  552.                 $instance->setDesactivationDate((new DateTime())->add($interval));
  553.                 $instance->setIsScheduled(true);
  554.             }
  555.         }
  556.         $status = ["Brouillon" => "0""Activé" => "1"];
  557.         yield IntegerField::new('position''bo.blog-post.field.position')
  558.             ->onlyOnDetail();
  559.         yield TextField::new('title''bo.blog-post.field.title')
  560.             ->hideOnForm();
  561.         yield ImageField::new('qrCode''common.qr-code')
  562.             ->setUploadDir($this->getParameter('app.folder.qrcode'))
  563.             ->setBasePath($this->getParameter('app.url.qrcode'))
  564.             ->onlyOnDetail();
  565.         yield FormField::addPanel('bo.blog-post.base-options')
  566.             ->collapsible()
  567.             ->addCssClass('col-md-8');
  568.         yield BooleanField::new('isActivated')
  569.             ->setLabel('bo.blog-post.field.is-activated')
  570.             ->setDisabled(in_array(User::ROLE_REDACTEUR$this->getUser()->getRoles()))
  571.             ->addCssClass('activated-toggle')
  572.             ->setColumns(3);
  573.         yield BooleanField::new('isFeatured')
  574.             ->setLabel('bo.blog-post.field.is-featured')
  575.             ->setColumns(3)
  576.             ->addCssClass('featured-toggle');
  577.         yield BooleanField::new('isScheduled')
  578.             ->setLabel('bo.blog-post.field.scheduling')
  579.             ->setDisabled(in_array(User::ROLE_REDACTEUR$this->getUser()->getRoles()))
  580.             ->setColumns(3)
  581.             ->setCssClass('scheduling-toggle')
  582.             ->onlyOnForms();
  583.         yield BooleanField::new('isNotify')
  584.             ->setLabel('bo.blog-post.field.is-notify')
  585.             ->setCssClass('notify-toggle')
  586.             ->setColumns(3)
  587.             ->onlyOnForms();
  588.         yield AssociationField::new('blogPostCategory')
  589.             ->setLabel('bo.blog-post-category.title')
  590.             ->setRequired(true)
  591.             ->setQueryBuilder(function (QueryBuilder $queryBuilder) {
  592.                 // If the user is ROLE_CHEF_RUBRIQUE then filter on the selectables Categories for this user
  593.                 if (array_search(User::ROLE_CHEF_RUBRIQUE$this->getUser()->getRoles())) {
  594.                     $queryBuilder->join('entity.users''user')
  595.                         ->andWhere("user.id = :userId")
  596.                         ->setParameter("userId"$this->getUser()->getId());
  597.                 }
  598.                 return $queryBuilder->andWhere('entity.isActivated = TRUE');
  599.             })
  600.             ->setColumns(6);
  601.         yield AssociationField::new('preference''Préference')
  602.             ->setColumns('col-md-12')
  603.             ->setColumns(6);
  604.         yield FormField::addPanel('bo.blog-post.access')
  605.             ->collapsible(true)
  606.             ->renderCollapsed(false)
  607.             ->addCssClass('col-md-4');
  608.         yield BooleanField::new('isPublic')
  609.             ->setLabel('bo.blog-post.field.is-public')
  610.             ->setDisabled($fieldRoleDisabled)
  611.             ->setCssClass('public-toggle')
  612.             ->setColumns('col-md-6')
  613.             ->hideOnIndex();
  614.         yield AssociationField::new('roles''Roles')
  615.             ->setQueryBuilder(function (QueryBuilder $queryBuilder) {
  616.                 return $queryBuilder->andWhere('entity.status = TRUE');
  617.             })
  618.             ->onlyOnForms()
  619.             ->setHelp("<span>Si vide, le contenu ne sera jamais visible.</span>")
  620.             ->setDisabled($fieldRoleDisabled)
  621.             ->setColumns('col-md-8 roles-toggle');
  622.         yield AssociationField::new('roles''Roles')
  623.             ->hideOnForm()
  624.             ->formatValue(function ($value$entity) {
  625.                 $count count($entity->getRoles());
  626.                 $rolesList implode(', 'array_map(function ($role$index) {
  627.                     return '<li><a href="#" class="category-list" data-list="category-list-' $index '" data-parent=".category-link">' $role->getName() . '</a></li>';
  628.                 }, $entity->getRoles()->toArray(), array_keys($entity->getRoles()->toArray())));
  629.                 return '<span class="category-link-wrapper"><a href="#" class="category-link" data-count="' $count '" data-list="' htmlspecialchars($rolesList) . '">' $count '</a></span>';
  630.             });
  631.         yield BooleanField::new('hasAllCriteria1')
  632.             ->setLabel('Tout ' $this->criteria1Repository->findOneBy([])->getName())
  633.             ->setDisabled($fieldCriteria1Disabled)
  634.             ->setCssClass('criteria1-toggle')
  635.             ->onlyOnForms();
  636.         yield AssociationField::new('criteria1Items')
  637.             ->setLabel($this->criteria1Repository->findOneBy([])->getName())
  638.             ->onlyOnForms()
  639.             ->setHelp("<span>Si vide, le contenu ne sera jamais visible.</span>")
  640.             ->setDisabled($fieldCriteria1Disabled)
  641.             ->setColumns('col-md-8 criteria1-items');
  642.         yield BooleanField::new('hasAllCriteria2')
  643.             ->setLabel('Tout ' $this->criteria2Repository->findOneBy([])->getName())
  644.             ->setDisabled($fieldCriteria2Disabled)
  645.             ->setCssClass('criteria2-toggle')
  646.             ->onlyOnForms();
  647.         yield AssociationField::new('criteria2Items')
  648.             ->setLabel($this->criteria2Repository->findOneBy([])->getName())
  649.             ->onlyOnForms()
  650.             ->setHelp("<span>Si vide, le contenu ne sera jamais visible.</span>")
  651.             ->setDisabled($fieldCriteria2Disabled)
  652.             ->setColumns('col-md-8 criteria2-items');
  653.         yield BooleanField::new('hasAllCriteria3')
  654.             ->setLabel('Tout ' $this->criteria3Repository->findOneBy([])->getName())
  655.             ->setDisabled($fieldCriteria3Disabled)
  656.             ->setCssClass('criteria3-toggle')
  657.             ->onlyOnForms();
  658.         yield AssociationField::new('criteria3Items')
  659.             ->setLabel($this->criteria3Repository->findOneBy([])->getName())
  660.             ->setHelp("<span>Si vide, le contenu ne sera jamais visible.</span>")
  661.             ->onlyOnForms()
  662.             ->setDisabled($fieldCriteria3Disabled)
  663.             ->setColumns('col-md-8 criteria3-items');
  664.         yield FormField::addPanel('Programmation')
  665.             ->addCssClass('col-md-8 collapsible collapse notification-panel')
  666.             ->setFormTypeOption('attr', ['style' => 'display: none;'])
  667.             ->collapsible();
  668.         yield DateTimeField::new('activation_date')
  669.             ->setLabel('bo.blog-post.field.activation_date')
  670.             ->setColumns(3)
  671.             ->onlyOnForms();
  672.         yield DateTimeField::new('desactivation_date')
  673.             ->setLabel('bo.blog-post.field.desactivation_date')
  674.             ->setColumns(3)
  675.             ->onlyOnForms();
  676.         yield NotificationField::new('notification'false)
  677.             ->setColumns(6)
  678.             ->onlyOnForms();
  679.         yield FormField::addPanel('bo.pages.content')
  680.             ->collapsible()
  681.             ->addCssClass('col-md-12');
  682.         yield TextField::new("title""bo.blog-post.field.title")
  683.             ->setRequired(true)
  684.             ->onlyOnForms()
  685.             ->setColumns(6);
  686.         yield TextField::new("slug""bo.blog-post.field.slug")
  687.             ->setHelp("Le champ doit contenir uniquement des lettres minuscules, chiffres et tirets.")
  688.             ->hideOnIndex()
  689.             ->setColumns(6);
  690.         yield TextareaField::new('description''bo.blog-post.field.description')
  691.             ->addCssClass("tinymce-enable")
  692.             ->hideOnIndex()
  693.             ->setColumns(12);
  694.         yield MediaField::new('media''bo.blog-post.field.media')
  695.             ->setRequired(false)
  696.             ->setAccept(implode(','Media::UPLOAD_MIMES))
  697.             ->setHelp($this->helpers->getAdminMediaHelp())
  698.             ->setDeleteAction('deleteMedia')
  699.             ->onlyOnForms();
  700.         yield FormField::addPanel('Prévisualisations')
  701.             ->collapsible()
  702.             ->addCssClass('col-md-12');
  703.         yield MediaField::new('imagePreviewMedia''bo.blog-post.field.image-preview')
  704.             ->setRequired(true)
  705.             ->setHelp($this->helpers->getAdminImgHelp('blog_preview'))
  706.             ->setDeleteAction('deleteImagePreviewMedia')
  707.             ->setAccept(implode(','Media::IMAGE_MIMES))
  708.             ->setColumns(6)
  709.             ->onlyWhenCreating();
  710.         yield MediaField::new('imagePreviewMedia''bo.blog-post.field.image-preview')
  711.             ->setRequired(false)
  712.             ->setHelp($this->helpers->getAdminImgHelp('blog_preview'))
  713.             ->setDeleteAction('deleteImagePreviewMedia')
  714.             ->setAccept(implode(','Media::IMAGE_MIMES))
  715.             ->setColumns(4)
  716.             ->onlyWhenUpdating();
  717.         yield BooleanField::new('isFeaturedTitle')
  718.             ->setLabel('bo.blog-post.field.is-featured-title')
  719.             ->hideOnIndex()
  720.             ->setColumns(3);
  721.         yield MediaField::new('previewVideo''bo.blog-post.field.video-preview')
  722.             ->setRequired(false)
  723.             ->addCssClass('video-preview')
  724.             ->setHelp($this->helpers->getAdminVideoHelp())
  725.             ->setDeleteAction('deletePreviewVideo')
  726.             ->setAccept(implode(','Media::VIDEO_MIMES))
  727.             ->setColumns(4)
  728.             ->onlyOnForms();
  729.         yield MediaField::new('featuringImageMedia''bo.blog-post.field.featuring-image')
  730.             ->setRequired(false)
  731.             ->addCssClass('featuring-image')
  732.             ->setAccept(implode(','Media::IMAGE_MIMES))
  733.             ->setHelp($this->helpers->getAdminImgHelp('blog_featuring'))
  734.             ->setDeleteAction('deleteFeaturingImageMedia')
  735.             ->onlyOnForms();
  736.         yield BooleanField::new('isPublic')
  737.             ->setLabel('bo.blog-post.field.public')
  738.             ->renderAsSwitch(false)
  739.             ->onlyOnIndex();
  740.         yield DateTimeField::new('notificationSentAt')
  741.             ->setLabel('bo.blog-post.field.notification-sent-at')
  742.             ->onlyOnIndex();
  743.         yield FormField::addRow();
  744.         yield DateTimeField::new('createdAt')
  745.             ->setLabel('bo.created-at')
  746.             ->setFormat('dd-MM-Y HH:mm:ss')
  747.             ->hideOnForm();
  748.         yield DateTimeField::new('updatedAt')
  749.             ->setLabel('bo.updated-at')
  750.             ->setFormat('dd-MM-Y HH:mm:ss')
  751.             ->hideOnForm();
  752.         yield DateTimeField::new('updatedAt')
  753.             ->setLabel('bo.updated-at')
  754.             ->setFormat('dd-MM-Y HH:mm:ss')
  755.             ->onlyOnDetail();
  756.         yield FormField::addPanel('bo.cms.page.seo-panel')
  757.             ->renderCollapsed(true);
  758.         yield SeoField::new('seo')
  759.             ->onlyOnForms();
  760.         yield FormField::addPanel('bo.blog-post.blogPostHistoryUpdates')
  761.             ->collapsible(true)
  762.             ->onlyOnDetail()
  763.             ->renderCollapsed(false);
  764.         yield AssociationField::new('blogPostHistoryUpdates''')
  765.             ->setTemplatePath('admin/crud/field/update-history.html.twig')
  766.             ->onlyOnDetail();
  767.     }
  768. }