選択できるのは25トピックまでです。 トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。

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