vendor/uvdesk/core-framework/Controller/Ticket.php line 55

Open in your IDE?
  1. <?php
  2. namespace Webkul\UVDesk\CoreFrameworkBundle\Controller;
  3. use Symfony\Component\HttpFoundation\Request;
  4. use Symfony\Component\HttpFoundation\Response;
  5. use Symfony\Component\EventDispatcher\GenericEvent;
  6. use Webkul\UVDesk\CoreFrameworkBundle\Form as CoreFrameworkBundleForms;
  7. use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
  8. use Webkul\UVDesk\CoreFrameworkBundle\Entity as CoreFrameworkBundleEntities;
  9. use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
  10. use Webkul\UVDesk\CoreFrameworkBundle\DataProxies as CoreFrameworkBundleDataProxies;
  11. use Webkul\UVDesk\CoreFrameworkBundle\Workflow\Events as CoreWorkflowEvents;
  12. use Webkul\UVDesk\CoreFrameworkBundle\Tickets\QuickActionButtonCollection;
  13. use Webkul\UVDesk\CoreFrameworkBundle\Services\CustomFieldsService;
  14. use Webkul\UVDesk\CoreFrameworkBundle\Repository\TicketRepository;
  15. use Webkul\UVDesk\CoreFrameworkBundle\Services\UserService;
  16. use Symfony\Contracts\Translation\TranslatorInterface;
  17. use Webkul\UVDesk\CoreFrameworkBundle\Services\UVDeskService;
  18. use Webkul\UVDesk\CoreFrameworkBundle\Services\TicketService;
  19. use Webkul\UVDesk\CoreFrameworkBundle\Services\EmailService;
  20. use Symfony\Component\EventDispatcher\EventDispatcherInterface;
  21. use Symfony\Component\HttpKernel\KernelInterface;
  22. use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
  23. use Symfony\Component\DependencyInjection\ContainerInterface;
  24. class Ticket extends AbstractController
  25. {
  26.     private $userService;
  27.     private $translator;
  28.     private $eventDispatcher;
  29.     private $ticketService;
  30.     private $emailService;
  31.     private $kernel;
  32.     private $customFieldsService;
  33.     public function __construct(UserService $userServiceTranslatorInterface $translatorTicketService $ticketServiceEmailService $emailServiceEventDispatcherInterface $eventDispatcherKernelInterface $kernelCustomFieldsService $customFieldsService)
  34.     {
  35.         $this->userService $userService;
  36.         $this->emailService $emailService;
  37.         $this->translator $translator;
  38.         $this->ticketService $ticketService;
  39.         $this->eventDispatcher $eventDispatcher;
  40.         $this->kernel $kernel;
  41.         $this->customFieldsService $customFieldsService;
  42.     }
  43.     public function listTicketCollection(Request $request)
  44.     {
  45.         $entityManager $this->getDoctrine()->getManager();
  46.         return $this->render('@UVDeskCoreFramework//ticketList.html.twig', [
  47.             'ticketStatusCollection' => $entityManager->getRepository('UVDeskCoreFrameworkBundle:TicketStatus')->findAll(),
  48.             'ticketTypeCollection' => $entityManager->getRepository('UVDeskCoreFrameworkBundle:TicketType')->findByIsActive(true),
  49.             'ticketPriorityCollection' => $entityManager->getRepository('UVDeskCoreFrameworkBundle:TicketPriority')->findAll(),
  50.         ]);
  51.     }
  52.     public function loadTicket($ticketIdQuickActionButtonCollection $quickActionButtonCollectionContainerInterface $container)
  53.     {
  54.         $entityManager $this->getDoctrine()->getManager();
  55.         $userRepository $entityManager->getRepository('UVDeskCoreFrameworkBundle:User');
  56.         $ticketRepository $entityManager->getRepository('UVDeskCoreFrameworkBundle:Ticket');
  57.         $ticket $ticketRepository->findOneById($ticketId);
  58.         
  59.         if (empty($ticket)) {
  60.             throw new NotFoundHttpException('Page not found!');
  61.         }
  62.         
  63.         $user $this->userService->getSessionUser();
  64.         
  65.         // Proceed only if user has access to the resource
  66.         if (false == $this->ticketService->isTicketAccessGranted($ticket$user)) {
  67.             throw new \Exception('Access Denied'403);
  68.         }
  69.         $agent $ticket->getAgent();
  70.         $customer $ticket->getCustomer();
  71.      
  72.     if($agent != null && !empty($agent)){    
  73.         $ticketAssignAgent $agent->getId();
  74.         $currentUser $user->getId();
  75.     }
  76.         
  77.         // Mark as viewed by agents
  78.         if (false == $ticket->getIsAgentViewed()) {
  79.             $ticket->setIsAgentViewed(true);
  80.             $entityManager->persist($ticket);
  81.             $entityManager->flush();
  82.         }
  83.     
  84.         // Ticket Authorization
  85.         $supportRole $user->getCurrentInstance()->getSupportRole()->getCode(); 
  86.         switch($supportRole) {
  87.             case 'ROLE_ADMIN':
  88.             case 'ROLE_SUPER_ADMIN':
  89.                 break;
  90.             case 'ROLE_AGENT':
  91.                 $accessLevel = (int) $user->getCurrentInstance()->getTicketAccessLevel();
  92.                 switch($accessLevel) {
  93.                     case TicketRepository::TICKET_GLOBAL_ACCESS:
  94.                         break;
  95.                     case TicketRepository::TICKET_GROUP_ACCESS:
  96.                         $supportGroups array_map(function($supportGroup) { return $supportGroup->getId(); }, $user->getCurrentInstance()->getSupportGroups()->getValues());                       
  97.                         $ticketAccessableGroups $ticket->getSupportGroup() ? [$ticket->getSupportGroup()->getId()] : [];
  98.  
  99.                         if ($ticket->getSupportTeam()) {
  100.                             $ticketSupportTeamGroups array_map(function($supportGroup) { return $supportGroup->getId(); }, $ticket->getSupportTeam()->getSupportGroups()->getValues());
  101.                             $ticketAccessableGroups array_merge($ticketAccessableGroups$ticketSupportTeamGroups);
  102.                         }
  103.                         $isAccessableGroupFound false;
  104.                         foreach($ticketAccessableGroups as $groupId) {
  105.                             if (in_array($groupId$supportGroups)) {
  106.                                 $isAccessableGroupFound true;
  107.                                 break;
  108.                             }
  109.                         }
  110.                         if (!$isAccessableGroupFound && !($ticketAssignAgent == $currentUser)) {
  111.                             throw new NotFoundHttpException('Page not found!');
  112.                         }
  113.                         break;
  114.                     case TicketRepository::TICKET_TEAM_ACCESS:
  115.                         $supportTeams array_map(function($supportTeam) { return $supportTeam->getId(); }, $user->getCurrentInstance()->getSupportTeams()->getValues());                         
  116.                         $supportTeam $ticket->getSupportTeam();
  117.                         if (!($supportTeam && in_array($supportTeam->getId(), $supportTeams)) && !($ticketAssignAgent == $currentUser)) {
  118.                             throw new NotFoundHttpException('Page not found!');
  119.                         }
  120.                         break;
  121.                     default:
  122.                         $collaborators array_map( function ($collaborator) { return $collaborator->getId(); }, $ticket->getCollaborators()->getValues());
  123.                         $accessableAgents array_merge($collaborators$ticket->getAgent() ? [$ticket->getAgent()->getId()] : []);
  124.                         if (!in_array($user->getId(), $accessableAgents)) {
  125.                             throw new NotFoundHttpException('Page not found!');
  126.                         }
  127.                         break;
  128.                 }
  129.                 break;
  130.             default:
  131.                 throw new NotFoundHttpException('Page not found!');
  132.         }
  133.         $quickActionButtonCollection->prepareAssets();
  134.         return $this->render('@UVDeskCoreFramework//ticket.html.twig', [
  135.             'ticket' => $ticket,
  136.             'totalReplies' => $ticketRepository->countTicketTotalThreads($ticket->getId()),
  137.             'totalCustomerTickets' => ($ticketRepository->countCustomerTotalTickets($customer$container) - 1),
  138.             'initialThread' => $this->ticketService->getTicketInitialThreadDetails($ticket),
  139.             'ticketAgent' => !empty($agent) ? $agent->getAgentInstance()->getPartialDetails() : null,
  140.             'customer' => $customer->getCustomerInstance()->getPartialDetails(),
  141.             'currentUserDetails' => $user->getAgentInstance()->getPartialDetails(),
  142.             'supportGroupCollection' => $userRepository->getSupportGroups(),
  143.             'supportTeamCollection' => $userRepository->getSupportTeams(),
  144.             'ticketStatusCollection' => $entityManager->getRepository('UVDeskCoreFrameworkBundle:TicketStatus')->findAll(),
  145.             'ticketTypeCollection' => $entityManager->getRepository('UVDeskCoreFrameworkBundle:TicketType')->findByIsActive(true),
  146.             'ticketPriorityCollection' => $entityManager->getRepository('UVDeskCoreFrameworkBundle:TicketPriority')->findAll(),
  147.             'ticketNavigationIteration' => $ticketRepository->getTicketNavigationIteration($ticket$container),
  148.             'ticketLabelCollection' => $ticketRepository->getTicketLabelCollection($ticket$user),
  149.         ]);
  150.     }
  151.     public function saveTicket(Request $request)
  152.     {
  153.         $requestParams $request->request->all();
  154.         $entityManager $this->getDoctrine()->getManager();
  155.         $response $this->redirect($this->generateUrl('helpdesk_member_ticket_collection'));
  156.         if ($request->getMethod() != 'POST' || false == $this->userService->isAccessAuthorized('ROLE_AGENT_CREATE_TICKET')) {
  157.             return $response;
  158.         }
  159.         // Get referral ticket if any
  160.         $ticketValidationGroup 'CreateTicket';
  161.         $referralURL $request->headers->get('referer');
  162.         if (!empty($referralURL)) {
  163.             $iterations explode('/'$referralURL);
  164.             $referralId array_pop($iterations);
  165.             $expectedReferralURL $this->generateUrl('helpdesk_member_ticket', ['ticketId' => $referralId], UrlGeneratorInterface::ABSOLUTE_URL);
  166.             if ($referralURL === $expectedReferralURL) {
  167.                 $referralTicket $entityManager->getRepository('UVDeskCoreFrameworkBundle:Ticket')->findOneById($referralId);
  168.                 if (!empty($referralTicket)) {
  169.                     $ticketValidationGroup 'CustomerCreateTicket';
  170.                 }
  171.             }
  172.         }
  173.         $ticketType $entityManager->getRepository('UVDeskCoreFrameworkBundle:TicketType')->findOneById($requestParams['type']);
  174.         extract($this->customFieldsService->customFieldsValidation($request'user'));
  175.         if(!empty($errorFlashMessage)) {
  176.             $this->addFlash('warning'$errorFlashMessage);
  177.         }
  178.         $ticketProxy = new CoreFrameworkBundleDataProxies\CreateTicketDataClass();
  179.         $form $this->createForm(CoreFrameworkBundleForms\CreateTicket::class, $ticketProxy);
  180.         // Validate Ticket Details
  181.         $form->submit($requestParams);
  182.         if (false == $form->isSubmitted() || false == $form->isValid()) {
  183.             if (false === $form->isValid()) {
  184.                 // @TODO: We need to handle form errors gracefully.
  185.                 // We should also look into switching to an xhr request instead.
  186.                 // $form->getErrors(true);
  187.             }
  188.             return $this->redirect(!empty($referralURL) ? $referralURL $this->generateUrl('helpdesk_member_ticket_collection'));
  189.         }
  190.         if ('CustomerCreateTicket' === $ticketValidationGroup && !empty($referralTicket)) {
  191.             // Retrieve customer details from referral ticket
  192.             $customer $referralTicket->getCustomer();
  193.             $customerPartialDetails $customer->getCustomerInstance()->getPartialDetails();
  194.         } else if (null != $ticketProxy->getFrom() && null != $ticketProxy->getName()) {
  195.             // Create customer if account does not exists
  196.             $customer $entityManager->getRepository('UVDeskCoreFrameworkBundle:User')->findOneByEmail($ticketProxy->getFrom());
  197.             if (empty($customer) || null == $customer->getCustomerInstance()) {
  198.                 $role $entityManager->getRepository('UVDeskCoreFrameworkBundle:SupportRole')->findOneByCode('ROLE_CUSTOMER');
  199.                 // Create User Instance
  200.                 $customer $this->userService->createUserInstance($ticketProxy->getFrom(), $ticketProxy->getName(), $role, [
  201.                     'source' => 'website',
  202.                     'active' => true
  203.                 ]);
  204.             }
  205.         }
  206.         $ticketData = [
  207.             'from' => $customer->getEmail(),
  208.             'name' => $customer->getFirstName() . ' ' $customer->getLastName(),
  209.             'type' => $ticketProxy->getType(),
  210.             'subject' => $ticketProxy->getSubject(),
  211.             // @TODO: We need to enable support for html messages. 
  212.             // Our focus here instead should be to prevent XSS (filter js)
  213.             'message' => str_replace(['&lt;script&gt;''&lt;/script&gt;'], ''htmlspecialchars($ticketProxy->getReply())),
  214.             'firstName' => $customer->getFirstName(),
  215.             'lastName' => $customer->getLastName(),
  216.             'type' => $ticketProxy->getType(),
  217.             'role' => 4,
  218.             'source' => 'website',
  219.             'threadType' => 'create',
  220.             'createdBy' => 'agent',
  221.             'customer' => $customer,
  222.             'user' => $this->getUser(),
  223.             'attachments' => $request->files->get('attachments'),
  224.         ];
  225.         $thread $this->ticketService->createTicketBase($ticketData);
  226.         // Trigger ticket created event
  227.         try {
  228.             $event = new GenericEvent(CoreWorkflowEvents\Ticket\Create::getId(), [
  229.                 'entity' =>  $thread->getTicket(),
  230.             ]);
  231.             $this->eventDispatcher->dispatch($event'uvdesk.automation.workflow.execute', );
  232.         } catch (\Exception $e) {
  233.             // Skip Automation
  234.         }
  235.         if (!empty($thread)) {
  236.             $ticket $thread->getTicket();
  237.             if($request->request->get('customFields') || $request->files->get('customFields')) {
  238.                 $this->ticketService->addTicketCustomFields($thread$request->request->get('customFields'), $request->files->get('customFields'));                        
  239.             }
  240.             $this->addFlash('success'$this->translator->trans('Success ! Ticket has been created successfully.'));
  241.             if ($this->userService->isAccessAuthorized('ROLE_ADMIN')) {
  242.                 return $this->redirect($this->generateUrl('helpdesk_member_ticket', ['ticketId' => $ticket->getId()]));
  243.             }
  244.         } else {
  245.             $this->addFlash('warning'$this->translator->trans('Could not create ticket, invalid details.'));
  246.         }
  247.         return $this->redirect(!empty($referralURL) ? $referralURL $this->generateUrl('helpdesk_member_ticket_collection'));
  248.     }
  249.     public function listTicketTypeCollection(Request $request)
  250.     {
  251.         if (!$this->userService->isAccessAuthorized('ROLE_AGENT_MANAGE_TICKET_TYPE')) {
  252.             return $this->redirect($this->generateUrl('helpdesk_member_dashboard'));
  253.         }
  254.         return $this->render('@UVDeskCoreFramework/ticketTypeList.html.twig');
  255.     }
  256.     public function ticketType(Request $request)
  257.     {
  258.         if (!$this->userService->isAccessAuthorized('ROLE_AGENT_MANAGE_TICKET_TYPE')) {
  259.             return $this->redirect($this->generateUrl('helpdesk_member_dashboard'));
  260.         }
  261.         $errorContext = [];
  262.         $em $this->getDoctrine()->getManager();
  263.         if($id $request->attributes->get('ticketTypeId')) {
  264.             $type $em->getRepository('UVDeskCoreFrameworkBundle:TicketType')->find($id);
  265.             if (!$type) {
  266.                 $this->noResultFound();
  267.             }
  268.         } else {
  269.             $type = new CoreFrameworkBundleEntities\TicketType();
  270.         }
  271.         if ($request->getMethod() == "POST") {
  272.             $data $request->request->all();
  273.             $ticketType $em->getRepository('UVDeskCoreFrameworkBundle:TicketType')->findOneByCode($data['code']);
  274.             if (!empty($ticketType) && $id != $ticketType->getId()) {
  275.                 $this->addFlash('warning'sprintf('Error! Ticket type with same name already exist'));
  276.             } else {
  277.                 $type->setCode($data['code']);
  278.                 $type->setDescription($data['description']);
  279.                 $type->setIsActive(isset($data['isActive']) ? 0);
  280.                 $em->persist($type);
  281.                 $em->flush();
  282.                 if (!$request->attributes->get('ticketTypeId')) {
  283.                     $this->addFlash('success'$this->translator->trans('Success! Ticket type saved successfully.'));
  284.                 } else {
  285.                     $this->addFlash('success'$this->translator->trans('Success! Ticket type updated successfully.'));
  286.                 }
  287.                 return $this->redirect($this->generateUrl('helpdesk_member_ticket_type_collection'));
  288.             }
  289.         }
  290.         return $this->render('@UVDeskCoreFramework/ticketTypeAdd.html.twig', array(
  291.             'type' => $type,
  292.             'errors' => json_encode($errorContext)
  293.         ));
  294.     }
  295.     public function listTagCollection(Request $request)
  296.     {
  297.         if (!$this->userService->isAccessAuthorized('ROLE_AGENT_MANAGE_TAG')) {
  298.             return $this->redirect($this->generateUrl('helpdesk_member_dashboard'));
  299.         }
  300.         $enabled_bundles $this->getParameter('kernel.bundles');
  301.         return $this->render('@UVDeskCoreFramework/supportTagList.html.twig', [
  302.             'articlesEnabled' => in_array('UVDeskSupportCenterBundle'array_keys($enabled_bundles)),
  303.         ]);
  304.     }
  305.     public function removeTicketTagXHR($tagIdRequest $request)
  306.     {
  307.         if (!$this->userService->isAccessAuthorized('ROLE_AGENT_MANAGE_TAG')) {
  308.             return $this->redirect($this->generateUrl('helpdesk_member_dashboard'));
  309.         }
  310.         $json = [];
  311.         if($request->getMethod() == "DELETE") {
  312.             $em $this->getDoctrine()->getManager();
  313.             $tag $em->getRepository('UVDeskCoreFrameworkBundle:Tag')->find($tagId);
  314.             if($tag) {
  315.                 $em->remove($tag);
  316.                 $em->flush();
  317.                 $json['alertClass'] = 'success';
  318.                 $json['alertMessage'] = $this->translator->trans('Success ! Tag removed successfully.');
  319.             }
  320.         }
  321.         $response = new Response(json_encode($json));
  322.         $response->headers->set('Content-Type''application/json');
  323.         return $response;
  324.     }
  325.     public function trashTicket(Request $request)
  326.     {
  327.         $ticketId $request->attributes->get('ticketId');
  328.         $entityManager $this->getDoctrine()->getManager();
  329.         $ticket $entityManager->getRepository('UVDeskCoreFrameworkBundle:Ticket')->find($ticketId);
  330.         if (!$ticket) {
  331.             $this->noResultFound();
  332.         }
  333.         $user $this->userService->getSessionUser();
  334.         // Proceed only if user has access to the resource
  335.         if (false == $this->ticketService->isTicketAccessGranted($ticket$user)) {
  336.             throw new \Exception('Access Denied'403);
  337.         }
  338.         if (!$ticket->getIsTrashed()) {
  339.             $ticket->setIsTrashed(1);
  340.             $entityManager->persist($ticket);
  341.             $entityManager->flush();
  342.         }
  343.         // Trigger ticket delete event
  344.         $event = new GenericEvent(CoreWorkflowEvents\Ticket\Delete::getId(), [
  345.             'entity' => $ticket,
  346.         ]);
  347.         $this->eventDispatcher->dispatch($event'uvdesk.automation.workflow.execute');
  348.         $this->addFlash('success'$this->translator->trans('Success ! Ticket moved to trash successfully.'));
  349.         return $this->redirectToRoute('helpdesk_member_ticket_collection');
  350.     }
  351.     // Delete a ticket ticket permanently
  352.     public function deleteTicket(Request $request)
  353.     {
  354.         $ticketId $request->attributes->get('ticketId');
  355.         $entityManager $this->getDoctrine()->getManager();
  356.         $ticket $entityManager->getRepository('UVDeskCoreFrameworkBundle:Ticket')->find($ticketId);
  357.         if (!$ticket) {
  358.             $this->noResultFound();
  359.         }
  360.         $user $this->userService->getSessionUser();
  361.         // Proceed only if user has access to the resource
  362.         if (false == $this->ticketService->isTicketAccessGranted($ticket$user)) {
  363.             throw new \Exception('Access Denied'403);
  364.         }
  365.         $entityManager->remove($ticket);
  366.         $entityManager->flush();
  367.         $this->addFlash('success'$this->translator->trans('Success ! Success ! Ticket Id #'$ticketId .' has been deleted successfully.'));
  368.         return $this->redirectToRoute('helpdesk_member_ticket_collection');
  369.     }
  370.     public function downloadZipAttachment(Request $request)
  371.     {
  372.         $threadId $request->attributes->get('threadId');
  373.         $attachmentRepository $this->getDoctrine()->getManager()->getRepository('UVDeskCoreFrameworkBundle:Attachment');
  374.         $threadRepository $this->getDoctrine()->getManager()->getRepository('UVDeskCoreFrameworkBundle:Thread');
  375.         $thread $threadRepository->findOneById($threadId);
  376.         $attachment $attachmentRepository->findByThread($threadId);
  377.         if (!$attachment) {
  378.             $this->noResultFound();
  379.         }
  380.         $ticket $thread->getTicket();
  381.         $user $this->userService->getSessionUser();
  382.         
  383.         // Proceed only if user has access to the resource
  384.         if (false == $this->ticketService->isTicketAccessGranted($ticket$user)) {
  385.             throw new \Exception('Access Denied'403);
  386.         }
  387.         $zipname 'attachments/' .$threadId.'.zip';
  388.         $zip = new \ZipArchive;
  389.         $zip->open($zipname, \ZipArchive::CREATE);
  390.         if (count($attachment)) {
  391.             foreach ($attachment as $attach) {
  392.                 $zip->addFile(substr($attach->getPath(), 1));
  393.             }
  394.         }
  395.         $zip->close();
  396.         $response = new Response();
  397.         $response->setStatusCode(200);
  398.         $response->headers->set('Content-type''application/zip');
  399.         $response->headers->set('Content-Disposition''attachment; filename=' $threadId '.zip');
  400.         $response->sendHeaders();
  401.         $response->setContent(readfile($zipname));
  402.         return $response;
  403.     }
  404.     public function downloadAttachment(Request $request)
  405.     {   
  406.         $attachmentId $request->attributes->get('attachmendId');
  407.         $attachmentRepository $this->getDoctrine()->getManager()->getRepository('UVDeskCoreFrameworkBundle:Attachment');
  408.         $attachment $attachmentRepository->findOneById($attachmentId);
  409.         $baseurl $request->getScheme() . '://' $request->getHttpHost() . $request->getBasePath();
  410.         if (!$attachment) {
  411.             $this->noResultFound();
  412.         }
  413.         $ticket $attachment->getThread()->getTicket();
  414.         $user $this->userService->getSessionUser();
  415.         
  416.         // Proceed only if user has access to the resource
  417.         if (false == $this->ticketService->isTicketAccessGranted($ticket$user)) {
  418.             throw new \Exception('Access Denied'403);
  419.         }
  420.         $path $this->kernel->getProjectDir() . "/public/"$attachment->getPath();
  421.         $response = new Response();
  422.         $response->setStatusCode(200);
  423.         $response->headers->set('Content-type'$attachment->getContentType());
  424.         $response->headers->set('Content-Disposition''attachment; filename='$attachment->getName());
  425.         $response->headers->set('Content-Length'$attachment->getSize());
  426.         $response->sendHeaders();
  427.         $response->setContent(readfile($path));
  428.         return $response;
  429.     }
  430.     /**
  431.      * If customer is playing with url and no result is found then what will happen
  432.      * @return 
  433.      */
  434.     protected function noResultFound()
  435.     {
  436.         throw new NotFoundHttpException('Not Found!');
  437.     }
  438. }