Nie możesz wybrać więcej, niż 25 tematów Tematy muszą się zaczynać od litery lub cyfry, mogą zawierać myślniki ('-') i mogą mieć do 35 znaków.

832 lines
31KB

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