SessionInterface::class, 'request' => RequestStack::class, 'em' => EntityManagerInterface::class, 'translator_admin' => TranslatorAdmin::class, ]); } public function configureActions(Actions $actions): Actions { /* Translatable */ 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; } ); } /* Boutons des actions dans les listes */ $actionsArray[Crud::PAGE_INDEX] = [ Action::NEW => [ 'icon' => 'plus', 'label' => $this->get('translator_admin')->transAction('create'), 'add_class' => 'btn-sm' ], 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') ) ], 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') ) ], Action::DELETE => [ 'icon' => 'trash', 'dropdown' => true, 'label' => $this->get('translator_admin')->transAction('delete') ], Action::BATCH_DELETE => [ 'class' => 'btn btn-sm btn-danger', 'icon' => 'trash', 'label' => $this->get('translator_admin')->transAction('delete') ], ]; /* Boutons des actions dans l'édition */ $actionSaveAndReturn = [ 'add_class' => 'float-right', 'icon' => 'check', 'label' => $this->get('translator_admin')->transAction('save_and_return') ]; $actionIndex = [ 'icon' => 'chevron-left', 'class' => 'btn btn-link', 'label' => $this->get('translator_admin')->transAction('back_index') ]; $actionsArray[Crud::PAGE_EDIT] = [ Action::SAVE_AND_CONTINUE => [ 'class' => 'btn btn-info float-right', 'label' => $this->get('translator_admin')->transAction('save_and_continue') ], Action::DELETE => [ 'icon' => 'trash', 'class' => 'btn btn-outline-danger action-delete', 'label' => $this->get('translator_admin')->transAction('delete') ], Action::SAVE_AND_RETURN => $actionSaveAndReturn, Action::INDEX => $actionIndex, ]; $actionsArray[Crud::PAGE_NEW] = [ Action::SAVE_AND_ADD_ANOTHER => [ 'class' => 'btn btn-info float-right', 'label' => $this->get('translator_admin')->transAction('save_and_add_another') ], Action::SAVE_AND_RETURN => $actionSaveAndReturn, Action::INDEX => $actionIndex, ]; $actions->add(Crud::PAGE_EDIT, Action::INDEX); $actions->add(Crud::PAGE_EDIT, Action::DELETE); $actions->add(Crud::PAGE_NEW, Action::INDEX); 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); } 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); } $actions->reorder(Crud::PAGE_EDIT, [Action::INDEX, Action::SAVE_AND_RETURN, Action::SAVE_AND_CONTINUE]); $actions->reorder(Crud::PAGE_NEW, [Action::INDEX, Action::SAVE_AND_RETURN, Action::SAVE_AND_ADD_ANOTHER]); foreach ($actionsArray as $crudActionName => $actionsStyle) { foreach ($actionsStyle as $actionName => $button) { // si l'action existe 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; } ); } } } return $actions; } public function configureResponseParameters(KeyValueStore $responseParameters): KeyValueStore { if (Crud::PAGE_INDEX === $responseParameters->get('pageName')) { $responseParameters->set('fields', $this->configureFields('index')); } return $responseParameters; } 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) { $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 ); 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 updateEntity(EntityManagerInterface $entityManager, $entityInstance): void { $entityManager->update($entityInstance); $entityManager->flush(); } public function persistEntity(EntityManagerInterface $entityManager, $entityInstance): void { $entityManager->create($entityInstance); $entityManager->flush(); } }