<?php
namespace App\Controller\Admin;
use Throwable;
use App\Entity\User;
use App\Entity\Media;
use App\Service\Role;
use App\Entity\BlogPost;
use App\Service\Helpers;
use App\Service\Position;
use App\Service\CsvExporter;
use App\Admin\Field\SeoField;
use App\Service\DuplicatePost;
use Doctrine\ORM\QueryBuilder;
use App\Admin\Action\CsvAction;
use App\Admin\Field\MediaField;
use App\Entity\BlogPostHistoryUpdate;
use App\Repository\BlogPostRepository;
use App\Admin\Field\NotificationField;
use App\Admin\Field\TextareaField;
use App\Entity\BlogPostCategory;
use App\Entity\ScoringQuiz;
use Doctrine\ORM\EntityManagerInterface;
use App\Service\BlogPost as BlogPostService;
use App\Repository\BlogPostCategoryRepository;
use App\Repository\Criteria1Repository;
use App\Repository\Criteria2Repository;
use App\Repository\Criteria3Repository;
use App\Repository\ScoringQuizRepository;
use App\Service\SiteConfig;
use Symfony\Component\HttpFoundation\Response;
use EasyCorp\Bundle\EasyAdminBundle\Config\Crud;
use EasyCorp\Bundle\EasyAdminBundle\Config\Action;
use EasyCorp\Bundle\EasyAdminBundle\Config\Assets;
use EasyCorp\Bundle\EasyAdminBundle\Dto\EntityDto;
use EasyCorp\Bundle\EasyAdminBundle\Dto\SearchDto;
use EasyCorp\Bundle\EasyAdminBundle\Config\Actions;
use EasyCorp\Bundle\EasyAdminBundle\Config\Filters;
use EasyCorp\Bundle\EasyAdminBundle\Field\FormField;
use EasyCorp\Bundle\EasyAdminBundle\Field\TextField;
use EasyCorp\Bundle\EasyAdminBundle\Field\ImageField;
use EasyCorp\Bundle\EasyAdminBundle\Field\ChoiceField;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\StreamedResponse;
use Symfony\Contracts\Translation\TranslatorInterface;
use EasyCorp\Bundle\EasyAdminBundle\Field\BooleanField;
use EasyCorp\Bundle\EasyAdminBundle\Field\IntegerField;
use EasyCorp\Bundle\EasyAdminBundle\Field\DateTimeField;
use EasyCorp\Bundle\EasyAdminBundle\Filter\EntityFilter;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use EasyCorp\Bundle\EasyAdminBundle\Config\KeyValueStore;
use EasyCorp\Bundle\EasyAdminBundle\Context\AdminContext;
use EasyCorp\Bundle\EasyAdminBundle\Filter\BooleanFilter;
use EasyCorp\Bundle\EasyAdminBundle\Field\AssociationField;
use Symfony\Component\Form\Extension\Core\Type\TextareaType;
use EasyCorp\Bundle\EasyAdminBundle\Router\AdminUrlGenerator;
use EasyCorp\Bundle\EasyAdminBundle\Collection\FieldCollection;
use EasyCorp\Bundle\EasyAdminBundle\Collection\FilterCollection;
use EasyCorp\Bundle\EasyAdminBundle\Provider\AdminContextProvider;
use EasyCorp\Bundle\EasyAdminBundle\Controller\AbstractCrudController;
use DateInterval;
use DateTime;
use Doctrine\Common\Collections\Collection;
use Symfony\Component\HttpFoundation\RequestStack;
class BlogPostCrudController extends AbstractCrudController
{
public function __construct(
private Helpers $helpers,
private BlogPostRepository $blogPostRepository,
private BlogPostCategoryRepository $blogPostCategoryRepository,
private Position $position,
private TranslatorInterface $translator,
private AdminUrlGenerator $adminUrlGenerator,
private Role $role,
private EntityManagerInterface $em,
private BlogPostService $blogPostService,
private CsvExporter $csvExporter,
private AdminContextProvider $adminContextProvider,
private SiteConfig $serviceSiteConfig,
private Criteria1Repository $criteria1Repository,
private Criteria2Repository $criteria2Repository,
private Criteria3Repository $criteria3Repository,
private RequestStack $requestStack,
private ScoringQuizRepository $scoringQuizRepository,
) {}
public static function getEntityFqcn(): string
{
return BlogPost::class;
}
public function createIndexQueryBuilder(SearchDto $searchDto, EntityDto $entityDto, FieldCollection $fields, FilterCollection $filters): QueryBuilder
{
$qb = parent::createIndexQueryBuilder($searchDto, $entityDto, $fields, $filters);
// Get only owned Post for ROLE_REDACTEUR
if (array_search(User::ROLE_REDACTEUR, $this->getUser()->getRoles())) {
$qb->where("entity.author = :user")
->setParameter("user", $this->getUser());
} else if (array_search(User::ROLE_CHEF_RUBRIQUE, $this->getUser()->getRoles())) {
// Get only Posts for the assigned categories of the current user
$qb->join('entity.blogPostCategory', 'bpc')
->join('bpc.users', 'user')
->andWhere("user.id = :userId")
->setParameter("userId", $this->getUser()->getId());
}
$qb->leftJoin('entity.scoringQuiz', 'sq')
->leftJoin('entity.identityForm', 'if');
return $qb;
}
/**
* @param Crud $crud
* @return Crud
*/
public function configureCrud(Crud $crud): Crud
{
$this->blogPostRepository->checkPositions();
return $crud
// the labels used to refer to this entity in titles, buttons, etc.
->setPageTitle(Crud::PAGE_INDEX, 'bo.blog-post.title-plural')
->setEntityLabelInSingular('bo.blog-post.title')
->setEntityLabelInPlural('bo.blog-post.title-plural')
->overrideTemplates([
'crud/index' => 'admin/sortable-list-index.html.twig',
'crud/edit' => 'admin/blog-post-edit.html.twig',
])
->setSearchFields(['title', 'description'])
->setDefaultSort(['position' => 'asc'])
->setFormThemes([
'@EasyAdmin/crud/form_theme.html.twig',
'@A2lixTranslationForm/bootstrap_5_layout.html.twig',
'admin/forms/contributor.html.twig',
]);
}
public function configureAssets(Assets $assets): Assets
{
return $assets
->addJsFile('assets/admin/js/blog.js')
->addJsFile('assets/admin/js/access-rights.js')
->addJsFile('https://scribens.fr/API/tinymce.plugin.js');
}
private function redirectToIndex(): RedirectResponse
{
$url = $this->get(AdminUrlGenerator::class)->setAction(Action::INDEX)->generateUrl();
if ($this->isFromFiltersCategory()) {
$categoryId = $this->requestStack->getMainRequest()->get('filters')['blogPostCategory']['value'];
$url = $this->get(AdminUrlGenerator::class)
->setAction(Action::INDEX)
->set('filters[blogPostCategory][value]', $categoryId)
->set('filters[blogPostCategory][comparison]', '=')
->generateUrl();
}
return new RedirectResponse($url);
}
/**
* @throws Throwable
*/
public function dropBlogPost(AdminContext $context): RedirectResponse
{
$categoryId = null;
if ($this->isFromFiltersCategory()) {
$categoryId = $this->requestStack->getMainRequest()->get('filters')['blogPostCategory']['value'];
}
$blogPost = $context->getEntity()->getInstance();
$this->blogPostRepository->moveBlogPostDown($blogPost, $categoryId);
return $this->redirectToIndex();
}
/**
* @throws Throwable
*/
public function raiseBlogPost(AdminContext $context): RedirectResponse
{
$categoryId = null;
if ($this->isFromFiltersCategory()) {
$categoryId = $this->requestStack->getMainRequest()->get('filters')['blogPostCategory']['value'];
}
$blogPost = $context->getEntity()->getInstance();
$this->blogPostRepository->moveBlogPostUp($blogPost, $categoryId);
return $this->redirectToIndex();
}
private function isFromCategory(): bool
{
return $this->requestStack->getMainRequest()->get('category') !== null;
}
private function isFromListProgram(): bool
{
$filters = $this->requestStack->getMainRequest()->get('filters');
if (is_array($filters) && array_key_exists('isScheduled', $filters)) {
return $this->requestStack->getMainRequest()->get('filters')['isScheduled'] !== null;
}
return false;
}
private function isFromFiltersCategory(): bool
{
$filters = $this->requestStack->getMainRequest()->get('filters');
if (is_array($filters) && array_key_exists('blogPostCategory', $filters)) {
return $this->requestStack->getMainRequest()->get('filters')['blogPostCategory'] !== null;
}
return false;
}
public function createEntity(string $entityFqcn)
{
/** @var BlogPost $entity */
$entity = new $entityFqcn();
if ($this->isFromFiltersCategory()) {
$categoryId = $this->requestStack->getMainRequest()->get('filters')['blogPostCategory']['value'];
$categoryIds = is_array($categoryId) ? $categoryId : [$categoryId];
foreach ($categoryIds as $id) {
$category = $this->blogPostCategoryRepository->find($id);
$entity->setBlogPostCategory($category);
}
}
return $entity;
}
public function persistEntity(EntityManagerInterface $entityManager, $entityInstance): void
{
$entityInstance->setAuthor($this->GetUser());
// Set the position of the new Blog Post to 0
$entityInstance->SetPosition(0);
// Increase the positions of the all the BlogPost in the Categoriy
$blogPosts = $entityInstance->getBlogPostCategory()->getBlogPosts();
foreach ($blogPosts as $blogPost) {
$blogPost->setPosition($blogPost->getPosition() + 1);
// dd($blogPost);
$this->em->persist($blogPost);
}
// Load the criterias from the category
$this->blogPostService->loadCategory($entityInstance);
$entityManager->flush();
parent::persistEntity($entityManager, $entityInstance);
}
public function updateEntity(EntityManagerInterface $entityManager, $entityInstance): void
{
// Update the updatedAt field of the current entity
$entityInstance->setUpdatedAt(new \DateTime());
// Set the Blog Post at first position
$this->blogPostService->movePositionTop($entityInstance);
// Create History
$user = $this->getUser();
$historyUpdate = new BlogPostHistoryUpdate();
$historyUpdate->setBlogPost($entityInstance);
$historyUpdate->setUser($user);
$historyUpdate->setUpdatedAt(new \DateTime());
$entityManager->persist($historyUpdate);
parent::updateEntity($entityManager, $entityInstance);
}
public function configureActions(Actions $actions): Actions
{
$dropBlogPost = Action::new('dropBlogPost', false, 'fas fa-chevron-down')
->displayAsLink()
->linkToCrudAction('dropBlogPost')
->addCssClass('btn')
->setTemplatePath('admin/block-position-action.html.twig');
$raiseBlogPost = Action::new('raiseBlogPost', false, 'fas fa-chevron-up')
->displayAsLink()
->linkToCrudAction('raiseBlogPost')
->addCssClass('btn m-1')
->setTemplatePath('admin/block-position-action.html.twig');
$loadCategory = Action::new('loadCategory', "Charger la rubrique", "fa fa-arrow-right")
->linkToCrudAction('loadCategoryAction')
->addCssClass('btn btn-secondary mx-2');
$viewScoringQuiz = Action::new('scoringQuizAction', 'bo.cms.view_blog_post_scoring_quiz', 'fa fa-list')
->linkToCrudAction("scoringQuizAction");
$viewIdentityForm = Action::new('identityFormAction', 'Formulaire d\'identité', 'fa fa-file')
->linkToCrudAction("identityFormAction");
$viewBlocks = Action::new('viewBlocks', 'bo.cms.view_blog_post_blocks', 'fa fa-th-large')
->addCssClass('btn btn-secondary')
->linkToUrl(function (BlogPost $entity) {
return $this->get(AdminUrlGenerator::class)
->setAction(Action::INDEX)
->setController(BlogPostGalleryCrudController::class)
->setEntityId(null)
->set('free_page_id', $entity->getId())
->generateUrl();
});
$viewEntity = Action::new('viewEntity', 'bo.blog-post.link', "fa fa-eye")
->setCssClass('btn btn-secondary')
->setHtmlAttributes(["target" => "_blank"])
->linkToRoute('podcast', function (BlogPost $entity) {
$blogPost = $this->blogPostRepository->findOneBy(['id' => $entity->getId()]);
return [
'slug' => $blogPost->getSlug(),
];
});
$downloadQRCode = Action::new('downloadQRCode', 'bo.download-qr-code')
->displayAsLink()
->setHtmlAttributes(["download" => ""])
->linkToUrl(function (BlogPost $entity) {
return $this->get('parameter_bag')->get('app.url.qrcode') . '/' . $entity->getQrCode();
});
$Duplicate = Action::new('Duplicate', 'bo.duplicate')
->linkToCrudAction('duplicateAction')->addCssClass('btn-duplicate');
$DuplicateEdit = Action::new('Duplicate', 'bo.duplicate', "fa fa-clone")
->linkToCrudAction('duplicateAction');
$deleteMedia = Action::new('deleteMedia', false)
->addCssClass('d-none')
->linkToCrudAction('deleteMedia');
$deleteImagePreviewMedia = Action::new('deleteImagePreviewMedia', false)
->addCssClass('d-none')
->linkToCrudAction('deleteImagePreviewMedia');
$deleteFeaturingImageMedia = Action::new('deleteFeaturingImageMedia', false)
->addCssClass('d-none')
->linkToCrudAction('deleteFeaturingImageMedia');
$deletePreviewVideo = Action::new('deletePreviewVideo', false)
->addCssClass('d-none')
->linkToCrudAction('deletePreviewVideo');
$programAction = Action::new('listProgram', 'bo.action.list-program')
->createAsGlobalAction()
->linkToCrudAction('listProgram');
if ($this->isFromCategory()) {
$actions
->add(Crud::PAGE_INDEX, CsvAction::new())
->add(Crud::PAGE_INDEX, $programAction)
->remove(Crud::PAGE_INDEX, Action::NEW)
->remove(Crud::PAGE_INDEX, Action::EDIT)
->remove(Crud::PAGE_INDEX, Action::DELETE)
->remove(Crud::PAGE_INDEX, Action::DETAIL);
}
return $actions
->remove(Crud::PAGE_NEW, Action::SAVE_AND_ADD_ANOTHER)
->add(Crud::PAGE_INDEX, CsvAction::new())
->add(Crud::PAGE_INDEX, $programAction)
->add(Crud::PAGE_DETAIL, $viewEntity)
->add(Crud::PAGE_INDEX, $downloadQRCode)
->add(Crud::PAGE_INDEX, $Duplicate)
->add(Crud::PAGE_INDEX, $dropBlogPost)
->add(Crud::PAGE_INDEX, $raiseBlogPost)
->add(Crud::PAGE_EDIT, $viewEntity)
->add(Crud::PAGE_EDIT, $DuplicateEdit)
->add(Crud::PAGE_EDIT, $viewScoringQuiz)
->add(Crud::PAGE_EDIT, $viewIdentityForm)
->add(Crud::PAGE_EDIT, $viewBlocks)
->add(Crud::PAGE_EDIT, $deleteMedia)
->add(Crud::PAGE_EDIT, $deleteImagePreviewMedia)
->add(Crud::PAGE_EDIT, $deleteFeaturingImageMedia)
->add(Crud::PAGE_EDIT, $deletePreviewVideo)
->add(Crud::PAGE_NEW, Action::SAVE_AND_CONTINUE)
->add(Crud::PAGE_EDIT, $loadCategory);
}
public function scoringQuizAction(AdminContext $context)
{
$this->em->clear();
$entityId = $context->getRequest()->query->get('entityId');
// Use the repository directly
$blogPostRepository = $this->em->getRepository(BlogPost::class);
/** @var BlogPost $instance */
$instance = $blogPostRepository->findWithRelationships($entityId);
if (!$instance) {
throw $this->createNotFoundException('Blog post not found');
}
$scoringQuiz = $instance->getScoringQuiz();
if ($scoringQuiz) {
$url = $this->adminUrlGenerator->setAction(Action::EDIT)
->set("blogPostId", $instance->getId())
->setEntityId($scoringQuiz->getId())
->setController(ScoringQuizCrudController::class)
->generateUrl();
} else {
$url = $this->adminUrlGenerator->setAction(Action::NEW)
->set("blogPostId", $instance->getId())
->setEntityId(null)
->setController(ScoringQuizCrudController::class)
->generateUrl();
}
return $this->redirect($url);
}
public function identityFormAction(AdminContext $context)
{
/** @var BlogPost $instance */
$instance = $context->getEntity()->getInstance();
$identityForm = $instance->getIdentityForm();
if ($identityForm) {
$url = $this->adminUrlGenerator->setAction(Action::EDIT)
->set("blogPostId", $instance->getId())
->setEntityId($identityForm->getId())
->setController(IdentityFormCrudController::class)
->generateUrl();
} else {
$url = $this->adminUrlGenerator->setAction(Action::NEW)
->set("blogPostId", $instance->getId())
->setEntityId(null)
->setController(IdentityFormCrudController::class)
->generateUrl();
}
return $this->redirect($url);
}
public function loadCategoryAction(AdminContext $context): Response
{
/** @var BlogPost $instance */
$instance = $context->getEntity()->getInstance();
$this->blogPostService->loadCategory($instance);
return $this->redirectToItem($instance);
}
public function duplicateAction(DuplicatePost $duplicatePost, EntityManagerInterface $entityManager, AdminContext $context)
{
$clonedEntity = $duplicatePost->createClonedEntity($context);
$this->blogPostService->movePositionTop($clonedEntity);
$url = $this->adminUrlGenerator->setAction(Action::EDIT)
->setEntityId($clonedEntity->getId())
->generateUrl();
return $this->redirect($url);
}
public function configureResponseParameters(KeyValueStore $responseParameters): KeyValueStore
{
if ($responseParameters->get('pageName') === Crud::PAGE_EDIT) {
/** @var BlogPost $entity */
$entity = $this->getContext()->getEntity()->getInstance();
$responseParameters->set('mediaMime', $entity->getMedia()?->getFile()?->getMimeType());
}
if ($responseParameters->get('pageName') == Crud::PAGE_INDEX) {
// get the current selected category
if ($this->isFromFiltersCategory()) {
$categoryId = $this->requestStack->getMainRequest()->get('filters')['blogPostCategory']['value'];
if ($categoryId) {
$category = $this->blogPostCategoryRepository->find($categoryId);
$blogPostPositions = $category->getBlogPosts()->map(fn(BlogPost $bp) => $bp->getPosition())->toArray();
}
} else {
$blogPosts = $this->blogPostRepository->findAll();
$blogPostPositions = array_map(fn(BlogPost $bp) => $bp->getPosition(), $blogPosts);
}
if ($blogPostPositions) {
$min = min($blogPostPositions);
$max = max($blogPostPositions);
} else {
$min = -1;
$max = -1;
}
$responseParameters->set('minPos', $min);
$responseParameters->set('maxPos', $max);
}
return $responseParameters;
}
public function configureFilters(Filters $filters): Filters
{
if (!$this->isFromCategory()) {
$filters
->add(EntityFilter::new('criteria1Items', $this->criteria1Repository->findOneBy([])->getName()))
->add(EntityFilter::new('criteria2Items', $this->criteria2Repository->findOneBy([])->getName()))
->add(EntityFilter::new('criteria3Items', $this->criteria3Repository->findOneBy([])->getName()))
->add(EntityFilter::new('blogPostCategory', 'bo.blog-post-category.title')
->setFormTypeOption('value_type_options.placeholder', 'Seléctionner une rubrique')
->setFormTypeOption('value_type_options.empty_data', null)
)
->add(BooleanFilter::new('isScheduled', 'bo.blog-post.field.is-scheduled')->setFormTypeOption('expanded', true))
->add(BooleanFilter::new('isActivated', 'bo.blog-post.field.is-activated')->setFormTypeOption('expanded', true));
}
return $filters;
}
public function deleteMedia(AdminContext $context): Response
{
/** @var BlogPost $entity */
$entity = $context->getEntity()->getInstance();
$this->em->remove($entity->getMedia());
$entity->setMedia(null);
$this->em->persist($entity);
$this->em->flush();
return $this->redirectToItem($entity);
}
public function deleteImagePreviewMedia(AdminContext $context): Response
{
/** @var BlogPost $entity */
$entity = $context->getEntity()->getInstance();
$this->em->remove($entity->getImagePreviewMedia());
$entity->setImagePreviewMedia(null);
$this->em->persist($entity);
$this->em->flush();
return $this->redirectToItem($entity);
}
public function deletePreviewVideo(AdminContext $context)
{
/** @var BlogPost $entity */
$entity = $context->getEntity()->getInstance();
$this->em->remove($entity->getPreviewVideo());
$entity->setPreviewVideo(null);
$this->em->persist($entity);
$this->em->flush();
return $this->redirectToItem($entity);
}
public function deleteFeaturingImageMedia(AdminContext $context)
{
/** @var BlogPost $entity */
$entity = $context->getEntity()->getInstance();
$this->em->remove($entity->getFeaturingImageMedia());
$entity->setFeaturingImageMedia(null);
$this->em->persist($entity);
$this->em->flush();
return $this->redirectToItem($entity);
}
private function redirectToItem(BlogPost $item): Response
{
return $this->redirect(
$this->adminUrlGenerator->setAction(Action::EDIT)
->setEntityId($item->getId())
->generateUrl()
);
}
public function listProgram(AdminContext $context): RedirectResponse
{
$url = $this->get(AdminUrlGenerator::class)
->setAction(Action::INDEX)
->set('filters[isScheduled][value]', true)
->generateUrl();
return new RedirectResponse($url);
}
public function csvExport(AdminContext $context): StreamedResponse
{
$entityClass = $this->getEntityFqcn();
$qb = $this->em->createQueryBuilder()
->from($entityClass, 'n')
->addSelect('n')
->orderBy('n.createdAt');
if ($this->isFromListProgram()) {
$qb->andWhere('n.isScheduled = :type')
->setParameter('type', true);
}
if ($this->isFromFiltersCategory()) {
$categoryId = $this->requestStack->getMainRequest()->get('filters')['blogPostCategory']['value'];
$qb->innerJoin('n.blogPostCategory', 'bpc')
->andWhere('bpc IN (:cat)')
->setParameter('cat', $categoryId);;
}
$fileName = sprintf('Contenu-%s.csv', date('d-M-Y_H-i'));
$res = $this->csvExporter->getResponseFromQueryBuilder($qb, $entityClass, $fileName);
return $res;
}
/**
* @param string $pageName
* @return iterable
*/
public function configureFields(string $pageName): iterable
{
/** @var BlogPost $instance */
$instance = $this->adminContextProvider->getContext()->getEntity()->getInstance();
if ($instance) {
/** @var BlogPostCategory $category */
$category = $instance->getBlogPostCategory();
}
$fieldRoleDisabled = isset($category) ? !$category->getIsPublic() : false;
$fieldCriteria1Disabled = isset($category) ? !$category->isHasAllCriteria1() : false;
$fieldCriteria2Disabled = isset($category) ? !$category->isHasAllCriteria2() : false;
$fieldCriteria3Disabled = isset($category) ? !$category->isHasAllCriteria3() : false;
if ($pageName === Crud::PAGE_NEW) {
$instance->setIsPublic(true);
$instance->setHasAllCriteria1(true);
$instance->setHasAllCriteria2(true);
$instance->setHasAllCriteria3(true);
// Set the default desactivation date
$defaultLifeTime = $this->serviceSiteConfig->isBlogPostLifeTime();
if ($defaultLifeTime) {
$defaultLifeTimeDays = $this->serviceSiteConfig->getBlogPostLifeTimeDays();
$interval = DateInterval::createFromDateString(strval($defaultLifeTimeDays ?? 0) . ' days');
$instance->setActivationDate(new DateTime());
$instance->setDesactivationDate((new DateTime())->add($interval));
$instance->setIsScheduled(true);
}
}
$status = ["Brouillon" => "0", "Activé" => "1"];
yield IntegerField::new('position', 'bo.blog-post.field.position')
->onlyOnDetail();
yield TextField::new('title', 'bo.blog-post.field.title')
->hideOnForm();
yield ImageField::new('qrCode', 'common.qr-code')
->setUploadDir($this->getParameter('app.folder.qrcode'))
->setBasePath($this->getParameter('app.url.qrcode'))
->onlyOnDetail();
yield FormField::addPanel('bo.blog-post.base-options')
->collapsible()
->addCssClass('col-md-8');
yield BooleanField::new('isActivated')
->setLabel('bo.blog-post.field.is-activated')
->setDisabled(in_array(User::ROLE_REDACTEUR, $this->getUser()->getRoles()))
->addCssClass('activated-toggle')
->setColumns(3);
yield BooleanField::new('isFeatured')
->setLabel('bo.blog-post.field.is-featured')
->setColumns(3)
->addCssClass('featured-toggle');
yield BooleanField::new('isScheduled')
->setLabel('bo.blog-post.field.scheduling')
->setDisabled(in_array(User::ROLE_REDACTEUR, $this->getUser()->getRoles()))
->setColumns(3)
->setCssClass('scheduling-toggle')
->onlyOnForms();
yield BooleanField::new('isNotify')
->setLabel('bo.blog-post.field.is-notify')
->setCssClass('notify-toggle')
->setColumns(3)
->onlyOnForms();
yield AssociationField::new('blogPostCategory')
->setLabel('bo.blog-post-category.title')
->setRequired(true)
->setQueryBuilder(function (QueryBuilder $queryBuilder) {
// If the user is ROLE_CHEF_RUBRIQUE then filter on the selectables Categories for this user
if (array_search(User::ROLE_CHEF_RUBRIQUE, $this->getUser()->getRoles())) {
$queryBuilder->join('entity.users', 'user')
->andWhere("user.id = :userId")
->setParameter("userId", $this->getUser()->getId());
}
return $queryBuilder->andWhere('entity.isActivated = TRUE');
})
->setColumns(6);
yield AssociationField::new('preference', 'Préference')
->setColumns('col-md-12')
->setColumns(6);
yield FormField::addPanel('bo.blog-post.access')
->collapsible(true)
->renderCollapsed(false)
->addCssClass('col-md-4');
yield BooleanField::new('isPublic')
->setLabel('bo.blog-post.field.is-public')
->setDisabled($fieldRoleDisabled)
->setCssClass('public-toggle')
->setColumns('col-md-6')
->hideOnIndex();
yield AssociationField::new('roles', 'Roles')
->setQueryBuilder(function (QueryBuilder $queryBuilder) {
return $queryBuilder->andWhere('entity.status = TRUE');
})
->onlyOnForms()
->setHelp("<span>Si vide, le contenu ne sera jamais visible.</span>")
->setDisabled($fieldRoleDisabled)
->setColumns('col-md-8 roles-toggle');
yield AssociationField::new('roles', 'Roles')
->hideOnForm()
->formatValue(function ($value, $entity) {
$count = count($entity->getRoles());
$rolesList = implode(', ', array_map(function ($role, $index) {
return '<li><a href="#" class="category-list" data-list="category-list-' . $index . '" data-parent=".category-link">' . $role->getName() . '</a></li>';
}, $entity->getRoles()->toArray(), array_keys($entity->getRoles()->toArray())));
return '<span class="category-link-wrapper"><a href="#" class="category-link" data-count="' . $count . '" data-list="' . htmlspecialchars($rolesList) . '">' . $count . '</a></span>';
});
yield BooleanField::new('hasAllCriteria1')
->setLabel('Tout ' . $this->criteria1Repository->findOneBy([])->getName())
->setDisabled($fieldCriteria1Disabled)
->setCssClass('criteria1-toggle')
->onlyOnForms();
yield AssociationField::new('criteria1Items')
->setLabel($this->criteria1Repository->findOneBy([])->getName())
->onlyOnForms()
->setHelp("<span>Si vide, le contenu ne sera jamais visible.</span>")
->setDisabled($fieldCriteria1Disabled)
->setColumns('col-md-8 criteria1-items');
yield BooleanField::new('hasAllCriteria2')
->setLabel('Tout ' . $this->criteria2Repository->findOneBy([])->getName())
->setDisabled($fieldCriteria2Disabled)
->setCssClass('criteria2-toggle')
->onlyOnForms();
yield AssociationField::new('criteria2Items')
->setLabel($this->criteria2Repository->findOneBy([])->getName())
->onlyOnForms()
->setHelp("<span>Si vide, le contenu ne sera jamais visible.</span>")
->setDisabled($fieldCriteria2Disabled)
->setColumns('col-md-8 criteria2-items');
yield BooleanField::new('hasAllCriteria3')
->setLabel('Tout ' . $this->criteria3Repository->findOneBy([])->getName())
->setDisabled($fieldCriteria3Disabled)
->setCssClass('criteria3-toggle')
->onlyOnForms();
yield AssociationField::new('criteria3Items')
->setLabel($this->criteria3Repository->findOneBy([])->getName())
->setHelp("<span>Si vide, le contenu ne sera jamais visible.</span>")
->onlyOnForms()
->setDisabled($fieldCriteria3Disabled)
->setColumns('col-md-8 criteria3-items');
yield FormField::addPanel('Programmation')
->addCssClass('col-md-8 collapsible collapse notification-panel')
->setFormTypeOption('attr', ['style' => 'display: none;'])
->collapsible();
yield DateTimeField::new('activation_date')
->setLabel('bo.blog-post.field.activation_date')
->setColumns(3)
->onlyOnForms();
yield DateTimeField::new('desactivation_date')
->setLabel('bo.blog-post.field.desactivation_date')
->setColumns(3)
->onlyOnForms();
yield NotificationField::new('notification', false)
->setColumns(6)
->onlyOnForms();
yield FormField::addPanel('bo.pages.content')
->collapsible()
->addCssClass('col-md-12');
yield TextField::new("title", "bo.blog-post.field.title")
->setRequired(true)
->onlyOnForms()
->setColumns(6);
yield TextField::new("slug", "bo.blog-post.field.slug")
->setHelp("Le champ doit contenir uniquement des lettres minuscules, chiffres et tirets.")
->hideOnIndex()
->setColumns(6);
yield TextareaField::new('description', 'bo.blog-post.field.description')
->addCssClass("tinymce-enable")
->hideOnIndex()
->setColumns(12);
yield MediaField::new('media', 'bo.blog-post.field.media')
->setRequired(false)
->setAccept(implode(',', Media::UPLOAD_MIMES))
->setHelp($this->helpers->getAdminMediaHelp())
->setDeleteAction('deleteMedia')
->onlyOnForms();
yield FormField::addPanel('Prévisualisations')
->collapsible()
->addCssClass('col-md-12');
yield MediaField::new('imagePreviewMedia', 'bo.blog-post.field.image-preview')
->setRequired(true)
->setHelp($this->helpers->getAdminImgHelp('blog_preview'))
->setDeleteAction('deleteImagePreviewMedia')
->setAccept(implode(',', Media::IMAGE_MIMES))
->setColumns(6)
->onlyWhenCreating();
yield MediaField::new('imagePreviewMedia', 'bo.blog-post.field.image-preview')
->setRequired(false)
->setHelp($this->helpers->getAdminImgHelp('blog_preview'))
->setDeleteAction('deleteImagePreviewMedia')
->setAccept(implode(',', Media::IMAGE_MIMES))
->setColumns(4)
->onlyWhenUpdating();
yield BooleanField::new('isFeaturedTitle')
->setLabel('bo.blog-post.field.is-featured-title')
->hideOnIndex()
->setColumns(3);
yield MediaField::new('previewVideo', 'bo.blog-post.field.video-preview')
->setRequired(false)
->addCssClass('video-preview')
->setHelp($this->helpers->getAdminVideoHelp())
->setDeleteAction('deletePreviewVideo')
->setAccept(implode(',', Media::VIDEO_MIMES))
->setColumns(4)
->onlyOnForms();
yield MediaField::new('featuringImageMedia', 'bo.blog-post.field.featuring-image')
->setRequired(false)
->addCssClass('featuring-image')
->setAccept(implode(',', Media::IMAGE_MIMES))
->setHelp($this->helpers->getAdminImgHelp('blog_featuring'))
->setDeleteAction('deleteFeaturingImageMedia')
->onlyOnForms();
yield BooleanField::new('isPublic')
->setLabel('bo.blog-post.field.public')
->renderAsSwitch(false)
->onlyOnIndex();
yield DateTimeField::new('notificationSentAt')
->setLabel('bo.blog-post.field.notification-sent-at')
->onlyOnIndex();
yield FormField::addRow();
yield DateTimeField::new('createdAt')
->setLabel('bo.created-at')
->setFormat('dd-MM-Y HH:mm:ss')
->hideOnForm();
yield DateTimeField::new('updatedAt')
->setLabel('bo.updated-at')
->setFormat('dd-MM-Y HH:mm:ss')
->hideOnForm();
yield DateTimeField::new('updatedAt')
->setLabel('bo.updated-at')
->setFormat('dd-MM-Y HH:mm:ss')
->onlyOnDetail();
yield FormField::addPanel('bo.cms.page.seo-panel')
->renderCollapsed(true);
yield SeoField::new('seo')
->onlyOnForms();
yield FormField::addPanel('bo.blog-post.blogPostHistoryUpdates')
->collapsible(true)
->onlyOnDetail()
->renderCollapsed(false);
yield AssociationField::new('blogPostHistoryUpdates', '')
->setTemplatePath('admin/crud/field/update-history.html.twig')
->onlyOnDetail();
}
}