Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.

830 lines
32KB

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