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

AbstractAdminController.php 28KB

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