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.

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