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.

800 lines
31KB

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