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.

852 lines
33KB

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