vendor/uvdesk/core-framework/Controller/Thread.php line 44

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\Entity\Ticket;
  7. use Symfony\Component\EventDispatcher\EventDispatcherInterface;
  8. use Webkul\UVDesk\CoreFrameworkBundle\Entity\Attachment;
  9. use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
  10. use Webkul\UVDesk\CoreFrameworkBundle\Entity\TicketStatus;
  11. use Webkul\UVDesk\CoreFrameworkBundle\Entity\Thread as TicketThread;
  12. use Webkul\UVDesk\CoreFrameworkBundle\Workflow\Events as CoreWorkflowEvents;
  13. use Webkul\UVDesk\CoreFrameworkBundle\Services\UserService;
  14. use Symfony\Contracts\Translation\TranslatorInterface;
  15. use Webkul\UVDesk\CoreFrameworkBundle\Services\UVDeskService;
  16. use Webkul\UVDesk\CoreFrameworkBundle\Services\TicketService;
  17. use Webkul\UVDesk\CoreFrameworkBundle\Services\EmailService;
  18. use Symfony\Component\HttpKernel\KernelInterface;
  19. use Webkul\UVDesk\CoreFrameworkBundle\Services\FileUploadService;
  20. class Thread extends AbstractController
  21. {
  22.     private $userService;
  23.     private $translator;
  24.     private $eventDispatcher;
  25.     private $ticketService;
  26.     private $emailService;
  27.     private $kernel;
  28.     private $fileUploadService;
  29.     public function __construct(UserService $userServiceTranslatorInterface $translatorTicketService $ticketServiceEmailService $emailServiceEventDispatcherInterface $eventDispatcherKernelInterface $kernelFileUploadService $fileUploadService)
  30.     {
  31.         $this->kernel $kernel;
  32.         $this->userService $userService;
  33.         $this->emailService $emailService;
  34.         $this->translator $translator;
  35.         $this->ticketService $ticketService;
  36.         $this->eventDispatcher $eventDispatcher;
  37.         $this->fileUploadService $fileUploadService;
  38.     }
  39.     public function saveThread($ticketIdRequest $request)
  40.     {
  41.         $params $request->request->all();
  42.         $entityManager $this->getDoctrine()->getManager();
  43.         $ticket $entityManager->getRepository(Ticket::class)->findOneById($ticketId);
  44.         // Proceed only if user has access to the resource
  45.         if (false == $this->ticketService->isTicketAccessGranted($ticket)) {
  46.             throw new \Exception('Access Denied'403);
  47.         }
  48.         if (empty($ticket)) {
  49.             throw new \Exception('Ticket not found'404);
  50.         } else if ('POST' !== $request->getMethod()) {
  51.             throw new \Exception('Invalid Request'403);
  52.         }
  53.         if (empty($params)) {
  54.             return $this->redirect($request->headers->get('referer') ?: $this->generateUrl('helpdesk_member_ticket_collection'));
  55.         } else if ('note' == $params['threadType'] && false == $this->userService->isAccessAuthorized('ROLE_AGENT_ADD_NOTE')) {
  56.             // Insufficient user privilege to create a note
  57.             throw new \Exception('Insufficient Permisions'400);
  58.         }
  59.         // // Deny access unles granted ticket view permission
  60.         // $this->denyAccessUnlessGranted('AGENT_VIEW', $ticket);
  61.         // Check if reply content is empty
  62.         $parsedMessage trim(strip_tags($params['reply'], '<img>'));
  63.         $parsedMessage str_replace('&nbsp;'''$parsedMessage);
  64.         $parsedMessage str_replace(' '''$parsedMessage);
  65.         if (null == $parsedMessage) {
  66.             $this->addFlash('warning'$this->translator->trans('Reply content cannot be left blank.'));
  67.         }
  68.         // @TODO: Validate file attachments
  69.         // if (true !== $this->get('file.service')->validateAttachments($request->files->get('attachments'))) {
  70.         //     $this->addFlash('warning', "Invalid attachments.");
  71.         // }
  72.         
  73.         // $adminReply =  str_replace(['<p>','</p>'],"",$params['reply']);
  74.         $threadDetails = [
  75.             'user' => $this->getUser(),
  76.             'createdBy' => 'agent',
  77.             'source' => 'website',
  78.             'threadType' => strtolower($params['threadType']),
  79.             'message' => str_replace(['&lt;script&gt;''&lt;/script&gt;'], ''htmlspecialchars($params['reply'])),
  80.             'attachments' => $request->files->get('attachments')
  81.         ];
  82.         if(!empty($params['status'])){
  83.             $ticketStatus $entityManager->getRepository(TicketStatus::class)->findOneByCode($params['status']);
  84.             $ticket->setStatus($ticketStatus);
  85.         }
  86.         if (isset($params['to'])) {
  87.             $threadDetails['to'] = $params['to'];
  88.         }
  89.         if (isset($params['cc'])) {
  90.             $threadDetails['cc'] = $params['cc'];
  91.         }
  92.         if (isset($params['cccol'])) {
  93.             $threadDetails['cccol'] = $params['cccol'];
  94.         }
  95.         if (isset($params['bcc'])) {
  96.             $threadDetails['bcc'] = $params['bcc'];
  97.         }
  98.         // Create Thread
  99.         $thread $this->ticketService->createThread($ticket$threadDetails);
  100.         // $this->addFlash('success', ucwords($params['threadType']) . " added successfully.");
  101.         // @TODO: Remove Agent Draft Thread
  102.         // @TODO: Trigger Thread Created Event
  103.         // @TODO: Cross Review
  104.         // check for thread types
  105.         switch ($thread->getThreadType()) {
  106.             case 'note':
  107.                 $event = new GenericEvent(CoreWorkflowEvents\Ticket\Note::getId(), [
  108.                     'entity' =>  $ticket,
  109.                     'thread' =>  $thread
  110.                 ]);
  111.                 $this->eventDispatcher->dispatch($event'uvdesk.automation.workflow.execute');
  112.                 // @TODO: Render response on the basis of event response (if propogation was stopped or not)
  113.                 $this->addFlash('success'$this->translator->trans('Note added to ticket successfully.'));
  114.                 break;
  115.             case 'reply':
  116.                 $event = new GenericEvent(CoreWorkflowEvents\Ticket\AgentReply::getId(), [
  117.                     'entity' =>  $ticket,
  118.                     'thread' =>  $thread
  119.                 ]);
  120.                 $this->eventDispatcher->dispatch($event'uvdesk.automation.workflow.execute');
  121.                 // @TODO: Render response on the basis of event response (if propogation was stopped or not)
  122.                 $this->addFlash('success'$this->translator->trans('Success ! Reply added successfully.'));
  123.                 break;
  124.             case 'forward':
  125.                 // Prepare headers
  126.                 $headers = ['References' => $ticket->getReferenceIds()];
  127.                 if (null != $ticket->currentThread->getMessageId()) {
  128.                     $headers['In-Reply-To'] = $ticket->currentThread->getMessageId();
  129.                 }
  130.                 // Prepare attachments
  131.                 $attachments $entityManager->getRepository(Attachment::class)->findByThread($thread);
  132.                 $projectDir $this->kernel->getProjectDir();
  133.                 $attachments array_map(function($attachment) use ($projectDir) {
  134.                 return str_replace('//''/'$projectDir "/public" $attachment->getPath());
  135.                 }, $attachments);
  136.                 $message '<html><body style="background-image: none"><p>'.html_entity_decode($thread->getMessage()).'</p></body></html>';
  137.                 // Forward thread to users
  138.                 try {
  139.                     $messageId $this->emailService->sendMail($params['subject'] ?? ("Forward: " $ticket->getSubject()), $message$thread->getReplyTo(), $headers$ticket->getMailboxEmail(), $attachments ?? [], $thread->getCc() ?: [], $thread->getBcc() ?: []);
  140.     
  141.                     if (!empty($messageId)) {
  142.                         $thread->setMessageId($messageId);
  143.     
  144.                         $entityManager->persist($createdThread);
  145.                         $entityManager->flush();
  146.                     }
  147.                 } catch (\Exception $e) {
  148.                     // Do nothing ...
  149.                     // @TODO: Log exception
  150.                 }
  151.                 // @TODO: Render response on the basis of event response (if propogation was stopped or not)
  152.                 $this->addFlash('success'$this->translator->trans('Reply added to the ticket and forwarded successfully.'));
  153.                 break;
  154.             default:
  155.                 break;
  156.         }
  157.         // Check if ticket status needs to be updated
  158.         $updateTicketToStatus = !empty($params['status']) ? (trim($params['status']) ?: null) : null;
  159.         if (!empty($updateTicketToStatus) && $this->userService->isAccessAuthorized('ROLE_AGENT_UPDATE_TICKET_STATUS')) {
  160.             $ticketStatus $entityManager->getRepository(TicketStatus::class)->findOneById($updateTicketToStatus);
  161.             if (!empty($ticketStatus) && $ticketStatus->getId() === $ticket->getStatus()->getId()) {
  162.                 $ticket->setStatus($ticketStatus);
  163.                 $entityManager->persist($ticket);
  164.                 $entityManager->flush();
  165.                 // @TODO: Trigger Ticket Status Updated Event
  166.             }
  167.         }
  168.         // Redirect to either Ticket View | Ticket Listings
  169.         if ('redirect' === $params['nextView']) {
  170.             return $this->redirect($this->generateUrl('helpdesk_member_ticket_collection'));
  171.         }
  172.         
  173.         return $this->redirect($this->generateUrl('helpdesk_member_ticket', ['ticketId' => $ticket->getId()]));
  174.     }
  175.     public function updateThreadXHR(Request $request)
  176.     {
  177.         $json = [];
  178.         $em $this->getDoctrine()->getManager();
  179.         $content json_decode($request->getContent(), true);
  180.         $thread $em->getRepository(TicketThread::class)->find($request->attributes->get('threadId'));
  181.         $ticket $thread->getTicket();
  182.         $user $this->userService->getSessionUser();
  183.         // Proceed only if user has access to the resource
  184.         if ( (!$this->userService->getSessionUser()) || (false == $this->ticketService->isTicketAccessGranted($ticket$user)) ) 
  185.         {
  186.             throw new \Exception('Access Denied'403);
  187.         }
  188.         if ($request->getMethod() == "PUT") {
  189.             // $this->isAuthorized('ROLE_AGENT_EDIT_THREAD_NOTE');
  190.             if (str_replace(' ','',str_replace('&nbsp;','',trim(strip_tags($content['reply'], '<img>')))) != "") {
  191.                 $thread->setMessage($content['reply']);
  192.                 $em->persist($thread);
  193.                 $em->flush();
  194.                 $ticket->currentThread $thread;
  195.                 // Trigger agent reply event
  196.                 $event = new GenericEvent(CoreWorkflowEvents\Ticket\ThreadUpdate::getId(), [
  197.                     'entity' =>  $ticket,
  198.                 ]);
  199.                 $this->eventDispatcher->dispatch($event'uvdesk.automation.workflow.execute');
  200.                 $json['alertMessage'] = $this->translator->trans('Success ! Thread updated successfully.');
  201.                 $json['alertClass'] = 'success';
  202.             } else {
  203.                 $json['alertMessage'] = $this->translator->trans('Error ! Reply field can not be blank.');
  204.                 $json['alertClass'] = 'error';
  205.             }
  206.         }
  207.         return new Response(json_encode($json), 200, ['Content-Type' => 'application/json']);
  208.     }
  209.     public function threadXHR(Request $request)
  210.     {
  211.         $json = array();
  212.         $content json_decode($request->getContent(), true);
  213.         $em $this->getDoctrine()->getManager();
  214.         $ticket $em->getRepository(Ticket::class)->findOneById($content['ticketId']); 
  215.         // Proceed only if user has access to the resource
  216.         if (false == $this->ticketService->isTicketAccessGranted($ticket)){
  217.             throw new \Exception('Access Denied'403);
  218.         }
  219.         
  220.         $threadId $request->attributes->get('threadId');
  221.         if ($request->getMethod() == "DELETE") {
  222.             $thread $em->getRepository(TicketThread::class)->findOneBy(array('id' => $threadId'ticket' => $content['ticketId']));
  223.             $projectDir $this->kernel->getProjectDir();
  224.             
  225.             if ($thread) {
  226.                 $this->fileUploadService->fileRemoveFromFolder($projectDir."/public/assets/threads/".$threadId);
  227.                 // Trigger thread deleted event
  228.                 //  $event = new GenericEvent(CoreWorkflowEvents\Ticket\ThreadUpdate::getId(), [
  229.                 //     'entity' =>  $ticket,
  230.                 // ]);
  231.                 // $this->eventDispatcher->dispatch('uvdesk.automation.workflow.execute', $event);
  232.                 $em->remove($thread);
  233.                 $em->flush();
  234.                 $json['alertClass'] = 'success';
  235.                 $json['alertMessage'] = $this->translator->trans('Success ! Thread removed successfully.');
  236.             } else {
  237.                 $json['alertClass'] = 'danger';
  238.                 $json['alertMessage'] = $this->translator->trans('Error ! Invalid thread.');
  239.             }
  240.         } elseif ($request->getMethod() == "PATCH") {
  241.             $thread $em->getRepository(TicketThread::class)->findOneBy(array('id' => $request->attributes->get('threadId'), 'ticket' => $content['ticketId']));
  242.             if ($thread) {
  243.                 if ($content['updateType'] == 'lock') {
  244.                     $thread->setIsLocked($content['isLocked']);
  245.                     $em->persist($thread);
  246.                     $em->flush();
  247.                     $json['alertMessage'] = $this->translator->trans($content['isLocked'] ? 'Success ! Thread locked successfully.' 'Success ! Thread unlocked successfully.');
  248.                     $json['alertClass'] = 'success';
  249.                 } elseif ($content['updateType'] == 'bookmark') {
  250.                     $thread->setIsBookmarked($content['bookmark']);
  251.                     $em->persist($thread);
  252.                     $em->flush();
  253.                     $json['alertMessage'] = $this->translator->trans($content['bookmark'] ? 'Success ! Thread pinned successfully.' 'Success ! unpinned removed successfully.');
  254.                     $json['alertClass'] = 'success';
  255.                 }
  256.             } else {
  257.                 $json['alertClass'] = 'danger';
  258.                 $json['alertMessage'] = $this->translator->trans('Error ! Invalid thread.');
  259.             }
  260.         }
  261.         return new Response(json_encode($json), 200, ['Content-Type' => 'application/json']);
  262.     }
  263. }