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.

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