vendor/store.shopware.com/dvsnticketsystem/src/Storefront/Controller/TicketSystemController.php line 521

Open in your IDE?
  1. <?php
  2. /**
  3.  * digitvision
  4.  *
  5.  * @category  digitvision
  6.  * @package   Shopware\Plugins\DvsnTicketSystem
  7.  * @copyright (c) 2020 digitvision
  8.  */
  9. namespace Dvsn\TicketSystem\Storefront\Controller;
  10. use Dvsn\TicketSystem\Core\System\Ticket\Aggregate\TicketForm\TicketFormEntity;
  11. use Dvsn\TicketSystem\Core\System\Ticket\Aggregate\TicketFormElement\TicketFormElementEntity;
  12. use Dvsn\TicketSystem\Core\System\Ticket\TicketEntity;
  13. use Dvsn\TicketSystem\Service\CaptchaService;
  14. use Dvsn\TicketSystem\Service\Ticket\ElementHandler\Exception\InvalidElementException;
  15. use Dvsn\TicketSystem\Service\Ticket\ElementHandlerFactoryInterface;
  16. use Dvsn\TicketSystem\Service\Ticket\TicketCreatorServiceInterface;
  17. use Shopware\Core\Checkout\Customer\CustomerEntity;
  18. use Shopware\Core\Checkout\Order\OrderEntity;
  19. use Shopware\Core\Framework\Adapter\Twig\StringTemplateRenderer;
  20. use Shopware\Core\Framework\Context;
  21. use Shopware\Core\Framework\DataAbstractionLayer\EntityRepositoryInterface;
  22. use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
  23. use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsFilter;
  24. use Shopware\Core\Framework\DataAbstractionLayer\Search\Sorting\FieldSorting;
  25. use Shopware\Core\Framework\Routing\Annotation\LoginRequired;
  26. use Shopware\Core\Framework\Uuid\Uuid;
  27. use Shopware\Core\Framework\Validation\DataBag\RequestDataBag;
  28. use Shopware\Core\SalesChannelRequest;
  29. use Shopware\Core\System\SalesChannel\Entity\SalesChannelRepositoryInterface;
  30. use Shopware\Core\System\SalesChannel\SalesChannelContext;
  31. use Shopware\Core\System\Salutation\SalutationCollection;
  32. use Shopware\Core\System\Salutation\SalutationEntity;
  33. use Shopware\Core\System\SystemConfig\SystemConfigService;
  34. use Shopware\Storefront\Controller\StorefrontController;
  35. use Shopware\Storefront\Page\GenericPageLoaderInterface;
  36. use Shopware\Storefront\Page\Page;
  37. use Symfony\Component\Routing\Annotation\Route;
  38. use Shopware\Core\Framework\Routing\Annotation\RouteScope;
  39. use Symfony\Component\HttpFoundation\Request;
  40. use Symfony\Component\HttpFoundation\Response;
  41. class TicketSystemController extends StorefrontController
  42. {
  43.     /**
  44.      * ...
  45.      *
  46.      * @var EntityRepositoryInterface
  47.      */
  48.     protected $ticketRepository;
  49.     /**
  50.      * ...
  51.      *
  52.      * @var EntityRepositoryInterface
  53.      */
  54.     protected $ticketFormRepository;
  55.     /**
  56.      * ...
  57.      *
  58.      * @var EntityRepositoryInterface
  59.      */
  60.     protected $ticketHistoryRepository;
  61.     /**
  62.      * ...
  63.      *
  64.      * @var SalesChannelRepositoryInterface
  65.      */
  66.     private $salutationRepository;
  67.     /**
  68.      * ...
  69.      *
  70.      * @var TicketCreatorServiceInterface
  71.      */
  72.     private $ticketCreatorService;
  73.     /**
  74.      * ...
  75.      *
  76.      * @var SystemConfigService
  77.      */
  78.     protected $systemConfigService;
  79.     /**
  80.      * ...
  81.      *
  82.      * @var GenericPageLoaderInterface
  83.      */
  84.     protected $genericPageLoader;
  85.     /**
  86.      * ...
  87.      *
  88.      * @var StringTemplateRenderer
  89.      */
  90.     protected $templateRenderer;
  91.     /**
  92.      * ...
  93.      *
  94.      * @var ElementHandlerFactoryInterface
  95.      */
  96.     protected $elementHandlerFactory;
  97.     /**
  98.      * ...
  99.      *
  100.      * @param EntityRepositoryInterface       $ticketRepository
  101.      * @param EntityRepositoryInterface       $ticketFormRepository
  102.      * @param EntityRepositoryInterface       $ticketHistoryRepository
  103.      * @param SalesChannelRepositoryInterface $salutationRepository
  104.      * @param TicketCreatorServiceInterface   $ticketCreatorService
  105.      * @param SystemConfigService             $systemConfigService
  106.      * @param GenericPageLoaderInterface      $genericPageLoader
  107.      * @param StringTemplateRenderer          $templateRenderer
  108.      * @param ElementHandlerFactoryInterface $elementHandlerFactory
  109.      */
  110.     public function __construct(
  111.         EntityRepositoryInterface $ticketRepository,
  112.         EntityRepositoryInterface $ticketFormRepository,
  113.         EntityRepositoryInterface $ticketHistoryRepository,
  114.         SalesChannelRepositoryInterface $salutationRepository,
  115.         TicketCreatorServiceInterface $ticketCreatorService,
  116.         SystemConfigService $systemConfigService,
  117.         GenericPageLoaderInterface $genericPageLoader,
  118.         StringTemplateRenderer $templateRenderer,
  119.         ElementHandlerFactoryInterface $elementHandlerFactory
  120.     )
  121.     {
  122.         // set params
  123.         $this->ticketRepository $ticketRepository;
  124.         $this->ticketFormRepository $ticketFormRepository;
  125.         $this->ticketHistoryRepository $ticketHistoryRepository;
  126.         $this->salutationRepository $salutationRepository;
  127.         $this->ticketCreatorService $ticketCreatorService;
  128.         $this->systemConfigService $systemConfigService;
  129.         $this->genericPageLoader $genericPageLoader;
  130.         $this->templateRenderer $templateRenderer;
  131.         $this->elementHandlerFactory $elementHandlerFactory;
  132.     }
  133.     /**
  134.      * ...
  135.      *
  136.      * @RouteScope(scopes={"storefront"})
  137.      * @Route("/dvsn/ticket-system",
  138.      *     name="frontend.dvsn.ticket-system",
  139.      *     options={"seo"="false"},
  140.      *     methods={"GET"}
  141.      * )
  142.      *
  143.      * @param Request $request
  144.      * @param RequestDataBag $data
  145.      * @param Context $context
  146.      * @param SalesChannelContext $salesChannelContext
  147.      *
  148.      * @return Response
  149.      */
  150.     public function index(Request $requestRequestDataBag $dataContext $contextSalesChannelContext $salesChannelContext): Response
  151.     {
  152.         throw new \Exception('not implemented yet');
  153.     }
  154.     /**
  155.      * ...
  156.      *
  157.      * @RouteScope(scopes={"storefront"})
  158.      * @Route("/dvsn/ticket-system/ticket/{id}",
  159.      *     name="frontend.dvsn.ticket-system.ticket",
  160.      *     options={"seo"="false"},
  161.      *     methods={"GET"}
  162.      * )
  163.      *
  164.      * @param string $id
  165.      * @param Request $request
  166.      * @param RequestDataBag $data
  167.      * @param Context $context
  168.      * @param SalesChannelContext $salesChannelContext
  169.      *
  170.      * @return Response
  171.      */
  172.     public function ticket(string $idRequest $requestRequestDataBag $dataContext $contextSalesChannelContext $salesChannelContext): Response
  173.     {
  174.         // get possible status
  175.         $status = (int) $request->query->get('status');
  176.         // get the ticket
  177.         try {
  178.             $ticket $this->getTicket($id$salesChannelContext);
  179.         } catch (\Exception $exception) {
  180.             throw new \Exception('ticket not found');
  181.         }
  182.         /** @var Page $page */
  183.         $page $this->genericPageLoader->load($request$salesChannelContext);
  184.         // render template
  185.         return $this->renderStorefront('@Storefront/storefront/page/dvsn/ticket-system/ticket.html.twig', ['page' => [
  186.             'ticket' => $ticket,
  187.             'status' => $status,
  188.             'config' => $this->systemConfigService->get('DvsnTicketSystem.config'),
  189.             'header' => $page->getHeader(),
  190.             'footer' => $page->getFooter(),
  191.             'salesChannelPaymentMethods' => $page->getSalesChannelPaymentMethods(),
  192.             'salesChannelShippingMethods' => $page->getSalesChannelShippingMethods(),
  193.             'metaInformation' => $page->getMetaInformation()
  194.         ]]);
  195.     }
  196.     /**
  197.      * ...
  198.      *
  199.      * @RouteScope(scopes={"storefront"})
  200.      * @Route("/dvsn/ticket-system/create/{id}",
  201.      *     name="frontend.dvsn.ticket-system.create",
  202.      *     options={"seo"="false"},
  203.      *     methods={"GET"}
  204.      * )
  205.      *
  206.      * @param string $id
  207.      * @param Request $request
  208.      * @param RequestDataBag $data
  209.      * @param Context $context
  210.      * @param SalesChannelContext $salesChannelContext
  211.      *
  212.      * @return Response
  213.      */
  214.     public function create(string $idRequest $requestRequestDataBag $dataContext $contextSalesChannelContext $salesChannelContext): Response
  215.     {
  216.         // get the form
  217.         try {
  218.             $form $this->getTicketForm($id$salesChannelContext);
  219.         } catch (\Exception $exception) {
  220.             throw new \Exception('form not found');
  221.         }
  222.         // default values
  223.         $values = [
  224.             'salutationId' => '',
  225.             'firstName' => '',
  226.             'lastName' => '',
  227.             'email' => '',
  228.             'phone' => ''
  229.         ];
  230.         // get the customer
  231.         $customer $salesChannelContext->getCustomer();
  232.         // do we have one?
  233.         if ($customer instanceof CustomerEntity) {
  234.             // set the defaults
  235.             $values['salutationId'] = $customer->getSalutationId();
  236.             $values['firstName'] = $customer->getFirstName();
  237.             $values['lastName'] = $customer->getLastName();
  238.             $values['email'] = $customer->getEmail();
  239.             $values['phone'] = (string) $customer->getActiveBillingAddress()->getPhoneNumber();
  240.         }
  241.         /** @var TicketFormElementEntity $element */
  242.         foreach ($form->getElements() as $element) {
  243.             // get key and value
  244.             $key $element->getId();
  245.             $value = (string) $element->getContext();
  246.             // parse the value
  247.             $value $this->templateRenderer->render(
  248.                 $value,
  249.                 [
  250.                     'salesChannel' => $salesChannelContext->getSalesChannel(),
  251.                     'customer' => $salesChannelContext->getCustomer(),
  252.                 ],
  253.                 $context
  254.             );
  255.             // set it
  256.             $values[$key] = $value;
  257.         }
  258.         // set captcha
  259.         $captcha = ($this->systemConfigService->get('DvsnTicketSystem.config.captchaStatus') === true)
  260.             ? $this->container->get('Dvsn\TicketSystem\Service\CaptchaService')->getBase64()
  261.             : '';
  262.         /** @var Page $page */
  263.         $page $this->genericPageLoader->load($request$salesChannelContext);
  264.         // render template
  265.         return $this->renderStorefront('@Storefront/storefront/page/dvsn/ticket-system/create.html.twig', ['page' => [
  266.             'form' => $form,
  267.             'values' => $values,
  268.             'captcha' => $captcha,
  269.             'salutations' => $this->getSalutations($salesChannelContext),
  270.             'config' => $this->systemConfigService->get('DvsnTicketSystem.config'),
  271.             'header' => $page->getHeader(),
  272.             'footer' => $page->getFooter(),
  273.             'salesChannelPaymentMethods' => $page->getSalesChannelPaymentMethods(),
  274.             'salesChannelShippingMethods' => $page->getSalesChannelShippingMethods(),
  275.             'metaInformation' => $page->getMetaInformation()
  276.         ]]);
  277.     }
  278.     /**
  279.      * ...
  280.      *
  281.      * @param SalesChannelContext $salesChannelContext
  282.      *
  283.      * @return array
  284.      */
  285.     private function getSalutations(SalesChannelContext $salesChannelContext): array
  286.     {
  287.         /** @var SalutationCollection $salutations */
  288.         $salutations $this->salutationRepository->search(new Criteria(), $salesChannelContext)->getEntities();
  289.         // sort by key
  290.         $salutations->sort(function (SalutationEntity $aSalutationEntity $b) {
  291.             return $b->getSalutationKey() <=> $a->getSalutationKey();
  292.         });
  293.         // we need them in a simple array
  294.         $arr = [];
  295.         // set every salutation to array
  296.         foreach ($salutations as $salutation) {
  297.             $arr[] = [
  298.                 'key' => $salutation->getId(),
  299.                 'value' => $salutation->getTranslation('displayName')
  300.             ];
  301.         }
  302.         // return it
  303.         return $arr;
  304.     }
  305.     /**
  306.      * ...
  307.      *
  308.      * @RouteScope(scopes={"storefront"})
  309.      * @Route("/dvsn/ticket-system/create-submit",
  310.      *     name="frontend.dvsn.ticket-system.create-submit",
  311.      *     options={"seo"="false"},
  312.      *     methods={"POST"}
  313.      * )
  314.      *
  315.      * @param string $id
  316.      * @param Request $request
  317.      * @param RequestDataBag $data
  318.      * @param Context $context
  319.      * @param SalesChannelContext $salesChannelContext
  320.      *
  321.      * @return Response
  322.      */
  323.     public function createSubmit(Request $requestRequestDataBag $dataContext $contextSalesChannelContext $salesChannelContext): Response
  324.     {
  325.         // get the form
  326.         try {
  327.             $form $this->getTicketForm($data->get('id'), $salesChannelContext);
  328.         } catch (\Exception $exception) {
  329.             throw new \Exception('form not found');
  330.         }
  331.         // check captcha
  332.         if ($this->systemConfigService->get('DvsnTicketSystem.config.captchaStatus') === true) {
  333.             /** @var CaptchaService $captchaService */
  334.             $captchaService $this->container->get('Dvsn\TicketSystem\Service\CaptchaService');
  335.             // not valid?
  336.             if ($captchaService->isValid($data->get('captcha')) === true) {
  337.                 // redirect back to ticket form
  338.                 $this->addFlash('danger'$this->trans('dvsn-ticket-system.create.flash.captcha-error'));
  339.                 return $this->redirectToRoute('frontend.dvsn.ticket-system.create', ['id' => $data->get('id')]);
  340.             }
  341.         }
  342.         // additional data here
  343.         $json = [];
  344.         /** @var TicketFormElementEntity $element */
  345.         foreach ($form->getElements() as $element) {
  346.             // get the value
  347.             $value = (string) $data->get('form-elements')->get($element->getId());
  348.             // try to handle the element and ignore elements without a handler
  349.             // which may be just a title or line-break
  350.             try {
  351.                 // handle it
  352.                 $value $this->elementHandlerFactory->get($element->getType())->handle(
  353.                     $value,
  354.                     $request,
  355.                     $form,
  356.                     $element,
  357.                     $salesChannelContext
  358.                 );
  359.                 // add to json
  360.                 $json[] = [
  361.                     'type' => $element->getType(),
  362.                     'key' => $element->getName(),
  363.                     'value' => $value
  364.                 ];
  365.             } catch (InvalidElementException $exception) {}
  366.         }
  367.         // create a ticket
  368.         $ticket $this->ticketCreatorService->create(
  369.             $form,
  370.             $data->get('salutation'),
  371.             strip_tags($data->get('firstName')),
  372.             strip_tags($data->get('lastName')),
  373.             strip_tags($data->get('email')),
  374.             strip_tags($data->get('phone')),
  375.             strip_tags((string) $data->get('message')),
  376.             $json,
  377.             ($salesChannelContext->getCustomer() instanceof CustomerEntity) ? $salesChannelContext->getCustomer()->getId() : null,
  378.             $salesChannelContext->getContext()->getLanguageId(),
  379.             $salesChannelContext->getSalesChannel()->getId(),
  380.             $request->attributes->get(SalesChannelRequest::ATTRIBUTE_DOMAIN_ID),
  381.             null,
  382.             $salesChannelContext->getContext()
  383.         );
  384.         // redirect to ticket
  385.         return $this->redirectToRoute('frontend.dvsn.ticket-system.ticket', ['id' => $ticket->getId(), 'status' => 10]);
  386.     }
  387.     /**
  388.      * ...
  389.      *
  390.      * @RouteScope(scopes={"storefront"})
  391.      * @Route("/dvsn/ticket-system/ticket-submit",
  392.      *     name="frontend.dvsn.ticket-system.ticket-submit",
  393.      *     options={"seo"="false"},
  394.      *     methods={"POST"}
  395.      * )
  396.      *
  397.      * @param string $id
  398.      * @param Request $request
  399.      * @param RequestDataBag $data
  400.      * @param Context $context
  401.      * @param SalesChannelContext $salesChannelContext
  402.      *
  403.      * @return Response
  404.      */
  405.     public function ticketSubmit(Request $requestRequestDataBag $dataContext $contextSalesChannelContext $salesChannelContext): Response
  406.     {
  407.         // get params
  408.         $id = (string) $data->get('id');
  409.         $message = (string) $data->get('message');
  410.         $message strip_tags($message);
  411.         // get the ticket
  412.         try {
  413.             $ticket $this->getTicket($id$salesChannelContext);
  414.         } catch (\Exception $exception) {
  415.             throw new \Exception('ticket not found');
  416.         }
  417.         // defaults
  418.         $preStatusId null;
  419.         $postStatusId null;
  420.         // current status id
  421.         $statusId $ticket->getStatusId();
  422.         // did we change it?
  423.         if ($ticket->getStatusId() !== $ticket->getAnswerStatusId()) {
  424.             // save
  425.             $preStatusId $ticket->getStatusId();
  426.             $postStatusId $ticket->getAnswerStatusId();
  427.             $statusId $ticket->getAnswerStatusId();
  428.         }
  429.         // force an update for updatedAt for the sorting
  430.         $this->ticketRepository->update(
  431.             [['id' => $id'statusId' => $statusId]],
  432.             $context
  433.         );
  434.         // set a history item
  435.         $history = [
  436.             'id' => Uuid::randomHex(),
  437.             'ticketId' => $id,
  438.             'message' => $message,
  439.             'customerId' => ($salesChannelContext->getCustomer() instanceof CustomerEntity) ? $salesChannelContext->getCustomer()->getId() : null,
  440.             'preStatusId' => $preStatusId,
  441.             'postStatusId' => $postStatusId
  442.         ];
  443.         // save it
  444.         $this->ticketHistoryRepository->create(
  445.             [$history],
  446.             $context
  447.         );
  448.         // return to ticket
  449.         return $this->redirectToRoute('frontend.dvsn.ticket-system.ticket', ['id' => $ticket->getId(), 'status' => 20]);
  450.     }
  451.     /**
  452.      * ...
  453.      *
  454.      * @RouteScope(scopes={"storefront"})
  455.      * @Route("/dvsn/ticket-system/list",
  456.      *     name="frontend.dvsn.ticket-system.list",
  457.      *     options={"seo"="false"},
  458.      *     methods={"GET"}
  459.      * )
  460.      * @LoginRequired()
  461.      *
  462.      * @param Request $request
  463.      * @param RequestDataBag $data
  464.      * @param Context $context
  465.      * @param SalesChannelContext $salesChannelContext
  466.      *
  467.      * @return Response
  468.      */
  469.     public function list(Request $requestRequestDataBag $dataContext $contextSalesChannelContext $salesChannelContext): Response
  470.     {
  471.         // get the tickets from the customer
  472.         $tickets $this->getCustomerTickets($salesChannelContext);
  473.         /** @var Page $page */
  474.         $page $this->genericPageLoader->load($request$salesChannelContext);
  475.         // render template
  476.         return $this->renderStorefront('@Storefront/storefront/page/dvsn/ticket-system/list.html.twig', ['page' => [
  477.             'tickets' => $tickets,
  478.             'salutations' => $this->getSalutations($salesChannelContext),
  479.             'config' => $this->systemConfigService->get('DvsnTicketSystem.config'),
  480.             'header' => $page->getHeader(),
  481.             'footer' => $page->getFooter(),
  482.             'salesChannelPaymentMethods' => $page->getSalesChannelPaymentMethods(),
  483.             'salesChannelShippingMethods' => $page->getSalesChannelShippingMethods(),
  484.             'metaInformation' => $page->getMetaInformation()
  485.         ]]);
  486.     }
  487.     /**
  488.      * ...
  489.      *
  490.      * @param string $id
  491.      * @param SalesChannelContext $salesChannelContext
  492.      *
  493.      * @return TicketFormEntity
  494.      */
  495.     private function getTicketForm(string $idSalesChannelContext $salesChannelContext): TicketFormEntity
  496.     {
  497.         // find the order
  498.         $criteria = new Criteria();
  499.         $criteria->addAssociation('elements');
  500.         $criteria->addFilter(new EqualsFilter('id'$id));
  501.         $criteria->getAssociation('elements')->addSorting(new FieldSorting('position'FieldSorting::ASCENDING));
  502.         /** @var OrderEntity $order */
  503.         $form $this->ticketFormRepository->search(
  504.             $criteria,
  505.             $salesChannelContext->getContext()
  506.         )->getEntities()->first();
  507.         // return it
  508.         return $form;
  509.     }
  510.     /**
  511.      * ...
  512.      *
  513.      * @param string $id
  514.      * @param SalesChannelContext $salesChannelContext
  515.      *
  516.      * @return TicketEntity
  517.      */
  518.     private function getTicket(string $idSalesChannelContext $salesChannelContext): TicketEntity
  519.     {
  520.         // find the order
  521.         $criteria = new Criteria();
  522.         $criteria->addAssociation('status');
  523.         $criteria->addAssociation('history');
  524.         $criteria->addAssociation('salutation');
  525.         $criteria->addFilter(new EqualsFilter('id'$id));
  526.         $criteria->getAssociation('history')->addSorting(new FieldSorting('createdAt'FieldSorting::ASCENDING));
  527.         $criteria->getAssociation('history')->addAssociation('preStatus');
  528.         $criteria->getAssociation('history')->addAssociation('postStatus');
  529.         /** @var TicketEntity $ticket */
  530.         $ticket $this->ticketRepository->search(
  531.             $criteria,
  532.             $salesChannelContext->getContext()
  533.         )->getEntities()->first();
  534.         // return it
  535.         return $ticket;
  536.     }
  537.     /**
  538.      * ...
  539.      *
  540.      * @param SalesChannelContext $salesChannelContext
  541.      *
  542.      * @return TicketEntity[]
  543.      */
  544.     private function getCustomerTickets(SalesChannelContext $salesChannelContext): array
  545.     {
  546.         // find the order
  547.         $criteria = new Criteria();
  548.         $criteria->addAssociation('status');
  549.         $criteria->addAssociation('history');
  550.         $criteria->addAssociation('salutation');
  551.         $criteria->addFilter(new EqualsFilter('customerId'$salesChannelContext->getCustomer()->getId()));
  552.         $criteria->getAssociation('history')->addSorting(new FieldSorting('createdAt'FieldSorting::ASCENDING));
  553.         $criteria->getAssociation('history')->addAssociation('preStatus');
  554.         $criteria->getAssociation('history')->addAssociation('postStatus');
  555.         /** @var TicketEntity[] $tickets */
  556.         $tickets $this->ticketRepository->search(
  557.             $criteria,
  558.             $salesChannelContext->getContext()
  559.         )->getElements();
  560.         // return it
  561.         return $tickets;
  562.     }
  563. }