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.

704 satır
25KB

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