SessionInterface::class, 'request' => RequestStack::class, 'em' => EntityManagerInterface::class, 'translator_admin' => TranslatorAdmin::class, ] ); } public function configureResponseParameters(KeyValueStore $responseParameters): KeyValueStore { $this->overrideGlobalActions($responseParameters->get('global_actions')); $this->overrideEntitiesActions($responseParameters->get('entities')); if (Crud::PAGE_INDEX === $responseParameters->get('pageName')) { $responseParameters->set('fields', $this->configureFields('index')); } return $responseParameters; } public function overrideEntitiesActions(?EntityCollection $entities): void { } public function overrideGlobalActions(?ActionCollection $actions): void { if ($actions) { $context = $this->get(AdminContextProvider::class)->getContext(); $adminUrlGenerator = $this->get(AdminUrlGenerator::class); foreach ($actions as $i => $action) { //récriture du bouton 'retour au parent' if ($action->getName() == 'index_parent') { $entity = $context->getEntity()->getInstance(); if ($entity !== null) { if ($entity->getParent() !== null) { $url = $adminUrlGenerator ->setController($context->getCrud()->getControllerFqcn()) ->set('entityId', $entity->getParent()->getId()) ->generateUrl(); $action->setLinkUrl($url); } } else { unset($actions[$i]); } } if ($action->getName() == 'sort') { $entityId = $context->getRequest()->get('entityId'); if ($entityId != null) { $url = $adminUrlGenerator ->setController($context->getCrud()->getControllerFqcn()) ->setAction($action->getName()) ->set('entityId', $entityId) ->generateUrl(); $action->setLinkUrl($url); } } } } } public function configureCrud(Crud $crud): Crud { $crud = parent::configureCrud($crud); $this->setMaxResults($crud); if ($this->isInstanceOf(SortableInterface::class)) { $crud->setDefaultSort(['position' => 'ASC']); } return $crud; } public function setMaxResults(Crud $crud): void { $entityClass = $this->getEntityFqcn(); $paramListMaxResults = 'listMaxResults'; $paramSessionListMaxResults = $entityClass.'-'.$paramListMaxResults; $requestListMaxResults = $this->get('request')->getCurrentRequest()->get($paramListMaxResults); if ($requestListMaxResults) { $this->get('session')->set($paramSessionListMaxResults, $requestListMaxResults); } $maxResults = $this->get('session')->get($paramSessionListMaxResults) ? $this->get('session')->get( $paramSessionListMaxResults ) : 30; $crud->setPaginatorPageSize($maxResults); } public function configureFields(string $pageName): iterable { $seoPanel = $confPanel = array(); if ($this->isInstanceOf(SeoInterface::class)) { $seoPanel = [ FormField::addPanel('seo')->setTemplateName('crud/field/generic'), TextField::new('metaTitle')->setLabel('Meta Title')->setHelp( 'Affiché dans les résultats de recherche Google' )->hideOnIndex(), TextareaField::new('metaDescription')->setLabel('Meta description')->setHelp( 'Affiché dans les résultats de recherche Google' )->hideOnIndex(), CollectionField::new('oldUrls') ->setFormTypeOption('entry_type', TextType::class)->setLabel( 'Anciennes urls du document' )->hideOnIndex(), ]; } if ($this->isInstanceOf(DevAliasInterface::class)) { $confPanel = [ FormField::addPanel('configuration')->setTemplateName('crud/field/generic'), TextField::new('devAlias')->hideOnIndex(), ]; } return array_merge($seoPanel, $confPanel); } public function sort(AdminContext $context) { $event = new BeforeCrudActionEvent($context); $this->get('event_dispatcher')->dispatch($event); if ($event->isPropagationStopped()) { return $event->getResponse(); } //if (!$this->isGranted(Permission::EA_EXECUTE_ACTION) || !$this->isInstanceOf(SortableInterface::class)) { if (!$this->isInstanceOf(SortableInterface::class)) { throw new ForbiddenActionException($context); } $fields = FieldCollection::new($this->configureFields(Crud::PAGE_INDEX)); $filters = $this->get(FilterFactory::class)->create( $context->getCrud()->getFiltersConfig(), $fields, $context->getEntity() ); $queryBuilder = $this->createIndexQueryBuilder($context->getSearch(), $context->getEntity(), $fields, $filters); $paginator = $this->get(PaginatorFactory::class)->create($queryBuilder); $entities = $this->get(EntityFactory::class)->createCollection($context->getEntity(), $paginator->getResults()); $this->get(EntityFactory::class)->processFieldsForAll($entities, $fields); $sortableForm = $this->createFormBuilder(array('entities', $paginator->getResults())) ->add( 'entities', CollectionType::class, array( 'required' => true, 'allow_add' => true, 'entry_type' => PositionType::class, ) ) ->getForm(); $entityManager = $this->getDoctrine()->getManagerForClass($this->getEntityFqcn()); $repository = $entityManager->getRepository($this->getEntityFqcn()); $sortableForm->handleRequest($context->getRequest()); if ($sortableForm->isSubmitted() && $sortableForm->isValid()) { foreach ($sortableForm->get('entities')->getData() as $elm) { $entityInstance = $repository->find($elm['id']); $entityDto = $context->getEntity()->newWithInstance($entityInstance); if (!$entityDto->isAccessible()) { throw new InsufficientEntityPermissionException($context); } $event = new BeforeEntityDeletedEvent($entityInstance); $this->get('event_dispatcher')->dispatch($event); $entityInstance = $event->getEntityInstance(); $entityInstance->setPosition($elm['position']); $this->updateEntity($entityManager, $entityInstance); $this->get('event_dispatcher')->dispatch(new AfterEntityUpdatedEvent($entityInstance)); } $url = $this->get(AdminUrlGenerator::class) ->setAction(Action::INDEX) ->generateUrl(); $this->addFlash('success', $this->translatorAdmin->transFlashMessage('sort'), array()); return $this->redirect($url); } $responseParameters = $this->configureResponseParameters( KeyValueStore::new( [ 'pageName' => Crud::PAGE_INDEX, 'templatePath' => '@LcSov/adminlte/crud/sort.html.twig', 'entities' => $entities, 'paginator' => $paginator, 'global_actions' => array(), 'batch_actions' => array(), 'filters' => $filters, 'sortable_form' => $sortableForm, ] ) ); $responseParameters->set('fields', $this->configureFields('index')); $event = new AfterCrudActionEvent($context, $responseParameters); $this->get('event_dispatcher')->dispatch($event); if ($event->isPropagationStopped()) { return $event->getResponse(); } return $responseParameters; } public function createIndexQueryBuilder( SearchDto $searchDto, EntityDto $entityDto, FieldCollection $fields, FilterCollection $filters ): QueryBuilder { $queryBuilder = parent::createIndexQueryBuilder( $searchDto, $entityDto, $fields, $filters ); //TOdo utiliser les repositoryQuery ? if ($this->isInstanceOf(TreeInterface::class)) { $entityId = $searchDto->getRequest()->get('entityId'); if ($entityId !== null) { $queryBuilder->andWhere('entity.parent = :entityId'); $queryBuilder->setParameter('entityId', $searchDto->getRequest()->get('entityId')); } else { $queryBuilder->andWhere('entity.parent IS NULL'); } } return $queryBuilder; } public function createSortQueryBuilder( SearchDto $searchDto, EntityDto $entityDto, FieldCollection $fields, FilterCollection $filters ): QueryBuilder { $queryBuilder = $this->createIndexQueryBuilder($searchDto, $entityDto, $fields, $filters); return $queryBuilder; } public function edit(AdminContext $context) { $response = parent::edit($context);; // on vide le flash bag si édition en ajax (notification déjà affichée en Javascript) if ($context->getRequest()->isXmlHttpRequest()) { $this->get('session')->getFlashBag()->clear(); } return $response; } public function isInstanceOf(string $interfaceName): bool { return in_array($interfaceName, class_implements($this->getEntityFqcn())); } public function getControllerFqcnByInterface(string $interface): string { $context = $this->get(AdminContextProvider::class)->getContext(); return $context->getCrudControllers()->findCrudFqcnByEntityFqcn( $this->get('em')->getEntityName($interface) ); } public function updateEntity(EntityManagerInterface $entityManager, $entityInstance): void { $entityManager->update($entityInstance); $entityManager->flush(); } public function persistEntity(EntityManagerInterface $entityManager, $entityInstance): void { $entityManager->create($entityInstance); $entityManager->flush(); } public function configureActions(Actions $actions): Actions { $this->buildIndexActions($actions); $this->buildEditActions($actions); $this->buildDetailActions($actions); $this->buildNewActions($actions); $this->handleTranslatableEntityActions($actions); $this->handleSortableEntityActions($actions); $this->handleTreeEntityActions($actions); /*$actions->reorder(Crud::PAGE_EDIT, [Action::INDEX, Action::SAVE_AND_RETURN, Action::SAVE_AND_CONTINUE, Action::DELETE]); $actions->reorder(Crud::PAGE_NEW, [Action::INDEX, Action::SAVE_AND_RETURN, Action::SAVE_AND_ADD_ANOTHER]);*/ return $actions; } public function buildIndexActions(Actions $actions): void { $this->actionUpdate( $actions, Crud::PAGE_INDEX, Action::NEW, [ 'icon' => 'plus', 'label' => $this->get('translator_admin')->transAction('create'), 'add_class' => 'btn-sm', ] ); $this->actionUpdate( $actions, Crud::PAGE_INDEX, Action::EDIT, [ 'class' => 'btn btn-sm btn-primary', 'icon' => 'edit', 'label' => false, 'html_attributes' => array( 'data-toggle' => 'tooltip', 'title' => $this->get('translator_admin')->transAction('edit'), ), ] ); $this->actionUpdate( $actions, Crud::PAGE_INDEX, Action::DETAIL, [ 'icon' => 'eye', 'add_class' => 'btn btn-sm btn-success', 'label' => false, 'html_attributes' => array( 'data-toggle' => 'tooltip', 'title' => $this->get('translator_admin')->transAction('detail'), ), ] ); $this->actionUpdate( $actions, Crud::PAGE_INDEX, Action::DELETE, [ 'icon' => 'trash', 'dropdown' => true, 'label' => $this->get('translator_admin')->transAction('delete'), ] ); $this->actionUpdate( $actions, Crud::PAGE_INDEX, Action::BATCH_DELETE, [ 'class' => 'btn btn-sm btn-danger', 'icon' => 'trash', 'label' => $this->get('translator_admin')->transAction('delete'), ] ); } public function buildEditActions(Actions $actions): void { $actions->add(Crud::PAGE_EDIT, Action::INDEX); $actions->add(Crud::PAGE_EDIT, Action::DELETE); $this->actionUpdate( $actions, Crud::PAGE_EDIT, Action::SAVE_AND_RETURN, [ 'add_class' => 'float-right', 'icon' => 'check', 'label' => $this->get('translator_admin')->transAction('save_and_return'), ] ); $this->actionUpdate( $actions, Crud::PAGE_EDIT, Action::INDEX, [ 'icon' => 'chevron-left', 'class' => 'btn btn-link', 'label' => $this->get('translator_admin')->transAction('back_index'), ] ); $this->actionUpdate( $actions, Crud::PAGE_EDIT, Action::SAVE_AND_CONTINUE, [ 'class' => 'btn btn-info float-right', 'label' => $this->get('translator_admin')->transAction('save_and_continue'), ] ); $this->actionUpdate( $actions, Crud::PAGE_EDIT, Action::DELETE, [ 'icon' => 'trash', 'class' => 'btn btn-outline-danger action-delete', 'label' => $this->get('translator_admin')->transAction('delete'), ] ); } public function buildDetailActions(Actions $actions): void { } public function buildNewActions(Actions $actions): void { $actions->add(Crud::PAGE_NEW, Action::INDEX); $this->actionUpdate( $actions, Crud::PAGE_EDIT, Action::SAVE_AND_RETURN, [ 'add_class' => 'float-right', 'icon' => 'check', 'label' => $this->get('translator_admin')->transAction('save_and_return'), ] ); $this->actionUpdate( $actions, Crud::PAGE_EDIT, Action::INDEX, [ 'icon' => 'chevron-left', 'class' => 'btn btn-link', 'label' => $this->get('translator_admin')->transAction('back_index'), ] ); $this->actionUpdate( $actions, Crud::PAGE_EDIT, Action::SAVE_AND_ADD_ANOTHER, [ 'class' => 'btn btn-info float-right', 'label' => $this->get('translator_admin')->transAction('save_and_add_another'), ] ); } public function handleTranslatableEntityActions(Actions $actions): void { if ($this->isInstanceOf(TranslatableInterface::class)) { $actions->update( Crud::PAGE_INDEX, Action::EDIT, function (Action $action) { $action->setTemplatePath('@LcSov/adminlte/crud/action/translatable.html.twig'); return $action; } ); } } public function handleSortableEntityActions(Actions $actions): void { if ($this->isInstanceOf(SortableInterface::class)) { $sortAction = Action::new('sort', $this->get('translator_admin')->transAction('sort'), 'fa fa-sort') ->linkToCrudAction('sort') ->setCssClass('btn btn-sm btn-success') ->createAsGlobalAction(); $actions->add(Crud::PAGE_INDEX, $sortAction); } } public function handleTreeEntityActions(Actions $actions): void { if ($this->isInstanceOf(TreeInterface::class)) { $indexChildAction = Action::new( 'index_children', $this->get('translator_admin')->transAction('index_children'), 'fa fa-list' ) ->linkToCrudAction(Action::INDEX) ->setLabel('') ->setHtmlAttributes(array('data-toggle' => 'tooltip', 'title' => 'Afficher les enfants')) ->setTemplatePath('@LcSov/adminlte/crud/action/index_children.html.twig') ->setCssClass('btn btn-sm btn-success'); $backParentAction = Action::new( 'index_parent', $this->get('translator_admin')->transAction('index_parent'), 'fa fa-chevron-left' ) ->linkToCrudAction(Action::INDEX) ->setCssClass('btn btn-sm btn-info') ->createAsGlobalAction(); $actions->add(Crud::PAGE_INDEX, $backParentAction); $actions->add(Crud::PAGE_INDEX, $indexChildAction); } } public function actionUpdate($actions, $crudActionName, $actionName, array $button): void { if ($actions->getAsDto('actions')->getAction($crudActionName, $actionName)) { $actions->update( $crudActionName, $actionName, function (Action $action) use ($button) { if (isset($button['add_class'])) { $action->addCssClass($button['add_class']); } if (isset($button['class'])) { $action->setCssClass($button['class']); } if (isset($button['icon'])) { $action->setIcon('fa fa-'.$button['icon']); } if (isset($button['label'])) { $action->setLabel($button['label']); } if (isset($button['dropdown']) && $button['dropdown']) { $action->addCssClass('in-dropdown'); } if (isset($button['html_attributes']) && $button['html_attributes']) { $action->setHtmlAttributes($button['html_attributes']); } return $action; } ); } } }