src/Controller/Admin/FormLeadCrudController.php line 264

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