src/Controller/Admin/FormLeadCrudController.php line 272

Open in your IDE?
  1. <?php
  2. namespace App\Controller\Admin;
  3. use App\Controller\Admin\Filter\DateCalendarFilter;
  4. use App\Entity\Campaign;
  5. use App\Entity\FormActionsSet;
  6. use App\Entity\FormLead;
  7. use App\Event\ActionFormEvent;
  8. use App\Repository\CampaignRepository;
  9. use App\Repository\FormLeadRepository;
  10. use App\Security\Voter\FormLeadVoter;
  11. use App\Service\FormLeadService;
  12. use App\Service\JsonFormManager;
  13. use Doctrine\ORM\OptimisticLockException;
  14. use Doctrine\ORM\ORMException;
  15. use Doctrine\ORM\QueryBuilder;
  16. use EasyCorp\Bundle\EasyAdminBundle\Collection\FieldCollection;
  17. use EasyCorp\Bundle\EasyAdminBundle\Collection\FilterCollection;
  18. use EasyCorp\Bundle\EasyAdminBundle\Config\Action;
  19. use EasyCorp\Bundle\EasyAdminBundle\Config\Actions;
  20. use EasyCorp\Bundle\EasyAdminBundle\Config\Crud;
  21. use EasyCorp\Bundle\EasyAdminBundle\Config\Filters;
  22. use EasyCorp\Bundle\EasyAdminBundle\Config\KeyValueStore;
  23. use EasyCorp\Bundle\EasyAdminBundle\Context\AdminContext;
  24. use EasyCorp\Bundle\EasyAdminBundle\Controller\AbstractCrudController;
  25. use EasyCorp\Bundle\EasyAdminBundle\Dto\EntityDto;
  26. use EasyCorp\Bundle\EasyAdminBundle\Dto\SearchDto;
  27. use EasyCorp\Bundle\EasyAdminBundle\Field\ArrayField;
  28. use EasyCorp\Bundle\EasyAdminBundle\Field\AssociationField;
  29. use EasyCorp\Bundle\EasyAdminBundle\Field\BooleanField;
  30. use EasyCorp\Bundle\EasyAdminBundle\Field\DateTimeField;
  31. use EasyCorp\Bundle\EasyAdminBundle\Field\IdField;
  32. use EasyCorp\Bundle\EasyAdminBundle\Field\TextField;
  33. use EasyCorp\Bundle\EasyAdminBundle\Orm\EntityRepository;
  34. use EasyCorp\Bundle\EasyAdminBundle\Router\AdminUrlGenerator;
  35. use League\Csv\CannotInsertRecord;
  36. use League\Csv\InvalidArgument;
  37. use Psr\Container\ContainerExceptionInterface;
  38. use Psr\Container\NotFoundExceptionInterface;
  39. use Symfony\Component\HttpFoundation\BinaryFileResponse;
  40. use Symfony\Component\HttpFoundation\RedirectResponse;
  41. use Symfony\Component\HttpFoundation\Request;
  42. use Symfony\Component\HttpFoundation\Response;
  43. use Symfony\Component\EventDispatcher\EventDispatcherInterface;
  44. use Symfony\Component\HttpFoundation\ResponseHeaderBag;
  45. use Symfony\Component\Routing\Annotation\Route;
  46. class FormLeadCrudController extends AbstractCrudController
  47. {
  48.     /** @var EventDispatcherInterface $dispatcher */
  49.     private $dispatcher;
  50.     /** @var AdminUrlGenerator $adminUrlGenerator */
  51.     private $adminUrlGenerator;
  52.     /** @var Campaign $campaign */
  53.     private $campaign;
  54.     /** @var FormLeadService $formLeadService */
  55.     private $formLeadService;
  56.     /** @var FormLeadRepository $repository */
  57.     private $repository;
  58.     /**
  59.      * @param EventDispatcherInterface $dispatcher
  60.      * @param AdminUrlGenerator $adminUrlGenerator
  61.      * @param FormLeadService $formLeadService
  62.      * @param FormLeadRepository $repository
  63.      */
  64.     public function __construct(
  65.         EventDispatcherInterface $dispatcher,
  66.         AdminUrlGenerator $adminUrlGenerator,
  67.         FormLeadService $formLeadService,
  68.         FormLeadRepository $repository
  69.     ) {
  70.         $this->dispatcher $dispatcher;
  71.         $this->adminUrlGenerator $adminUrlGenerator;
  72.         $this->formLeadService $formLeadService;
  73.         $this->repository $repository;
  74.     }
  75.     /**
  76.      * @param AdminContext $context
  77.      * @return KeyValueStore|RedirectResponse|Response
  78.      */
  79.     public function index(AdminContext $context)
  80.     {
  81.         $this->campaign $this->get('doctrine')->getRepository(Campaign::class)
  82.             ->find((int) $context->getRequest()->query->get('entityId'))
  83.         ;
  84.         return parent::index($context);
  85.     }
  86.     /**
  87.      * @return string
  88.      */
  89.     public static function getEntityFqcn(): string
  90.     {
  91.         return FormLead::class;
  92.     }
  93.     /**
  94.      * @param Crud $crud
  95.      * @return Crud
  96.      */
  97.     public function configureCrud(Crud $crud): Crud
  98.     {
  99.         return $crud
  100.             ->setEntityLabelInPlural('FormLeads')
  101.             ->setPageTitle('index''%entity_label_plural% de ')
  102.             ->setEntityPermission(FormLeadVoter::VIEW)
  103.             ->overrideTemplates([
  104.                 'crud/index' => 'admin/crud/lead/index.html.twig',
  105.             ])
  106.             ->setSearchFields(['id''formLeadData.value'])
  107.         ;
  108.     }
  109.     /**
  110.      * @param string $pageName
  111.      * @return iterable
  112.      */
  113.     public function configureFields(string $pageName): iterable
  114.     {
  115.         return [
  116.             IdField::new('id')->hideOnForm(),
  117.             TextField::new('uuid')->hideOnForm()->hideOnIndex(),
  118.             AssociationField::new('formLeadData')->setTemplatePath('admin/field/form-lead-data.html.twig')->hideOnIndex(),
  119.             BooleanField::new('active')->hideOnForm(),
  120.             DateTimeField::new('periodStartsAt')->hideOnForm(),
  121.             DateTimeField::new('periodUpdatedAt')->hideOnForm(),
  122.             BooleanField::new('eventForced')->hideOnForm(),
  123.             ArrayField::new('annexPdfIgnoredFields')
  124.                 ->setTemplatePath('admin/field/annex-pdf-ignored-fields.html.twig')
  125.                 ->hideOnIndex()
  126.                 ->setHelp('Formato: name-type (p.ej. mujeres-plantilla)')
  127.         
  128.             
  129.         ];
  130.     }
  131.     /**
  132.      * @param Filters $filters
  133.      * @return Filters
  134.      */
  135.     public function configureFilters(Filters $filters): Filters
  136.     {
  137.         return $filters
  138.            ->add('active')
  139.            ->add(DateCalendarFilter::new('periodStartsAt'))
  140.            ->add(DateCalendarFilter::new('periodUpdatedAt'))
  141.         ;
  142.     }
  143.     /**
  144.      * @param Actions $actions
  145.      * @return Actions
  146.      */
  147.     public function configureActions(Actions $actions): Actions
  148.     {
  149.         $executeActions Action::new('executeActions''Enviar Renovación')
  150.             ->linkToCrudAction('executeActions')
  151.         ;
  152.         $returnList Action::new('indexByCampaign''Volver al listado')
  153.             ->linkToRoute('index_by_campaign', function (FormLead $lead): array {
  154.                 return [
  155.                     'id' => $lead->getId()
  156.                 ];
  157.             })
  158.         ;
  159.         $exportLeads Action::new('exportAllLeads''Exportar')
  160.             ->linkToCrudAction('exportAllLeads')
  161.             ->addCssClass('btn btn-primary')
  162.             ->setIcon('fas fa-file-export')
  163.             ->createAsGlobalAction()
  164.         ;
  165.         $exportLeadsWithFilters Action::new('exportLeadsWithFilters''Exportar con filtros')
  166.             ->linkToCrudAction('exportLeadsWithFilters')
  167.             ->addCssClass('btn btn-primary')
  168.             ->setIcon('fas fa-file-export')
  169.             ->createAsGlobalAction()
  170.         ;
  171.         return $actions
  172.             ->add(Crud::PAGE_INDEX$exportLeads)
  173.             ->add(Crud::PAGE_INDEX$exportLeadsWithFilters)
  174.             ->add(Crud::PAGE_INDEX$executeActions)
  175.             ->add(Crud::PAGE_INDEXAction::DETAIL)
  176.             ->remove(Crud::PAGE_INDEXAction::DELETE)
  177.             ->remove(Crud::PAGE_INDEXAction::EDIT)
  178.             ->remove(Crud::PAGE_INDEXAction::NEW)
  179.             ->remove(Crud::PAGE_DETAILAction::DELETE)
  180.             ->remove(Crud::PAGE_DETAILAction::EDIT)
  181.             ->remove(Crud::PAGE_DETAILAction::INDEX)
  182.             ->add(Crud::PAGE_DETAIL$returnList)
  183.         ;
  184.     }
  185.     /**
  186.      * @param SearchDto $searchDto
  187.      * @param EntityDto $entityDto
  188.      * @param FieldCollection $fields
  189.      * @param FilterCollection $filters
  190.      * @return QueryBuilder
  191.      * @throws ContainerExceptionInterface
  192.      * @throws NotFoundExceptionInterface
  193.      */
  194.     public function createIndexQueryBuilder(SearchDto $searchDtoEntityDto $entityDtoFieldCollection $fieldsFilterCollection $filters): QueryBuilder
  195.     {
  196.         $queryBuilder $this->container->get(EntityRepository::class)->createQueryBuilder($searchDto$entityDto$fields$filters);
  197.         if (!$this->campaign) {
  198.             $result $queryBuilder->getQuery()->getResult();
  199.             if (isset($result[0]) && $result[0] instanceof FormLead) {
  200.                 $this->campaign $result[0]->getCampaign();
  201.             }
  202.         }
  203.         if (!$this->campaign) {
  204.             return $queryBuilder;
  205.         }
  206.         $queryBuilder
  207.             ->andWhere('entity.campaign = :campaign')
  208.             ->setParameter('campaign'$this->campaign->getId())
  209.         ;
  210.         return $queryBuilder;
  211.     }
  212.     /**
  213.      * @param AdminContext $context
  214.      * @param FormLeadRepository $repository
  215.      * @return RedirectResponse
  216.      * @throws ORMException
  217.      * @throws OptimisticLockException
  218.      */
  219.     public function executeActions(AdminContext $contextFormLeadRepository $repository): RedirectResponse
  220.     {
  221.         /** @var FormLead $lead */
  222.         $lead $context->getEntity()->getInstance();
  223.         if (!$lead->isActive()) {
  224.             $this->addFlash('warning''El registro no está activo. No se ha ejecutado ninguna acción');
  225.             return $this->redirect($context->getReferrer());
  226.         }
  227.         $campaign $lead->getCampaign();
  228.         foreach ($campaign->getForms() as $form) {
  229.             foreach ($form->getFormActionsSets() as $actionsSet) {
  230.                 if (FormActionsSet::EVENT_FORCED !== $actionsSet->getEvent()) {
  231.                     continue;
  232.                 }
  233.                 // Dispatch Event
  234.                 $event = new ActionFormEvent($form$lead$actionsSet->getEvent());
  235.                 $this->dispatcher->dispatch($eventActionFormEvent::KEY);
  236.                 // Update lead
  237.                 $lead->setEventForced(true);
  238.                 $repository->store($lead);
  239.             }
  240.         }
  241.         return $this->redirect($context->getReferrer());
  242.     }
  243.     /**
  244.      * @Route(name="index_by_campaign")
  245.      * @param FormLead $lead
  246.      * @return RedirectResponse
  247.      */
  248.     public function indexByCampaign(FormLead $lead): RedirectResponse
  249.     {
  250.         $url $this->adminUrlGenerator
  251.             ->setController(FormLeadCrudController::class)
  252.             ->setAction(Action::INDEX)
  253.             ->setEntityId($lead->getCampaign()->getId())
  254.             ->generateUrl();
  255.         return $this->redirect($url);
  256.     }
  257.     /**
  258.      * @param AdminContext $context
  259.      * @return BinaryFileResponse|RedirectResponse
  260.      * @throws CannotInsertRecord
  261.      * @throws InvalidArgument
  262.      */
  263.     public function exportAllLeads(AdminContext $context)
  264.     {
  265.         return $this->exportLeads($context);
  266.     }
  267.     /**
  268.      * @param AdminContext $context
  269.      * @param CampaignRepository $campaignRepository
  270.      * @return BinaryFileResponse|RedirectResponse
  271.      * @throws CannotInsertRecord
  272.      * @throws InvalidArgument
  273.      */
  274.     public function exportLeadsWithFilters(AdminContext $contextCampaignRepository $campaignRepository)
  275.     {
  276.         $referrer $context->getReferrer();
  277.         $campaignId $this->getCampaignByReferrer($referrer);
  278.         if (!$campaignId) {
  279.             $this->addFlash('danger''No se encuentra la campaña');
  280.             return $this->redirect($referrer);
  281.         }
  282.         $campaign $campaignRepository->find($campaignId);
  283.         if (!$campaign->getExportLeadFields()) {
  284.             $this->addFlash('warning''No hay filtros definidos en la campaña');
  285.             return $this->redirect($referrer);
  286.         }
  287.         $filters = [];
  288.         foreach ($campaign->getExportLeadFields() as $field) {
  289.             $filters[] = [
  290.                 'field' => JsonFormManager::getNameFromFieldName($field),
  291.                 'type' => JsonFormManager::getTypeFromFieldName($field)
  292.             ];
  293.         }
  294.         return $this->exportLeads($context$filters);
  295.     }
  296.     /**
  297.      * @param Campaign $campaign
  298.      * @return string
  299.      */
  300.     public function getCampaignDetailUrl(Campaign $campaign): string
  301.     {
  302.         return $this->adminUrlGenerator
  303.             ->setController(CampaignCrudController::class)
  304.             ->setAction(Action::DETAIL)
  305.             ->setEntityId($campaign->getId())
  306.             ->generateUrl()
  307.         ;
  308.     }
  309.     /**
  310.      * @param KeyValueStore $responseParameters
  311.      * @return KeyValueStore
  312.      */
  313.      public function configureResponseParameters(KeyValueStore $responseParameters): KeyValueStore
  314.      {
  315.          if (Crud::PAGE_INDEX === $responseParameters->get('pageName')) {
  316.              $addParameters = [
  317.                  'campaign' => $this->campaign,
  318.                  'campaign_detail_url' => $this->getCampaignDetailUrl($this->campaign)
  319.              ];
  320.              foreach ($addParameters as $key => $value) {
  321.                  $responseParameters->set($key$value);
  322.              }
  323.          }
  324.          return $responseParameters;
  325.      }
  326.     /**
  327.      * @param string $referrer
  328.      * @return null
  329.      */
  330.      private function getCampaignByReferrer(string $referrer): ?int
  331.      {
  332.          $referrer explode('&'$referrer);
  333.          foreach ($referrer as $item) {
  334.              $entityIndex 'entityId=';
  335.              if (str_contains($item$entityIndex)) {
  336.                  return (int) explode($entityIndex$item)[1];
  337.              }
  338.          }
  339.          return null;
  340.      }
  341.     /**
  342.      * @param AdminContext $context
  343.      * @param array $filters
  344.      * @return BinaryFileResponse|RedirectResponse
  345.      * @throws CannotInsertRecord
  346.      * @throws InvalidArgument
  347.      */
  348.      public function exportLeads(AdminContext $context, array $filters = [])
  349.      {
  350.          ini_set('max_execution_time''-1');
  351.          set_time_limit(0);
  352.          $referrer $context->getReferrer();
  353.          $campaignId $this->getCampaignByReferrer($referrer);
  354.          if (!$campaignId) {
  355.              $this->addFlash('danger''No se encuentra la campaña');
  356.              return $this->redirect($referrer);
  357.          }
  358.          $leads $this->repository->findBy(['campaign' => $campaignId]);
  359.          if (empty($leads)) {
  360.              $this->addFlash('warning''No hay registros');
  361.              return $this->redirect($referrer);
  362.          }
  363.          $fileName $this->formLeadService->exportLeads($campaignId$leads$filters);
  364.          if ('' === $fileName) {
  365.              $this->addFlash('warning''No se han encontrado registros');
  366.              return $this->redirect($referrer);
  367.          }
  368.          if (null === $fileName) {
  369.              $this->addFlash('danger''Se ha producido un error');
  370.              return $this->redirect($referrer);
  371.          }
  372.          $response = new BinaryFileResponse(
  373.              $fileName200, []
  374.          );
  375.          return $response
  376.              ->setContentDisposition(ResponseHeaderBag::DISPOSITION_ATTACHMENT)
  377.              ->deleteFileAfterSend()
  378.          ;
  379.      }
  380.     /**
  381.      * @Route("/form-lead/{id}/edit-annex-fields", name="form_lead_edit_annex_fields", methods={"POST"})
  382.      * @param Request $request
  383.      * @param FormLead $lead
  384.      * @param FormLeadRepository $repository
  385.      * @return RedirectResponse
  386.      */
  387.     public function editAnnexPdfIgnoredFields(Request $requestFormLead $leadFormLeadRepository $repository): RedirectResponse
  388.     {
  389.         $newValue $request->request->get('annex-fields-' $lead->getId());
  390.         
  391.         if ($newValue !== null) {
  392.             try {
  393.                 // Parse the textarea input (one field per line)
  394.                 $fields array_filter(array_map('trim'explode("\n"$newValue)));
  395.                 $lead->setAnnexPdfIgnoredFields($fields);
  396.                 $repository->store($lead);
  397.                 $this->addFlash('success''Campos ignorados modificados con éxito');
  398.             } catch (\Exception $exception) {
  399.                 $this->addFlash('danger''Error al modificar campos ignorados: ' $exception->getMessage());
  400.             }
  401.         }
  402.         return $this->redirect($request->headers->get('referer'));
  403.     }
  404. }