You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

775 line
30KB

  1. <?php
  2. namespace Lc\SovBundle\Controller;
  3. use Doctrine\ORM\EntityManagerInterface;
  4. use Doctrine\ORM\QueryBuilder;
  5. use EasyCorp\Bundle\EasyAdminBundle\Collection\ActionCollection;
  6. use EasyCorp\Bundle\EasyAdminBundle\Collection\EntityCollection;
  7. use EasyCorp\Bundle\EasyAdminBundle\Collection\FieldCollection;
  8. use EasyCorp\Bundle\EasyAdminBundle\Collection\FilterCollection;
  9. use EasyCorp\Bundle\EasyAdminBundle\Config\Action;
  10. use EasyCorp\Bundle\EasyAdminBundle\Config\Actions;
  11. use EasyCorp\Bundle\EasyAdminBundle\Config\Crud;
  12. use EasyCorp\Bundle\EasyAdminBundle\Config\KeyValueStore;
  13. use EasyCorp\Bundle\EasyAdminBundle\Config\Option\EA;
  14. use EasyCorp\Bundle\EasyAdminBundle\Context\AdminContext;
  15. use EasyCorp\Bundle\EasyAdminBundle\Contracts\Controller\CrudControllerInterface;
  16. use EasyCorp\Bundle\EasyAdminBundle\Controller\AbstractCrudController as EaAbstractCrudController;
  17. use EasyCorp\Bundle\EasyAdminBundle\Dto\EntityDto;
  18. use EasyCorp\Bundle\EasyAdminBundle\Dto\FieldDto;
  19. use EasyCorp\Bundle\EasyAdminBundle\Dto\SearchDto;
  20. use EasyCorp\Bundle\EasyAdminBundle\Event\AfterCrudActionEvent;
  21. use EasyCorp\Bundle\EasyAdminBundle\Event\AfterEntityUpdatedEvent;
  22. use EasyCorp\Bundle\EasyAdminBundle\Event\BeforeCrudActionEvent;
  23. use EasyCorp\Bundle\EasyAdminBundle\Event\BeforeEntityDeletedEvent;
  24. use EasyCorp\Bundle\EasyAdminBundle\Exception\ForbiddenActionException;
  25. use EasyCorp\Bundle\EasyAdminBundle\Exception\InsufficientEntityPermissionException;
  26. use EasyCorp\Bundle\EasyAdminBundle\Factory\ControllerFactory;
  27. use EasyCorp\Bundle\EasyAdminBundle\Factory\EntityFactory;
  28. use EasyCorp\Bundle\EasyAdminBundle\Factory\FilterFactory;
  29. use EasyCorp\Bundle\EasyAdminBundle\Factory\PaginatorFactory;
  30. use EasyCorp\Bundle\EasyAdminBundle\Field\AssociationField;
  31. use EasyCorp\Bundle\EasyAdminBundle\Field\FormField;
  32. use EasyCorp\Bundle\EasyAdminBundle\Field\TextareaField;
  33. use EasyCorp\Bundle\EasyAdminBundle\Field\TextField;
  34. use EasyCorp\Bundle\EasyAdminBundle\Provider\AdminContextProvider;
  35. use EasyCorp\Bundle\EasyAdminBundle\Router\AdminUrlGenerator;
  36. use EasyCorp\Bundle\EasyAdminBundle\Security\Permission;
  37. use Lc\SovBundle\Component\EntityComponent;
  38. use Lc\SovBundle\Container\ComponentContainer;
  39. use Lc\SovBundle\Container\File\FileContainer;
  40. use Lc\SovBundle\Container\Newsletter\NewsletterContainer;
  41. use Lc\SovBundle\Container\Reminder\ReminderContainer;
  42. use Lc\SovBundle\Container\Setting\SiteSettingContainer;
  43. use Lc\SovBundle\Container\Site\NewsContainer;
  44. use Lc\SovBundle\Container\Site\PageContainer;
  45. use Lc\SovBundle\Container\Site\SiteContainer;
  46. use Lc\SovBundle\Container\Ticket\TicketContainer;
  47. use Lc\SovBundle\Container\Ticket\TicketMessageContainer;
  48. use Lc\SovBundle\Container\User\GroupUserContainer;
  49. use Lc\SovBundle\Container\User\UserContainer;
  50. use Lc\SovBundle\Doctrine\Extension\DevAliasInterface;
  51. use Lc\SovBundle\Doctrine\Extension\SeoInterface;
  52. use Lc\SovBundle\Doctrine\Extension\SortableInterface;
  53. use Lc\SovBundle\Doctrine\Extension\TranslatableInterface;
  54. use Lc\SovBundle\Doctrine\Extension\TreeInterface;
  55. use Lc\SovBundle\Field\CollectionField;
  56. use Lc\SovBundle\Field\Filter\FilterManager;
  57. use Lc\SovBundle\Form\Common\FiltersFormType;
  58. use Lc\SovBundle\Form\Common\PositionType;
  59. use Lc\SovBundle\Translation\TranslatorAdmin;
  60. use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
  61. use Symfony\Component\Form\Extension\Core\Type\CollectionType;
  62. use Symfony\Component\Form\Extension\Core\Type\DateTimeType;
  63. use Symfony\Component\Form\Extension\Core\Type\DateType;
  64. use Symfony\Component\Form\Extension\Core\Type\IntegerType;
  65. use Symfony\Component\Form\Extension\Core\Type\TextType;
  66. use Symfony\Component\Form\FormInterface;
  67. use Symfony\Component\HttpFoundation\JsonResponse;
  68. use Symfony\Component\HttpFoundation\RequestStack;
  69. use Symfony\Component\HttpFoundation\Session\SessionInterface;
  70. abstract class AbstractAdminController extends EaAbstractCrudController
  71. {
  72. protected FormInterface $filtersForm;
  73. public static function getSubscribedServices()
  74. {
  75. return array_merge(
  76. parent::getSubscribedServices(),
  77. [
  78. TranslatorAdmin::class => TranslatorAdmin::class,
  79. SessionInterface::class => SessionInterface::class,
  80. RequestStack::class => RequestStack::class,
  81. EntityManagerInterface::class => EntityManagerInterface::class,
  82. FilterManager::class => FilterManager::class,
  83. ComponentContainer::class => ComponentContainer::class,
  84. FileContainer::class => FileContainer::class,
  85. NewsletterContainer::class => NewsletterContainer::class,
  86. ReminderContainer::class => ReminderContainer::class,
  87. NewsContainer::class => NewsContainer::class,
  88. PageContainer::class => PageContainer::class,
  89. SiteContainer::class => SiteContainer::class,
  90. TicketContainer::class => TicketContainer::class,
  91. TicketMessageContainer::class => TicketMessageContainer::class,
  92. GroupUserContainer::class => GroupUserContainer::class,
  93. UserContainer::class => UserContainer::class,
  94. SiteSettingContainer::class => SiteSettingContainer::class,
  95. ]
  96. );
  97. }
  98. public function configureResponseParameters(KeyValueStore $responseParameters): KeyValueStore
  99. {
  100. $this->overrideGlobalActions($responseParameters->get('global_actions'));
  101. $this->overrideEntitiesActions($responseParameters->get('entities'));
  102. if (Crud::PAGE_INDEX === $responseParameters->get('pageName')) {
  103. $responseParameters->set('fields', $this->configureFields('index'));
  104. if ($this->filtersForm === null) {
  105. die('nncncd');
  106. //TODO delete under code
  107. $options['fields'] = $responseParameters->get('fields');
  108. $options['entity_class'] = $this->getEntityFqcn();
  109. $options['entity_name'] = $responseParameters->get('entity')->getName();
  110. $this->filtersForm = $this->createForm(FiltersFormType::class, null, $options);
  111. }
  112. $responseParameters->set('filters_form', $this->filtersForm);
  113. }
  114. return $responseParameters;
  115. }
  116. public function overrideEntitiesActions(?EntityCollection $entities): void
  117. {
  118. }
  119. public function overrideGlobalActions(?ActionCollection $actions): void
  120. {
  121. if ($actions) {
  122. $context = $this->get(AdminContextProvider::class)->getContext();
  123. $adminUrlGenerator = $this->get(AdminUrlGenerator::class);
  124. foreach ($actions as $i => $action) {
  125. //récriture du bouton 'retour au parent'
  126. if ($action->getName() == 'index_parent') {
  127. $entity = $context->getEntity()->getInstance();
  128. if ($entity !== null) {
  129. if ($entity->getParent() !== null) {
  130. $url = $adminUrlGenerator
  131. ->setController($context->getCrud()->getControllerFqcn())
  132. ->set('entityId', $entity->getParent()->getId())
  133. ->generateUrl();
  134. $action->setLinkUrl($url);
  135. }
  136. } else {
  137. unset($actions[$i]);
  138. }
  139. }
  140. if ($action->getName() == 'sort') {
  141. $entityId = $context->getRequest()->get('entityId');
  142. if ($entityId != null) {
  143. $url = $adminUrlGenerator
  144. ->setController($context->getCrud()->getControllerFqcn())
  145. ->setAction($action->getName())
  146. ->set('entityId', $entityId)
  147. ->generateUrl();
  148. $action->setLinkUrl($url);
  149. }
  150. }
  151. }
  152. }
  153. }
  154. public function configureCrud(Crud $crud): Crud
  155. {
  156. $crud = parent::configureCrud($crud);
  157. $this->setMaxResults($crud);
  158. if ($this->isInstanceOf(SortableInterface::class)) {
  159. $crud->setDefaultSort(['position' => 'ASC']);
  160. }
  161. return $crud;
  162. }
  163. public function setMaxResults(Crud $crud): void
  164. {
  165. $entityClass = $this->getEntityFqcn();
  166. $paramListMaxResults = 'listMaxResults';
  167. $paramSessionListMaxResults = $entityClass.'-'.$paramListMaxResults;
  168. $requestListMaxResults = $this->get(RequestStack::class)->getCurrentRequest()->get($paramListMaxResults);
  169. if ($requestListMaxResults) {
  170. $this->get('session')->set($paramSessionListMaxResults, $requestListMaxResults);
  171. }
  172. $maxResults = $this->get('session')->get($paramSessionListMaxResults) ? $this->get('session')->get(
  173. $paramSessionListMaxResults
  174. ) : 30;
  175. $crud->setPaginatorPageSize($maxResults);
  176. }
  177. public function getSeoPanel(): ?array
  178. {
  179. if ($this->isInstanceOf(SeoInterface::class)) {
  180. return [
  181. FormField::addPanel('seo')->setTemplateName('crud/field/generic'),
  182. TextField::new('metaTitle')->setLabel('Meta Title')->setHelp(
  183. 'Affiché dans les résultats de recherche Google'
  184. )->hideOnIndex(),
  185. TextareaField::new('metaDescription')->setLabel('Meta description')->setHelp(
  186. 'Affiché dans les résultats de recherche Google'
  187. )->hideOnIndex(),
  188. CollectionField::new('oldUrls')
  189. ->setFormTypeOption('entry_type', TextType::class)->setLabel(
  190. 'Anciennes urls du document'
  191. )->hideOnIndex(),
  192. ];
  193. } else {
  194. return null;
  195. }
  196. }
  197. public function getConfPanel(): ?array
  198. {
  199. if ($this->isInstanceOf(DevAliasInterface::class)) {
  200. return [
  201. FormField::addPanel('configuration')->setTemplateName('crud/field/generic'),
  202. TextField::new('devAlias')->hideOnIndex(),
  203. ];
  204. } else {
  205. return null;
  206. }
  207. }
  208. public function sort(AdminContext $context)
  209. {
  210. $event = new BeforeCrudActionEvent($context);
  211. $this->get('event_dispatcher')->dispatch($event);
  212. if ($event->isPropagationStopped()) {
  213. return $event->getResponse();
  214. }
  215. //if (!$this->isGranted(Permission::EA_EXECUTE_ACTION) || !$this->isInstanceOf(SortableInterface::class)) {
  216. if (!$this->isInstanceOf(SortableInterface::class)) {
  217. throw new ForbiddenActionException($context);
  218. }
  219. $fields = FieldCollection::new($this->configureFields(Crud::PAGE_INDEX));
  220. $filters = $this->get(FilterFactory::class)->create(
  221. $context->getCrud()->getFiltersConfig(),
  222. $fields,
  223. $context->getEntity()
  224. );
  225. $queryBuilder = $this->createIndexQueryBuilder($context->getSearch(), $context->getEntity(), $fields, $filters);
  226. $paginator = $this->get(PaginatorFactory::class)->create($queryBuilder);
  227. $entities = $this->get(EntityFactory::class)->createCollection($context->getEntity(), $paginator->getResults());
  228. $this->get(EntityFactory::class)->processFieldsForAll($entities, $fields);
  229. $sortableForm = $this->createFormBuilder(array('entities', $paginator->getResults()))
  230. ->add(
  231. 'entities',
  232. CollectionType::class,
  233. array(
  234. 'required' => true,
  235. 'allow_add' => true,
  236. 'entry_type' => PositionType::class,
  237. )
  238. )
  239. ->getForm();
  240. $entityManager = $this->getDoctrine()->getManagerForClass($this->getEntityFqcn());
  241. $repository = $entityManager->getRepository($this->getEntityFqcn());
  242. $sortableForm->handleRequest($context->getRequest());
  243. if ($sortableForm->isSubmitted() && $sortableForm->isValid()) {
  244. foreach ($sortableForm->get('entities')->getData() as $elm) {
  245. $entityInstance = $repository->find($elm['id']);
  246. $entityDto = $context->getEntity()->newWithInstance($entityInstance);
  247. if (!$entityDto->isAccessible()) {
  248. throw new InsufficientEntityPermissionException($context);
  249. }
  250. $event = new BeforeEntityDeletedEvent($entityInstance);
  251. $this->get('event_dispatcher')->dispatch($event);
  252. $entityInstance = $event->getEntityInstance();
  253. $entityInstance->setPosition($elm['position']);
  254. $this->updateEntity($entityManager, $entityInstance);
  255. $this->get('event_dispatcher')->dispatch(new AfterEntityUpdatedEvent($entityInstance));
  256. }
  257. $url = $this->get(AdminUrlGenerator::class)
  258. ->setAction(Action::INDEX)
  259. ->generateUrl();
  260. $this->addFlash('success', $this->translatorAdmin->transFlashMessage('sort'), array());
  261. return $this->redirect($url);
  262. }
  263. $responseParameters = $this->configureResponseParameters(
  264. KeyValueStore::new(
  265. [
  266. 'pageName' => Crud::PAGE_INDEX,
  267. 'templatePath' => '@LcSov/adminlte/crud/sort.html.twig',
  268. 'entities' => $entities,
  269. 'paginator' => $paginator,
  270. 'global_actions' => array(),
  271. 'batch_actions' => array(),
  272. 'filters' => $filters,
  273. 'sortable_form' => $sortableForm,
  274. ]
  275. )
  276. );
  277. $responseParameters->set('fields', $this->configureFields('index'));
  278. $event = new AfterCrudActionEvent($context, $responseParameters);
  279. $this->get('event_dispatcher')->dispatch($event);
  280. if ($event->isPropagationStopped()) {
  281. return $event->getResponse();
  282. }
  283. return $responseParameters;
  284. }
  285. public function duplicate(AdminContext $context, EntityComponent $entityComponent, TranslatorAdmin $translatorAdmin, EntityManagerInterface $em)
  286. {
  287. if (!$this->isGranted(
  288. Permission::EA_EXECUTE_ACTION,
  289. ['action' => "duplicate", 'entity' => $context->getEntity()]
  290. )) {
  291. throw new ForbiddenActionException($context);
  292. }
  293. if (!$context->getEntity()->isAccessible()) {
  294. throw new InsufficientEntityPermissionException($context);
  295. }
  296. $newEntity = $entityComponent->duplicateEntity($context->getEntity()->getInstance());
  297. $em->create($newEntity);
  298. $em->flush();
  299. $url = $this->get(AdminUrlGenerator::class)
  300. ->setAction(Action::EDIT)
  301. ->setEntityId($newEntity->getId())
  302. ->generateUrl();
  303. $this->addFlash('success', $translatorAdmin->transFlashMessage('duplicate'), array());
  304. return $this->redirect($url);
  305. }
  306. public function createIndexQueryBuilder(
  307. SearchDto $searchDto,
  308. EntityDto $entityDto,
  309. FieldCollection $fields,
  310. FilterCollection $filters
  311. ): QueryBuilder {
  312. $queryBuilder = parent::createIndexQueryBuilder(
  313. $searchDto,
  314. $entityDto,
  315. $fields,
  316. $filters
  317. );
  318. //TOdo utiliser les repositoryQuery ?
  319. if ($this->isInstanceOf(TreeInterface::class)) {
  320. $entityId = $searchDto->getRequest()->get('entityId');
  321. if ($entityId !== null) {
  322. $queryBuilder->andWhereParent('entity', $entityId);
  323. } else {
  324. $queryBuilder->andWhereParentIsNull('entity');
  325. }
  326. }
  327. $this->filtersForm = $this->createForm(
  328. FiltersFormType::class,
  329. null,
  330. array(
  331. 'fields' => $fields,
  332. 'entity_dto' => $entityDto,
  333. 'entity_class' => $this->getEntityFqcn(),
  334. 'entity_name' => $entityDto->getName(),
  335. )
  336. );
  337. $filterManager = $this->get(FilterManager::class);
  338. $this->filtersForm->handleRequest($searchDto->getRequest());
  339. /*if (($this->filtersForm->isSubmitted() && $this->filtersForm->isValid())) {
  340. }*/
  341. $filterManager->handleFiltersForm($queryBuilder, $this->filtersForm, $fields, $entityDto);
  342. return $queryBuilder;
  343. }
  344. public function createSortQueryBuilder(
  345. SearchDto $searchDto,
  346. EntityDto $entityDto,
  347. FieldCollection $fields,
  348. FilterCollection $filters
  349. ): QueryBuilder {
  350. $queryBuilder = $this->createIndexQueryBuilder($searchDto, $entityDto, $fields, $filters);
  351. return $queryBuilder;
  352. }
  353. public function edit(AdminContext $context)
  354. {
  355. $response = parent::edit($context);;
  356. // on vide le flash bag si édition en ajax (notification déjà affichée en Javascript)
  357. if ($context->getRequest()->isXmlHttpRequest()) {
  358. $this->get('session')->getFlashBag()->clear();
  359. }
  360. return $response;
  361. }
  362. public function isInstanceOf(string $interfaceName): bool
  363. {
  364. return in_array($interfaceName, class_implements($this->getEntityFqcn()));
  365. }
  366. public function getControllerFqcnByInterface(string $interface): string
  367. {
  368. $context = $this->get(AdminContextProvider::class)->getContext();
  369. return $context->getCrudControllers()->findCrudFqcnByEntityFqcn(
  370. $this->get(EntityManagerInterface::class)->getEntityName($interface)
  371. );
  372. }
  373. public function updateEntity(EntityManagerInterface $entityManager, $entityInstance): void
  374. {
  375. $entityManager->update($entityInstance);
  376. $entityManager->flush();
  377. }
  378. public function persistEntity(EntityManagerInterface $entityManager, $entityInstance): void
  379. {
  380. $entityManager->create($entityInstance);
  381. $entityManager->flush();
  382. }
  383. public function configureActions(Actions $actions): Actions
  384. {
  385. $this->buildIndexActions($actions);
  386. $this->buildEditActions($actions);
  387. $this->buildDetailActions($actions);
  388. $this->buildNewActions($actions);
  389. $this->handleTranslatableEntityActions($actions);
  390. $this->handleSortableEntityActions($actions);
  391. $this->handleTreeEntityActions($actions);
  392. /*$actions->reorder(Crud::PAGE_EDIT, [Action::INDEX, Action::SAVE_AND_RETURN, Action::SAVE_AND_CONTINUE, Action::DELETE]);
  393. $actions->reorder(Crud::PAGE_NEW, [Action::INDEX, Action::SAVE_AND_RETURN, Action::SAVE_AND_ADD_ANOTHER]);*/
  394. return $actions;
  395. }
  396. public function getDuplicateAction(): Action
  397. {
  398. $duplicateAction = Action::new(
  399. 'duplicate',
  400. $this->get(TranslatorAdmin::class)->transAction('duplicate'),
  401. 'fa fa-fw fa-copy'
  402. )
  403. ->linkToCrudAction('duplicate')
  404. ->setLabel($this->get(TranslatorAdmin::class)->transAction('duplicate'))
  405. ->setCssClass('in-dropdown text-info action-confirm');
  406. return $duplicateAction;
  407. }
  408. public function buildIndexActions(Actions $actions): void
  409. {
  410. $actions->add(Crud::PAGE_INDEX, $this->getDuplicateAction());
  411. $this->actionUpdate(
  412. $actions,
  413. Crud::PAGE_INDEX,
  414. Action::NEW,
  415. [
  416. 'icon' => 'plus',
  417. 'label' => $this->get(TranslatorAdmin::class)->transAction('create'),
  418. 'add_class' => 'btn-sm',
  419. ]
  420. );
  421. $this->actionUpdate(
  422. $actions,
  423. Crud::PAGE_INDEX,
  424. Action::EDIT,
  425. [
  426. 'class' => 'btn btn-sm btn-primary',
  427. 'icon' => 'edit',
  428. 'label' => false,
  429. 'html_attributes' => array(
  430. 'data-toggle' => 'tooltip',
  431. 'title' => $this->get(TranslatorAdmin::class)->transAction('edit'),
  432. ),
  433. ]
  434. );
  435. $this->actionUpdate(
  436. $actions,
  437. Crud::PAGE_INDEX,
  438. Action::DETAIL,
  439. [
  440. 'icon' => 'eye',
  441. 'add_class' => 'btn btn-sm btn-success',
  442. 'label' => false,
  443. 'html_attributes' => array(
  444. 'data-toggle' => 'tooltip',
  445. 'title' => $this->get(TranslatorAdmin::class)->transAction('detail'),
  446. ),
  447. ]
  448. );
  449. $this->actionUpdate(
  450. $actions,
  451. Crud::PAGE_INDEX,
  452. Action::DELETE,
  453. [
  454. 'icon' => 'trash',
  455. 'dropdown' => true,
  456. 'label' => $this->get(TranslatorAdmin::class)->transAction('delete'),
  457. ]
  458. );
  459. $this->actionUpdate(
  460. $actions,
  461. Crud::PAGE_INDEX,
  462. Action::BATCH_DELETE,
  463. [
  464. 'class' => 'btn btn-sm btn-danger',
  465. 'icon' => 'trash',
  466. 'label' => $this->get(TranslatorAdmin::class)->transAction('delete'),
  467. ]
  468. );
  469. }
  470. public function buildEditActions(Actions $actions): void
  471. {
  472. $actions->add(Crud::PAGE_EDIT, Action::INDEX);
  473. $actions->add(Crud::PAGE_EDIT, Action::DELETE);
  474. $this->actionUpdate(
  475. $actions,
  476. Crud::PAGE_EDIT,
  477. Action::SAVE_AND_RETURN,
  478. [
  479. 'add_class' => 'float-right',
  480. 'icon' => 'check',
  481. 'label' => $this->get(TranslatorAdmin::class)->transAction('save_and_return'),
  482. ]
  483. );
  484. $this->actionUpdate(
  485. $actions,
  486. Crud::PAGE_EDIT,
  487. Action::INDEX,
  488. [
  489. 'icon' => 'chevron-left',
  490. 'class' => 'btn btn-link',
  491. 'label' => $this->get(TranslatorAdmin::class)->transAction('back_index'),
  492. ]
  493. );
  494. $this->actionUpdate(
  495. $actions,
  496. Crud::PAGE_EDIT,
  497. Action::SAVE_AND_CONTINUE,
  498. [
  499. 'class' => 'btn btn-info float-right',
  500. 'label' => $this->get(TranslatorAdmin::class)->transAction('save_and_continue'),
  501. ]
  502. );
  503. $this->actionUpdate(
  504. $actions,
  505. Crud::PAGE_EDIT,
  506. Action::DELETE,
  507. [
  508. 'icon' => 'trash',
  509. 'class' => 'btn btn-outline-danger action-delete',
  510. 'label' => $this->get(TranslatorAdmin::class)->transAction('delete'),
  511. ]
  512. );
  513. }
  514. public function buildDetailActions(Actions $actions): void
  515. {
  516. }
  517. public function buildNewActions(Actions $actions): void
  518. {
  519. $actions->add(Crud::PAGE_NEW, Action::INDEX);
  520. $this->actionUpdate(
  521. $actions,
  522. Crud::PAGE_EDIT,
  523. Action::SAVE_AND_RETURN,
  524. [
  525. 'add_class' => 'float-right',
  526. 'icon' => 'check',
  527. 'label' => $this->get(TranslatorAdmin::class)->transAction('save_and_return'),
  528. ]
  529. );
  530. $this->actionUpdate(
  531. $actions,
  532. Crud::PAGE_EDIT,
  533. Action::INDEX,
  534. [
  535. 'icon' => 'chevron-left',
  536. 'class' => 'btn btn-link',
  537. 'label' => $this->get(TranslatorAdmin::class)->transAction('back_index'),
  538. ]
  539. );
  540. $this->actionUpdate(
  541. $actions,
  542. Crud::PAGE_EDIT,
  543. Action::SAVE_AND_ADD_ANOTHER,
  544. [
  545. 'class' => 'btn btn-info float-right',
  546. 'label' => $this->get(TranslatorAdmin::class)->transAction('save_and_add_another'),
  547. ]
  548. );
  549. }
  550. public function handleTranslatableEntityActions(Actions $actions): void
  551. {
  552. if ($this->isInstanceOf(TranslatableInterface::class)) {
  553. $actions->update(
  554. Crud::PAGE_INDEX,
  555. Action::EDIT,
  556. function (Action $action) {
  557. $action->setTemplatePath('@LcSov/adminlte/crud/action/translatable.html.twig');
  558. return $action;
  559. }
  560. );
  561. }
  562. }
  563. public function handleSortableEntityActions(Actions $actions): void
  564. {
  565. if ($this->isInstanceOf(SortableInterface::class)) {
  566. $sortAction = Action::new('sort', $this->get(TranslatorAdmin::class)->transAction('sort'), 'fa fa-sort')
  567. ->linkToCrudAction('sort')
  568. ->setCssClass('btn btn-sm btn-success')
  569. ->createAsGlobalAction();
  570. $actions->add(Crud::PAGE_INDEX, $sortAction);
  571. }
  572. }
  573. public function handleTreeEntityActions(Actions $actions): void
  574. {
  575. if ($this->isInstanceOf(TreeInterface::class)) {
  576. $indexChildAction = Action::new(
  577. 'index_children',
  578. $this->get(TranslatorAdmin::class)->transAction('index_children'),
  579. 'fa fa-list'
  580. )
  581. ->linkToCrudAction(Action::INDEX)
  582. ->setLabel('')
  583. ->setHtmlAttributes(array('data-toggle' => 'tooltip', 'title' => 'Afficher les enfants'))
  584. ->setTemplatePath('@LcSov/adminlte/crud/action/index_children.html.twig')
  585. ->setCssClass('btn btn-sm btn-success');
  586. $backParentAction = Action::new(
  587. 'index_parent',
  588. $this->get(TranslatorAdmin::class)->transAction('index_parent'),
  589. 'fa fa-chevron-left'
  590. )
  591. ->linkToCrudAction(Action::INDEX)
  592. ->setCssClass('btn btn-sm btn-info')
  593. ->createAsGlobalAction();
  594. $actions->add(Crud::PAGE_INDEX, $backParentAction);
  595. $actions->add(Crud::PAGE_INDEX, $indexChildAction);
  596. }
  597. }
  598. public function actionUpdate($actions, $crudActionName, $actionName, array $button): void
  599. {
  600. if ($actions->getAsDto('actions')->getAction($crudActionName, $actionName)) {
  601. $actions->update(
  602. $crudActionName,
  603. $actionName,
  604. function (Action $action) use ($button) {
  605. if (isset($button['add_class'])) {
  606. $action->addCssClass($button['add_class']);
  607. }
  608. if (isset($button['class'])) {
  609. $action->setCssClass($button['class']);
  610. }
  611. if (isset($button['icon'])) {
  612. $action->setIcon('fa fa-'.$button['icon']);
  613. }
  614. if (isset($button['label'])) {
  615. $action->setLabel($button['label']);
  616. }
  617. if (isset($button['dropdown']) && $button['dropdown']) {
  618. $action->addCssClass('in-dropdown');
  619. }
  620. if (isset($button['html_attributes']) && $button['html_attributes']) {
  621. $action->setHtmlAttributes($button['html_attributes']);
  622. }
  623. return $action;
  624. }
  625. );
  626. }
  627. }
  628. public function autocompleteFilter(AdminContext $context): JsonResponse
  629. {
  630. $queryBuilder = $this->createIndexQueryBuilder(
  631. $context->getSearch(),
  632. $context->getEntity(),
  633. FieldCollection::new([]),
  634. FilterCollection::new()
  635. );
  636. $autocompleteContext = $context->getRequest()->get(AssociationField::PARAM_AUTOCOMPLETE_CONTEXT);
  637. /** @var CrudControllerInterface $controller */
  638. $controller = $this->get(ControllerFactory::class)->getCrudControllerInstance(
  639. $autocompleteContext[EA::CRUD_CONTROLLER_FQCN],
  640. Action::INDEX,
  641. $context->getRequest()
  642. );
  643. /** @var FieldDto $field */
  644. $field = FieldCollection::new(
  645. $controller->configureFields($autocompleteContext['originatingPage'])
  646. )->getByProperty($autocompleteContext['propertyName']);
  647. $filterManager = $this->get(FilterManager::class);
  648. $filterManager->applyFilter($queryBuilder, $field, $context->getRequest()->query->get('q'));
  649. if ($filterManager->isRelationField($field->getProperty())) {
  650. $queryBuilder->select($autocompleteContext['propertyName']);
  651. } else {
  652. $queryBuilder->select('entity.'.$autocompleteContext['propertyName']);
  653. }
  654. $responses = array();
  655. foreach ($queryBuilder->getQuery()->getArrayResult() as $result) {
  656. $responses[] = array_values($result)[0];
  657. }
  658. return JsonResponse::fromJsonString(json_encode($responses));
  659. }
  660. }