vendor/uvdesk/core-framework/Controller/TicketXHR.php line 939

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\Entity as CoreFrameworkBundleEntities;
  6. use Webkul\UVDesk\CoreFrameworkBundle\Entity\SupportLabel;
  7. use Webkul\UVDesk\CoreFrameworkBundle\Entity\Thread;
  8. use Webkul\UVDesk\CoreFrameworkBundle\Entity\Ticket;
  9. use Webkul\UVDesk\CoreFrameworkBundle\Entity\Tag;
  10. use Webkul\UVDesk\CoreFrameworkBundle\Entity\TicketType;
  11. use Webkul\UVDesk\CoreFrameworkBundle\Entity\SupportRole;
  12. use Webkul\UVDesk\CoreFrameworkBundle\Entity\User;
  13. use Webkul\UVDesk\CoreFrameworkBundle\Entity\TicketPriority;
  14. use Webkul\UVDesk\CoreFrameworkBundle\Entity\TicketStatus;
  15. use Webkul\UVDesk\CoreFrameworkBundle\Entity\SupportGroup;
  16. use Webkul\UVDesk\CoreFrameworkBundle\Entity\SupportTeam;
  17. use Webkul\UVDesk\CoreFrameworkBundle\Entity\TicketLabel;
  18. use Symfony\Component\EventDispatcher\GenericEvent;
  19. use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
  20. use Webkul\UVDesk\CoreFrameworkBundle\Workflow\Events as CoreWorkflowEvents;
  21. use Webkul\UVDesk\CoreFrameworkBundle\Form as CoreFrameworkBundleForms;
  22. use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
  23. use Webkul\UVDesk\CoreFrameworkBundle\DataProxies as CoreFrameworkBundleDataProxies;
  24. use Webkul\UVDesk\CoreFrameworkBundle\Services\UserService;
  25. use Symfony\Contracts\Translation\TranslatorInterface;
  26. use Webkul\UVDesk\CoreFrameworkBundle\Services\UVDeskService;
  27. use Webkul\UVDesk\CoreFrameworkBundle\Services\TicketService;
  28. use Webkul\UVDesk\CoreFrameworkBundle\Services\EmailService;
  29. use Symfony\Component\EventDispatcher\EventDispatcherInterface;
  30. use Symfony\Component\DependencyInjection\ContainerInterface;
  31. use Webkul\UVDesk\SupportCenterBundle\Entity\ArticleTags;
  32. use PhpOffice\PhpSpreadsheet\Spreadsheet;
  33. use PhpOffice\PhpSpreadsheet\Writer\Xlsx;
  34. class TicketXHR extends AbstractController
  35. {
  36.     private $userService;
  37.     private $translator;
  38.     private $eventDispatcher;
  39.     private $ticketService;
  40.     private $emailService;
  41.     public function __construct(UserService $userServiceTranslatorInterface $translatorTicketService $ticketServiceEmailService $emailServiceEventDispatcherInterface $eventDispatcher)
  42.     {
  43.         $this->userService $userService;
  44.         $this->emailService $emailService;
  45.         $this->translator $translator;
  46.         $this->ticketService $ticketService;
  47.         $this->eventDispatcher $eventDispatcher;
  48.     }
  49.     public function loadTicketXHR($ticketId)
  50.     {
  51.         $entityManager $this->getDoctrine()->getManager();
  52.         $request $this->container->get('request_stack')->getCurrentRequest();
  53.     }
  54.     public function bookmarkTicketXHR()
  55.     {
  56.         $entityManager $this->getDoctrine()->getManager();
  57.         $request $this->container->get('request_stack')->getCurrentRequest();
  58.         $requestContent json_decode($request->getContent(), true);
  59.         $ticket $entityManager->getRepository(Ticket::class)->findOneById($requestContent['id']);
  60.         // Process only if user have ticket access
  61.         if (false == $this->ticketService->isTicketAccessGranted($ticket)) {
  62.             throw new \Exception('Access Denied'403);
  63.         }
  64.         if (!empty($ticket)) {
  65.             $ticket->setIsStarred(!$ticket->getIsStarred());
  66.             $entityManager->persist($ticket);
  67.             $entityManager->flush();
  68.             return new Response(json_encode(['alertClass' => 'success']), 200, ['Content-Type' => 'application/json']);
  69.         }
  70.         return new Response(json_encode([]), 404, ['Content-Type' => 'application/json']);
  71.     }
  72.     public function ticketLabelXHR(Request $request)
  73.     {
  74.         $method $request->getMethod();
  75.         $content $request->getContent();
  76.         $em $this->getDoctrine()->getManager();
  77.         if($method == "POST") {
  78.             $data json_decode($contenttrue);
  79.             if($data['name'] != "") {
  80.                 $label = new SupportLabel();
  81.                 $label->setName($data['name']);
  82.                 if(isset($data['colorCode']))
  83.                     $label->setColorCode($data['colorCode']);
  84.                 $label->setUser($this->userService->getCurrentUser());
  85.                 $em->persist($label);
  86.                 $em->flush();
  87.                 $json['alertClass'] = 'success';
  88.                 $json['alertMessage'] = $this->translator->trans('Success ! Label created successfully.');
  89.                 $json['label'] = json_encode([
  90.                     'id' => $label->getId(),
  91.                     'name' => $label->getName(),
  92.                     'colorCode' => $label->getColorCode(),
  93.                     'labelUser' => $label->getUser()->getId(),
  94.                 ]);
  95.             } else {
  96.                 $json['alertClass'] = 'danger';
  97.                 $json['alertMessage'] = $this->translator->trans('Error ! Label name can not be blank.');
  98.             }
  99.         } elseif($method == "PUT") {
  100.             $data json_decode($contenttrue);
  101.             $label $em->getRepository(SupportLabel::class)->findOneBy(array('id' => $request->attributes->get('ticketLabelId')));
  102.             if($label) {
  103.                 $label->setName($data['name']);
  104.                 if(!empty($data['colorCode'])) {
  105.                     $label->setColorCode($data['colorCode']);
  106.                 }
  107.                 $em->persist($label);
  108.                 $em->flush();
  109.                 $json['label'] = json_encode([
  110.                     'id' => $label->getId(),
  111.                     'name' => $label->getName(),
  112.                     'colorCode' => $label->getColorCode(),
  113.                     'labelUser' => $label->getUser()->getId(),
  114.                 ]);
  115.                 $json['alertClass'] = 'success';
  116.                 $json['alertMessage'] = $this->translator->trans('Success ! Label updated successfully.');
  117.             } else {
  118.                 $json['alertClass'] = 'danger';
  119.                 $json['alertMessage'] = $this->translator->trans('Error ! Invalid label id.');
  120.             }
  121.         } elseif($method == "DELETE") {
  122.             $label $em->getRepository(SupportLabel::class)->findOneBy(array('id' => $request->attributes->get('ticketLabelId')));
  123.             if($label) {
  124.                 $em->remove($label);
  125.                 $em->flush();
  126.                 $json['alertClass'] = 'success';
  127.                 $json['alertMessage'] = $this->translator->trans('Success ! Label removed successfully.');
  128.             } else {
  129.                 $json['alertClass'] = 'danger';
  130.                 $json['alertMessage'] = $this->translator->trans('Error ! Invalid label id.');
  131.             }
  132.         }
  133.         return new Response(json_encode($json), 200, ['Content-Type' => 'application/json']);
  134.     }
  135.     public function updateTicketDetails(Request $request)
  136.     {
  137.         $ticketId $request->attributes->get('ticketId');
  138.         $entityManager $this->getDoctrine()->getManager();
  139.         $ticket $entityManager->getRepository(Ticket::class)->find($ticketId);
  140.         if (!$ticket)
  141.             $this->noResultFound();
  142.         // Proceed only if user has access to the resource
  143.         if (false == $this->ticketService->isTicketAccessGranted($ticket)) {
  144.             throw new \Exception('Access Denied'403);
  145.         }
  146.         $error false;
  147.         $message '';
  148.         if ($request->request->get('subject') == '') {
  149.             $error true;
  150.             $message $this->translator->trans('Error! Subject field is mandatory');
  151.         } elseif ($request->request->get('reply') == '') {
  152.             $error true;
  153.             $message $this->translator->trans('Error! Reply field is mandatory');
  154.         }
  155.         if (!$error) {
  156.             $ticket->setSubject($request->request->get('subject'));
  157.             $createThread $this->ticketService->getCreateReply($ticket->getId(), false);
  158.             $createThread $entityManager->getRepository(Thread::class)->find($createThread['id']);
  159.             $createThread->setMessage($request->request->get('reply'));
  160.             $entityManager->persist($createThread);
  161.             $entityManager->persist($ticket);
  162.             $entityManager->flush();
  163.             $this->addFlash('success'$this->translator->trans('Success ! Ticket has been updated successfully.'));
  164.         } else {
  165.             $this->addFlash('warning'$message);
  166.         }
  167.         return $this->redirect($this->generateUrl('helpdesk_member_ticket', ['ticketId'=> $ticketId] ));
  168.     }
  169.     public function updateTicketAttributes($ticketId)
  170.     {
  171.         // @TODO: Ticket Voter
  172.         // $this->denyAccessUnlessGranted('VIEW', $ticket);
  173.         $entityManager $this->getDoctrine()->getManager();
  174.         $request $this->container->get('request_stack')->getCurrentRequest();
  175.         $requestContent $request->request->all() ?: json_decode($request->getContent(), true);
  176.         $ticketId =  $ticketId != $ticketId $requestContent['ticketId'];
  177.         $ticket $entityManager->getRepository(Ticket::class)->findOneById($ticketId);
  178.         // Proceed only if user has access to the resource
  179.         if (false == $this->ticketService->isTicketAccessGranted($ticket)) {
  180.             throw new \Exception('Access Denied'403);
  181.         }
  182.         // Validate request integrity
  183.         if (empty($ticket)) {
  184.             $responseContent = [
  185.                 'alertClass' => 'danger',
  186.                 'alertMessage' => $this->translator->trans('Unable to retrieve details for ticket #%ticketId%.', [
  187.                     '%ticketId%' => $ticketId,
  188.                 ]),
  189.             ];
  190.             return new Response(json_encode($responseContent), 200, ['Content-Type' => 'application/json']);
  191.         } else if (!isset($requestContent['attribute'])) {
  192.             $responseContent = [
  193.                 'alertClass' => 'danger',
  194.                 'alertMessage' => $this->translator->trans('Insufficient details provided.'),
  195.             ];
  196.             return new Response(json_encode($responseContent), 400, ['Content-Type' => 'application/json']);
  197.         }
  198.         // Update attribute
  199.         switch ($requestContent['attribute']) {
  200.             case 'agent':
  201.                 $agent $entityManager->getRepository(User::class)->findOneById($requestContent['value']);
  202.                 if (empty($agent)) {
  203.                     // User does not exist
  204.                     return new Response(json_encode([
  205.                         'alertClass' => 'danger',
  206.                         'alertMessage' => $this->translator->trans('Unable to retrieve agent details'),
  207.                     ]), 404, ['Content-Type' => 'application/json']);
  208.                 } else {
  209.                     // Check if an agent instance exists for the user
  210.                     $agentInstance $agent->getAgentInstance();
  211.                     if (empty($agentInstance)) {
  212.                         // Agent does not exist
  213.                         return new Response(json_encode([
  214.                             'alertClass' => 'danger',
  215.                             'alertMessage' => $this->translator->trans('Unable to retrieve agent details'),
  216.                         ]), 404, ['Content-Type' => 'application/json']);
  217.                     }
  218.                 }
  219.                 $agentDetails $agentInstance->getPartialDetails();
  220.                 // Check if ticket is already assigned to the agent
  221.                 if ($ticket->getAgent() && $agent->getId() === $ticket->getAgent()->getId()) {
  222.                     return new Response(json_encode([
  223.                         'alertClass' => 'success',
  224.                         'alertMessage' => $this->translator->trans('Ticket already assigned to %agent%', [
  225.                             '%agent%' => $agentDetails['name'],
  226.                         ]),
  227.                     ]), 200, ['Content-Type' => 'application/json']);
  228.                 } else {
  229.                     $ticket->setAgent($agent);
  230.                     $entityManager->persist($ticket);
  231.                     $entityManager->flush();
  232.                     // Trigger Agent Assign event
  233.                     $event = new GenericEvent(CoreWorkflowEvents\Ticket\Agent::getId(), [
  234.                         'entity' => $ticket,
  235.                         'customfields' => "",
  236.                     ]);
  237.                     $this->eventDispatcher->dispatch($event'uvdesk.automation.workflow.execute');
  238.                     return new Response(json_encode([
  239.                         'alertClass' => 'success',
  240.                         'alertMessage' => $this->translator->trans('Ticket successfully assigned to %agent%', [
  241.                             '%agent%' => $agentDetails['name'],
  242.                         ]),
  243.                     ]), 200, ['Content-Type' => 'application/json']);
  244.                 }
  245.                 break;
  246.             case 'status':
  247.                 $ticketStatus $entityManager->getRepository(TicketStatus::class)->findOneById((int) $requestContent['value']);
  248.                 if (empty($ticketStatus)) {
  249.                     // Selected ticket status does not exist
  250.                     return new Response(json_encode([
  251.                         'alertClass' => 'danger',
  252.                         'alertMessage' => $this->translator->trans('Unable to retrieve status details'),
  253.                     ]), 404, ['Content-Type' => 'application/json']);
  254.                 }
  255.                 if ($ticketStatus->getId() === $ticket->getStatus()->getId()) {
  256.                     return new Response(json_encode([
  257.                         'alertClass' => 'success',
  258.                         'alertMessage' => $this->translator->trans('Ticket status already set to %status%', [
  259.                             '%status%' => $ticketStatus->getDescription()
  260.                         ]),
  261.                     ]), 200, ['Content-Type' => 'application/json']);
  262.                 } else {
  263.                     $ticket->setStatus($ticketStatus);
  264.                     $entityManager->persist($ticket);
  265.                     $entityManager->flush();
  266.                     // Trigger ticket status event
  267.                     $event = new GenericEvent(CoreWorkflowEvents\Ticket\Status::getId(), [
  268.                         'entity' => $ticket,
  269.                     ]);
  270.                     $this->eventDispatcher->dispatch($event'uvdesk.automation.workflow.execute');
  271.                     return new Response(json_encode([
  272.                         'alertClass' => 'success',
  273.                         'alertMessage' => $this->translator->trans('Ticket status update to %status%', [
  274.                             '%status%' => $ticketStatus->getDescription()
  275.                         ]),
  276.                     ]), 200, ['Content-Type' => 'application/json']);
  277.                 }
  278.                 break;
  279.             case 'priority':
  280.                 // $this->isAuthorized('ROLE_AGENT_UPDATE_TICKET_PRIORITY');
  281.                 $ticketPriority $entityManager->getRepository(TicketPriority::class)->findOneById($requestContent['value']);
  282.                 if (empty($ticketPriority)) {
  283.                     // Selected ticket priority does not exist
  284.                     return new Response(json_encode([
  285.                         'alertClass' => 'danger',
  286.                         'alertMessage' => $this->translator->trans('Unable to retrieve priority details'),
  287.                     ]), 404, ['Content-Type' => 'application/json']);
  288.                 }
  289.                 if ($ticketPriority->getId() === $ticket->getPriority()->getId()) {
  290.                     return new Response(json_encode([
  291.                         'alertClass' => 'success',
  292.                         'alertMessage' => $this->translator->trans('Ticket priority already set to %priority%', [
  293.                             '%priority%' => $ticketPriority->getDescription()
  294.                         ]),
  295.                     ]), 200, ['Content-Type' => 'application/json']);
  296.                 } else {
  297.                     $ticket->setPriority($ticketPriority);
  298.                     $entityManager->persist($ticket);
  299.                     $entityManager->flush();
  300.                     // Trigger ticket Priority event
  301.                     $event = new GenericEvent(CoreWorkflowEvents\Ticket\Priority::getId(), [
  302.                         'entity' => $ticket,
  303.                     ]);
  304.                     $this->eventDispatcher->dispatch($event'uvdesk.automation.workflow.execute');
  305.                     return new Response(json_encode([
  306.                         'alertClass' => 'success',
  307.                         'alertMessage' => $this->translator->trans('Ticket priority updated to %priority%', [
  308.                             '%priority%' => $ticketPriority->getDescription()
  309.                         ]),
  310.                     ]), 200, ['Content-Type' => 'application/json']);
  311.                 }
  312.                 break;
  313.             case 'group':
  314.                 $supportGroup $entityManager->getRepository(SupportGroup::class)->findOneById($requestContent['value']);
  315.                 if (empty($supportGroup)) {
  316.                     if ($requestContent['value'] == "") {
  317.                         if ($ticket->getSupportGroup() != null) {
  318.                             $ticket->setSupportGroup(null);
  319.                             $entityManager->persist($ticket);
  320.                             $entityManager->flush();
  321.                         }
  322.                         $responseCode 200;
  323.                         $response = [
  324.                             'alertClass' => 'success',
  325.                             'alertMessage' => $this->translator->trans('Ticket support group updated successfully'),
  326.                         ];
  327.                     } else {
  328.                         $responseCode 404;
  329.                         $response = [
  330.                             'alertClass' => 'danger',
  331.                             'alertMessage' => $this->translator->trans('Unable to retrieve support group details'),
  332.                         ];
  333.                     }
  334.                     return new Response(json_encode($response), $responseCode, ['Content-Type' => 'application/json']);;
  335.                 }
  336.                 if ($ticket->getSupportGroup() != null && $supportGroup->getId() === $ticket->getSupportGroup()->getId()) {
  337.                     return new Response(json_encode([
  338.                         'alertClass' => 'success',
  339.                         'alertMessage' => 'Ticket already assigned to support group ' $supportGroup->getName(),
  340.                     ]), 200, ['Content-Type' => 'application/json']);
  341.                 } else {
  342.                     $ticket->setSupportGroup($supportGroup);
  343.                     $entityManager->persist($ticket);
  344.                     $entityManager->flush();
  345.                     // Trigger Support group event
  346.                     $event = new GenericEvent(CoreWorkflowEvents\Ticket\Group::getId(), [
  347.                         'entity' => $ticket,
  348.                     ]);
  349.                     $this->eventDispatcher->dispatch($event'uvdesk.automation.workflow.execute');
  350.                     return new Response(json_encode([
  351.                         'alertClass' => 'success',
  352.                         'alertMessage' => $this->translator->trans('Ticket assigned to support group '). $supportGroup->getName(),
  353.                     ]), 200, ['Content-Type' => 'application/json']);
  354.                 }
  355.                 break;
  356.             case 'team':
  357.                 $supportTeam $entityManager->getRepository(SupportTeam::class)->findOneById($requestContent['value']);
  358.                 if (empty($supportTeam)) {
  359.                     if ($requestContent['value'] == "") {
  360.                         if ($ticket->getSupportTeam() != null) {
  361.                             $ticket->setSupportTeam(null);
  362.                             $entityManager->persist($ticket);
  363.                             $entityManager->flush();
  364.                         }
  365.                         $responseCode 200;
  366.                         $response = [
  367.                             'alertClass' => 'success',
  368.                             'alertMessage' => $this->translator->trans('Ticket support team updated successfully'),
  369.                         ];
  370.                     } else {
  371.                         $responseCode 404;
  372.                         $response = [
  373.                             'alertClass' => 'danger',
  374.                             'alertMessage' => $this->translator->trans('Unable to retrieve support team details'),
  375.                         ];
  376.                     }
  377.                     return new Response(json_encode($response), $responseCode, ['Content-Type' => 'application/json']);;
  378.                 }
  379.                 if ($ticket->getSupportTeam() != null && $supportTeam->getId() === $ticket->getSupportTeam()->getId()) {
  380.                     return new Response(json_encode([
  381.                         'alertClass' => 'success',
  382.                         'alertMessage' => 'Ticket already assigned to support team ' $supportTeam->getName(),
  383.                     ]), 200, ['Content-Type' => 'application/json']);
  384.                 } else {
  385.                     $ticket->setSupportTeam($supportTeam);
  386.                     $entityManager->persist($ticket);
  387.                     $entityManager->flush();
  388.                     // Trigger ticket delete event
  389.                     $event = new GenericEvent(CoreWorkflowEvents\Ticket\Team::getId(), [
  390.                         'entity' => $ticket,
  391.                     ]);
  392.                     $this->eventDispatcher->dispatch($event'uvdesk.automation.workflow.execute');
  393.                     return new Response(json_encode([
  394.                         'alertClass' => 'success',
  395.                         'alertMessage' => 'Ticket assigned to support team ' $supportTeam->getName(),
  396.                     ]), 200, ['Content-Type' => 'application/json']);
  397.                 }
  398.                 break;
  399.             case 'type':
  400.                 // $this->isAuthorized('ROLE_AGENT_UPDATE_TICKET_TYPE');
  401.                 $ticketType $entityManager->getRepository(TicketType::class)->findOneById($requestContent['value']);
  402.                 if (empty($ticketType)) {
  403.                     // Selected ticket priority does not exist
  404.                     return new Response(json_encode([
  405.                         'alertClass' => 'danger',
  406.                         'alertMessage' => 'Unable to retrieve ticket type details',
  407.                     ]), 404, ['Content-Type' => 'application/json']);
  408.                 }
  409.                 if (null != $ticket->getType() && $ticketType->getId() === $ticket->getType()->getId()) {
  410.                     return new Response(json_encode([
  411.                         'alertClass' => 'success',
  412.                         'alertMessage' => 'Ticket type already set to ' $ticketType->getDescription(),
  413.                     ]), 200, ['Content-Type' => 'application/json']);
  414.                 } else {
  415.                     $ticket->setType($ticketType);
  416.                     $entityManager->persist($ticket);
  417.                     $entityManager->flush();
  418.                     // Trigger ticket delete event
  419.                     $event = new GenericEvent(CoreWorkflowEvents\Ticket\Type::getId(), [
  420.                         'entity' => $ticket,
  421.                     ]);
  422.                     $this->eventDispatcher->dispatch($event'uvdesk.automation.workflow.execute');
  423.                     return new Response(json_encode([
  424.                         'alertClass' => 'success',
  425.                         'alertMessage' => 'Ticket type updated to ' $ticketType->getDescription(),
  426.                     ]), 200, ['Content-Type' => 'application/json']);
  427.                 }
  428.                 break;
  429.             case 'label':
  430.                 $label $entityManager->getRepository(SupportLabel::class)->find($requestContent['labelId']);
  431.                 if($label) {
  432.                     $ticket->removeSupportLabel($label);
  433.                     $entityManager->persist($ticket);
  434.                     $entityManager->flush();
  435.                     return new Response(json_encode([
  436.                         'alertClass' => 'success',
  437.                         'alertMessage' => $this->translator->trans('Success ! Ticket to label removed successfully.'),
  438.                     ]), 200, ['Content-Type' => 'application/json']);
  439.                 }
  440.                 break;
  441.             default:
  442.                 break;
  443.         }
  444.         return new Response(json_encode([]), 400, ['Content-Type' => 'application/json']);
  445.     }
  446.     public function exportTicketsToExcel(Request $request)
  447. {
  448.     ob_start(); // Start output buffering
  449.     // Retrieve the JSON data from the session
  450.     $ticketData $request->getSession()->get('ticket_data', []);
  451.     if (empty($ticketData)) {
  452.         return new Response('No data available to export'404);
  453.     }
  454.     // Decode the JSON data
  455.     $data json_decode($ticketDatatrue);
  456.     // Create a new Spreadsheet object
  457.     $spreadsheet = new Spreadsheet();
  458.     $sheet $spreadsheet->getActiveSheet();
  459.     // Extract headers from the data
  460.     $headers = [];
  461.     if (isset($data['tickets'][0])) {
  462.         foreach ($data['tickets'][0] as $key => $value) {
  463.             if (is_array($value)) {
  464.                 foreach ($value as $subKey => $subValue) {
  465.                     $headers[] = $key ' ' $subKey;
  466.                 }
  467.             } else {
  468.                 $headers[] = $key;
  469.             }
  470.         }
  471.     }
  472.     // Set the header row
  473.     $col 'A';
  474.     foreach ($headers as $header) {
  475.         $sheet->setCellValue($col '1'$header);
  476.         $col++;
  477.     }
  478.     // Fill the data rows
  479.     $row 2;
  480.     foreach ($data['tickets'] as $ticket) {
  481.         $col 'A';
  482.         foreach ($ticket as $key => $value) {
  483.             if (is_array($value)) {
  484.                 foreach ($value as $subValue) {
  485.                     $sheet->setCellValue($col $row$subValue);
  486.                     $col++;
  487.                 }
  488.             } else {
  489.                 $sheet->setCellValue($col $row$value);
  490.                 $col++;
  491.             }
  492.         }
  493.         $row++;
  494.     }
  495.     // Generate and return the Excel file
  496.     $writer = new Xlsx($spreadsheet);
  497.     $filename 'tickets.xlsx';
  498.     $response = new Response();
  499.     $response->headers->set('Content-Type''application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
  500.     $response->headers->set('Content-Disposition''attachment; filename="' $filename '"');
  501.     $response->headers->set('Cache-Control''max-age=0');
  502.     $writer->save('php://output');
  503.     return $response;
  504. }
  505. public function listTicketCollectionXHR(Request $request)
  506. {
  507.     if ($request->isXmlHttpRequest()) {
  508.         $paginationResponse $this->ticketService->paginateMembersTicketCollection($request);
  509.         $fullResponse $this->ticketService->getAllMembersTicketCollection($request);
  510.         // Store the JSON data in the session
  511.         $request->getSession()->set('ticket_data'json_encode($fullResponse));
  512.         return new Response(json_encode($paginationResponse), 200, ['Content-Type' => 'application/json']);
  513.     }
  514.     return new Response(json_encode([]), 404, ['Content-Type' => 'application/json']);
  515. }
  516.     public function updateTicketCollectionXHR(Request $request)
  517.     {
  518.         if ($request->isXmlHttpRequest()) {
  519.             $massResponse $this->ticketService->massXhrUpdate($request);
  520.             return new Response(json_encode($massResponse), 200, ['Content-Type' => 'application/json']);
  521.         }
  522.         return new Response(json_encode([]), 404);
  523.     }
  524.     public function loadTicketFilterOptionsXHR(Request $request)
  525.     {
  526.         return new Response(json_encode([]), 404);
  527.     }
  528.     public function saveTicketLabel(Request $request)
  529.     {
  530.         $entityManager $this->getDoctrine()->getManager();
  531.         $request $this->container->get('request_stack')->getCurrentRequest();
  532.         $requestContent json_decode($request->getContent(), true);
  533.         $ticket $entityManager->getRepository(Ticket::class)->findOneById($requestContent['ticketId']);
  534.         // Process only if user have ticket access
  535.         if (false == $this->ticketService->isTicketAccessGranted($ticket)) {
  536.             throw new \Exception('Access Denied'403);
  537.         }
  538.         if ('POST' == $request->getMethod()) {
  539.             $responseContent = [];
  540.             $user $this->userService->getSessionUser();
  541.             $supportLabel $entityManager->getRepository(SupportLabel::class)->findOneBy([
  542.                 'user' => $user->getId(),
  543.                 'name' => $requestContent['name'],
  544.             ]);
  545.             if (empty($supportLabel)) {
  546.                 $supportLabel = new SupportLabel();
  547.                 $supportLabel->setName($requestContent['name']);
  548.                 $supportLabel->setUser($user);
  549.                 $entityManager->persist($supportLabel);
  550.                 $entityManager->flush();
  551.             }
  552.             $ticketLabelCollection $ticket->getSupportLabels()->toArray();
  553.             if (empty($ticketLabelCollection)) {
  554.                 $ticket->addSupportLabel($supportLabel);
  555.                 $entityManager->persist($ticket);
  556.                 $entityManager->flush();
  557.                 $responseContent['alertClass'] = 'success';
  558.                 $responseContent['alertMessage'] = $this->translator->trans(
  559.                     'Label %label% added to ticket successfully', [
  560.                     '%label%' => $supportLabel->getName(),
  561.                 ]);
  562.             } else {
  563.                 $isLabelAlreadyAdded false;
  564.                 foreach ($ticketLabelCollection as $ticketLabel) {
  565.                     if ($supportLabel->getId() == $ticketLabel->getId()) {
  566.                         $isLabelAlreadyAdded true;
  567.                         break;
  568.                     }
  569.                 }
  570.                 if (false == $isLabelAlreadyAdded) {
  571.                     $ticket->addSupportLabel($supportLabel);
  572.                     $entityManager->persist($ticket);
  573.                     $entityManager->flush();
  574.                     $responseContent['alertClass'] = 'success';
  575.                     $responseContent['alertMessage'] = $this->translator->trans(
  576.                         'Label %label% added to ticket successfully', [
  577.                         '%label%' => $supportLabel->getName(),
  578.                     ]);
  579.                 } else {
  580.                     $responseContent['alertClass'] = 'warning';
  581.                     $responseContent['alertMessage'] = $this->translator->trans(
  582.                         'Label %label% already added to ticket', [
  583.                         '%label%' => $supportLabel->getName(),
  584.                     ]);
  585.                 }
  586.             }
  587.             $responseContent['label'] = [
  588.                 'id' => $supportLabel->getId(),
  589.                 'name' => $supportLabel->getName(),
  590.                 'color' => $supportLabel->getColorCode(),
  591.             ];
  592.             return new Response(json_encode($responseContent), 200, ['Content-Type' => 'application/json']);
  593.         }
  594.         return new Response(json_encode([]), 404, ['Content-Type' => 'application/json']);
  595.     }
  596.     public function getLabels($request null)
  597.     {
  598.         static $labels;
  599.         if (null !== $labels)
  600.             return $labels;
  601.         $qb $this->em->createQueryBuilder();
  602.         $qb->select('tl')->from(TicketLabel::class, 'tl')
  603.             ->andwhere('tl.labelUser = :labelUserId')
  604.             ->andwhere('tl.company = :companyId')
  605.             ->setParameter('labelUserId'$this->getUser()->getId())
  606.             ->setParameter('companyId'$this->getCompany()->getId());
  607.         if($request) {
  608.             $qb->andwhere("tl.name LIKE :labelName");
  609.             $qb->setParameter('labelName''%'.urldecode($request->query->get('query')).'%');
  610.         }
  611.         return $labels $qb->getQuery()->getArrayResult();
  612.     }
  613.     public function loadTicketSearchFilterOptions(Request $request)
  614.     {
  615.         if (true === $request->isXmlHttpRequest()) {
  616.             switch ($request->query->get('type')) {
  617.                 case 'agent':
  618.                     $filtersResponse $this->userService->getAgentPartialDataCollection($request);
  619.                     break;
  620.                 case 'customer':
  621.                     $filtersResponse $this->userService->getCustomersPartial($request);
  622.                     break;
  623.                 case 'group':
  624.                     $filtersResponse $this->userService->getSupportGroups($request);
  625.                     break;
  626.                 case 'team':
  627.                     $filtersResponse $this->userService->getSupportTeams($request);
  628.                     break;
  629.                 case 'tag':
  630.                     $filtersResponse $this->ticketService->getTicketTags($request);
  631.                     break;
  632.                 case 'label':
  633.                     $searchTerm $request->query->get('query');
  634.                     $entityManager $this->getDoctrine()->getManager();
  635.                     $supportLabelQuery $entityManager->createQueryBuilder()->select('supportLabel')
  636.                         ->from(SupportLabel::class, 'supportLabel')
  637.                         ->where('supportLabel.user = :user')->setParameter('user'$this->userService->getSessionUser());
  638.                     if (!empty($searchTerm)) {
  639.                         $supportLabelQuery->andWhere('supportLabel.name LIKE :labelName')->setParameter('labelName''%' urldecode($searchTerm) . '%');
  640.                     }
  641.                     $supportLabelCollection $supportLabelQuery->getQuery()->getArrayResult();
  642.                     return new Response(json_encode($supportLabelCollection), 200, ['Content-Type' => 'application/json']);
  643.                     break;
  644.                 default:
  645.                     break;
  646.             }
  647.         }
  648.         return new Response(json_encode([]), 404, ['Content-Type' => 'application/json']);
  649.     }
  650.     public function loadTicketCollectionSearchFilterOptionsXHR(Request $request)
  651.     {
  652.         $json = [];
  653.         if ($request->isXmlHttpRequest()) {
  654.             if ($request->query->get('type') == 'agent') {
  655.                 $json $this->userService->getAgentsPartialDetails($request);
  656.             } elseif ($request->query->get('type') == 'customer') {
  657.                 $json $this->userService->getCustomersPartial($request);
  658.             } elseif ($request->query->get('type') == 'group') {
  659.                 $json $this->userService->getSupportGroups($request);
  660.             } elseif ($request->query->get('type') == 'team') {
  661.                 $json $this->userService->getSupportTeams($request);
  662.             } elseif ($request->query->get('type') == 'tag') {
  663.                 $json $this->ticketService->getTicketTags($request);
  664.             } elseif ($request->query->get('type') == 'label') {
  665.                 $json $this->ticketService->getLabels($request);
  666.             }
  667.         }
  668.         return new Response(json_encode($json), 200, ['Content-Type' => 'application/json']);
  669.     }
  670.     public function listTicketTypeCollectionXHR(Request $request)
  671.     {
  672.         if (!$this->userService->isAccessAuthorized('ROLE_AGENT_MANAGE_TICKET_TYPE')) {
  673.             return $this->redirect($this->generateUrl('helpdesk_member_dashboard'));
  674.         }
  675.         if (true === $request->isXmlHttpRequest()) {
  676.             $paginationResponse $this->ticketService->paginateMembersTicketTypeCollection($request);
  677.             return new Response(json_encode($paginationResponse), 200, ['Content-Type' => 'application/json']);
  678.         }
  679.         return new Response(json_encode([]), 404, ['Content-Type' => 'application/json']);
  680.     }
  681.     public function removeTicketTypeXHR($typeIdRequest $request)
  682.     {
  683.         if (!$this->userService->isAccessAuthorized('ROLE_AGENT_MANAGE_TICKET_TYPE')) {
  684.             return $this->redirect($this->generateUrl('helpdesk_member_dashboard'));
  685.         }
  686.         $json = [];
  687.         if($request->getMethod() == "DELETE") {
  688.             $em $this->getDoctrine()->getManager();
  689.             $id $request->attributes->get('typeId');
  690.             $type $em->getRepository(TicketType::class)->find($id);
  691.             // $this->get('event.manager')->trigger([
  692.             //             'event' => 'type.deleted',
  693.             //             'entity' => $type
  694.             //         ]);
  695.             $em->remove($type);
  696.             $em->flush();
  697.             $json['alertClass'] = 'success';
  698.             $json['alertMessage'] = $this->translator->trans('Success ! Type removed successfully.');
  699.         }
  700.         $response = new Response(json_encode($json));
  701.         $response->headers->set('Content-Type''application/json');
  702.         return $response;
  703.     }
  704.     public function listTagCollectionXHR(Request $request)
  705.     {
  706.         if (!$this->userService->isAccessAuthorized('ROLE_AGENT_MANAGE_TAG')) {
  707.             return $this->redirect($this->generateUrl('helpdesk_member_dashboard'));
  708.         }
  709.         if (true === $request->isXmlHttpRequest()) {
  710.             $paginationResponse $this->ticketService->paginateMembersTagCollection($request);
  711.             return new Response(json_encode($paginationResponse), 200, ['Content-Type' => 'application/json']);
  712.         }
  713.         return new Response(json_encode([]), 404, ['Content-Type' => 'application/json']);
  714.     }
  715.     public function applyTicketPreparedResponseXHR(Request $request)
  716.     {
  717.         $id $request->attributes->get('id');
  718.         $ticketId $request->attributes->get('ticketId');
  719.         $ticket $this->getDoctrine()->getManager()->getRepository(Ticket::class)->findOneById($ticketId);
  720.         // Process only if user have ticket access
  721.         if (false == $this->ticketService->isTicketAccessGranted($ticket)) {
  722.             return $this->redirect($this->generateUrl('helpdesk_member_dashboard'));
  723.         }
  724.         $event = new GenericEvent($id, [
  725.             'entity' =>  $ticket
  726.         ]);
  727.         $this->eventDispatcher->dispatch($event'uvdesk.automation.prepared_response.execute');
  728.         $this->addFlash('success'$this->translator->trans('Success ! Prepared Response applied successfully.'));
  729.         return $this->redirect($this->generateUrl('helpdesk_member_ticket',['ticketId' => $ticketId]));
  730.     }
  731.     public function loadTicketSavedReplies(Request $request)
  732.     {
  733.         $json = array();
  734.         $data $request->query->all();
  735.         if ($request->isXmlHttpRequest()) {
  736.             $json['message'] = $this->ticketService->getSavedReplyContent($data['id'],$data['ticketId']);
  737.         }
  738.         $response = new Response(json_encode($json));
  739.         return $response;
  740.     }
  741.     public function createTicketTagXHR(Request $request)
  742.     {
  743.         $json = [];
  744.         $content json_decode($request->getContent(), true);
  745.         $em $this->getDoctrine()->getManager();
  746.         $ticket $em->getRepository(Ticket::class)->find($content['ticketId']);
  747.         // Process only if user have ticket access
  748.         if (false == $this->ticketService->isTicketAccessGranted($ticket)) {
  749.             throw new \Exception('Access Denied'403);
  750.         }
  751.         if($request->getMethod() == "POST") {
  752.             $tag = new CoreFrameworkBundleEntities\Tag();
  753.             if ($content['name'] != "") {
  754.                 $checkTag $em->getRepository(Tag::class)->findOneBy(array('name' => $content['name']));
  755.                 if(!$checkTag) {
  756.                     $tag->setName($content['name']);
  757.                     $em->persist($tag);
  758.                     $em->flush();
  759.                     //$json['tag'] = json_decode($this->objectSerializer($tag));
  760.                     $ticket->addSupportTag($tag);
  761.                 } else {
  762.                     //$json['tag'] = json_decode($this->objectSerializer($checkTag));
  763.                     $ticket->addSupportTag($checkTag);
  764.                 }
  765.                 $em->persist($ticket);
  766.                 $em->flush();
  767.                 $json['alertClass'] = 'success';
  768.                 $json['alertMessage'] = $this->translator->trans('Success ! Tag added successfully.');
  769.             } else {
  770.                 $json['alertClass'] = 'danger';
  771.                 $json['alertMessage'] = $this->translator->trans('Please enter tag name.');
  772.             }
  773.         } elseif($request->getMethod() == "DELETE") {
  774.             $tag $em->getRepository(Tag::class)->findOneBy(array('id' => $request->attributes->get('id')));
  775.             if($tag) {
  776.                 $articles $em->getRepository(ArticleTags::class)->findOneBy(array('tagId' => $tag->getId()));
  777.                 if($articles)
  778.                     foreach ($articles as $entry) {
  779.                         $em->remove($entry);
  780.                     }
  781.                 $ticket->removeSupportTag($tag);
  782.                 $em->persist($ticket);
  783.                 $em->flush();
  784.                 $json['alertClass'] = 'success';
  785.                 $json['alertMessage'] = $this->translator->trans('Success ! Tag unassigned successfully.');
  786.             } else {
  787.                 $json['alertClass'] = 'danger';
  788.                 $json['alertMessage'] = $this->translator->trans('Error ! Invalid tag.');
  789.             }
  790.         }
  791.         $response = new Response(json_encode($json));
  792.         $response->headers->set('Content-Type''application/json');
  793.         return $response;
  794.     }
  795.     public function getSearchFilterOptionsXhr(Request $request)
  796.     {
  797.         $json = [];
  798.         if ($request->isXmlHttpRequest()) {
  799.             if($request->query->get('type') == 'agent') {
  800.                 $json $this->userService->getAgentsPartialDetails($request);
  801.             } elseif($request->query->get('type') == 'customer') {
  802.                 $json $this->userService->getCustomersPartial($request);
  803.             } elseif($request->query->get('type') == 'group') {
  804.                 $json $this->userService->getSupportGroups($request);
  805.             } elseif($request->query->get('type') == 'team') {
  806.                 $json $this->userService->getSupportTeams($request);
  807.             } elseif($request->query->get('type') == 'tag') {
  808.                 $json $this->ticketService->getTicketTags($request);
  809.             } elseif($request->query->get('type') == 'label') {
  810.                 $json $this->ticketService->getLabels($request);
  811.             }
  812.         }
  813.         $response = new Response(json_encode($json));
  814.         $response->headers->set('Content-Type''application/json');
  815.         return $response;
  816.     }
  817.     public function updateCollaboratorXHR(Request $request)
  818.     {
  819.         $json = [];
  820.         $content json_decode($request->getContent(), true);
  821.         $em $this->getDoctrine()->getManager();
  822.         $ticket $em->getRepository(Ticket::class)->find($content['ticketId']);
  823.         // Process only if user have ticket access
  824.         if (false == $this->ticketService->isTicketAccessGranted($ticket)) {
  825.             throw new \Exception('Access Denied'403);
  826.         }
  827.         if($request->getMethod() == "POST") {
  828.             if($content['email'] == $ticket->getCustomer()->getEmail()) {
  829.                 $json['alertClass'] = 'danger';
  830.                 $json['alertMessage'] = $this->translator->trans('Error ! Customer can not be added as collaborator.');
  831.             } else {
  832.                 $data = array(
  833.                     'from' => $content['email'],
  834.                     'firstName' => ($firstName ucfirst(current(explode('@'$content['email'])))),
  835.                     'lastName' => ' ',
  836.                     'role' => 4,
  837.                 );
  838.                 $supportRole $em->getRepository(SupportRole::class)->findOneByCode('ROLE_CUSTOMER');
  839.                 $collaborator $this->userService->createUserInstance($data['from'], $data['firstName'], $supportRole$extras = ["active" => true]);
  840.                 $checkTicket $em->getRepository(Ticket::class)->isTicketCollaborator($ticket$content['email']);
  841.                 if (!$checkTicket) {
  842.                     $ticket->addCollaborator($collaborator);
  843.                     $em->persist($ticket);
  844.                     $em->flush();
  845.                     $ticket->lastCollaborator $collaborator;
  846.                     if ($collaborator->getCustomerInstance())
  847.                         $json['collaborator'] = $collaborator->getCustomerInstance()->getPartialDetails();
  848.                     else
  849.                         $json['collaborator'] = $collaborator->getAgentInstance()->getPartialDetails();
  850.                     $event = new GenericEvent(CoreWorkflowEvents\Ticket\Collaborator::getId(), [
  851.                         'entity' => $ticket,
  852.                     ]);
  853.                     $this->eventDispatcher->dispatch($event'uvdesk.automation.workflow.execute');
  854.                     $json['alertClass'] = 'success';
  855.                     $json['alertMessage'] = $this->translator->trans('Success ! Collaborator added successfully.');
  856.                 } else {
  857.                     $json['alertClass'] = 'danger';
  858.                     $message "Collaborator is already added.";
  859.                     $json['alertMessage'] = $this->translator->trans('Error ! ' $message);
  860.                 }
  861.             }
  862.         } elseif($request->getMethod() == "DELETE") {
  863.             $collaborator $em->getRepository(User::class)->findOneBy(array('id' => $request->attributes->get('id')));
  864.             if($collaborator) {
  865.                 $ticket->removeCollaborator($collaborator);
  866.                 $em->persist($ticket);
  867.                 $em->flush();
  868.                 $json['alertClass'] = 'success';
  869.                 $json['alertMessage'] = $this->translator->trans('Success ! Collaborator removed successfully.');
  870.             } else {
  871.                 $json['alertClass'] = 'danger';
  872.                 $json['alertMessage'] = $this->translator->trans('Error ! Invalid Collaborator.');
  873.             }
  874.         }
  875.         $response = new Response(json_encode($json));
  876.         $response->headers->set('Content-Type''application/json');
  877.         return $response;
  878.     }
  879.     // Apply quick Response action
  880.     public function getTicketQuickViewDetailsXhr(Request $requestContainerInterface $container)
  881.     {
  882.         $json = [];
  883.         if ($request->isXmlHttpRequest()) {
  884.             $ticketId $request->query->get('ticketId');
  885.             $json $this->getDoctrine()->getRepository(Ticket::class)->getTicketDetails($request->query$container);
  886.         }
  887.         $response = new Response(json_encode($json));
  888.         $response->headers->set('Content-Type''application/json');
  889.         return $response;
  890.     }
  891.     public function updateDueDateXHR(Request $request)
  892.     {
  893.         try {
  894.             // Decode the JSON content
  895.             $content json_decode($request->getContent(), true);
  896.     
  897.             // Validate the request payload
  898.             if (empty($content['ticketId']) || empty($content['dueDate'])) {
  899.                 return new JsonResponse([
  900.                     'success' => false,
  901.                     'message' => 'Invalid request payload. Ticket ID or Due Date is missing.',
  902.                 ]);
  903.             }
  904.     
  905.             // Fetch the ticket
  906.             $em $this->getDoctrine()->getManager();
  907.             $ticket $em->getRepository(Ticket::class)->find($content['ticketId']);
  908.     
  909.             if (!$ticket) {
  910.                 return new JsonResponse([
  911.                     'success' => false,
  912.                     'message' => 'Error! Ticket not found.',
  913.                 ]);
  914.             }
  915.     
  916.             // Update the due date       
  917.                 $newDueDate = new \DateTime($content['dueDate']);
  918.                 $ticket->setDueDate($newDueDate);
  919.                 $em->persist($ticket);
  920.                 $em->flush();
  921.     
  922.         } catch (\Exception $e) {
  923.             return new JsonResponse([
  924.                 'success' => false,
  925.                 'message' => 'An unexpected error occurred. Please try again.',
  926.             ]);
  927.         }
  928.         $response = new Response();
  929.         $response->headers->set('Content-Type''application/json');
  930.         return $response;
  931.     }
  932.     public function updateTicketTagXHR(Request $request$tagId)
  933.     {
  934.         $content json_decode($request->getContent(), true);
  935.         $entityManager $this->getDoctrine()->getManager();
  936.         if (isset($content['name']) && $content['name'] != "") {
  937.             $checkTag $entityManager->getRepository(Tag::class)->findOneBy(array('id' => $tagId));
  938.             if($checkTag) {
  939.                 $checkTag->setName($content['name']);
  940.                 $entityManager->persist($checkTag);
  941.                 $entityManager->flush();
  942.             }
  943.             $json['alertClass'] = 'success';
  944.             $json['alertMessage'] = $this->translator->trans('Success ! Tag updated successfully.');
  945.         }
  946.         $response = new Response(json_encode($json));
  947.         $response->headers->set('Content-Type''application/json');
  948.         return $response;
  949.     }
  950.     public function removeTicketTagXHR($tagId)
  951.     {
  952.         $entityManager $this->getDoctrine()->getManager();
  953.         $checkTag $entityManager->getRepository(Tag::class)->findOneBy(array('id' => $tagId));
  954.         if($checkTag) {
  955.             $entityManager->remove($checkTag);
  956.             $entityManager->flush();
  957.             $json['alertClass'] = 'success';
  958.             $json['alertMessage'] = $this->translator->trans('Success ! Tag removed successfully.');
  959.         }
  960.         $response = new Response(json_encode($json));
  961.         $response->headers->set('Content-Type''application/json');
  962.         return $response;
  963.     }
  964. }