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

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