vendor/uvdesk/core-framework/Services/TicketService.php line 246

Open in your IDE?
  1. <?php
  2. namespace Webkul\UVDesk\CoreFrameworkBundle\Services;
  3. use Doctrine\ORM\Query;
  4. use Symfony\Component\Yaml\Yaml;
  5. use Doctrine\ORM\EntityManagerInterface;
  6. use Symfony\Component\HttpFoundation\Request;
  7. use Symfony\Component\HttpFoundation\Response;
  8. use Symfony\Component\HttpFoundation\RequestStack;
  9. use Webkul\UVDesk\CoreFrameworkBundle\Entity\User;
  10. use Webkul\UVDesk\CoreFrameworkBundle\Entity\AgentActivity;
  11. use Webkul\UVDesk\MailboxBundle\Utils\Mailbox\Mailbox;
  12. use Symfony\Component\EventDispatcher\GenericEvent;
  13. use Webkul\UVDesk\CoreFrameworkBundle\Entity\Ticket;
  14. use Webkul\UVDesk\CoreFrameworkBundle\Entity\Thread;
  15. use Webkul\UVDesk\CoreFrameworkBundle\Entity\Tag;
  16. use Webkul\UVDesk\CoreFrameworkBundle\Entity\TicketType;
  17. use Webkul\UVDesk\CoreFrameworkBundle\Entity\TicketStatus;
  18. use Webkul\UVDesk\CoreFrameworkBundle\Entity\TicketPriority;
  19. use Webkul\UVDesk\CoreFrameworkBundle\Entity\SupportRole;
  20. use Webkul\UVDesk\CoreFrameworkBundle\Entity\Website;
  21. use Webkul\UVDesk\CoreFrameworkBundle\Entity\SupportGroup;
  22. use Webkul\UVDesk\CoreFrameworkBundle\Entity\SupportTeam;
  23. use Webkul\UVDesk\CoreFrameworkBundle\Entity\SupportLabel;
  24. use Webkul\UVDesk\CoreFrameworkBundle\Entity\SavedReplies;
  25. use Webkul\UVDesk\CoreFrameworkBundle\Entity\Attachment;
  26. use Webkul\UVDesk\MailboxBundle\Utils\MailboxConfiguration;
  27. use Webkul\UVDesk\CoreFrameworkBundle\Utils\TokenGenerator;
  28. use Symfony\Component\DependencyInjection\ContainerInterface;
  29. use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
  30. use Webkul\UVDesk\CoreFrameworkBundle\Workflow\Events as CoreWorkflowEvents;
  31. use Webkul\UVDesk\CoreFrameworkBundle\Services\FileUploadService;
  32. use Webkul\UVDesk\CoreFrameworkBundle\Services\UserService;
  33. use UVDesk\CommunityPackages\UVDesk\FormComponent\Entity;
  34. use Webkul\UVDesk\MailboxBundle\Utils\Imap\Configuration as ImapConfiguration;
  35. use Symfony\Component\Filesystem\Filesystem;
  36. use Webkul\UVDesk\SupportCenterBundle\Entity\Article;
  37. use Webkul\UVDesk\SupportCenterBundle\Entity\KnowledgebaseWebsite;
  38. use Webkul\UVDesk\AutomationBundle\Entity\PreparedResponses;
  39. use UVDesk\CommunityPackages\UVDesk as UVDeskCommunityPackages;
  40. class TicketService
  41. {
  42.     const PATH_TO_CONFIG '/config/packages/uvdesk_mailbox.yaml';
  43.     protected $container;
  44.     protected $requestStack;
  45.     protected $entityManager;
  46.     protected $fileUploadService;
  47.     protected $userService;
  48.     
  49.     public function __construct(
  50.         ContainerInterface $container
  51.         RequestStack $requestStack
  52.         EntityManagerInterface $entityManager
  53.         FileUploadService $fileUploadService,
  54.         UserService $userService)
  55.     {
  56.         $this->container $container;
  57.         $this->requestStack $requestStack;
  58.         $this->entityManager $entityManager;
  59.         $this->fileUploadService $fileUploadService;
  60.         $this->userService $userService;
  61.     }
  62.     public function getAllMailboxes()
  63.     {
  64.         $collection array_map(function ($mailbox) {
  65.             return [
  66.                 'id' => $mailbox->getId(),
  67.                 'name' => $mailbox->getName(),
  68.                 'isEnabled' => $mailbox->getIsEnabled(),
  69.                 'email'     => $mailbox->getImapConfiguration()->getUsername(),
  70.             ];
  71.         }, $this->parseMailboxConfigurations()->getMailboxes());
  72.         return $collection;
  73.     }
  74.     public function parseMailboxConfigurations(bool $ignoreInvalidAttributes false
  75.     {
  76.         $path $this->getPathToConfigurationFile();
  77.         if (!file_exists($path)) {
  78.             throw new \Exception("File '$path' not found.");
  79.         }
  80.         // Read configurations from package config.
  81.         $mailboxConfiguration = new MailboxConfiguration();
  82.         $swiftmailerService $this->container->get('swiftmailer.service');
  83.         $swiftmailerConfigurations $swiftmailerService->parseSwiftMailerConfigurations();
  84.         foreach (Yaml::parse(file_get_contents($path))['uvdesk_mailbox']['mailboxes'] ?? [] as $id => $params) {
  85.             // Swiftmailer Configuration
  86.             $swiftmailerConfiguration null;
  87.             foreach ($swiftmailerConfigurations as $configuration) {
  88.                 if ($configuration->getId() == $params['smtp_server']['mailer_id']) {
  89.                     $swiftmailerConfiguration $configuration;
  90.                     break;
  91.                 }
  92.             }
  93.             // IMAP Configuration
  94.             ($imapConfiguration ImapConfiguration::guessTransportDefinition($params['imap_server']['host']))
  95.                 ->setUsername($params['imap_server']['username'])
  96.                 ->setPassword($params['imap_server']['password']);
  97.             // Mailbox Configuration
  98.             ($mailbox = new Mailbox($id))
  99.                 ->setName($params['name'])
  100.                 ->setIsEnabled($params['enabled'])
  101.                 ->setImapConfiguration($imapConfiguration);
  102.             
  103.             if (!empty($swiftmailerConfiguration)) {
  104.                 $mailbox->setSwiftMailerConfiguration($swiftmailerConfiguration);
  105.             } else if (!empty($params['smtp_server']['mailer_id']) && true === $ignoreInvalidAttributes) {
  106.                 $mailbox->setSwiftMailerConfiguration($swiftmailerService->createConfiguration('smtp'$params['smtp_server']['mailer_id']));
  107.             }
  108.             $mailboxConfiguration->addMailbox($mailbox);
  109.         }
  110.         return $mailboxConfiguration;
  111.     }
  112.     public function getPathToConfigurationFile()
  113.     {
  114.         return $this->container->get('kernel')->getProjectDir() . self::PATH_TO_CONFIG;
  115.     }
  116.     public function getRandomRefrenceId($email null)
  117.     {
  118.         $email = !empty($email) ? $email $this->container->getParameter('uvdesk.support_email.id');
  119.         $emailDomain substr($emailstrpos($email'@'));
  120.         return sprintf("<%s%s>"TokenGenerator::generateToken(20'0123456789abcdefghijklmnopqrstuvwxyz'), $emailDomain);
  121.     }
  122.     // @TODO: Refactor this out of this service. Use UserService::getSessionUser() instead.
  123.     public function getUser()
  124.     {
  125.         return $this->container->get('user.service')->getCurrentUser();
  126.     }
  127.     public function getDefaultType()
  128.     {
  129.         $typeCode $this->container->getParameter('uvdesk.default.ticket.type');
  130.         $ticketType $this->entityManager->getRepository(TicketType::class)->findOneByCode($typeCode);
  131.         return !empty($ticketType) ? $ticketType null;
  132.     }
  133.     public function getDefaultStatus()
  134.     {
  135.         $statusCode $this->container->getParameter('uvdesk.default.ticket.status');
  136.         $ticketStatus $this->entityManager->getRepository(TicketStatus::class)->findOneByCode($statusCode);
  137.         return !empty($ticketStatus) ? $ticketStatus null;
  138.     }
  139.     public function getDefaultPriority()
  140.     {
  141.         $priorityCode $this->container->getParameter('uvdesk.default.ticket.priority');
  142.         $ticketPriority $this->entityManager->getRepository(TicketPriority::class)->findOneByCode($priorityCode);
  143.         return !empty($ticketPriority) ? $ticketPriority null;
  144.     }
  145.     public function appendTwigSnippet($snippet '')
  146.     {
  147.         switch ($snippet) {
  148.             case 'createMemberTicket':
  149.                 return $this->getMemberCreateTicketSnippet();
  150.                 break;
  151.             default:
  152.                 break;
  153.         }
  154.         return '';
  155.     }
  156.     public function getMemberCreateTicketSnippet()
  157.     {   
  158.         $twigTemplatingEngine $this->container->get('twig');
  159.         $ticketTypeCollection $this->entityManager->getRepository(TicketType::class)->findByIsActive(true);
  160.         
  161.         try {
  162.             if ($this->userService->isfileExists('apps/uvdesk/custom-fields')) {
  163.                 $headerCustomFields $this->container->get('uvdesk_package_custom_fields.service')->getCustomFieldsArray('user');
  164.             } else if ($this->userService->isfileExists('apps/uvdesk/form-component')) {
  165.                 $headerCustomFields $this->container->get('uvdesk_package_form_component.service')->getCustomFieldsArray('user');
  166.             }
  167.         } catch (\Exception $e) {
  168.             // @TODO: Log execption message
  169.         }
  170.         return $twigTemplatingEngine->render('@UVDeskCoreFramework/Snippets/createMemberTicket.html.twig', [
  171.             'ticketTypeCollection' => $ticketTypeCollection,
  172.             'headerCustomFields' => $headerCustomFields ?? null,
  173.         ]);
  174.     }
  175.     public function getCustomerCreateTicketCustomFieldSnippet()
  176.     {
  177.         try {
  178.             if ($this->userService->isfileExists('apps/uvdesk/custom-fields')) {
  179.                 $customFields $this->container->get('uvdesk_package_custom_fields.service')->getCustomFieldsArray('customer');
  180.             } else if ($this->userService->isfileExists('apps/uvdesk/form-component')) {
  181.                 $customFields $this->container->get('uvdesk_package_form_component.service')->getCustomFieldsArray('customer');
  182.             }
  183.         } catch (\Exception $e) {
  184.             // @TODO: Log execption message
  185.         }
  186.         return $customFields ?? null;
  187.     }
  188.     public function createTicket(array $params = [])
  189.     {
  190.         $thread $this->entityManager->getRepository(Thread::class)->findOneByMessageId($params['messageId']);
  191.         if (empty($thread)) {
  192.             $user $this->entityManager->getRepository(User::class)->findOneByEmail($params['from']);
  193.             if (empty($user) || null == $user->getCustomerInstance()) {
  194.                 $role $this->entityManager->getRepository(SupportRole::class)->findOneByCode($params['role']);
  195.                 if (empty($role)) {
  196.                     throw new \Exception("The requested role '" $params['role'] . "' does not exist.");
  197.                 }
  198.                 
  199.                 // Create User Instance
  200.                 $user $this->container->get('user.service')->createUserInstance($params['from'], $params['name'], $role, [
  201.                     'source' => strtolower($params['source']),
  202.                     'active' => true,
  203.                 ]);
  204.             }
  205.             $params['role'] = 4;
  206.             $params['customer'] = $params['user'] = $user;
  207.             return $this->createTicketBase($params);
  208.         }
  209.         return;
  210.     }
  211.     public function createTicketBase(array $ticketData = [])
  212.     {
  213.         if ('email' == $ticketData['source']) {
  214.             try {
  215.                 if (array_key_exists('UVDeskMailboxBundle'$this->container->getParameter('kernel.bundles'))) {
  216.                     $mailbox $this->container->get('uvdesk.mailbox')->getMailboxByEmail($ticketData['mailboxEmail']);
  217.                     $ticketData['mailboxEmail'] = $mailbox['email'];
  218.                 }
  219.             } catch (\Exception $e) {
  220.                 // No mailbox found for this email. Skip ticket creation.
  221.                 return;
  222.             }
  223.         }
  224.         // Set Defaults
  225.         $ticketType = !empty($ticketData['type']) ? $ticketData['type'] : $this->getDefaultType();
  226.         $ticketStatus = !empty($ticketData['status']) ? $ticketData['status'] : $this->getDefaultStatus();
  227.         $ticketPriority = !empty($ticketData['priority']) ? $ticketData['priority'] : $this->getDefaultPriority();
  228.         $ticketMessageId 'email' == $ticketData['source'] ? (!empty($ticketData['messageId']) ? $ticketData['messageId'] : null) : $this->getRandomRefrenceId();
  229.         $ticketData['type'] = $ticketType;
  230.         $ticketData['status'] = $ticketStatus;
  231.         $ticketData['priority'] = $ticketPriority;
  232.         $ticketData['messageId'] = $ticketMessageId;
  233.         $ticketData['isTrashed'] = false;
  234.         $ticket = new Ticket();
  235.         foreach ($ticketData as $property => $value) {
  236.             $callable 'set' ucwords($property);
  237.             if (method_exists($ticket$callable)) {
  238.                 $ticket->$callable($value);
  239.             }
  240.         }
  241.         $this->entityManager->persist($ticket);
  242.         $this->entityManager->flush();
  243.         return $this->createThread($ticket$ticketData);
  244.     }
  245.     
  246.     public function createThread(Ticket $ticket, array $threadData)
  247.     {
  248.         $threadData['isLocked'] = 0;
  249.       
  250.         if ('forward' === $threadData['threadType']) {
  251.             $threadData['replyTo'] = $threadData['to'];
  252.         }
  253.         $collaboratorEmails array_merge(!empty($threadData['cccol']) ? $threadData['cccol'] : [], !empty($threadData['cc']) ? $threadData['cc'] : []);
  254.         if (!empty($collaboratorEmails)) {
  255.             $threadData['cc'] = $collaboratorEmails;
  256.         }
  257.    
  258.         $thread = new Thread();
  259.         $thread->setTicket($ticket);
  260.         $thread->setCreatedAt(new \DateTime());
  261.         $thread->setUpdatedAt(new \DateTime());
  262.         if ($threadData['threadType'] != "note") {
  263.             foreach ($threadData as $property => $value) {
  264.                 if (!empty($value)) {
  265.                     $callable 'set' ucwords($property);
  266.                     if (method_exists($thread$callable)) {
  267.                         $thread->$callable($value);
  268.                     }
  269.                 }
  270.             }
  271.         } else {
  272.             $this->setTicketNotePlaceholderValue($thread$threadData$ticket);
  273.         }
  274.         // Update ticket reference ids is thread message id is defined
  275.         if (null != $thread->getMessageId() && false === strpos($ticket->getReferenceIds(), $thread->getMessageId())) {
  276.             $updatedReferenceIds $ticket->getReferenceIds() . ' ' $thread->getMessageId();            
  277.             $ticket->setReferenceIds($updatedReferenceIds);
  278.             $this->entityManager->persist($ticket);
  279.         }
  280.         if ('reply' === $threadData['threadType']) {
  281.             if ('agent' === $threadData['createdBy']) {
  282.                 // Ticket has been updated by support agents, mark as agent replied | customer view pending
  283.                 $ticket->setIsCustomerViewed(false);
  284.                 $ticket->setIsReplied(true);
  285.                 $customerName $ticket->getCustomer()->getFirstName().' '.$ticket->getCustomer()->getLastName();
  286.                 $agentActivity = new AgentActivity();
  287.                 $agentActivity->setThreadType('reply');
  288.                 $agentActivity->setTicket($ticket);
  289.                 $agentActivity->setAgent($thread->getUser());
  290.                 $agentActivity->setCustomerName($customerName);
  291.                 $agentActivity->setAgentName('agent');
  292.                 $agentActivity->setCreatedAt(new \DateTime());
  293.                 $this->entityManager->persist($agentActivity);
  294.             } else {
  295.                 // Ticket has been updated by customer, mark as agent view | reply pending
  296.                 $ticket->setIsAgentViewed(false);
  297.                 $ticket->setIsReplied(false);
  298.             }
  299.             $this->entityManager->persist($ticket);
  300.         } else if ('create' === $threadData['threadType']) {
  301.             $ticket->setIsReplied(false);
  302.             $this->entityManager->persist($ticket);
  303.             $customerName $ticket->getCustomer()->getFirstName().' '.$ticket->getCustomer()->getLastName();
  304.             $agentActivity = new AgentActivity();
  305.             $agentActivity->setThreadType('create');
  306.             $agentActivity->setTicket($ticket);
  307.             $agentActivity->setAgent($thread->getUser());
  308.             $agentActivity->setCustomerName($customerName );
  309.             $agentActivity->setAgentName('agent');
  310.             $agentActivity->setCreatedAt(new \DateTime());
  311.             $this->entityManager->persist($agentActivity);
  312.         }
  313.         
  314.         $ticket->currentThread $this->entityManager->getRepository(Thread::class)->getTicketCurrentThread($ticket);
  315.         
  316.         $this->entityManager->persist($thread);
  317.         $this->entityManager->flush();
  318.         
  319.         $ticket->createdThread $thread;
  320.         // Uploading Attachments
  321.         if (!empty($threadData['attachments'])) {
  322.             if ('email' == $threadData['source']) {
  323.                 $this->saveThreadEmailAttachments($thread$threadData['attachments']);
  324.             } else if (!empty($threadData['attachments'])) {
  325.                 $this->saveThreadAttachment($thread$threadData['attachments']);
  326.             }
  327.         }
  328.         return $thread;
  329.     }
  330.     public function setTicketNotePlaceholderValue($thread$threadData$ticket)
  331.     {
  332.         if (!empty($threadData)) {
  333.             foreach ($threadData as $property => $value) {
  334.                 if (!empty($value)) {
  335.                     $callable 'set' ucwords($property);
  336.                     if (method_exists($thread$callable)) {
  337.                         if($callable != "setMessage") {
  338.                             $thread->$callable($value);
  339.                         } else {
  340.                             $notesPlaceholders $this->getNotePlaceholderValues($ticket'customer');
  341.                             $content $value;
  342.                             foreach ($notesPlaceholders as $key => $val) {
  343.                                 if(strpos($value"{%$key%}") !== false){
  344.                                     $content strtr($value, ["{%$key%}" => $val"{% $key %}" => $val]);
  345.                                 }
  346.                             }
  347.                             
  348.                             $content stripslashes($content);
  349.                             $thread->$callable($content);
  350.                         }
  351.                     }
  352.                 }
  353.             }
  354.         }
  355.     }
  356.     public function saveThreadAttachment($thread, array $attachments)
  357.     {
  358.         $prefix 'threads/' $thread->getId();
  359.         $uploadManager $this->container->get('uvdesk.core.file_system.service')->getUploadManager();
  360.         foreach ($attachments as $attachment) {
  361.             $uploadedFileAttributes $uploadManager->uploadFile($attachment$prefix);
  362.             if (!empty($uploadedFileAttributes['path'])) {
  363.                 ($threadAttachment = new Attachment())
  364.                     ->setThread($thread)
  365.                     ->setName($uploadedFileAttributes['name'])
  366.                     ->setPath($uploadedFileAttributes['path'])
  367.                     ->setSize($uploadedFileAttributes['size'])
  368.                     ->setContentType($uploadedFileAttributes['content-type']);
  369.                 
  370.                 $this->entityManager->persist($threadAttachment);
  371.             }
  372.         }
  373.         $this->entityManager->flush();
  374.     }
  375.     public function saveThreadEmailAttachments($thread, array $attachments)
  376.     {
  377.         $prefix 'threads/' $thread->getId();
  378.         $uploadManager $this->container->get('uvdesk.core.file_system.service')->getUploadManager();
  379.         
  380.         // Upload thread attachments
  381.         foreach ($attachments as $attachment) {
  382.             $uploadedFileAttributes $uploadManager->uploadEmailAttachment($attachment$prefix);
  383.             
  384.             if (!empty($uploadedFileAttributes['path'])) {
  385.                 ($threadAttachment = new Attachment())
  386.                     ->setThread($thread)
  387.                     ->setName($uploadedFileAttributes['name'])
  388.                     ->setPath($uploadedFileAttributes['path'])
  389.                     ->setSize($uploadedFileAttributes['size'])
  390.                     ->setContentType($uploadedFileAttributes['content-type']);
  391.                 
  392.                 $this->entityManager->persist($threadAttachment);
  393.             }
  394.         }
  395.         $this->entityManager->flush();
  396.     }
  397.     public function getTypes()
  398.     {
  399.         static $types;
  400.         if (null !== $types)
  401.             return $types;
  402.         $qb $this->entityManager->createQueryBuilder();
  403.         $qb->select('tp.id','tp.code As name')->from(TicketType::class, 'tp')
  404.                 ->andwhere('tp.isActive = 1')
  405.                 ->orderBy('tp.code''ASC');
  406.         return $types $qb->getQuery()->getArrayResult();
  407.     }
  408.     public function getStatus()
  409.     {
  410.         static $statuses;
  411.         if (null !== $statuses)
  412.             return $statuses;
  413.         $qb $this->entityManager->createQueryBuilder();
  414.         $qb->select('ts')->from(TicketStatus::class, 'ts');
  415.         // $qb->orderBy('ts.sortOrder', Criteria::ASC);
  416.         return $statuses $qb->getQuery()->getArrayResult();
  417.     }
  418.     public function getTicketTotalThreads($ticketId)
  419.     {
  420.         $qb $this->entityManager->createQueryBuilder();
  421.         $qb->select('COUNT(th.id) as threadCount')->from(Ticket::class, 't')
  422.             ->leftJoin('t.threads''th')
  423.             ->andWhere('t.id = :ticketId')
  424.             ->andWhere('th.threadType = :threadType')
  425.             ->setParameter('threadType','reply')
  426.             ->setParameter('ticketId'$ticketId);
  427.         $qb $this->entityManager->createQueryBuilder();
  428.         $qb->select('COUNT(t.id) as threadCount')->from(Thread::class, 't')
  429.             ->andWhere('t.ticket = :ticketId')
  430.             ->andWhere('t.threadType = :threadType')
  431.             ->setParameter('threadType','reply')
  432.             ->setParameter('ticketId'$ticketId);
  433.         return $qb->getQuery()->getSingleScalarResult();
  434.     }
  435.     public function getTicketTags($request null)
  436.     {
  437.         $qb $this->entityManager->createQueryBuilder();
  438.         $qb->select('tg')->from(Tag::class, 'tg');
  439.         if($request) {
  440.             $qb->andwhere("tg.name LIKE :tagName");
  441.             $qb->setParameter('tagName''%'.urldecode($request->query->get('query')).'%');
  442.             $qb->andwhere("tg.id NOT IN (:ids)");
  443.             $qb->setParameter('ids'explode(',',urldecode($request->query->get('not'))));
  444.         }
  445.         return $qb->getQuery()->getArrayResult();
  446.     }
  447.     
  448.     public function paginateMembersTicketCollection(Request $request)
  449.     {
  450.         $params $request->query->all();
  451.         $activeUser $this->container->get('user.service')->getSessionUser();
  452.         $activeUserTimeZone $this->entityManager->getRepository(Website::class)->findOneBy(['code' => 'Knowledgebase']);
  453.         $agentTimeZone = !empty($activeUser->getTimezone()) ? $activeUser->getTimezone() : $activeUserTimeZone->getTimezone();
  454.         $agentTimeFormat = !empty($activeUser->getTimeformat()) ? $activeUser->getTimeformat() : $activeUserTimeZone->getTimeformat();
  455.         $ticketRepository $this->entityManager->getRepository(Ticket::class);
  456.         $website $this->entityManager->getRepository(Website::class)->findOneBy(['code' => 'helpdesk']);
  457.         $timeZone $website->getTimezone();
  458.         $timeFormat $website->getTimeformat();
  459.         $supportGroupReference $this->entityManager->getRepository(User::class)->getUserSupportGroupReferences($activeUser);
  460.         $supportTeamReference  $this->entityManager->getRepository(User::class)->getUserSupportTeamReferences($activeUser);
  461.         // Get base query
  462.         $baseQuery $ticketRepository->prepareBaseTicketQuery($activeUser$supportGroupReference$supportTeamReference$params);
  463.         $ticketTabs $ticketRepository->getTicketTabDetails($activeUser$supportGroupReference$supportTeamReference$params);
  464.         // Apply Pagination
  465.         $pageNumber = !empty($params['page']) ? (int) $params['page'] : 1;
  466.         $itemsLimit = !empty($params['limit']) ? (int) $params['limit'] : $ticketRepository::DEFAULT_PAGINATION_LIMIT;
  467.         if (isset($params['repliesLess']) || isset($params['repliesMore'])) {
  468.             $paginationOptions = ['wrap-queries' => true];
  469.             $paginationQuery $baseQuery->getQuery()
  470.                 ->setHydrationMode(Query::HYDRATE_ARRAY);
  471.         } else {
  472.             $paginationOptions = ['distinct' => true];
  473.             $paginationQuery $baseQuery->getQuery()
  474.                 ->setHydrationMode(Query::HYDRATE_ARRAY)
  475.                 ->setHint('knp_paginator.count', isset($params['status']) ? $ticketTabs[$params['status']] : $ticketTabs[1]);
  476.         }
  477.         $pagination $this->container->get('knp_paginator')->paginate($paginationQuery$pageNumber$itemsLimit$paginationOptions);
  478.         // Process Pagination Response
  479.         $ticketCollection = [];
  480.         $paginationParams $pagination->getParams();
  481.         $paginationData $pagination->getPaginationData();
  482.         $paginationParams['page'] = 'replacePage';
  483.         $paginationData['url'] = '#' $this->container->get('uvdesk.service')->buildPaginationQuery($paginationParams);
  484.         // $container->get('default.service')->buildSessionUrl('ticket',$queryParameters);
  485.         $ticketThreadCountQueryTemplate $this->entityManager->createQueryBuilder()
  486.             ->select('COUNT(thread.id) as threadCount')
  487.             ->from(Ticket::class, 'ticket')
  488.             ->leftJoin('ticket.threads''thread')
  489.             ->where('ticket.id = :ticketId')
  490.             ->andWhere('thread.threadType = :threadType')->setParameter('threadType''reply');
  491.         
  492.         foreach ($pagination->getItems() as $ticketDetails) {
  493.             $ticket array_shift($ticketDetails);
  494.             $ticketThreadCountQuery = clone $ticketThreadCountQueryTemplate;
  495.             $ticketThreadCountQuery->setParameter('ticketId'$ticket['id']);
  496.             $totalTicketReplies = (int) $ticketThreadCountQuery->getQuery()->getSingleScalarResult();
  497.             $ticketHasAttachments false;
  498.             $dbTime $ticket['createdAt'];
  499.             
  500.             $formattedTime$this->fomatTimeByPreference($dbTime,$timeZone,$timeFormat,$agentTimeZone,$agentTimeFormat);
  501.             $currentDateTime  = new \DateTime('now');
  502.             if($this->getLastReply($ticket['id'])) {
  503.                 $lastRepliedTime 
  504.                 $this->time2string($currentDateTime->getTimeStamp() - $this->getLastReply($ticket['id'])['createdAt']->getTimeStamp());
  505.             } else {
  506.                 $lastRepliedTime 
  507.                 $this->time2string($currentDateTime->getTimeStamp() - $ticket['createdAt']->getTimeStamp());
  508.             }
  509.             $ticketResponse = [
  510.                 'id' => $ticket['id'],
  511.                 'subject' => $ticket['subject'],
  512.                 'isStarred' => $ticket['isStarred'],
  513.                 'isAgentView' => $ticket['isAgentViewed'],
  514.                 'isAgentCustomViewed' => $ticket['isAgentCustomViewed'],
  515.                 'isTrashed' => $ticket['isTrashed'],
  516.                 'source' => $ticket['source'],
  517.                 'group' => $ticketDetails['groupName'],
  518.                 'team' => $ticketDetails['teamName'],
  519.                 'priority' => $ticket['priority'],
  520.                 'type' => $ticketDetails['typeName'],
  521.                 'timestamp' => $formattedTime['dateTimeZone'],
  522.                 'formatedCreatedAt' => $formattedTime['dateTimeZone']->format($formattedTime['timeFormatString']),
  523.                 'totalThreads' => $totalTicketReplies,
  524.                 'agent' => null,
  525.                 'customer' => null,
  526.                 'hasAttachments' => $ticketHasAttachments,
  527.                 'lastReplyTime' => $lastRepliedTime
  528.             ];
  529.            
  530.             if (!empty($ticketDetails['agentId'])) {
  531.                 $ticketResponse['agent'] = [
  532.                     'id' => $ticketDetails['agentId'],
  533.                     'name' => $ticketDetails['agentName'],
  534.                     'smallThumbnail' => $ticketDetails['smallThumbnail'],
  535.                 ];
  536.             }
  537.             if (!empty($ticketDetails['customerId'])) {
  538.                 $ticketResponse['customer'] = [
  539.                     'id' => $ticketDetails['customerId'],
  540.                     'name' => $ticketDetails['customerName'],
  541.                     'email' => $ticketDetails['customerEmail'],
  542.                     'smallThumbnail' => $ticketDetails['customersmallThumbnail'],
  543.                 ];
  544.             }
  545.             array_push($ticketCollection$ticketResponse);
  546.         }
  547.          
  548.         return [
  549.             'tickets' => $ticketCollection,
  550.             'pagination' => $paginationData,
  551.             'tabs' => $ticketTabs,
  552.             'labels' => [
  553.                 'predefind' => $this->getPredefindLabelDetails($activeUser$supportGroupReference$supportTeamReference$params),
  554.                 'custom' => $this->getCustomLabelDetails($this->container),
  555.             ],
  556.           
  557.         ];
  558.     }
  559.     // Convert Timestamp to day/hour/min
  560.     Public function time2string($time) {
  561.         $d floor($time/86400);
  562.         $_d = ($d 10 '0' '').$d;
  563.         $h floor(($time-$d*86400)/3600);
  564.         $_h = ($h 10 '0' '').$h;
  565.         $m floor(($time-($d*86400+$h*3600))/60);
  566.         $_m = ($m 10 '0' '').$m;
  567.         $s $time-($d*86400+$h*3600+$m*60);
  568.         $_s = ($s 10 '0' '').$s;
  569.         $time_str "0 minutes";
  570.         if($_d != 00)
  571.             $time_str $_d." ".'days';
  572.         elseif($_h != 00)
  573.             $time_str $_h." ".'hours';
  574.         elseif($_m != 00)
  575.             $time_str $_m." ".'minutes';
  576.         return $time_str." "."ago";
  577.     }
  578.     public function getPredefindLabelDetails(User $currentUser, array $supportGroupIds = [], array $supportTeamIds = [], array $params = [])
  579.     {
  580.         $data = array();
  581.         $queryBuilder $this->entityManager->createQueryBuilder();
  582.         $ticketRepository $this->entityManager->getRepository(Ticket::class);
  583.         $queryBuilder->select('COUNT(DISTINCT ticket.id) as ticketCount')->from(Ticket::class, 'ticket');
  584.             
  585.         // // applyFilter according to permission
  586.         $queryBuilder->where('ticket.isTrashed != 1');
  587.         $userInstance $currentUser->getAgentInstance();
  588.         if (!empty($userInstance) &&  'ROLE_AGENT' == $userInstance->getSupportRole()->getCode() 
  589.         && $userInstance->getTicketAccesslevel() != 1) {
  590.             $supportGroupIds implode(','$supportGroupIds);
  591.             $supportTeamIds implode(','$supportTeamIds);
  592.             if ($userInstance->getTicketAccesslevel() == 4) {
  593.                 $queryBuilder->andwhere('ticket.agent = ' $currentUser->getId());
  594.             } elseif ($userInstance->getTicketAccesslevel() == 2) {
  595.                 $query '';
  596.                 if ($supportGroupIds){
  597.                     $query .= ' OR supportGroup.id IN('.$supportGroupIds.') ';
  598.                 }
  599.                 if ($supportTeamIds) {
  600.                     $query .= ' OR supportTeam.id IN('.$supportTeamIds.') ';
  601.                 }
  602.                 $queryBuilder->leftJoin('ticket.supportGroup''supportGroup')
  603.                             ->leftJoin('ticket.supportTeam''supportTeam')
  604.                             ->andwhere('( ticket.agent = ' $currentUser->getId().$query.')');
  605.                     
  606.             } elseif ($userInstance->getTicketAccesslevel() == 3) {
  607.                 $query '';
  608.                 if ($supportTeamIds) {
  609.                     $query .= ' OR supportTeam.id IN('.$supportTeamIds.') ';
  610.                 }
  611.                 $queryBuilder->leftJoin('ticket.supportGroup''supportGroup')
  612.                             ->leftJoin('ticket.supportTeam''supportTeam')
  613.                             ->andwhere('( ticket.agent = ' $currentUser->getId().$query')');
  614.             }
  615.         }
  616.         // for all tickets count
  617.         $data['all'] = $queryBuilder->getQuery()->getSingleScalarResult();
  618.         // for new tickets count
  619.         $newQb = clone $queryBuilder;
  620.         $newQb->andwhere('ticket.isNew = 1');
  621.         $data['new'] = $newQb->getQuery()->getSingleScalarResult();
  622.         // for unassigned tickets count
  623.         $unassignedQb = clone $queryBuilder;
  624.         $unassignedQb->andwhere("ticket.agent is NULL");
  625.         $data['unassigned'] = $unassignedQb->getQuery()->getSingleScalarResult();
  626.         // for unanswered ticket count
  627.         $unansweredQb = clone $queryBuilder;
  628.         $unansweredQb->andwhere('ticket.isReplied = 0');
  629.         $data['notreplied'] = $unansweredQb->getQuery()->getSingleScalarResult();
  630.         // for my tickets count
  631.         $mineQb = clone $queryBuilder;
  632.         $mineQb->andWhere("ticket.agent = :agentId")
  633.                 ->setParameter('agentId'$currentUser->getId());
  634.         $data['mine'] = $mineQb->getQuery()->getSingleScalarResult();
  635.         // for starred tickets count
  636.         $starredQb = clone $queryBuilder;
  637.         $starredQb->andwhere('ticket.isStarred = 1');
  638.         $data['starred'] = $starredQb->getQuery()->getSingleScalarResult();
  639.         // for trashed tickets count
  640.         $trashedQb = clone $queryBuilder;
  641.         $trashedQb->where('ticket.isTrashed = 1');
  642.         if ($currentUser->getRoles()[0] != 'ROLE_SUPER_ADMIN' && $userInstance->getTicketAccesslevel() != 1) {
  643.             $trashedQb->andwhere('ticket.agent = ' $currentUser->getId());
  644.         }
  645.         $data['trashed'] = $trashedQb->getQuery()->getSingleScalarResult();
  646.         return $data;
  647.     }
  648.     
  649.     public function paginateMembersTicketThreadCollection(Ticket $ticketRequest $request)
  650.     {
  651.         $params $request->query->all();
  652.         $entityManager $this->entityManager;
  653.         $activeUser $this->container->get('user.service')->getSessionUser();
  654.         $activeUserTimeZone $this->entityManager->getRepository(Website::class)->findOneBy(['code' => 'Knowledgebase']);
  655.         $agentTimeZone = !empty($activeUser->getTimezone()) ? $activeUser->getTimezone() : $activeUserTimeZone->getTimezone();
  656.         $agentTimeFormat = !empty($activeUser->getTimeformat()) ? $activeUser->getTimeformat() : $activeUserTimeZone->getTimeformat();
  657.         
  658.         $threadRepository $entityManager->getRepository(Thread::class);
  659.         $uvdeskFileSystemService $this->container->get('uvdesk.core.file_system.service');
  660.         // Get base query
  661.         $enableLockedThreads $this->container->get('user.service')->isAccessAuthorized('ROLE_AGENT_MANAGE_LOCK_AND_UNLOCK_THREAD');
  662.         $baseQuery $threadRepository->prepareBasePaginationRecentThreadsQuery($ticket$params$enableLockedThreads);
  663.         
  664.         // Apply Pagination
  665.         $paginationItemsQuery = clone $baseQuery;
  666.         $totalPaginationItems $paginationItemsQuery->select('COUNT(DISTINCT thread.id)')->getQuery()->getSingleScalarResult();
  667.         
  668.         $pageNumber = !empty($params['page']) ? (int) $params['page'] : 1;
  669.         $itemsLimit = !empty($params['limit']) ? (int) $params['limit'] : $threadRepository::DEFAULT_PAGINATION_LIMIT;
  670.         
  671.         $paginationOptions = ['distinct' => true];
  672.         $paginationQuery $baseQuery->getQuery()->setHydrationMode(Query::HYDRATE_ARRAY)->setHint('knp_paginator.count', (int) $totalPaginationItems);
  673.         $pagination $this->container->get('knp_paginator')->paginate($paginationQuery$pageNumber$itemsLimit$paginationOptions);
  674.         // Process Pagination Response
  675.         $threadCollection = [];
  676.         $paginationParams $pagination->getParams();
  677.         $paginationData $pagination->getPaginationData();
  678.         $website $this->entityManager->getRepository(Website::class)->findOneBy(['code' => 'helpdesk']);
  679.         $timeZone $website->getTimezone();
  680.         $timeFormat $website->getTimeformat();
  681.         if (!empty($params['threadRequestedId'])) {
  682.             $requestedThreadCollection $baseQuery
  683.                 ->andWhere('thread.id >= :threadRequestedId')->setParameter('threadRequestedId', (int) $params['threadRequestedId'])
  684.                 ->getQuery()->getArrayResult();
  685.             
  686.             $totalRequestedThreads count($requestedThreadCollection);
  687.             $paginationData['current'] = ceil($totalRequestedThreads $threadRepository::DEFAULT_PAGINATION_LIMIT);
  688.             if ($paginationData['current'] > 1) {
  689.                 $paginationData['firstItemNumber'] = 1;
  690.                 $paginationData['lastItemNumber'] = $totalRequestedThreads;
  691.                 $paginationData['next'] = ceil(($totalRequestedThreads 1) / $threadRepository::DEFAULT_PAGINATION_LIMIT);
  692.             }
  693.         }
  694.         $paginationParams['page'] = 'replacePage';
  695.         $paginationData['url'] = '#' $this->container->get('uvdesk.service')->buildPaginationQuery($paginationParams);
  696.         foreach ($pagination->getItems() as $threadDetails) {
  697.             $dbTime $threadDetails['createdAt'];
  698.             $formattedTime $this->fomatTimeByPreference($dbTime,$timeZone,$timeFormat,$agentTimeZone,$agentTimeFormat);
  699.             $threadResponse = [
  700.                 'id' => $threadDetails['id'],
  701.                 'user' => null,
  702.                 'fullname' => null,
  703.                 'reply' => html_entity_decode($threadDetails['message']),
  704.                 'source' => $threadDetails['source'],
  705.                 'threadType' => $threadDetails['threadType'],
  706.                 'userType' => $threadDetails['createdBy'],
  707.                 'timestamp' => $formattedTime['dateTimeZone'],
  708.                 'formatedCreatedAt' => $formattedTime['dateTimeZone']->format($formattedTime['timeFormatString']),
  709.                 'bookmark' => $threadDetails['isBookmarked'],
  710.                 'isLocked' => $threadDetails['isLocked'],
  711.                 'replyTo' => $threadDetails['replyTo'],
  712.                 'cc' => $threadDetails['cc'],
  713.                 'bcc' => $threadDetails['bcc'],
  714.                 'attachments' => $threadDetails['attachments'],
  715.             ];
  716.   
  717.             if (!empty($threadDetails['user'])) {
  718.                 $threadResponse['fullname'] = trim($threadDetails['user']['firstName'] . ' ' $threadDetails['user']['lastName']);
  719.                 $threadResponse['user'] = [
  720.                     'id' => $threadDetails['user']['id'],
  721.                     'smallThumbnail' => $threadDetails['user']['userInstance'][0]['profileImagePath'],
  722.                     'name' => $threadResponse['fullname'],
  723.                 ];
  724.             }
  725.             if (!empty($threadResponse['attachments'])) {
  726.                 $threadResponse['attachments'] = array_map(function ($attachment) use ($entityManager$uvdeskFileSystemService) {
  727.                     $attachmentReferenceObject $entityManager->getReference(Attachment::class, $attachment['id']);
  728.                     return $uvdeskFileSystemService->getFileTypeAssociations($attachmentReferenceObject);
  729.                 }, $threadResponse['attachments']);
  730.             }
  731.             array_push($threadCollection$threadResponse);
  732.         }
  733.         return [
  734.             'threads' => $threadCollection,
  735.             'pagination' => $paginationData,
  736.         ];
  737.     }
  738.     public function massXhrUpdate(Request $request)
  739.     {
  740.         $params $request->request->get('data');
  741.         foreach ($params['ids'] as $ticketId) {
  742.             $ticket $this->entityManager->getRepository(Ticket::class)->find($ticketId);
  743.             if (false == $this->isTicketAccessGranted($ticket)) {
  744.                 throw new \Exception('Access Denied'403);
  745.             }
  746.             
  747.             if (empty($ticket)) {
  748.                 continue;
  749.             }
  750.             switch ($params['actionType']) {
  751.                 case 'trashed':
  752.                     if (false == $ticket->getIsTrashed()) {
  753.                         $ticket->setIsTrashed(true);
  754.                         
  755.                         $this->entityManager->persist($ticket);
  756.                     }
  757.                     // Trigger ticket delete event
  758.                     $event = new CoreWorkflowEvents\Ticket\Delete();
  759.                     $event
  760.                         ->setTicket($ticket)
  761.                     ;
  762.                     $this->container->get('event_dispatcher')->dispatch($event'uvdesk.automation.workflow.execute');
  763.                     break;
  764.                 case 'delete':
  765.                     $threads $ticket->getThreads();
  766.                     $fileService = new Filesystem();
  767.                     if (count($threads) > 0) {
  768.                         foreach($threads as $thread) {
  769.                             if (!empty($thread)) {
  770.                                 $fileService->remove($this->container->getParameter('kernel.project_dir').'/public/assets/threads/'.$thread->getId());
  771.                             }
  772.                         }
  773.                     }
  774.                     $this->entityManager->remove($ticket);
  775.                     
  776.                     break;
  777.                 case 'restored':
  778.                     if (true == $ticket->getIsTrashed()) {
  779.                         $ticket->setIsTrashed(false);
  780.                         $this->entityManager->persist($ticket);
  781.                     }
  782.                     break;
  783.                 case 'agent':
  784.                     if ($ticket->getAgent() == null || $ticket->getAgent() && $ticket->getAgent()->getId() != $params['targetId']) {
  785.                         $agent $this->entityManager->getRepository(User::class)->find($params['targetId']);
  786.                         $ticket->setAgent($agent);
  787.     
  788.                         $this->entityManager->persist($ticket);
  789.     
  790.                         // Trigger Agent Assign event
  791.                         $event = new CoreWorkflowEvents\Ticket\Agent();
  792.                         $event
  793.                             ->setTicket($ticket)
  794.                         ;
  795.     
  796.                         $this->container->get('event_dispatcher')->dispatch($event'uvdesk.automation.workflow.execute');
  797.                     }
  798.                     break;
  799.                 case 'status':
  800.                     if ($ticket->getStatus() == null || $ticket->getStatus() && $ticket->getStatus()->getId() != $params['targetId']) {
  801.                         $status $this->entityManager->getRepository(TicketStatus::class)->findOneById($params['targetId']);
  802.                         $ticket->setStatus($status);
  803.                         $this->entityManager->persist($ticket);
  804.                         // Trigger ticket status event
  805.                         $event = new CoreWorkflowEvents\Ticket\Status();
  806.                         $event
  807.                             ->setTicket($ticket)
  808.                         ;
  809.                         
  810.                         $this->container->get('event_dispatcher')->dispatch($event'uvdesk.automation.workflow.execute');
  811.                     }
  812.                     
  813.                     break;
  814.                 case 'type':
  815.                     if ($ticket->getType() == null || $ticket->getType() && $ticket->getType()->getId() != $params['targetId']) {
  816.                         $type $this->entityManager->getRepository(TicketType::class)->findOneById($params['targetId']);
  817.                         $ticket->setType($type);
  818.     
  819.                         $this->entityManager->persist($ticket);
  820.     
  821.                         // Trigger ticket type event
  822.                         $event = new CoreWorkflowEvents\Ticket\Type();
  823.                         $event
  824.                             ->setTicket($ticket)
  825.                         ;
  826.     
  827.                         $this->container->get('event_dispatcher')->dispatch($event'uvdesk.automation.workflow.execute');
  828.                     }
  829.                     break;
  830.                 case 'group':
  831.                     if ($ticket->getSupportGroup() == null || $ticket->getSupportGroup() && $ticket->getSupportGroup()->getId() != $params['targetId']) {
  832.                         $group $this->entityManager->getRepository(SupportGroup::class)->find($params['targetId']);
  833.                         $ticket->setSupportGroup($group);
  834.     
  835.                         $this->entityManager->persist($ticket);
  836.     
  837.                         // Trigger Support group event
  838.                         $event = new CoreWorkflowEvents\Ticket\Group();
  839.                         $event
  840.                             ->setTicket($ticket)
  841.                         ;
  842.     
  843.                         $this->container->get('event_dispatcher')->dispatch($event'uvdesk.automation.workflow.execute');
  844.                     }
  845.                     break;
  846.                 case 'team':
  847.                     if ($ticket->getSupportTeam() == null || $ticket->getSupportTeam() && $ticket->getSupportTeam()->getId() != $params['targetId']){
  848.                         $team $this->entityManager->getRepository(SupportTeam::class)->find($params['targetId']);
  849.                         $ticket->setSupportTeam($team);
  850.                         
  851.                         $this->entityManager->persist($ticket);
  852.         
  853.                         // Trigger team event
  854.                         $event = new CoreWorkflowEvents\Ticket\Team();
  855.                         $event
  856.                             ->setTicket($ticket)
  857.                         ;
  858.         
  859.                         $this->container->get('event_dispatcher')->dispatch($event'uvdesk.automation.workflow.execute');
  860.                     }
  861.                     break;
  862.                 case 'priority':
  863.                     if ($ticket->getPriority() == null || $ticket->getPriority() && $ticket->getPriority()->getId() != $params['targetId']) {
  864.                         
  865.                         $priority $this->entityManager->getRepository(TicketPriority::class)->find($params['targetId']);
  866.                         $ticket->setPriority($priority);
  867.     
  868.                         $this->entityManager->persist($ticket);
  869.     
  870.                         // Trigger ticket Priority event
  871.                         $event = new CoreWorkflowEvents\Ticket\Priority();
  872.                         $event
  873.                             ->setTicket($ticket)
  874.                         ;
  875.     
  876.                         $this->container->get('event_dispatcher')->dispatch($event'uvdesk.automation.workflow.execute');
  877.                     }
  878.                     break;
  879.                 case 'label':
  880.                     $label $this->entityManager->getRepository(SupportLabel::class)->find($params['targetId']);
  881.                     
  882.                     if ($label && !$this->entityManager->getRepository(Ticket::class)->isLabelAlreadyAdded($ticket$label)) {
  883.                         $ticket->addSupportLabel($label);
  884.                     }
  885.                     
  886.                     $this->entityManager->persist($ticket);
  887.                     break;
  888.                 default:
  889.                     break;
  890.             }
  891.         } 
  892.         $this->entityManager->flush();
  893.         return [
  894.             'alertClass' => 'success',
  895.             'alertMessage' => $this->trans('Tickets have been updated successfully'),
  896.         ];
  897.     }
  898.     
  899.     public function getNotePlaceholderValues($ticket$type "customer")
  900.     {
  901.         $variables = array();
  902.         $variables['ticket.id'] = $ticket->getId();
  903.         $variables['ticket.subject'] = $ticket->getSubject();
  904.         $variables['ticket.status'] = $ticket->getStatus()->getCode();
  905.         $variables['ticket.priority'] = $ticket->getPriority()->getCode();
  906.         if($ticket->getSupportGroup())
  907.             $variables['ticket.group'] = $ticket->getSupportGroup()->getName();
  908.         else
  909.             $variables['ticket.group'] = '';
  910.         $variables['ticket.team'] = ($ticket->getSupportTeam() ? $ticket->getSupportTeam()->getName() : '');
  911.         $customer $this->container->get('user.service')->getCustomerPartialDetailById($ticket->getCustomer()->getId());
  912.         $variables['ticket.customerName'] = $customer['name'];
  913.         $userService $this->container->get('user.service');
  914.       
  915.         $variables['ticket.agentName'] = '';
  916.         $variables['ticket.agentEmail'] = '';
  917.         if ($ticket->getAgent()) {
  918.             $agent $this->container->get('user.service')->getAgentDetailById($ticket->getAgent()->getId());
  919.             if($agent) {
  920.                 $variables['ticket.agentName'] = $agent['name'];
  921.                 $variables['ticket.agentEmail'] = $agent['email'];
  922.             }
  923.         }
  924.         $router $this->container->get('router');
  925.         if ($type == 'customer') {
  926.             $ticketListURL $router->generate('helpdesk_member_ticket_collection', [
  927.                 'id' => $ticket->getId(),
  928.             ], UrlGeneratorInterface::ABSOLUTE_URL);
  929.         } else {
  930.             $ticketListURL $router->generate('helpdesk_customer_ticket_collection', [
  931.                 'id' => $ticket->getId(),
  932.             ], UrlGeneratorInterface::ABSOLUTE_URL);
  933.         }
  934.         $variables['ticket.link'] = sprintf("<a href='%s'>#%s</a>"$ticketListURL$ticket->getId());
  935.         return $variables;
  936.     }
  937.     public function paginateMembersTicketTypeCollection(Request $request)
  938.     {
  939.         // Get base query
  940.         $params $request->query->all();
  941.         $ticketRepository $this->entityManager->getRepository(Ticket::class);
  942.         $paginationQuery $ticketRepository->prepareBasePaginationTicketTypesQuery($params);
  943.         // Apply Pagination
  944.         $paginationOptions = ['distinct' => true];
  945.         $pageNumber = !empty($params['page']) ? (int) $params['page'] : 1;
  946.         $itemsLimit = !empty($params['limit']) ? (int) $params['limit'] : $ticketRepository::DEFAULT_PAGINATION_LIMIT;
  947.         $pagination $this->container->get('knp_paginator')->paginate($paginationQuery$pageNumber$itemsLimit$paginationOptions);
  948.         // Process Pagination Response
  949.         $paginationParams $pagination->getParams();
  950.         $paginationData $pagination->getPaginationData();
  951.         $paginationParams['page'] = 'replacePage';
  952.         $paginationData['url'] = '#' $this->container->get('uvdesk.service')->buildPaginationQuery($paginationParams);
  953.         return [
  954.             'types' => array_map(function ($ticketType) {
  955.                 return [
  956.                     'id' => $ticketType->getId(),
  957.                     'code' => strtoupper($ticketType->getCode()),
  958.                     'description' => $ticketType->getDescription(),
  959.                     'isActive' => $ticketType->getIsActive(),
  960.                 ];
  961.             }, $pagination->getItems()),
  962.             'pagination_data' => $paginationData,
  963.         ];
  964.     }
  965.     public function paginateMembersTagCollection(Request $request)
  966.     {
  967.         // Get base query
  968.         $params $request->query->all();
  969.         $ticketRepository $this->entityManager->getRepository(Ticket::class);
  970.         $baseQuery $ticketRepository->prepareBasePaginationTagsQuery($params);
  971.         // Apply Pagination
  972.         $paginationResultsQuery = clone $baseQuery;
  973.         $paginationResultsQuery->select('COUNT(supportTag.id)');
  974.         $paginationQuery $baseQuery->getQuery()->setHydrationMode(Query::HYDRATE_ARRAY)->setHint('knp_paginator.count'count($paginationResultsQuery->getQuery()->getResult()));
  975.         $paginationOptions = ['distinct' => true];
  976.         $pageNumber = !empty($params['page']) ? (int) $params['page'] : 1;
  977.         $itemsLimit = !empty($params['limit']) ? (int) $params['limit'] : $ticketRepository::DEFAULT_PAGINATION_LIMIT;
  978.         $pagination $this->container->get('knp_paginator')->paginate($paginationQuery$pageNumber$itemsLimit$paginationOptions);
  979.         // Process Pagination Response
  980.         $paginationParams $pagination->getParams();
  981.         $paginationData $pagination->getPaginationData();
  982.         $paginationParams['page'] = 'replacePage';
  983.         $paginationData['url'] = '#' $this->container->get('uvdesk.service')->buildPaginationQuery($paginationParams);
  984.         if (in_array('UVDeskSupportCenterBundle'array_keys($this->container->getParameter('kernel.bundles')))) {
  985.             $articleRepository $this->entityManager->getRepository(Article::class);
  986.             return [
  987.                 'tags' => array_map(function ($supportTag) use ($articleRepository) {
  988.                     return [
  989.                         'id' => $supportTag['id'],
  990.                         'name' => $supportTag['name'],
  991.                         'ticketCount' => $supportTag['totalTickets'],
  992.                         'articleCount' => $articleRepository->getTotalArticlesBySupportTag($supportTag['id']),
  993.                     ];
  994.                 }, $pagination->getItems()),
  995.                 'pagination_data' => $paginationData,
  996.             ];
  997.         } else {
  998.             return [
  999.                 'tags' => array_map(function ($supportTag) {
  1000.                     return [
  1001.                         'id' => $supportTag['id'],
  1002.                         'name' => $supportTag['name'],
  1003.                         'ticketCount' => $supportTag['totalTickets'],
  1004.                     ];
  1005.                 }, $pagination->getItems()),
  1006.                 'pagination_data' => $paginationData,
  1007.             ];
  1008.         }
  1009.     }
  1010.     public function getTicketInitialThreadDetails(Ticket $ticket)
  1011.     {
  1012.         $initialThread $this->entityManager->getRepository(Thread::class)->findOneBy([
  1013.             'ticket' => $ticket,
  1014.             'threadType' => 'create',
  1015.         ]);
  1016.         if (!empty($initialThread)) {
  1017.             $author $initialThread->getUser();
  1018.             $authorInstance 'agent' == $initialThread->getCreatedBy() ? $author->getAgentInstance() : $author->getCustomerInstance();
  1019.         
  1020.             $threadDetails = [
  1021.                 'id' => $initialThread->getId(),
  1022.                 'source' => $initialThread->getSource(),
  1023.                 'messageId' => $initialThread->getMessageId(),
  1024.                 'threadType' => $initialThread->getThreadType(),
  1025.                 'createdBy' => $initialThread->getCreatedBy(),
  1026.                 'message' => html_entity_decode($initialThread->getMessage()),
  1027.                 'attachments' => $initialThread->getAttachments(),
  1028.                 'timestamp' => $initialThread->getCreatedAt()->getTimestamp(),
  1029.                 'createdAt' => $initialThread->getCreatedAt()->format('d-m-Y h:ia'),
  1030.                 'user' => $authorInstance->getPartialDetails(),
  1031.                 'cc' => is_array($initialThread->getCc()) ? implode(', '$initialThread->getCc()) : '',
  1032.             ];
  1033.             $attachments $threadDetails['attachments']->getValues();
  1034.             if (!empty($attachments)) {
  1035.                 $uvdeskFileSystemService $this->container->get('uvdesk.core.file_system.service');
  1036.                 $threadDetails['attachments'] = array_map(function ($attachment) use ($uvdeskFileSystemService) {
  1037.                     return $uvdeskFileSystemService->getFileTypeAssociations($attachment);
  1038.                 }, $attachments);
  1039.             }
  1040.         }
  1041.         return $threadDetails ?? null;
  1042.     }
  1043.     public function getCreateReply($ticketId$firewall 'member')
  1044.     {
  1045.         $qb $this->entityManager->createQueryBuilder();
  1046.         $qb->select("th,a,u.id as userId")->from(Thread::class, 'th')
  1047.                 ->leftJoin('th.ticket','t')
  1048.                 ->leftJoin('th.attachments''a')
  1049.                 ->leftJoin('th.user','u')
  1050.                 ->andWhere('t.id = :ticketId')
  1051.                 ->andWhere('th.threadType = :threadType')
  1052.                 ->setParameter('threadType','create')
  1053.                 ->setParameter('ticketId',$ticketId)
  1054.                 ->orderBy('th.id''DESC')
  1055.                 ->getMaxResults(1);
  1056.         $threadResponse $qb->getQuery()->getArrayResult();
  1057.         if((!empty($threadResponse[0][0]))) {
  1058.             $threadDetails $threadResponse[0][0];
  1059.             $userService $this->container->get('user.service');
  1060.             
  1061.             if ($threadDetails['createdBy'] == 'agent') {
  1062.                 $threadDetails['user'] = $userService->getAgentDetailById($threadResponse[0]['userId']);
  1063.             } else {
  1064.                 $threadDetails['user'] = $userService->getCustomerPartialDetailById($threadResponse[0]['userId']);
  1065.             }
  1066.             
  1067.             $threadDetails['reply'] = html_entity_decode($threadDetails['message']);
  1068.             $threadDetails['formatedCreatedAt'] = $this->timeZoneConverter($threadDetails['createdAt']);    
  1069.             $threadDetails['timestamp'] = $userService->convertToDatetimeTimezoneTimestamp($threadDetails['createdAt']);
  1070.         
  1071.             if (!empty($threadDetails['attachments'])) {
  1072.                 $entityManager $this->entityManager;
  1073.                 $uvdeskFileSystemService $this->container->get('uvdesk.core.file_system.service');
  1074.                 $threadDetails['attachments'] = array_map(function ($attachment) use ($entityManager$uvdeskFileSystemService$firewall) {
  1075.                     $attachmentReferenceObject $entityManager->getReference(Attachment::class, $attachment['id']);
  1076.                     return $uvdeskFileSystemService->getFileTypeAssociations($attachmentReferenceObject$firewall);
  1077.                 }, $threadDetails['attachments']);
  1078.             }
  1079.         }
  1080.         
  1081.         return $threadDetails ?? null;
  1082.     }
  1083.     public function hasAttachments($ticketId) {
  1084.         $qb $this->entityManager->createQueryBuilder();
  1085.         $qb->select("DISTINCT COUNT(a.id) as attachmentCount")->from(Thread::class, 'th')
  1086.                 ->leftJoin('th.ticket','t')
  1087.                 ->leftJoin('th.attachments','a')
  1088.                 ->andWhere('t.id = :ticketId')
  1089.                 ->setParameter('ticketId',$ticketId);
  1090.         return intval($qb->getQuery()->getSingleScalarResult());
  1091.     }
  1092.     public function getAgentDraftReply()
  1093.     {
  1094.         $signature $this->getUser()->getAgentInstance()->getSignature();
  1095.         
  1096.         return str_replace"\n"'<br/>'$signature);
  1097.     }
  1098.     public function trans($text)
  1099.     {
  1100.         return $this->container->get('translator')->trans($text);
  1101.     }
  1102.     public function getAllSources()
  1103.     {
  1104.         $sources = ['email' => 'Email''website' => 'Website'];
  1105.         return $sources;
  1106.     }
  1107.     public function getCustomLabelDetails($container)
  1108.     {
  1109.         $currentUser $container->get('user.service')->getCurrentUser();
  1110.         $qb $this->entityManager->createQueryBuilder();
  1111.         $qb->select('COUNT(DISTINCT t) as ticketCount,sl.id')->from(Ticket::class, 't')
  1112.                 ->leftJoin('t.supportLabels','sl')
  1113.                 ->andwhere('sl.user = :userId')
  1114.                 ->setParameter('userId'$currentUser->getId())
  1115.                 ->groupBy('sl.id');
  1116.         $ticketCountResult $qb->getQuery()->getResult();
  1117.         $data = array();
  1118.         $qb $this->entityManager->createQueryBuilder();
  1119.         $qb->select('sl.id,sl.name,sl.colorCode')->from(SupportLabel::class, 'sl')
  1120.                 ->andwhere('sl.user = :userId')
  1121.                 ->setParameter('userId'$currentUser->getId());
  1122.         $labels $qb->getQuery()->getResult();
  1123.         foreach ($labels as $key => $label) {
  1124.             $labels[$key]['count'] = 0;
  1125.             foreach ($ticketCountResult as $ticketCount) {
  1126.                 if(($label['id'] == $ticketCount['id']))
  1127.                     $labels[$key]['count'] = $ticketCount['ticketCount'] ?: 0;
  1128.             }
  1129.         }
  1130.         return $labels;
  1131.     }
  1132.     public function getLabels($request null)
  1133.     {
  1134.         static $labels;
  1135.         if (null !== $labels)
  1136.             return $labels;
  1137.         $qb $this->entityManager->createQueryBuilder();
  1138.         $qb->select('sl')->from(SupportLabel::class, 'sl')
  1139.             ->andwhere('sl.user = :userId')
  1140.             ->setParameter('userId'$this->getUser()->getId());
  1141.         if($request) {
  1142.             $qb->andwhere("sl.name LIKE :labelName");
  1143.             $qb->setParameter('labelName''%'.urldecode($request->query->get('query')).'%');
  1144.         }
  1145.         return $labels $qb->getQuery()->getArrayResult();
  1146.     }
  1147.     public function getTicketCollaborators($ticketId)
  1148.     {
  1149.         $qb $this->entityManager->createQueryBuilder();
  1150.         $qb->select("DISTINCT c.id, c.email, CONCAT(c.firstName,' ', c.lastName) AS name, userInstance.profileImagePath, userInstance.profileImagePath as smallThumbnail")->from(Ticket::class, 't')
  1151.                 ->leftJoin('t.collaborators''c')
  1152.                 ->leftJoin('c.userInstance''userInstance')
  1153.                 ->andwhere('t.id = :ticketId')
  1154.                 ->andwhere('userInstance.supportRole = :roles')
  1155.                 ->setParameter('ticketId'$ticketId)
  1156.                 ->setParameter('roles'4)
  1157.                 ->orderBy('name','ASC');
  1158.         return $qb->getQuery()->getArrayResult();
  1159.     }
  1160.     public function getTicketTagsById($ticketId)
  1161.     {
  1162.         $qb $this->entityManager->createQueryBuilder();
  1163.         $qb->select('tg')->from(Tag::class, 'tg')
  1164.                 ->leftJoin('tg.tickets' ,'t')
  1165.                 ->andwhere('t.id = :ticketId')
  1166.                 ->setParameter('ticketId'$ticketId);
  1167.         return $qb->getQuery()->getArrayResult();
  1168.     }
  1169.     public function getTicketLabels($ticketId)
  1170.     {
  1171.         $qb $this->entityManager->createQueryBuilder();
  1172.         $qb->select('DISTINCT sl.id,sl.name,sl.colorCode')->from(Ticket::class, 't')
  1173.                 ->leftJoin('t.supportLabels','sl')
  1174.                 ->leftJoin('sl.user','slu')
  1175.                 ->andWhere('slu.id = :userId')
  1176.                 ->andWhere('t.id = :ticketId')
  1177.                 ->setParameter('userId'$this->getUser()->getId())
  1178.                 ->setParameter('ticketId'$ticketId);
  1179.         $result $qb->getQuery()->getResult();
  1180.         
  1181.         return $result $result : [];
  1182.     }
  1183.     public function getUserLabels()
  1184.     {
  1185.         $qb $this->entityManager->createQueryBuilder();
  1186.         $qb->select('sl')->from(SupportLabel::class, 'sl')
  1187.                 ->leftJoin('sl.user','slu')
  1188.                 ->andWhere('slu.id = :userId')
  1189.                 ->setParameter('userId'$this->getUser()->getId());
  1190.         $result $qb->getQuery()->getResult();
  1191.         
  1192.         return $result $result : [];
  1193.     }
  1194.     public function getTicketLabelsAll($ticketId)
  1195.     {
  1196.         $qb $this->entityManager->createQueryBuilder();
  1197.         $qb->select('DISTINCT sl.id,sl.name,sl.colorCode')->from(Ticket::class, 't')
  1198.                 ->leftJoin('t.supportLabels','sl')
  1199.                 ->andWhere('t.id = :ticketId')
  1200.                 ->setParameter('ticketId'$ticketId);
  1201.         $result $qb->getQuery()->getResult();
  1202.         
  1203.         return $result $result : [];
  1204.     }
  1205.     public function getManualWorkflow()
  1206.     {
  1207.         $preparedResponseIds = [];
  1208.         $groupIds = [];
  1209.         $teamIds = []; 
  1210.         $userId $this->container->get('user.service')->getCurrentUser()->getAgentInstance()->getId();
  1211.         $preparedResponseRepo $this->entityManager->getRepository(PreparedResponses::class)->findAll();
  1212.         foreach ($preparedResponseRepo as $pr) {
  1213.             if ($userId == $pr->getUser()->getId()) {
  1214.                 //Save the ids of the saved reply.
  1215.                 array_push($preparedResponseIds, (int)$pr->getId());
  1216.             }
  1217.         }
  1218.         // Get the ids of the Group(s) the current user is associated with.
  1219.         $query "select * from uv_user_support_groups where userInstanceId =".$userId;
  1220.         $connection $this->entityManager->getConnection();
  1221.         $stmt $connection->prepare($query);
  1222.         $stmt->execute();
  1223.         $result $stmt->fetchAll();
  1224.         foreach ($result as $row) {
  1225.             array_push($groupIds$row['supportGroupId']);
  1226.         }
  1227.         // Get all the saved reply's ids that is associated with the user's group(s).
  1228.         $query "select * from uv_prepared_response_support_groups";
  1229.         $stmt $connection->prepare($query);
  1230.         $stmt->execute();
  1231.         $result $stmt->fetchAll();
  1232.         foreach ($result as $row) {
  1233.             if (in_array($row['group_id'], $groupIds)) {
  1234.                 array_push($preparedResponseIds, (int) $row['savedReply_id']);
  1235.             }
  1236.         }
  1237.         // Get the ids of the Team(s) the current user is associated with.
  1238.         $query "select * from uv_user_support_teams";
  1239.         $connection $this->entityManager->getConnection();
  1240.         $stmt $connection->prepare($query);
  1241.         $stmt->execute();
  1242.         $result $stmt->fetchAll();
  1243.         foreach($result as $row) {
  1244.             if ($row['userInstanceId'] == $userId) {
  1245.                 array_push($teamIds$row['supportTeamId']);
  1246.             }
  1247.         }
  1248.         $query "select * from uv_prepared_response_support_teams";
  1249.         $stmt $connection->prepare($query);
  1250.         $stmt->execute();
  1251.         $result $stmt->fetchAll();
  1252.         foreach ($result as $row) {
  1253.             if (in_array($row['subgroup_id'], $teamIds)) {
  1254.                 array_push($preparedResponseIds, (int)$row['savedReply_id']);
  1255.             }
  1256.         }
  1257.         $qb $this->entityManager->createQueryBuilder();
  1258.         $qb->select('DISTINCT mw')
  1259.             ->from(PreparedResponses::class, 'mw')
  1260.             ->where('mw.status = 1')
  1261.             ->andWhere('mw.id IN (:ids)')
  1262.             ->setParameter('ids'$preparedResponseIds);
  1263.         
  1264.         return $qb->getQuery()->getResult();
  1265.     }
  1266.     public function getSavedReplies()
  1267.     {   
  1268.         $savedReplyIds = [];
  1269.         $groupIds = [];
  1270.         $teamIds = []; 
  1271.         $userId $this->container->get('user.service')->getCurrentUser()->getAgentInstance()->getId();
  1272.         $savedReplyRepo $this->entityManager->getRepository(SavedReplies::class)->findAll();
  1273.         foreach ($savedReplyRepo as $sr) {
  1274.             if ($userId == $sr->getUser()->getId()) {
  1275.                 //Save the ids of the saved reply.
  1276.                 array_push($savedReplyIds, (int)$sr->getId());
  1277.             }
  1278.         }
  1279.         // Get the ids of the Group(s) the current user is associated with.
  1280.         $query "select * from uv_user_support_groups where userInstanceId =".$userId;
  1281.         $connection $this->entityManager->getConnection();
  1282.         $stmt $connection->prepare($query);
  1283.         $stmt->execute();
  1284.         $result $stmt->fetchAll();
  1285.         foreach ($result as $row) {
  1286.             array_push($groupIds$row['supportGroupId']);
  1287.         }
  1288.         // Get all the saved reply's ids that is associated with the user's group(s).
  1289.         $query "select * from uv_saved_replies_groups";
  1290.         $stmt $connection->prepare($query);
  1291.         $stmt->execute();
  1292.         $result $stmt->fetchAll();
  1293.         foreach ($result as $row) {
  1294.             if (in_array($row['group_id'], $groupIds)) {
  1295.                 array_push($savedReplyIds, (int) $row['savedReply_id']);
  1296.             }
  1297.         }
  1298.         // Get the ids of the Team(s) the current user is associated with.
  1299.         $query "select * from uv_user_support_teams";
  1300.         $connection $this->entityManager->getConnection();
  1301.         $stmt $connection->prepare($query);
  1302.         $stmt->execute();
  1303.         $result $stmt->fetchAll();
  1304.         foreach($result as $row) {
  1305.             if ($row['userInstanceId'] == $userId) {
  1306.                 array_push($teamIds$row['supportTeamId']);
  1307.             }
  1308.         }
  1309.         $query "select * from uv_saved_replies_teams";
  1310.         $stmt $connection->prepare($query);
  1311.         $stmt->execute();
  1312.         $result $stmt->fetchAll();
  1313.         foreach ($result as $row) {
  1314.             if (in_array($row['subgroup_id'], $teamIds)) {
  1315.                 array_push($savedReplyIds, (int)$row['savedReply_id']);
  1316.             }
  1317.         }
  1318.         $qb $this->entityManager->createQueryBuilder();
  1319.         $qb->select('DISTINCT sr')
  1320.         ->from(SavedReplies::class, 'sr')
  1321.         ->Where('sr.id IN (:ids)')
  1322.         ->setParameter('ids'$savedReplyIds);
  1323.         
  1324.         return $qb->getQuery()->getResult();
  1325.     }
  1326.     public function getPriorities()
  1327.     {
  1328.         static $priorities;
  1329.         if (null !== $priorities)
  1330.             return $priorities;
  1331.         $qb $this->entityManager->createQueryBuilder();
  1332.         $qb->select('tp')->from(TicketPriority::class, 'tp');
  1333.         return $priorities $qb->getQuery()->getArrayResult();
  1334.     }
  1335.     public function getTicketLastThread($ticketId)
  1336.     {
  1337.         $qb $this->entityManager->createQueryBuilder();
  1338.         $qb->select("th")->from(Thread::class, 'th')
  1339.                 ->leftJoin('th.ticket','t')
  1340.                 ->andWhere('t.id = :ticketId')
  1341.                 ->setParameter('ticketId',$ticketId)
  1342.                 ->orderBy('th.id''DESC');
  1343.         return $qb->getQuery()->setMaxResults(1)->getSingleResult();
  1344.     }
  1345.     public function getlastReplyAgentName($ticketId)
  1346.     {
  1347.         $qb $this->entityManager->createQueryBuilder();
  1348.         $qb->select("u.id,CONCAT(u.firstName,' ', u.lastName) AS name,u.firstName")->from(Thread::class, 'th')
  1349.                 ->leftJoin('th.ticket','t')
  1350.                 ->leftJoin('th.user''u')
  1351.                 ->leftJoin('u.userInstance''userInstance')
  1352.                 ->andwhere('userInstance.supportRole != :roles')
  1353.                 ->andWhere('t.id = :ticketId')
  1354.                 ->andWhere('th.threadType = :threadType')
  1355.                 ->setParameter('threadType','reply')
  1356.                 ->andWhere('th.createdBy = :createdBy')
  1357.                 ->setParameter('createdBy','agent')
  1358.                 ->setParameter('ticketId',$ticketId)
  1359.                 ->setParameter('roles'4)
  1360.                 ->orderBy('th.id''DESC');
  1361.         $result $qb->getQuery()->setMaxResults(1)->getResult();
  1362.         return $result $result[0] : null;
  1363.     }
  1364.     public function getLastReply($ticketId$userType null
  1365.     {
  1366.         $queryBuilder $this->entityManager->createQueryBuilder();
  1367.         $queryBuilder->select("th, a, u.id as userId")
  1368.             ->from(Thread::class, 'th')
  1369.             ->leftJoin('th.ticket','t')
  1370.             ->leftJoin('th.attachments''a')
  1371.             ->leftJoin('th.user','u')
  1372.             ->andWhere('t.id = :ticketId')
  1373.             ->andWhere('th.threadType = :threadType')
  1374.             ->setParameter('threadType','reply')
  1375.             ->setParameter('ticketId',$ticketId)
  1376.             ->orderBy('th.id''DESC')
  1377.             ->getMaxResults(1);
  1378.         if (!empty($userType)) {
  1379.             $queryBuilder->andWhere('th.createdBy = :createdBy')->setParameter('createdBy'$userType);
  1380.         }
  1381.         
  1382.         $threadResponse $queryBuilder->getQuery()->getArrayResult();
  1383.         
  1384.         if (!empty($threadResponse[0][0])) {
  1385.             $threadDetails $threadResponse[0][0];
  1386.             $userService $this->container->get('user.service');
  1387.             
  1388.             if ($threadDetails['createdBy'] == 'agent') {
  1389.                 $threadDetails['user'] = $userService->getAgentDetailById($threadResponse[0]['userId']);
  1390.             } else {
  1391.                 $threadDetails['user'] = $userService->getCustomerPartialDetailById($threadResponse[0]['userId']);
  1392.             }
  1393.             
  1394.             $threadDetails['reply'] = html_entity_decode($threadDetails['message']);
  1395.             $threadDetails['formatedCreatedAt'] = $this->timeZoneConverter($threadDetails['createdAt']);
  1396.             $threadDetails['timestamp'] = $userService->convertToDatetimeTimezoneTimestamp($threadDetails['createdAt']);
  1397.             if (!empty($threadDetails['attachments'])) {
  1398.                 $entityManager $this->entityManager;
  1399.                 $uvdeskFileSystemService $this->container->get('uvdesk.core.file_system.service');
  1400.                 $threadDetails['attachments'] = array_map(function ($attachment) use ($entityManager$uvdeskFileSystemService) {
  1401.                     $attachmentReferenceObject $this->entityManager->getReference(Attachment::class, $attachment['id']);
  1402.                     return $uvdeskFileSystemService->getFileTypeAssociations($attachmentReferenceObject);
  1403.                 }, $threadDetails['attachments']);
  1404.             }
  1405.         }
  1406.         return $threadDetails ?? null;
  1407.     }
  1408.     public function getSavedReplyContent($savedReplyId$ticketId)
  1409.     {
  1410.         $ticket $this->entityManager->getRepository(Ticket::class)->find($ticketId);
  1411.         $savedReply $this->entityManager->getRepository(SavedReplies::class)->findOneById($savedReplyId);
  1412.         $emailPlaceholders $this->getSavedReplyPlaceholderValues($ticket'customer');
  1413.         return $this->container->get('email.service')->processEmailContent($savedReply->getMessage(), $emailPlaceholderstrue);
  1414.     }
  1415.     public function getSavedReplyPlaceholderValues($ticket$type "customer")
  1416.     {
  1417.         $variables = array();
  1418.         $variables['ticket.id'] = $ticket->getId();
  1419.         $variables['ticket.subject'] = $ticket->getSubject();
  1420.         $variables['ticket.status'] = $ticket->getStatus()->getCode();
  1421.         $variables['ticket.priority'] = $ticket->getPriority()->getCode();
  1422.         if($ticket->getSupportGroup())
  1423.             $variables['ticket.group'] = $ticket->getSupportGroup()->getName();
  1424.         else
  1425.             $variables['ticket.group'] = '';
  1426.         $variables['ticket.team'] = ($ticket->getSupportTeam() ? $ticket->getSupportTeam()->getName() : '');
  1427.         $customer $this->container->get('user.service')->getCustomerPartialDetailById($ticket->getCustomer()->getId());
  1428.         $variables['ticket.customerName'] = $customer['name'];
  1429.         $variables['ticket.customerEmail'] = $customer['email'];
  1430.         $userService $this->container->get('user.service');
  1431.       
  1432.         $variables['ticket.agentName'] = '';
  1433.         $variables['ticket.agentEmail'] = '';
  1434.         if ($ticket->getAgent()) {
  1435.             $agent $this->container->get('user.service')->getAgentDetailById($ticket->getAgent()->getId());
  1436.             if($agent) {
  1437.                 $variables['ticket.agentName'] = $agent['name'];
  1438.                 $variables['ticket.agentEmail'] = $agent['email'];
  1439.             }
  1440.         }
  1441.         
  1442.         $router $this->container->get('router');
  1443.         if ($type == 'customer') {
  1444.             $ticketListURL $router->generate('helpdesk_customer_ticket_collection', [
  1445.                 'id' => $ticket->getId(),
  1446.             ], UrlGeneratorInterface::ABSOLUTE_URL);
  1447.         } else {
  1448.             $ticketListURL $router->generate('helpdesk_member_ticket_collection', [
  1449.                 'id' => $ticket->getId(),
  1450.             ], UrlGeneratorInterface::ABSOLUTE_URL);
  1451.         }
  1452.         $variables['ticket.link'] = sprintf("<a href='%s'>#%s</a>"$ticketListURL$ticket->getId());
  1453.         return $variables;
  1454.     }
  1455.     public function isEmailBlocked($email$website
  1456.     {
  1457.         $flag false;
  1458.         $email strtolower($email);
  1459.         $knowlegeBaseWebsite $this->entityManager->getRepository(KnowledgebaseWebsite::class)->findOneBy(['website' => $website->getId(), 'isActive' => 1]);
  1460.         $list $this->container->get('user.service')->getWebsiteSpamDetails($knowlegeBaseWebsite);
  1461.         // Blacklist
  1462.         if (!empty($list['blackList']['email']) && in_array($email$list['blackList']['email'])) {
  1463.             // Emails
  1464.             $flag true;
  1465.         } elseif (!empty($list['blackList']['domain'])) {
  1466.             // Domains
  1467.             foreach ($list['blackList']['domain'] as $domain) {
  1468.                 if (strpos($email$domain)) {
  1469.                     $flag true;
  1470.                     break;
  1471.                 }
  1472.             }
  1473.         }
  1474.         // Whitelist
  1475.         if ($flag) {
  1476.             if (isset($email$list['whiteList']['email']) && in_array($email$list['whiteList']['email'])) {
  1477.                 // Emails
  1478.                 return false;
  1479.             } elseif (isset($list['whiteList']['domain'])) {
  1480.                 // Domains
  1481.                 foreach ($list['whiteList']['domain'] as $domain) {
  1482.                     if (strpos($email$domain)) {
  1483.                         $flag false;
  1484.                     }
  1485.                 }
  1486.             }
  1487.         }
  1488.         return $flag;
  1489.     }
  1490.     public function timeZoneConverter($dateFlag)
  1491.     {
  1492.         $website $this->entityManager->getRepository(Website::class)->findOneBy(['code' => 'Knowledgebase']);
  1493.         $timeZone $website->getTimezone();
  1494.         $timeFormat $website->getTimeformat();
  1495.         $activeUser $this->container->get('user.service')->getSessionUser();
  1496.         $agentTimeZone = !empty($activeUser) ? $activeUser->getTimezone() : null;
  1497.         $agentTimeFormat = !empty($activeUser) ? $activeUser->getTimeformat() : null;
  1498.         $parameterType gettype($dateFlag);
  1499.         if($parameterType == 'string'){
  1500.             if(is_null($agentTimeZone) && is_null($agentTimeFormat)){
  1501.                 if(is_null($timeZone) && is_null($timeFormat)){
  1502.                     $datePattern date_create($dateFlag);
  1503.                     return date_format($datePattern,'d-m-Y h:ia');
  1504.                 } else {
  1505.                     $dateFlag = new \DateTime($dateFlag);
  1506.                     $datePattern $dateFlag->setTimezone(new \DateTimeZone($timeZone));
  1507.                     return date_format($datePattern$timeFormat);
  1508.                 }
  1509.             } else {
  1510.                 $dateFlag = new \DateTime($dateFlag);
  1511.                 $datePattern $dateFlag->setTimezone(new \DateTimeZone($agentTimeZone));
  1512.                 return date_format($datePattern$agentTimeFormat);
  1513.             }          
  1514.         } else {
  1515.             if(is_null($agentTimeZone) && is_null($agentTimeFormat)){
  1516.                 if(is_null($timeZone) && is_null($timeFormat)){
  1517.                     return date_format($dateFlag,'d-m-Y h:ia');
  1518.                 } else {
  1519.                     $datePattern $dateFlag->setTimezone(new \DateTimeZone($timeZone));
  1520.                     return date_format($datePattern$timeFormat);
  1521.                 }
  1522.             } else {
  1523.                 $datePattern $dateFlag->setTimezone(new \DateTimeZone($agentTimeZone));
  1524.                 return date_format($datePattern$agentTimeFormat);
  1525.             }    
  1526.         }         
  1527.     }
  1528.     public function fomatTimeByPreference($dbTime,$timeZone,$timeFormat,$agentTimeZone,$agentTimeFormat)
  1529.     {
  1530.         if(is_null($agentTimeZone) && is_null($agentTimeFormat)) {
  1531.             if(is_null($timeZone) && is_null($timeFormat)){
  1532.                 $dateTimeZone $dbTime;
  1533.                 $timeFormatString 'd-m-Y h:ia';
  1534.             } else {
  1535.                 $dateTimeZone $dbTime->setTimezone(new \DateTimeZone($timeZone));
  1536.                 $timeFormatString $timeFormat;
  1537.             }
  1538.         } else {
  1539.             $dateTimeZone $dbTime->setTimezone(new \DateTimeZone($agentTimeZone));
  1540.             $timeFormatString $agentTimeFormat;
  1541.         }
  1542.         $time['dateTimeZone'] = $dateTimeZone;
  1543.         $time['timeFormatString'] = $timeFormatString;
  1544.         return $time;
  1545.     }
  1546.     
  1547.     public function isTicketAccessGranted(Ticket $ticketUser $user null$firewall 'members')
  1548.     {
  1549.         // @TODO: Take current firewall into consideration (access check on behalf of agent/customer)
  1550.         if (empty($user)) {
  1551.             $user $this->container->get('user.service')->getSessionUser();
  1552.         }
  1553.         if (empty($user)) {
  1554.             return false;
  1555.         } else {
  1556.             $agentInstance $user->getAgentInstance();
  1557.     
  1558.             if (empty($agentInstance)) {
  1559.                 return false;
  1560.             }
  1561.         }
  1562.         if ($agentInstance->getSupportRole()->getId() == && in_array($agentInstance->getTicketAccessLevel(), [234])) {
  1563.             $accessLevel $agentInstance->getTicketAccessLevel();
  1564.             // Check if user has been given inidividual access
  1565.             if ($ticket->getAgent() != null && $ticket->getAgent()->getId() == $user->getId()) {
  1566.                 return true;
  1567.             }
  1568.             
  1569.             if ($accessLevel == || $accessLevel == 3) {
  1570.                 // Check if user belongs to a support team assigned to ticket
  1571.                 $teamReferenceIds array_map(function ($team) { return $team->getId(); }, $agentInstance->getSupportTeams()->toArray());
  1572.                 
  1573.                 if ($ticket->getSupportTeam() != null && in_array($ticket->getSupportTeam()->getId(), $teamReferenceIds)) {
  1574.                     return true;
  1575.                 } else if ($accessLevel == 2) {
  1576.                     // Check if user belongs to a support group assigned to ticket
  1577.                     $groupReferenceIds array_map(function ($group) { return $group->getId(); }, $agentInstance->getSupportGroups()->toArray());
  1578.                     if ($ticket->getSupportGroup() != null && in_array($ticket->getSupportGroup()->getId(), $groupReferenceIds)) {
  1579.                         return true;
  1580.                     }
  1581.                 }
  1582.             }
  1583.             return false;
  1584.         }
  1585.         return true;
  1586.     }
  1587.     public function addTicketCustomFields($thread$submittedCustomFields = [], $uploadedFilesCollection = [])
  1588.     {
  1589.         $customFieldsService null;
  1590.         $customFieldsEntityReference null;
  1591.         
  1592.         if ($this->userService->isfileExists('apps/uvdesk/custom-fields')) {
  1593.             $customFieldsService $this->container->get('uvdesk_package_custom_fields.service');
  1594.             $customFieldsEntityReference UVDeskCommunityPackages\CustomFields\Entity\CustomFields::class;
  1595.             $customFieldValuesEntityReference UVDeskCommunityPackages\CustomFields\Entity\CustomFieldsValues::class;
  1596.             $ticketCustomFieldValuesEntityReference UVDeskCommunityPackages\CustomFields\Entity\TicketCustomFieldsValues::class;
  1597.         } else if ($this->userService->isfileExists('apps/uvdesk/form-component')) {
  1598.             $customFieldsService $this->container->get('uvdesk_package_form_component.service');
  1599.             $customFieldsEntityReference UVDeskCommunityPackages\FormComponent\Entity\CustomFields::class;
  1600.             $customFieldValuesEntityReference UVDeskCommunityPackages\FormComponent\Entity\CustomFieldsValues::class;
  1601.             $ticketCustomFieldValuesEntityReference UVDeskCommunityPackages\FormComponent\Entity\TicketCustomFieldsValues::class;
  1602.         } else {
  1603.             return;
  1604.         }
  1605.         $ticket $thread->getTicket();
  1606.         $customFieldsCollection $this->entityManager->getRepository($customFieldsEntityReference)->findAll();
  1607.         $customFieldValuesEntityRepository $this->entityManager->getRepository($customFieldValuesEntityReference);
  1608.         foreach ($customFieldsCollection as $customFields) {
  1609.             if (in_array($customFields->getFieldType(), ['select''checkbox''radio']) && !count($customFields->getCustomFieldValues())) {
  1610.                 continue;
  1611.             }
  1612.             
  1613.             if (
  1614.                 !empty($submittedCustomFields
  1615.                 && $customFields->getFieldType() != 'file' 
  1616.                 && isset($submittedCustomFields[$customFields->getId()])
  1617.             ) {
  1618.                 // Check if custom field dependency criterias are fullfilled
  1619.                 if (
  1620.                     count($customFields->getCustomFieldsDependency()) 
  1621.                     && !in_array($ticket->getType(), $customFields->getCustomFieldsDependency()->toArray())
  1622.                 ) {
  1623.                     continue;
  1624.                 }
  1625.                 // Save ticket custom fields
  1626.                 $ticketCustomField = new $ticketCustomFieldValuesEntityReference();
  1627.                 $ticketCustomField
  1628.                     ->setTicket($ticket)
  1629.                     ->setTicketCustomFieldsValues($customFields)
  1630.                     ->setValue(json_encode($submittedCustomFields[$customFields->getId()]))
  1631.                 ;
  1632.                 if (in_array($customFields->getFieldType(), ['select''checkbox''radio'])) {
  1633.                     // Add custom field values mapping too
  1634.                     if (is_array($submittedCustomFields[$customFields->getId()])) {
  1635.                         foreach ($submittedCustomFields[$customFields->getId()] as $value) {
  1636.                             $ticketCustomFieldValues $customFieldValuesEntityRepository->findOneBy([
  1637.                                 'id' => $value
  1638.                                 'customFields' => $customFields
  1639.                             ]);
  1640.                             if (!empty($ticketCustomFieldValues)) {
  1641.                                 $ticketCustomField
  1642.                                     ->setTicketCustomFieldValueValues($ticketCustomFieldValues)
  1643.                                 ;
  1644.                             }
  1645.                         }
  1646.                     } else {
  1647.                         $ticketCustomFieldValues $customFieldValuesEntityRepository->findOneBy([
  1648.                             'id' => $submittedCustomFields[$customFields->getId()], 
  1649.                             'customFields' => $customFields
  1650.                         ]);
  1651.                         if (!empty($ticketCustomFieldValues)) {
  1652.                             $ticketCustomField
  1653.                                 ->setTicketCustomFieldValueValues($ticketCustomFieldValues)
  1654.                             ;
  1655.                         }
  1656.                     }
  1657.                 }
  1658.                 $this->entityManager->persist($ticketCustomField);
  1659.                 $this->entityManager->flush();
  1660.             } else if (
  1661.                 !empty($uploadedFilesCollection
  1662.                 && isset($uploadedFilesCollection[$customFields->getId()]) 
  1663.             ) {
  1664.                 // Upload files
  1665.                 $path '/custom-fields/ticket/' $ticket->getId() . '/';
  1666.                 $fileNames $this->fileUploadService->uploadFile($uploadedFilesCollection[$customFields->getid()], $pathtrue);
  1667.                 if (!empty($fileNames)) {
  1668.                     // Save files entry to attachment table
  1669.                     try {
  1670.                         $newFilesNames $customFieldsService->addFilesEntryToAttachmentTable([$fileNames], $thread);
  1671.                         foreach ($newFilesNames as $value) {
  1672.                             // Save ticket custom fields
  1673.                             $ticketCustomField = new $ticketCustomFieldValuesEntityReference();
  1674.                             $ticketCustomField
  1675.                                 ->setTicket($ticket)
  1676.                                 ->setTicketCustomFieldsValues($customFields)
  1677.                                 ->setValue(json_encode([
  1678.                                     'name' => $value['name'], 
  1679.                                     'path' => $value['path'], 
  1680.                                     'id' => $value['id'], 
  1681.                                 ]))
  1682.                             ;
  1683.                             $this->entityManager->persist($ticketCustomField);
  1684.                             $this->entityManager->flush();
  1685.                         }
  1686.                     } catch (\Exception $e) {
  1687.                         // @TODO: Log execption message
  1688.                     }
  1689.                 }
  1690.             }
  1691.         }
  1692.     }
  1693.     // return attachemnt for initial thread
  1694.     public function getInitialThread($ticketId)
  1695.     {
  1696.         $firstThread null;
  1697.         $intialThread $this->entityManager->getRepository(Thread::class)->findBy(['ticket'=>$ticketId]);
  1698.         
  1699.         foreach ($intialThread as $key => $value) {
  1700.             if ($value->getThreadType() == "create"){
  1701.                 $firstThread $value;
  1702.             }
  1703.         }
  1704.         return $firstThread;
  1705.     }
  1706.     
  1707.     public function sendFembuddyNotification($ticketId$threadId$ticket_type)
  1708.     {
  1709.         $curl_handle curl_init();
  1710.         $url "https://gutandhealth.com/api/sendUVSupportNotification/";
  1711.         curl_setopt($curl_handleCURLOPT_URL$url);
  1712.         curl_setopt($curl_handleCURLOPT_POST1);
  1713.         curl_setopt($curl_handleCURLOPT_POSTFIELDS,
  1714.             "ticketId=$ticketId&threadId=$threadId&ticket_type=$ticket_type");
  1715.         curl_setopt($curl_handleCURLOPT_RETURNTRANSFERtrue);
  1716.         
  1717.         $curl_data curl_exec($curl_handle);
  1718.         curl_close($curl_handle);
  1719.         
  1720.         return true;
  1721.     }
  1722.     
  1723.     
  1724. }