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.

773 line
29KB

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