Você não pode selecionar mais de 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.

424 linhas
16KB

  1. <?php
  2. namespace Lc\SovBundle\Controller\Admin;
  3. use Doctrine\ORM\EntityManagerInterface;
  4. use Doctrine\ORM\QueryBuilder;
  5. use EasyCorp\Bundle\EasyAdminBundle\Collection\FieldCollection;
  6. use EasyCorp\Bundle\EasyAdminBundle\Collection\FilterCollection;
  7. use EasyCorp\Bundle\EasyAdminBundle\Config\Action;
  8. use EasyCorp\Bundle\EasyAdminBundle\Config\Actions;
  9. use EasyCorp\Bundle\EasyAdminBundle\Config\Assets;
  10. use EasyCorp\Bundle\EasyAdminBundle\Config\Crud;
  11. use EasyCorp\Bundle\EasyAdminBundle\Config\KeyValueStore;
  12. use EasyCorp\Bundle\EasyAdminBundle\Config\Option\EA;
  13. use EasyCorp\Bundle\EasyAdminBundle\Context\AdminContext;
  14. use EasyCorp\Bundle\EasyAdminBundle\Controller\AbstractCrudController as EaAbstractCrudController;
  15. use EasyCorp\Bundle\EasyAdminBundle\Dto\EntityDto;
  16. use EasyCorp\Bundle\EasyAdminBundle\Dto\SearchDto;
  17. use EasyCorp\Bundle\EasyAdminBundle\Event\AfterCrudActionEvent;
  18. use EasyCorp\Bundle\EasyAdminBundle\Event\AfterEntityUpdatedEvent;
  19. use EasyCorp\Bundle\EasyAdminBundle\Event\BeforeCrudActionEvent;
  20. use EasyCorp\Bundle\EasyAdminBundle\Event\BeforeEntityDeletedEvent;
  21. use EasyCorp\Bundle\EasyAdminBundle\Event\BeforeEntityUpdatedEvent;
  22. use EasyCorp\Bundle\EasyAdminBundle\Exception\ForbiddenActionException;
  23. use EasyCorp\Bundle\EasyAdminBundle\Exception\InsufficientEntityPermissionException;
  24. use EasyCorp\Bundle\EasyAdminBundle\Factory\EntityFactory;
  25. use EasyCorp\Bundle\EasyAdminBundle\Factory\FilterFactory;
  26. use EasyCorp\Bundle\EasyAdminBundle\Factory\PaginatorFactory;
  27. use EasyCorp\Bundle\EasyAdminBundle\Field\FormField;
  28. use EasyCorp\Bundle\EasyAdminBundle\Field\TextareaField;
  29. use EasyCorp\Bundle\EasyAdminBundle\Field\TextField;
  30. use EasyCorp\Bundle\EasyAdminBundle\Router\AdminUrlGenerator;
  31. use EasyCorp\Bundle\EasyAdminBundle\Security\Permission;
  32. use Lc\SovBundle\Doctrine\EntityManager;
  33. use Lc\SovBundle\Doctrine\Extension\DevAliasInterface;
  34. use Lc\SovBundle\Doctrine\Extension\SeoInterface;
  35. use Lc\SovBundle\Doctrine\Extension\SortableInterface;
  36. use Lc\SovBundle\Doctrine\Extension\TranslatableInterface;
  37. use Lc\SovBundle\Doctrine\Extension\TreeInterface;
  38. use Lc\SovBundle\Field\CollectionField;
  39. use Lc\SovBundle\Field\GalleryManagerField;
  40. use Lc\SovBundle\Form\Type\Crud\PositionType;
  41. use Symfony\Component\Form\Extension\Core\Type\CollectionType;
  42. use Symfony\Component\Form\Extension\Core\Type\TextType;
  43. use Symfony\Component\HttpFoundation\RequestStack;
  44. use Symfony\Component\HttpFoundation\Session\SessionInterface;
  45. abstract class AbstractCrudController extends EaAbstractCrudController
  46. {
  47. protected $session;
  48. protected $request;
  49. protected $em;
  50. public function __construct(SessionInterface $session, RequestStack $request, EntityManager $em)
  51. {
  52. $this->session = $session;
  53. $this->request = $request;
  54. $this->em = $em;
  55. }
  56. public function configureActions(Actions $actions): Actions
  57. {
  58. /* Translatable */
  59. if ($this->isInstanceOf(TranslatableInterface::class)) {
  60. $actions->update(
  61. Crud::PAGE_INDEX,
  62. Action::EDIT,
  63. function (Action $action) {
  64. $action->setTemplatePath('@LcSov/adminlte/crud/action/translatable.html.twig');
  65. return $action;
  66. }
  67. );
  68. }
  69. /* Boutons des actions dans les listes */
  70. $actionsArray[Crud::PAGE_INDEX] = [
  71. Action::NEW => [
  72. 'icon' => 'plus',
  73. 'label' => 'Créer',
  74. 'add_class'=>'btn-sm'
  75. ],
  76. Action::EDIT => [
  77. 'class' => 'btn btn-sm btn-primary',
  78. 'icon' => 'edit',
  79. 'label' => false,
  80. 'html_attributes'=> array('data-toggle'=> 'tooltip', 'title'=> 'Éditer')
  81. ],
  82. Action::DELETE => [
  83. 'icon' => 'trash',
  84. 'dropdown' => true,
  85. ],
  86. Action::BATCH_DELETE => [
  87. 'class' => 'btn btn-sm btn-danger',
  88. 'icon' => 'trash',
  89. ],
  90. ];
  91. /* Boutons des actions dans l'édition */
  92. $actionSaveAndReturn = [
  93. 'add_class' => 'float-right',
  94. 'icon' => 'check',
  95. ];
  96. $actionIndex = [
  97. 'icon' => 'chevron-left',
  98. 'class' => 'btn btn-link',
  99. ];
  100. $actionsArray[Crud::PAGE_EDIT] = [
  101. Action::SAVE_AND_CONTINUE => [
  102. 'class' => 'btn btn-info float-right',
  103. ],
  104. Action::DELETE => [
  105. 'icon' => 'trash',
  106. 'class' => 'btn btn-outline-danger action-delete',
  107. ],
  108. Action::SAVE_AND_RETURN => $actionSaveAndReturn,
  109. Action::INDEX => $actionIndex,
  110. ];
  111. $actionsArray[Crud::PAGE_NEW] = [
  112. Action::SAVE_AND_ADD_ANOTHER => [
  113. 'class' => 'btn btn-info float-right',
  114. ],
  115. Action::SAVE_AND_RETURN => $actionSaveAndReturn,
  116. Action::INDEX => $actionIndex,
  117. ];
  118. $actions->add(Crud::PAGE_EDIT, Action::INDEX);
  119. $actions->add(Crud::PAGE_EDIT, Action::DELETE);
  120. $actions->add(Crud::PAGE_NEW, Action::INDEX);
  121. if ($this->isInstanceOf(SortableInterface::class)) {
  122. $sortAction = Action::new('sort', 'Ordonner', 'fa fa-sort')
  123. ->linkToCrudAction('sort')
  124. ->setCssClass('btn btn-sm btn-success')
  125. ->createAsGlobalAction();
  126. $actions->add(Crud::PAGE_INDEX, $sortAction);
  127. }
  128. if ($this->isInstanceOf(TreeInterface::class)) {
  129. $indexChildAction = Action::new('index_children', 'Afficher les enfants', 'fa fa-list')
  130. ->linkToCrudAction(Action::INDEX)
  131. ->setLabel('')
  132. ->setHtmlAttributes(array('data-toggle'=> 'tooltip', 'title'=> 'Afficher les enfants'))
  133. ->setTemplatePath('@LcSov/adminlte/crud/action/index_children.html.twig')
  134. ->setCssClass('btn btn-sm btn-success');
  135. $backParentAction = Action::new('index_parent', 'Retour au parent', 'fa fa-chevron-left')
  136. ->linkToCrudAction(Action::INDEX)
  137. ->setCssClass('btn btn-sm btn-info')
  138. ->createAsGlobalAction();
  139. $actions->add(Crud::PAGE_INDEX, $backParentAction);
  140. $actions->add(Crud::PAGE_INDEX, $indexChildAction);
  141. }
  142. $actions->reorder(Crud::PAGE_EDIT, [Action::INDEX, Action::SAVE_AND_RETURN, Action::SAVE_AND_CONTINUE]);
  143. $actions->reorder(Crud::PAGE_NEW, [Action::INDEX, Action::SAVE_AND_RETURN, Action::SAVE_AND_ADD_ANOTHER]);
  144. foreach ($actionsArray as $crudActionName => $actionsStyle) {
  145. foreach ($actionsStyle as $actionName => $button) {
  146. $actions->update(
  147. $crudActionName,
  148. $actionName,
  149. function (Action $action) use ($button) {
  150. if (isset($button['add_class'])) {
  151. $action->addCssClass($button['add_class']);
  152. }
  153. if (isset($button['class'])) {
  154. $action->setCssClass($button['class']);
  155. }
  156. if (isset($button['icon'])) {
  157. $action->setIcon('fa fa-'.$button['icon']);
  158. }
  159. if (isset($button['label'])) {
  160. $action->setLabel($button['label']);
  161. }
  162. if (isset($button['dropdown']) && $button['dropdown']) {
  163. $action->addCssClass('in-dropdown');
  164. }
  165. if (isset($button['html_attributes']) && $button['html_attributes']) {
  166. $action->setHtmlAttributes( $button['html_attributes']);
  167. }
  168. return $action;
  169. }
  170. );
  171. }
  172. }
  173. return $actions;
  174. }
  175. public function configureResponseParameters(KeyValueStore $responseParameters): KeyValueStore
  176. {
  177. if (Crud::PAGE_INDEX === $responseParameters->get('pageName')) {
  178. $responseParameters->set('fields', $this->configureFields('index'));
  179. }
  180. return $responseParameters;
  181. }
  182. public function configureCrud(Crud $crud): Crud
  183. {
  184. $crud = parent::configureCrud($crud);
  185. $this->setMaxResults($crud);
  186. if($this->isInstanceOf(SortableInterface::class)){
  187. $crud->setDefaultSort(['position' => 'ASC']);
  188. }
  189. return $crud;
  190. }
  191. public function setMaxResults(Crud $crud)
  192. {
  193. $entityClass = $this->getEntityFqcn();
  194. $paramListMaxResults = 'listMaxResults';
  195. $paramSessionListMaxResults = $entityClass.'-'.$paramListMaxResults;
  196. $requestListMaxResults = $this->request->getCurrentRequest()->get($paramListMaxResults);
  197. if ($requestListMaxResults) {
  198. $this->session->set($paramSessionListMaxResults, $requestListMaxResults);
  199. }
  200. $maxResults = $this->session->get($paramSessionListMaxResults) ? $this->session->get(
  201. $paramSessionListMaxResults
  202. ) : 30;
  203. $crud->setPaginatorPageSize($maxResults);
  204. }
  205. public function configureFields(string $pageName): iterable
  206. {
  207. if ($this->isInstanceOf(SortableInterface::class)) {
  208. $seoPanel = [
  209. FormField::addPanel('Seo'),
  210. TextField::new('metaTitle')->setLabel('Meta Title')->setHelp(
  211. 'Affiché dans les résultats de recherche Google'
  212. )->hideOnIndex(),
  213. TextareaField::new('metaDescription')->setLabel('Meta description')->setHelp(
  214. 'Affiché dans les résultats de recherche Google'
  215. )->hideOnIndex(),
  216. CollectionField::new('oldUrls')
  217. ->setFormTypeOption('entry_type', TextType::class)->setLabel(
  218. 'Anciennes urls du document'
  219. )->hideOnIndex(),
  220. ];
  221. }
  222. if ($this->isInstanceOf(DevAliasInterface::class)) {
  223. $confPanel = [
  224. FormField::addPanel('Conf'),
  225. TextField::new('devAlias')->hideOnIndex(),
  226. ];
  227. }
  228. return array_merge($seoPanel, $confPanel);
  229. }
  230. public function sort(AdminContext $context)
  231. {
  232. $event = new BeforeCrudActionEvent($context);
  233. $this->get('event_dispatcher')->dispatch($event);
  234. if ($event->isPropagationStopped()) {
  235. return $event->getResponse();
  236. }
  237. if (!$this->isGranted(Permission::EA_EXECUTE_ACTION) || !$this->isInstanceOf(SortableInterface::class)) {
  238. throw new ForbiddenActionException($context);
  239. }
  240. $fields = FieldCollection::new($this->configureFields(Crud::PAGE_INDEX));
  241. $filters = $this->get(FilterFactory::class)->create(
  242. $context->getCrud()->getFiltersConfig(),
  243. $fields,
  244. $context->getEntity()
  245. );
  246. $queryBuilder = $this->createIndexQueryBuilder($context->getSearch(), $context->getEntity(), $fields, $filters);
  247. $paginator = $this->get(PaginatorFactory::class)->create($queryBuilder);
  248. $entities = $this->get(EntityFactory::class)->createCollection($context->getEntity(), $paginator->getResults());
  249. $this->get(EntityFactory::class)->processFieldsForAll($entities, $fields);
  250. $sortableForm = $this->createFormBuilder(array('entities', $paginator->getResults()))
  251. ->add(
  252. 'entities',
  253. CollectionType::class,
  254. array(
  255. 'required' => true,
  256. 'allow_add' => true,
  257. 'entry_type' => PositionType::class,
  258. )
  259. )
  260. ->getForm();
  261. $entityManager = $this->getDoctrine()->getManagerForClass($this->getEntityFqcn());
  262. $repository = $entityManager->getRepository($this->getEntityFqcn());
  263. $sortableForm->handleRequest($context->getRequest());
  264. if ($sortableForm->isSubmitted() && $sortableForm->isValid()) {
  265. foreach ($sortableForm->get('entities')->getData() as $elm) {
  266. $entityInstance = $repository->find($elm['id']);
  267. $entityDto = $context->getEntity()->newWithInstance($entityInstance);
  268. if (!$entityDto->isAccessible()) {
  269. throw new InsufficientEntityPermissionException($context);
  270. }
  271. $event = new BeforeEntityDeletedEvent($entityInstance);
  272. $this->get('event_dispatcher')->dispatch($event);
  273. $entityInstance = $event->getEntityInstance();
  274. $entityInstance->setPosition($elm['position']);
  275. $this->updateEntity($entityManager, $entityInstance);
  276. $this->get('event_dispatcher')->dispatch(new AfterEntityUpdatedEvent($entityInstance));
  277. }
  278. $url = $this->get(AdminUrlGenerator::class)
  279. ->setAction(Action::INDEX)
  280. ->generateUrl();
  281. $this->addFlash('success', 'Position modifié', array());
  282. return $this->redirect($url);
  283. }
  284. $responseParameters = $this->configureResponseParameters(
  285. KeyValueStore::new(
  286. [
  287. 'pageName' => Crud::PAGE_INDEX,
  288. 'templatePath' => '@LcSov/adminlte/crud/sort.html.twig',
  289. 'entities' => $entities,
  290. 'paginator' => $paginator,
  291. 'global_actions' => array(),
  292. 'batch_actions' => array(),
  293. 'filters' => $filters,
  294. 'sortable_form' => $sortableForm,
  295. ]
  296. )
  297. );
  298. $responseParameters->set('fields', $this->configureFields('index'));
  299. $event = new AfterCrudActionEvent($context, $responseParameters);
  300. $this->get('event_dispatcher')->dispatch($event);
  301. if ($event->isPropagationStopped()) {
  302. return $event->getResponse();
  303. }
  304. return $responseParameters;
  305. }
  306. public function createIndexQueryBuilder(
  307. SearchDto $searchDto,
  308. EntityDto $entityDto,
  309. FieldCollection $fields,
  310. FilterCollection $filters
  311. ): QueryBuilder {
  312. $queryBuilder = parent::createIndexQueryBuilder(
  313. $searchDto,
  314. $entityDto,
  315. $fields,
  316. $filters
  317. );
  318. if ($this->isInstanceOf(TreeInterface::class)) {
  319. $entityId = $searchDto->getRequest()->get('entityId');
  320. if ($entityId !== null) {
  321. $queryBuilder->andWhere('entity.parent = :entityId');
  322. $queryBuilder->setParameter('entityId', $searchDto->getRequest()->get('entityId'));
  323. } else {
  324. $queryBuilder->andWhere('entity.parent IS NULL');
  325. }
  326. }
  327. return $queryBuilder;
  328. }
  329. public function createSortQueryBuilder(
  330. SearchDto $searchDto,
  331. EntityDto $entityDto,
  332. FieldCollection $fields,
  333. FilterCollection $filters
  334. ): QueryBuilder {
  335. $queryBuilder = $this->createIndexQueryBuilder($searchDto,$entityDto,$fields,$filters);
  336. return $queryBuilder;
  337. }
  338. public function isInstanceOf(string $interfaceName): bool
  339. {
  340. return in_array($interfaceName, class_implements($this->getEntityFqcn()));
  341. }
  342. public function updateEntity(EntityManagerInterface $entityManager, $entityInstance): void
  343. {
  344. $entityManager->update($entityInstance);
  345. $entityManager->flush();
  346. }
  347. public function persistEntity(EntityManagerInterface $entityManager, $entityInstance): void
  348. {
  349. $entityManager->create($entityInstance);
  350. $entityManager->flush();
  351. }
  352. }