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

Open in your IDE?
  1. <?php
  2. namespace Webkul\UVDesk\CoreFrameworkBundle\Services;
  3. use Doctrine\ORM\EntityManagerInterface;
  4. use Doctrine\ORM\Query;
  5. use Symfony\Component\DependencyInjection\ContainerInterface;
  6. use Symfony\Component\Filesystem\Filesystem;
  7. use Symfony\Component\HttpFoundation\Request;
  8. use Symfony\Component\HttpFoundation\Response;
  9. use Symfony\Component\HttpFoundation\RequestStack;
  10. use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
  11. use Symfony\Component\Yaml\Yaml;
  12. use UVDesk\CommunityPackages\UVDesk\FormComponent\Entity;
  13. use UVDesk\CommunityPackages\UVDesk\FormComponent\Entity as CommunityPackageEntities;
  14. use Webkul\UVDesk\AutomationBundle\Entity\PreparedResponses;
  15. use Webkul\UVDesk\CoreFrameworkBundle\Entity\User;
  16. use Webkul\UVDesk\CoreFrameworkBundle\Entity\UserInstance;
  17. use Webkul\UVDesk\CoreFrameworkBundle\Entity\AgentActivity;
  18. use Webkul\UVDesk\CoreFrameworkBundle\Entity\Ticket;
  19. use Webkul\UVDesk\CoreFrameworkBundle\Entity\Thread;
  20. use Webkul\UVDesk\CoreFrameworkBundle\Entity\Tag;
  21. use Webkul\UVDesk\CoreFrameworkBundle\Entity\TicketType;
  22. use Webkul\UVDesk\CoreFrameworkBundle\Entity\TicketStatus;
  23. use Webkul\UVDesk\CoreFrameworkBundle\Entity\TicketPriority;
  24. use Webkul\UVDesk\CoreFrameworkBundle\Entity\SupportRole;
  25. use Webkul\UVDesk\CoreFrameworkBundle\Entity\Website;
  26. use Webkul\UVDesk\CoreFrameworkBundle\Entity\SupportGroup;
  27. use Webkul\UVDesk\CoreFrameworkBundle\Entity\SupportTeam;
  28. use Webkul\UVDesk\CoreFrameworkBundle\Entity\SupportLabel;
  29. use Webkul\UVDesk\CoreFrameworkBundle\Entity\SavedReplies;
  30. use Webkul\UVDesk\CoreFrameworkBundle\Entity\Attachment;
  31. use Webkul\UVDesk\CoreFrameworkBundle\Utils\TokenGenerator;
  32. use Webkul\UVDesk\CoreFrameworkBundle\Workflow\Events as CoreWorkflowEvents;
  33. use Webkul\UVDesk\CoreFrameworkBundle\Services\FileUploadService;
  34. use Webkul\UVDesk\CoreFrameworkBundle\Services\UserService;
  35. use Webkul\UVDesk\MailboxBundle\Utils\Mailbox\Mailbox;
  36. use Webkul\UVDesk\MailboxBundle\Utils\MailboxConfiguration;
  37. use Webkul\UVDesk\MailboxBundle\Utils\IMAP\Configuration as ImapConfiguration;
  38. use Webkul\UVDesk\SupportCenterBundle\Entity\Article;
  39. use Webkul\UVDesk\SupportCenterBundle\Entity\KnowledgebaseWebsite;
  40. use Webkul\UVDesk\MailboxBundle\Services\MailboxService;
  41. use Symfony\Contracts\Translation\TranslatorInterface;
  42. use UVDesk\CommunityPackages\UVDesk as UVDeskCommunityPackages;
  43. class TicketService
  44. {
  45. const PATH_TO_CONFIG = '/config/packages/uvdesk_mailbox.yaml';
  46. protected $container;
  47. protected $requestStack;
  48. protected $entityManager;
  49. protected $fileUploadService;
  50. protected $userService;
  51. public function __construct(
  52. ContainerInterface $container,
  53. RequestStack $requestStack,
  54. EntityManagerInterface $entityManager,
  55. FileUploadService $fileUploadService,
  56. UserService $userService,
  57. MailboxService $mailboxService,
  58. TranslatorInterface $translator
  59. ) {
  60. $this->container = $container;
  61. $this->requestStack = $requestStack;
  62. $this->entityManager = $entityManager;
  63. $this->fileUploadService = $fileUploadService;
  64. $this->userService = $userService;
  65. $this->mailboxService = $mailboxService;
  66. $this->translator = $translator;
  67. }
  68. public function getAllMailboxes()
  69. {
  70. $mailboxConfiguration = $this->mailboxService->parseMailboxConfigurations();
  71. $defaultMailbox = $mailboxConfiguration->getDefaultMailbox();
  72. $collection = array_map(function ($mailbox) use ($defaultMailbox) {
  73. return [
  74. 'id' => $mailbox->getId(),
  75. 'name' => $mailbox->getName(),
  76. 'isEnabled' => $mailbox->getIsEnabled(),
  77. 'email' => $mailbox->getImapConfiguration()->getUsername(),
  78. ];
  79. }, array_values($mailboxConfiguration->getMailboxes()));
  80. return ($collection ?? []);
  81. }
  82. public function generateRandomEmailReferenceId()
  83. {
  84. $emailDomain = null;
  85. $mailbox = $this->mailboxService->parseMailboxConfigurations()->getDefaultMailbox();
  86. if (!empty($mailbox)) {
  87. $smtpConfiguration = $mailbox->getSmtpConfiguration();
  88. if (!empty($smtpConfiguration)) {
  89. $emailDomain = substr($smtpConfiguration->getUsername(), strpos($smtpConfiguration->getUsername(), '@'));
  90. }
  91. }
  92. if (!empty($emailDomain)) {
  93. return sprintf("<%s%s>", TokenGenerator::generateToken(20, '0123456789abcdefghijklmnopqrstuvwxyz'), $emailDomain);
  94. }
  95. return null;
  96. }
  97. // @TODO: Refactor this out of this service. Use UserService::getSessionUser() instead.
  98. public function getUser()
  99. {
  100. return $this->container->get('user.service')->getCurrentUser();
  101. }
  102. public function getDefaultType()
  103. {
  104. $typeCode = $this->container->getParameter('uvdesk.default.ticket.type');
  105. $ticketType = $this->entityManager->getRepository(TicketType::class)->findOneByCode($typeCode);
  106. return !empty($ticketType) ? $ticketType : null;
  107. }
  108. public function getDefaultStatus()
  109. {
  110. $statusCode = $this->container->getParameter('uvdesk.default.ticket.status');
  111. $ticketStatus = $this->entityManager->getRepository(TicketStatus::class)->findOneByCode($statusCode);
  112. return !empty($ticketStatus) ? $ticketStatus : null;
  113. }
  114. public function getDefaultPriority()
  115. {
  116. $priorityCode = $this->container->getParameter('uvdesk.default.ticket.priority');
  117. $ticketPriority = $this->entityManager->getRepository(TicketPriority::class)->findOneByCode($priorityCode);
  118. return !empty($ticketPriority) ? $ticketPriority : null;
  119. }
  120. public function appendTwigSnippet($snippet = '')
  121. {
  122. switch ($snippet) {
  123. case 'createMemberTicket':
  124. return $this->getMemberCreateTicketSnippet();
  125. break;
  126. default:
  127. break;
  128. }
  129. return '';
  130. }
  131. public function getMemberCreateTicketSnippet()
  132. {
  133. $twigTemplatingEngine = $this->container->get('twig');
  134. $ticketTypeCollection = $this->entityManager->getRepository(TicketType::class)->findByIsActive(true);
  135. try {
  136. if ($this->userService->isFileExists('apps/uvdesk/custom-fields')) {
  137. $headerCustomFields = $this->container->get('uvdesk_package_custom_fields.service')->getCustomFieldsArray('user');
  138. } else if ($this->userService->isFileExists('apps/uvdesk/form-component')) {
  139. $headerCustomFields = $this->container->get('uvdesk_package_form_component.service')->getCustomFieldsArray('user');
  140. }
  141. } catch (\Exception $e) {
  142. // @TODO: Log exception message
  143. }
  144. return $twigTemplatingEngine->render('@UVDeskCoreFramework/Snippets/createMemberTicket.html.twig', [
  145. 'ticketTypeCollection' => $ticketTypeCollection,
  146. 'headerCustomFields' => $headerCustomFields ?? null,
  147. ]);
  148. }
  149. public function getCustomerCreateTicketCustomFieldSnippet()
  150. {
  151. try {
  152. if ($this->userService->isFileExists('apps/uvdesk/custom-fields')) {
  153. $customFields = $this->container->get('uvdesk_package_custom_fields.service')->getCustomFieldsArray('customer');
  154. } else if ($this->userService->isFileExists('apps/uvdesk/form-component')) {
  155. $customFields = $this->container->get('uvdesk_package_form_component.service')->getCustomFieldsArray('customer');
  156. }
  157. } catch (\Exception $e) {
  158. // @TODO: Log exception message
  159. }
  160. return $customFields ?? null;
  161. }
  162. public function createTicket(array $params = [])
  163. {
  164. $thread = $this->entityManager->getRepository(Thread::class)->findOneByMessageId($params['messageId']);
  165. if (empty($thread)) {
  166. $user = $this->entityManager->getRepository(User::class)->findOneByEmail($params['from']);
  167. if (empty($user) || null == $user->getCustomerInstance()) {
  168. $role = $this->entityManager->getRepository(SupportRole::class)->findOneByCode($params['role']);
  169. if (empty($role)) {
  170. throw new \Exception("The requested role '" . $params['role'] . "' does not exist.");
  171. }
  172. // Create User Instance
  173. $user = $this->container->get('user.service')->createUserInstance($params['from'], $params['name'], $role, [
  174. 'source' => strtolower($params['source']),
  175. 'active' => true,
  176. ]);
  177. }
  178. $params['role'] = 4;
  179. $params['mailboxEmail'] = current($params['replyTo']);
  180. $params['customer'] = $params['user'] = $user;
  181. return $this->createTicketBase($params);
  182. }
  183. return;
  184. }
  185. public function getDemanedFilterOptions($filterType,$ids) {
  186. $qb = $this->entityManager->createQueryBuilder();
  187. switch ($filterType) {
  188. case 'agent':
  189. $qb->select("u.id,u.email,CONCAT(u.firstName,' ', u.lastName) AS name")->from(User::class, 'u')
  190. ->leftJoin(UserInstance::class, 'ud', 'WITH', 'u.id = ud.user')
  191. ->where('ud.supportRole != :roles')
  192. ->andwhere('ud.isActive = 1')
  193. ->andwhere('u.id IN (:ids)')
  194. ->setParameter('roles', 4)
  195. ->setParameter('ids', $ids)
  196. ->orderBy('name','ASC');
  197. return $qb->getQuery()->getArrayResult();
  198. case 'customer':
  199. $qb->select("c.id,c.email,CONCAT(c.firstName,' ', c.lastName) AS name")->from(User::class, 'c')
  200. ->leftJoin(UserInstance::class, 'ud', 'WITH', 'c.id = ud.user')
  201. ->where('ud.supportRole = :roles')
  202. ->andwhere('ud.isActive = 1')
  203. ->andwhere('c.id IN (:ids)')
  204. ->setParameter('roles', 4)
  205. ->setParameter('ids', $ids)
  206. ->orderBy('name','ASC');
  207. return $qb->getQuery()->getArrayResult();
  208. case 'group':
  209. $qb->select("ug.id,ug.description")->from(SupportGroup::class, 'ug')
  210. ->andwhere('ug.isEnabled = 1')
  211. ->andwhere('ug.id IN (:ids)')
  212. ->setParameter('ids', $ids)
  213. ->orderBy('ug.description','ASC');
  214. return $qb->getQuery()->getArrayResult();
  215. case 'team':
  216. $qb->select("usg.id,usg.description")->from(SupportTeam::class, 'usg')
  217. ->andwhere('usg.isActive = 1')
  218. ->andwhere('usg.id IN (:ids)')
  219. ->setParameter('ids', $ids)
  220. ->orderBy('usg.description','ASC');
  221. return $qb->getQuery()->getArrayResult();
  222. case 'tag':
  223. $qb->select("t.id,t.name")->from(Tag::class, 't')
  224. ->andwhere('t.id IN (:ids)')
  225. ->setParameter('ids', $ids)
  226. ->orderBy('t.name','ASC');
  227. return $qb->getQuery()->getArrayResult();
  228. }
  229. }
  230. public function createTicketBase(array $ticketData = [])
  231. {
  232. if ('email' == $ticketData['source']) {
  233. try {
  234. if (array_key_exists('UVDeskMailboxBundle', $this->container->getParameter('kernel.bundles'))) {
  235. $mailbox = $this->mailboxService->getMailboxByEmail($ticketData['mailboxEmail']);
  236. $ticketData['mailboxEmail'] = $mailbox['email'];
  237. }
  238. } catch (\Exception $e) {
  239. // No mailbox found for this email. Skip ticket creation.
  240. return;
  241. }
  242. }
  243. // Set Defaults
  244. $ticketType = !empty($ticketData['type']) ? $ticketData['type'] : $this->getDefaultType();
  245. $ticketStatus = !empty($ticketData['status']) ? $ticketData['status'] : $this->getDefaultStatus();
  246. $ticketPriority = !empty($ticketData['priority']) ? $ticketData['priority'] : $this->getDefaultPriority();
  247. if ('email' == $ticketData['source']) {
  248. $ticketMessageId = !empty($ticketData['messageId']) ? $ticketData['messageId'] : null;
  249. } else {
  250. $ticketMessageId = $this->generateRandomEmailReferenceId();
  251. }
  252. $ticketData['type'] = $ticketType;
  253. $ticketData['status'] = $ticketStatus;
  254. $ticketData['priority'] = $ticketPriority;
  255. $ticketData['messageId'] = $ticketMessageId;
  256. $ticketData['isTrashed'] = false;
  257. $ticket = new Ticket();
  258. foreach ($ticketData as $property => $value) {
  259. $callable = 'set' . ucwords($property);
  260. if (method_exists($ticket, $callable)) {
  261. $ticket->$callable($value);
  262. }
  263. }
  264. $this->entityManager->persist($ticket);
  265. $this->entityManager->flush();
  266. return $this->createThread($ticket, $ticketData);
  267. }
  268. public function createThread(Ticket $ticket, array $threadData)
  269. {
  270. $threadData['isLocked'] = 0;
  271. if ('forward' === $threadData['threadType']) {
  272. $threadData['replyTo'] = $threadData['to'];
  273. }
  274. $collaboratorEmails = [];
  275. // check if $threadData['cc'] is not empty then merge it with $collaboratorEmails
  276. if (! empty($threadData['cc'])) {
  277. if (! is_array($threadData['cc'])) {
  278. $threadData['cc'] = [$threadData['cc']];
  279. }
  280. $collaboratorEmails = array_merge($collaboratorEmails, $threadData['cc']);
  281. }
  282. // check if $threadData['cccol'] is not empty
  283. if (! empty($threadData['cccol'])) {
  284. if (! is_array($threadData['cccol'])) {
  285. $threadData['cccol'] = [$threadData['cccol']];
  286. }
  287. $collaboratorEmails = array_merge($collaboratorEmails, $threadData['cccol']);
  288. }
  289. if (! empty($collaboratorEmails)) {
  290. $threadData['cc'] = $collaboratorEmails;
  291. }
  292. $thread = new Thread();
  293. $thread->setTicket($ticket);
  294. $thread->setCreatedAt(new \DateTime());
  295. $thread->setUpdatedAt(new \DateTime());
  296. if ($threadData['threadType'] != "note") {
  297. foreach ($threadData as $property => $value) {
  298. if (!empty($value)) {
  299. $callable = 'set' . ucwords($property);
  300. if (method_exists($thread, $callable)) {
  301. $thread->$callable($value);
  302. }
  303. }
  304. }
  305. } else {
  306. $this->setTicketNotePlaceholderValue($thread, $threadData, $ticket);
  307. }
  308. // Update ticket reference ids is thread message id is defined
  309. if (null != $thread->getMessageId() && false === strpos($ticket->getReferenceIds(), $thread->getMessageId())) {
  310. $updatedReferenceIds = $ticket->getReferenceIds() . ' ' . $thread->getMessageId();
  311. $ticket->setReferenceIds($updatedReferenceIds);
  312. $this->entityManager->persist($ticket);
  313. }
  314. if ('reply' === $threadData['threadType']) {
  315. if ('agent' === $threadData['createdBy']) {
  316. // Ticket has been updated by support agents, mark as agent replied | customer view pending
  317. $ticket->setIsCustomerViewed(false);
  318. $ticket->setIsReplied(true);
  319. $customerName = $ticket->getCustomer()->getFirstName().' '.$ticket->getCustomer()->getLastName();
  320. $agentActivity = new AgentActivity();
  321. $agentActivity->setThreadType('reply');
  322. $agentActivity->setTicket($ticket);
  323. $agentActivity->setAgent($thread->getUser());
  324. $agentActivity->setCustomerName($customerName);
  325. $agentActivity->setAgentName('agent');
  326. $agentActivity->setCreatedAt(new \DateTime());
  327. $this->entityManager->persist($agentActivity);
  328. } else {
  329. // Ticket has been updated by customer, mark as agent view | reply pending
  330. $ticket->setIsAgentViewed(false);
  331. $ticket->setIsReplied(false);
  332. }
  333. $this->entityManager->persist($ticket);
  334. } else if ('create' === $threadData['threadType']) {
  335. $ticket->setIsReplied(false);
  336. $this->entityManager->persist($ticket);
  337. $customerName = $ticket->getCustomer()->getFirstName().' '.$ticket->getCustomer()->getLastName();
  338. $agentActivity = new AgentActivity();
  339. $agentActivity->setThreadType('create');
  340. $agentActivity->setTicket($ticket);
  341. $agentActivity->setAgent($thread->getUser());
  342. $agentActivity->setCustomerName($customerName );
  343. $agentActivity->setAgentName('agent');
  344. $agentActivity->setCreatedAt(new \DateTime());
  345. $this->entityManager->persist($agentActivity);
  346. }
  347. $ticket->currentThread = $this->entityManager->getRepository(Thread::class)->getTicketCurrentThread($ticket);
  348. $this->entityManager->persist($thread);
  349. $this->entityManager->flush();
  350. $ticket->createdThread = $thread;
  351. // Uploading Attachments.
  352. if (
  353. (isset($threadData['attachments']) && ! empty($threadData['attachments'])) || (isset($threadData['attachmentContent']) && ! empty($threadData['attachmentContent']))
  354. ) {
  355. if ('email' == $threadData['source']) {
  356. // Saving Email attachments in case of outlook with $threadData['attachmentContent']
  357. $this->saveThreadEmailAttachments($thread, $threadData['attachments'], $threadData['attachmentContent'] ?? []);
  358. } else if (!empty($threadData['attachments'])) {
  359. $this->saveThreadAttachment($thread, $threadData['attachments']);
  360. }
  361. }
  362. return $thread;
  363. }
  364. public function setTicketNotePlaceholderValue($thread, $threadData, $ticket)
  365. {
  366. if (!empty($threadData)) {
  367. foreach ($threadData as $property => $value) {
  368. if (!empty($value)) {
  369. $callable = 'set' . ucwords($property);
  370. if (method_exists($thread, $callable)) {
  371. if($callable != "setMessage") {
  372. $thread->$callable($value);
  373. } else {
  374. $notesPlaceholders = $this->getNotePlaceholderValues($ticket, 'customer');
  375. $content = $value;
  376. foreach ($notesPlaceholders as $key => $val) {
  377. if(strpos($value, "{%$key%}") !== false){
  378. $content = strtr($value, ["{%$key%}" => $val, "{% $key %}" => $val]);
  379. }
  380. }
  381. $content = stripslashes($content);
  382. $thread->$callable($content);
  383. }
  384. }
  385. }
  386. }
  387. }
  388. }
  389. public function saveThreadAttachment($thread, array $attachments)
  390. {
  391. $prefix = 'threads/' . $thread->getId();
  392. $uploadManager = $this->container->get('uvdesk.core.file_system.service')->getUploadManager();
  393. foreach ($attachments as $attachment) {
  394. $uploadedFileAttributes = $uploadManager->uploadFile($attachment, $prefix);
  395. if (!empty($uploadedFileAttributes['path'])) {
  396. ($threadAttachment = new Attachment())
  397. ->setThread($thread)
  398. ->setName($uploadedFileAttributes['name'])
  399. ->setPath($uploadedFileAttributes['path'])
  400. ->setSize($uploadedFileAttributes['size'])
  401. ->setContentType($uploadedFileAttributes['content-type']);
  402. $this->entityManager->persist($threadAttachment);
  403. }
  404. }
  405. $this->entityManager->flush();
  406. }
  407. public function saveThreadEmailAttachments($thread, array $attachments, array $attachmentContents)
  408. {
  409. $prefix = 'threads/' . $thread->getId();
  410. $uploadManager = $this->container->get('uvdesk.core.file_system.service')->getUploadManager();
  411. // Upload thread attachments
  412. foreach ($attachments as $attachment) {
  413. $uploadedFileAttributes = $uploadManager->uploadEmailAttachment($attachment, $prefix);
  414. if (!empty($uploadedFileAttributes['path'])) {
  415. ($threadAttachment = new Attachment())
  416. ->setThread($thread)
  417. ->setName($uploadedFileAttributes['name'])
  418. ->setPath($uploadedFileAttributes['path'])
  419. ->setSize($uploadedFileAttributes['size'])
  420. ->setContentType($uploadedFileAttributes['content-type']);
  421. $this->entityManager->persist($threadAttachment);
  422. }
  423. }
  424. // Microsoft 365 Attachments.
  425. $prefixOutlook = 'public/assets/threads/'. $thread->getId(). '/';
  426. foreach ($attachmentContents as $attachmentContent) {
  427. $decodedData = base64_decode(preg_replace('#^data:image/\w+;base64,#i', '', $attachmentContent['content']));
  428. $filePath = $prefixOutlook . $attachmentContent['name'];
  429. if (! is_dir($prefixOutlook)) {
  430. mkdir($prefixOutlook, 0755, true);
  431. }
  432. // Save attachment content to file
  433. if (file_put_contents($filePath, $decodedData) === false) {
  434. error_log("Error: Failed to save attachment to $filePath");
  435. }
  436. if (! empty($filePath)) {
  437. ($threadAttachment = new Attachment())
  438. ->setThread($thread)
  439. ->setName($attachmentContent['name'])
  440. ->setPath(str_replace('public/', '' , $filePath))
  441. ->setSize(23343)
  442. ->setContentType($attachmentContent['mimeType']);
  443. $this->entityManager->persist($threadAttachment);
  444. }
  445. $this->entityManager->flush();
  446. }
  447. }
  448. public function getTypes()
  449. {
  450. static $types;
  451. if (null !== $types)
  452. return $types;
  453. $qb = $this->entityManager->createQueryBuilder();
  454. $qb->select('tp.id','tp.code As name')->from(TicketType::class, 'tp')
  455. ->andWhere('tp.isActive = 1')
  456. ->orderBy('tp.code', 'ASC');
  457. return $types = $qb->getQuery()->getArrayResult();
  458. }
  459. public function getStatus()
  460. {
  461. static $statuses;
  462. if (null !== $statuses)
  463. return $statuses;
  464. $qb = $this->entityManager->createQueryBuilder();
  465. $qb->select('ts')->from(TicketStatus::class, 'ts');
  466. // $qb->orderBy('ts.sortOrder', Criteria::ASC);
  467. return $statuses = $qb->getQuery()->getArrayResult();
  468. }
  469. public function getTicketTotalThreads($ticketId)
  470. {
  471. $qb = $this->entityManager->createQueryBuilder();
  472. $qb->select('COUNT(th.id) as threadCount')->from(Ticket::class, 't')
  473. ->leftJoin('t.threads', 'th')
  474. ->andWhere('t.id = :ticketId')
  475. ->andWhere('th.threadType = :threadType')
  476. ->setParameter('threadType','reply')
  477. ->setParameter('ticketId', $ticketId);
  478. $qb = $this->entityManager->createQueryBuilder();
  479. $qb->select('COUNT(t.id) as threadCount')->from(Thread::class, 't')
  480. ->andWhere('t.ticket = :ticketId')
  481. ->andWhere('t.threadType = :threadType')
  482. ->setParameter('threadType','reply')
  483. ->setParameter('ticketId', $ticketId);
  484. return $qb->getQuery()->getSingleScalarResult();
  485. }
  486. public function getTicketTags($request = null)
  487. {
  488. $qb = $this->entityManager->createQueryBuilder();
  489. $qb->select('tg')->from(Tag::class, 'tg');
  490. if($request) {
  491. $qb->andWhere("tg.name LIKE :tagName");
  492. $qb->setParameter('tagName', '%'.urldecode(trim($request->query->get('query'))).'%');
  493. $qb->andWhere("tg.id NOT IN (:ids)");
  494. $qb->setParameter('ids', explode(',',urldecode($request->query->get('not'))));
  495. }
  496. return $qb->getQuery()->getArrayResult();
  497. }
  498. public function paginateMembersTicketCollection(Request $request)
  499. {
  500. $params = $request->query->all();
  501. $activeUser = $this->container->get('user.service')->getSessionUser();
  502. $activeUserTimeZone = $this->entityManager->getRepository(Website::class)->findOneBy(['code' => 'Knowledgebase']);
  503. $agentTimeZone = !empty($activeUser->getTimezone()) ? $activeUser->getTimezone() : $activeUserTimeZone->getTimezone();
  504. $agentTimeFormat = !empty($activeUser->getTimeformat()) ? $activeUser->getTimeformat() : $activeUserTimeZone->getTimeformat();
  505. $ticketRepository = $this->entityManager->getRepository(Ticket::class);
  506. $website = $this->entityManager->getRepository(Website::class)->findOneBy(['code' => 'helpdesk']);
  507. $timeZone = $website->getTimezone();
  508. $timeFormat = $website->getTimeformat();
  509. $supportGroupReference = $this->entityManager->getRepository(User::class)->getUserSupportGroupReferences($activeUser);
  510. $supportTeamReference = $this->entityManager->getRepository(User::class)->getUserSupportTeamReferences($activeUser);
  511. // Get base query
  512. $baseQuery = $ticketRepository->prepareBaseTicketQuery($activeUser, $supportGroupReference, $supportTeamReference, $params);
  513. $ticketTabs = $ticketRepository->getTicketTabDetails($activeUser, $supportGroupReference, $supportTeamReference, $params);
  514. // Apply Pagination
  515. $pageNumber = !empty($params['page']) ? (int) $params['page'] : 1;
  516. $itemsLimit = !empty($params['limit']) ? (int) $params['limit'] : $ticketRepository::DEFAULT_PAGINATION_LIMIT;
  517. if (isset($params['repliesLess']) || isset($params['repliesMore'])) {
  518. $paginationOptions = ['wrap-queries' => true];
  519. $paginationQuery = $baseQuery->getQuery()
  520. ->setHydrationMode(Query::HYDRATE_ARRAY);
  521. } else {
  522. $paginationOptions = ['distinct' => true];
  523. $paginationQuery = $baseQuery->getQuery()
  524. ->setHydrationMode(Query::HYDRATE_ARRAY)
  525. ->setHint('knp_paginator.count', isset($params['status']) ? $ticketTabs[$params['status']] : $ticketTabs[1]);
  526. }
  527. $pagination = $this->container->get('knp_paginator')->paginate($paginationQuery, $pageNumber, $itemsLimit, $paginationOptions);
  528. // Process Pagination Response
  529. $ticketCollection = [];
  530. $paginationParams = $pagination->getParams();
  531. $paginationData = $pagination->getPaginationData();
  532. $paginationParams['page'] = 'replacePage';
  533. $paginationData['url'] = '#' . $this->container->get('uvdesk.service')->buildPaginationQuery($paginationParams);
  534. // $container->get('default.service')->buildSessionUrl('ticket',$queryParameters);
  535. $ticketThreadCountQueryTemplate = $this->entityManager->createQueryBuilder()
  536. ->select('COUNT(thread.id) as threadCount')
  537. ->from(Ticket::class, 'ticket')
  538. ->leftJoin('ticket.threads', 'thread')
  539. ->where('ticket.id = :ticketId')
  540. ->andWhere('thread.threadType = :threadType')->setParameter('threadType', 'reply');
  541. foreach ($pagination->getItems() as $ticketDetails) {
  542. $ticket = array_shift($ticketDetails);
  543. $ticketThreadCountQuery = clone $ticketThreadCountQueryTemplate;
  544. $ticketThreadCountQuery->setParameter('ticketId', $ticket['id']);
  545. $totalTicketReplies = (int) $ticketThreadCountQuery->getQuery()->getSingleScalarResult();
  546. $ticketHasAttachments = false;
  547. $dbTime = $ticket['createdAt'];
  548. $formattedTime= $this->fomatTimeByPreference($dbTime,$timeZone,$timeFormat,$agentTimeZone,$agentTimeFormat);
  549. $currentDateTime = new \DateTime('now');
  550. if ($this->getLastReply($ticket['id'])) {
  551. $lastRepliedTime =
  552. $this->time2string($currentDateTime->getTimeStamp() - $this->getLastReply($ticket['id'])['createdAt']->getTimeStamp());
  553. } else {
  554. $lastRepliedTime =
  555. $this->time2string($currentDateTime->getTimeStamp() - $ticket['createdAt']->getTimeStamp());
  556. }
  557. $ticketResponse = [
  558. 'id' => $ticket['id'],
  559. 'subject' => $ticket['subject'],
  560. 'isStarred' => $ticket['isStarred'],
  561. 'isAgentView' => $ticket['isAgentViewed'],
  562. 'isTrashed' => $ticket['isTrashed'],
  563. 'source' => $ticket['source'],
  564. 'group' => $ticketDetails['groupName'],
  565. 'team' => $ticketDetails['teamName'],
  566. 'priority' => $ticket['priority'],
  567. 'type' => $ticketDetails['typeName'],
  568. 'timestamp' => $formattedTime['dateTimeZone'],
  569. 'formatedCreatedAt' => $formattedTime['dateTimeZone']->format($formattedTime['timeFormatString']),
  570. 'totalThreads' => $totalTicketReplies,
  571. 'agent' => null,
  572. 'customer' => null,
  573. 'hasAttachments' => $ticketHasAttachments,
  574. 'lastReplyTime' => $lastRepliedTime
  575. ];
  576. if (!empty($ticketDetails['agentId'])) {
  577. $ticketResponse['agent'] = [
  578. 'id' => $ticketDetails['agentId'],
  579. 'name' => $ticketDetails['agentName'],
  580. 'smallThumbnail' => $ticketDetails['smallThumbnail'],
  581. ];
  582. }
  583. if (!empty($ticketDetails['customerId'])) {
  584. $ticketResponse['customer'] = [
  585. 'id' => $ticketDetails['customerId'],
  586. 'name' => $ticketDetails['customerName'],
  587. 'email' => $ticketDetails['customerEmail'],
  588. 'smallThumbnail' => $ticketDetails['customersmallThumbnail'],
  589. ];
  590. }
  591. array_push($ticketCollection, $ticketResponse);
  592. }
  593. return [
  594. 'tickets' => $ticketCollection,
  595. 'pagination' => $paginationData,
  596. 'tabs' => $ticketTabs,
  597. 'labels' => [
  598. 'predefind' => $this->getPredefindLabelDetails($activeUser, $supportGroupReference, $supportTeamReference, $params),
  599. 'custom' => $this->getCustomLabelDetails($this->container),
  600. ],
  601. ];
  602. }
  603. // Convert Timestamp to day/hour/min
  604. Public function time2string($time) {
  605. $d = floor($time/86400);
  606. $_d = ($d < 10 ? '0' : '').$d;
  607. $h = floor(($time-$d*86400)/3600);
  608. $_h = ($h < 10 ? '0' : '').$h;
  609. $m = floor(($time-($d*86400+$h*3600))/60);
  610. $_m = ($m < 10 ? '0' : '').$m;
  611. $s = $time-($d*86400+$h*3600+$m*60);
  612. $_s = ($s < 10 ? '0' : '').$s;
  613. $time_str = "0 minutes";
  614. if ($_d != 00)
  615. $time_str = $_d." ".'days';
  616. elseif ($_h != 00)
  617. $time_str = $_h." ".'hours';
  618. elseif ($_m != 00)
  619. $time_str = $_m." ".'minutes';
  620. return $time_str." "."ago";
  621. }
  622. public function getPredefindLabelDetails(User $currentUser, array $supportGroupIds = [], array $supportTeamIds = [], array $params = [])
  623. {
  624. $data = array();
  625. $queryBuilder = $this->entityManager->createQueryBuilder();
  626. $ticketRepository = $this->entityManager->getRepository(Ticket::class);
  627. $queryBuilder->select('COUNT(DISTINCT ticket.id) as ticketCount')->from(Ticket::class, 'ticket');
  628. // // applyFilter according to permission
  629. $queryBuilder->where('ticket.isTrashed != 1');
  630. $userInstance = $currentUser->getAgentInstance();
  631. if (!empty($userInstance) && 'ROLE_AGENT' == $userInstance->getSupportRole()->getCode()
  632. && $userInstance->getTicketAccesslevel() != 1) {
  633. $supportGroupIds = implode(',', $supportGroupIds);
  634. $supportTeamIds = implode(',', $supportTeamIds);
  635. if ($userInstance->getTicketAccesslevel() == 4) {
  636. $queryBuilder->andWhere('ticket.agent = ' . $currentUser->getId());
  637. } elseif ($userInstance->getTicketAccesslevel() == 2) {
  638. $query = '';
  639. if ($supportGroupIds){
  640. $query .= ' OR supportGroup.id IN('.$supportGroupIds.') ';
  641. }
  642. if ($supportTeamIds) {
  643. $query .= ' OR supportTeam.id IN('.$supportTeamIds.') ';
  644. }
  645. $queryBuilder->leftJoin('ticket.supportGroup', 'supportGroup')
  646. ->leftJoin('ticket.supportTeam', 'supportTeam')
  647. ->andWhere('( ticket.agent = ' . $currentUser->getId().$query.')');
  648. } elseif ($userInstance->getTicketAccesslevel() == 3) {
  649. $query = '';
  650. if ($supportTeamIds) {
  651. $query .= ' OR supportTeam.id IN('.$supportTeamIds.') ';
  652. }
  653. $queryBuilder->leftJoin('ticket.supportGroup', 'supportGroup')
  654. ->leftJoin('ticket.supportTeam', 'supportTeam')
  655. ->andWhere('( ticket.agent = ' . $currentUser->getId().$query. ')');
  656. }
  657. }
  658. // for all tickets count
  659. $data['all'] = $queryBuilder->getQuery()->getSingleScalarResult();
  660. // for new tickets count
  661. $newQb = clone $queryBuilder;
  662. $newQb->andWhere('ticket.isNew = 1');
  663. $data['new'] = $newQb->getQuery()->getSingleScalarResult();
  664. // for unassigned tickets count
  665. $unassignedQb = clone $queryBuilder;
  666. $unassignedQb->andWhere("ticket.agent is NULL");
  667. $data['unassigned'] = $unassignedQb->getQuery()->getSingleScalarResult();
  668. // for unanswered ticket count
  669. $unansweredQb = clone $queryBuilder;
  670. $unansweredQb->andWhere('ticket.isReplied = 0');
  671. $data['notreplied'] = $unansweredQb->getQuery()->getSingleScalarResult();
  672. // for my tickets count
  673. $mineQb = clone $queryBuilder;
  674. $mineQb->andWhere("ticket.agent = :agentId")
  675. ->setParameter('agentId', $currentUser->getId());
  676. $data['mine'] = $mineQb->getQuery()->getSingleScalarResult();
  677. // for starred tickets count
  678. $starredQb = clone $queryBuilder;
  679. $starredQb->andWhere('ticket.isStarred = 1');
  680. $data['starred'] = $starredQb->getQuery()->getSingleScalarResult();
  681. // for trashed tickets count
  682. $trashedQb = clone $queryBuilder;
  683. $trashedQb->where('ticket.isTrashed = 1');
  684. if ($currentUser->getRoles()[0] != 'ROLE_SUPER_ADMIN' && $userInstance->getTicketAccesslevel() != 1) {
  685. $trashedQb->andWhere('ticket.agent = ' . $currentUser->getId());
  686. }
  687. $data['trashed'] = $trashedQb->getQuery()->getSingleScalarResult();
  688. return $data;
  689. }
  690. public function paginateMembersTicketThreadCollection(Ticket $ticket, Request $request)
  691. {
  692. $params = $request->query->all();
  693. $entityManager = $this->entityManager;
  694. $activeUser = $this->container->get('user.service')->getSessionUser();
  695. $activeUserTimeZone = $this->entityManager->getRepository(Website::class)->findOneBy(['code' => 'Knowledgebase']);
  696. $agentTimeZone = !empty($activeUser->getTimezone()) ? $activeUser->getTimezone() : $activeUserTimeZone->getTimezone();
  697. $agentTimeFormat = !empty($activeUser->getTimeformat()) ? $activeUser->getTimeformat() : $activeUserTimeZone->getTimeformat();
  698. $threadRepository = $entityManager->getRepository(Thread::class);
  699. $uvdeskFileSystemService = $this->container->get('uvdesk.core.file_system.service');
  700. // Get base query
  701. $enableLockedThreads = $this->container->get('user.service')->isAccessAuthorized('ROLE_AGENT_MANAGE_LOCK_AND_UNLOCK_THREAD');
  702. $baseQuery = $threadRepository->prepareBasePaginationRecentThreadsQuery($ticket, $params, $enableLockedThreads);
  703. // Apply Pagination
  704. $paginationItemsQuery = clone $baseQuery;
  705. $totalPaginationItems = $paginationItemsQuery->select('COUNT(DISTINCT thread.id)')->getQuery()->getSingleScalarResult();
  706. $pageNumber = !empty($params['page']) ? (int) $params['page'] : 1;
  707. $itemsLimit = !empty($params['limit']) ? (int) $params['limit'] : $threadRepository::DEFAULT_PAGINATION_LIMIT;
  708. $paginationOptions = ['distinct' => true];
  709. $paginationQuery = $baseQuery->getQuery()->setHydrationMode(Query::HYDRATE_ARRAY)->setHint('knp_paginator.count', (int) $totalPaginationItems);
  710. $pagination = $this->container->get('knp_paginator')->paginate($paginationQuery, $pageNumber, $itemsLimit, $paginationOptions);
  711. // Process Pagination Response
  712. $threadCollection = [];
  713. $paginationParams = $pagination->getParams();
  714. $paginationData = $pagination->getPaginationData();
  715. $website = $this->entityManager->getRepository(Website::class)->findOneBy(['code' => 'helpdesk']);
  716. $timeZone = $website->getTimezone();
  717. $timeFormat = $website->getTimeformat();
  718. if (!empty($params['threadRequestedId'])) {
  719. $requestedThreadCollection = $baseQuery
  720. ->andWhere('thread.id >= :threadRequestedId')->setParameter('threadRequestedId', (int) $params['threadRequestedId'])
  721. ->getQuery()->getArrayResult();
  722. $totalRequestedThreads = count($requestedThreadCollection);
  723. $paginationData['current'] = ceil($totalRequestedThreads / $threadRepository::DEFAULT_PAGINATION_LIMIT);
  724. if ($paginationData['current'] > 1) {
  725. $paginationData['firstItemNumber'] = 1;
  726. $paginationData['lastItemNumber'] = $totalRequestedThreads;
  727. $paginationData['next'] = ceil(($totalRequestedThreads + 1) / $threadRepository::DEFAULT_PAGINATION_LIMIT);
  728. }
  729. }
  730. $paginationParams['page'] = 'replacePage';
  731. $paginationData['url'] = '#' . $this->container->get('uvdesk.service')->buildPaginationQuery($paginationParams);
  732. foreach ($pagination->getItems() as $threadDetails) {
  733. $dbTime = $threadDetails['createdAt'];
  734. $formattedTime = $this->fomatTimeByPreference($dbTime,$timeZone,$timeFormat,$agentTimeZone,$agentTimeFormat);
  735. $threadResponse = [
  736. 'id' => $threadDetails['id'],
  737. 'user' => null,
  738. 'fullname' => null,
  739. 'reply' => html_entity_decode($threadDetails['message']),
  740. 'source' => $threadDetails['source'],
  741. 'threadType' => $threadDetails['threadType'],
  742. 'userType' => $threadDetails['createdBy'],
  743. 'timestamp' => $formattedTime['dateTimeZone'],
  744. 'formatedCreatedAt' => $formattedTime['dateTimeZone']->format($formattedTime['timeFormatString']),
  745. 'bookmark' => $threadDetails['isBookmarked'],
  746. 'isLocked' => $threadDetails['isLocked'],
  747. 'replyTo' => $threadDetails['replyTo'],
  748. 'cc' => $threadDetails['cc'],
  749. 'bcc' => $threadDetails['bcc'],
  750. 'attachments' => $threadDetails['attachments'],
  751. ];
  752. if (!empty($threadDetails['user'])) {
  753. $threadResponse['fullname'] = trim($threadDetails['user']['firstName'] . ' ' . $threadDetails['user']['lastName']);
  754. $threadResponse['user'] = [
  755. 'id' => $threadDetails['user']['id'],
  756. 'smallThumbnail' => $threadDetails['user']['userInstance'][0]['profileImagePath'],
  757. 'name' => $threadResponse['fullname'],
  758. ];
  759. }
  760. if (!empty($threadResponse['attachments'])) {
  761. $threadResponse['attachments'] = array_map(function ($attachment) use ($entityManager, $uvdeskFileSystemService) {
  762. $attachmentReferenceObject = $entityManager->getReference(Attachment::class, $attachment['id']);
  763. return $uvdeskFileSystemService->getFileTypeAssociations($attachmentReferenceObject);
  764. }, $threadResponse['attachments']);
  765. }
  766. array_push($threadCollection, $threadResponse);
  767. }
  768. return [
  769. 'threads' => $threadCollection,
  770. 'pagination' => $paginationData,
  771. ];
  772. }
  773. public function massXhrUpdate(Request $request)
  774. {
  775. $params = $request->request->get('data');
  776. foreach ($params['ids'] as $ticketId) {
  777. $ticket = $this->entityManager->getRepository(Ticket::class)->find($ticketId);
  778. if (false == $this->isTicketAccessGranted($ticket)) {
  779. throw new \Exception('Access Denied', 403);
  780. }
  781. if (empty($ticket)) {
  782. continue;
  783. }
  784. switch ($params['actionType']) {
  785. case 'trashed':
  786. if (false == $ticket->getIsTrashed()) {
  787. $ticket->setIsTrashed(true);
  788. $this->entityManager->persist($ticket);
  789. }
  790. // Trigger ticket delete event
  791. $event = new CoreWorkflowEvents\Ticket\Delete();
  792. $event
  793. ->setTicket($ticket)
  794. ;
  795. $this->container->get('event_dispatcher')->dispatch($event, 'uvdesk.automation.workflow.execute');
  796. break;
  797. case 'delete':
  798. $threads = $ticket->getThreads();
  799. $fileService = new Filesystem();
  800. if (count($threads) > 0) {
  801. foreach($threads as $thread) {
  802. if (!empty($thread)) {
  803. $fileService->remove($this->container->getParameter('kernel.project_dir').'/public/assets/threads/'.$thread->getId());
  804. }
  805. }
  806. }
  807. $this->entityManager->remove($ticket);
  808. break;
  809. case 'restored':
  810. if (true == $ticket->getIsTrashed()) {
  811. $ticket->setIsTrashed(false);
  812. $this->entityManager->persist($ticket);
  813. }
  814. break;
  815. case 'agent':
  816. if ($ticket->getAgent() == null || $ticket->getAgent() && $ticket->getAgent()->getId() != $params['targetId']) {
  817. $agent = $this->entityManager->getRepository(User::class)->find($params['targetId']);
  818. $ticket->setAgent($agent);
  819. $this->entityManager->persist($ticket);
  820. // Trigger Agent Assign event
  821. $event = new CoreWorkflowEvents\Ticket\Agent();
  822. $event
  823. ->setTicket($ticket)
  824. ;
  825. $this->container->get('event_dispatcher')->dispatch($event, 'uvdesk.automation.workflow.execute');
  826. }
  827. break;
  828. case 'status':
  829. if ($ticket->getStatus() == null || $ticket->getStatus() && $ticket->getStatus()->getId() != $params['targetId']) {
  830. $status = $this->entityManager->getRepository(TicketStatus::class)->findOneById($params['targetId']);
  831. $ticket->setStatus($status);
  832. $this->entityManager->persist($ticket);
  833. // Trigger ticket status event
  834. $event = new CoreWorkflowEvents\Ticket\Status();
  835. $event
  836. ->setTicket($ticket)
  837. ;
  838. $this->container->get('event_dispatcher')->dispatch($event, 'uvdesk.automation.workflow.execute');
  839. }
  840. break;
  841. case 'type':
  842. if ($ticket->getType() == null || $ticket->getType() && $ticket->getType()->getId() != $params['targetId']) {
  843. $type = $this->entityManager->getRepository(TicketType::class)->findOneById($params['targetId']);
  844. $ticket->setType($type);
  845. $this->entityManager->persist($ticket);
  846. // Trigger ticket type event
  847. $event = new CoreWorkflowEvents\Ticket\Type();
  848. $event
  849. ->setTicket($ticket)
  850. ;
  851. $this->container->get('event_dispatcher')->dispatch($event, 'uvdesk.automation.workflow.execute');
  852. }
  853. break;
  854. case 'group':
  855. if ($ticket->getSupportGroup() == null || $ticket->getSupportGroup() && $ticket->getSupportGroup()->getId() != $params['targetId']) {
  856. $group = $this->entityManager->getRepository(SupportGroup::class)->find($params['targetId']);
  857. $ticket->setSupportGroup($group);
  858. $this->entityManager->persist($ticket);
  859. // Trigger Support group event
  860. $event = new CoreWorkflowEvents\Ticket\Group();
  861. $event
  862. ->setTicket($ticket)
  863. ;
  864. $this->container->get('event_dispatcher')->dispatch($event, 'uvdesk.automation.workflow.execute');
  865. }
  866. break;
  867. case 'team':
  868. if ($ticket->getSupportTeam() == null || $ticket->getSupportTeam() && $ticket->getSupportTeam()->getId() != $params['targetId']){
  869. $team = $this->entityManager->getRepository(SupportTeam::class)->find($params['targetId']);
  870. $ticket->setSupportTeam($team);
  871. $this->entityManager->persist($ticket);
  872. // Trigger team event
  873. $event = new CoreWorkflowEvents\Ticket\Team();
  874. $event
  875. ->setTicket($ticket)
  876. ;
  877. $this->container->get('event_dispatcher')->dispatch($event, 'uvdesk.automation.workflow.execute');
  878. }
  879. break;
  880. case 'priority':
  881. if ($ticket->getPriority() == null || $ticket->getPriority() && $ticket->getPriority()->getId() != $params['targetId']) {
  882. $priority = $this->entityManager->getRepository(TicketPriority::class)->find($params['targetId']);
  883. $ticket->setPriority($priority);
  884. $this->entityManager->persist($ticket);
  885. // Trigger ticket Priority event
  886. $event = new CoreWorkflowEvents\Ticket\Priority();
  887. $event
  888. ->setTicket($ticket)
  889. ;
  890. $this->container->get('event_dispatcher')->dispatch($event, 'uvdesk.automation.workflow.execute');
  891. }
  892. break;
  893. case 'label':
  894. $label = $this->entityManager->getRepository(SupportLabel::class)->find($params['targetId']);
  895. if ($label && !$this->entityManager->getRepository(Ticket::class)->isLabelAlreadyAdded($ticket, $label)) {
  896. $ticket->addSupportLabel($label);
  897. }
  898. $this->entityManager->persist($ticket);
  899. break;
  900. default:
  901. break;
  902. }
  903. }
  904. $this->entityManager->flush();
  905. if ($params['actionType'] == 'trashed') {
  906. $message = 'Success ! Tickets moved to trashed successfully.';
  907. } elseif ($params['actionType'] == 'restored') {
  908. $message = 'Success ! Tickets restored successfully.';
  909. } elseif ($params['actionType'] == 'delete') {
  910. $message = 'Success ! Tickets removed successfully.';
  911. } elseif ($params['actionType'] == 'agent'){
  912. $message = 'Success ! Agent assigned successfully.';
  913. } elseif ($params['actionType'] == 'status'){
  914. $message = 'Success ! Tickets status updated successfully.';
  915. } elseif ($params['actionType'] == 'type'){
  916. $message = 'Success ! Tickets type updated successfully.';
  917. } elseif ($params['actionType'] == 'group'){
  918. $message = 'Success ! Tickets group updated successfully.';
  919. } elseif ($params['actionType'] == 'team') {
  920. $message = 'Success ! Tickets team updated successfully.';
  921. } elseif ($params['actionType'] == 'priority') {
  922. $message = 'Success ! Tickets priority updated successfully.';
  923. } elseif ($params['actionType'] == 'label') {
  924. $message = 'Success ! Tickets added to label successfully.';
  925. } else {
  926. $message = 'Success ! Tickets have been updated successfully';
  927. }
  928. return [
  929. 'alertClass' => 'success',
  930. 'alertMessage' => $this->trans($message),
  931. ];
  932. }
  933. public function getNotePlaceholderValues($ticket, $type = "customer")
  934. {
  935. $variables = array();
  936. $variables['ticket.id'] = $ticket->getId();
  937. $variables['ticket.subject'] = $ticket->getSubject();
  938. $variables['ticket.status'] = $ticket->getStatus()->getCode();
  939. $variables['ticket.priority'] = $ticket->getPriority()->getCode();
  940. if($ticket->getSupportGroup())
  941. $variables['ticket.group'] = $ticket->getSupportGroup()->getName();
  942. else
  943. $variables['ticket.group'] = '';
  944. $variables['ticket.team'] = ($ticket->getSupportTeam() ? $ticket->getSupportTeam()->getName() : '');
  945. $customer = $this->container->get('user.service')->getCustomerPartialDetailById($ticket->getCustomer()->getId());
  946. $variables['ticket.customerName'] = $customer['name'];
  947. $userService = $this->container->get('user.service');
  948. $variables['ticket.agentName'] = '';
  949. $variables['ticket.agentEmail'] = '';
  950. if ($ticket->getAgent()) {
  951. $agent = $this->container->get('user.service')->getAgentDetailById($ticket->getAgent()->getId());
  952. if($agent) {
  953. $variables['ticket.agentName'] = $agent['name'];
  954. $variables['ticket.agentEmail'] = $agent['email'];
  955. }
  956. }
  957. $router = $this->container->get('router');
  958. if ($type == 'customer') {
  959. $ticketListURL = $router->generate('helpdesk_member_ticket_collection', [
  960. 'id' => $ticket->getId(),
  961. ], UrlGeneratorInterface::ABSOLUTE_URL);
  962. } else {
  963. $ticketListURL = $router->generate('helpdesk_customer_ticket_collection', [
  964. 'id' => $ticket->getId(),
  965. ], UrlGeneratorInterface::ABSOLUTE_URL);
  966. }
  967. $variables['ticket.link'] = sprintf("<a href='%s'>#%s</a>", $ticketListURL, $ticket->getId());
  968. return $variables;
  969. }
  970. public function paginateMembersTicketTypeCollection(Request $request)
  971. {
  972. // Get base query
  973. $params = $request->query->all();
  974. $ticketRepository = $this->entityManager->getRepository(Ticket::class);
  975. $paginationQuery = $ticketRepository->prepareBasePaginationTicketTypesQuery($params);
  976. // Apply Pagination
  977. $paginationOptions = ['distinct' => true];
  978. $pageNumber = !empty($params['page']) ? (int) $params['page'] : 1;
  979. $itemsLimit = !empty($params['limit']) ? (int) $params['limit'] : $ticketRepository::DEFAULT_PAGINATION_LIMIT;
  980. $pagination = $this->container->get('knp_paginator')->paginate($paginationQuery, $pageNumber, $itemsLimit, $paginationOptions);
  981. // Process Pagination Response
  982. $paginationParams = $pagination->getParams();
  983. $paginationData = $pagination->getPaginationData();
  984. $paginationParams['page'] = 'replacePage';
  985. $paginationData['url'] = '#' . $this->container->get('uvdesk.service')->buildPaginationQuery($paginationParams);
  986. return [
  987. 'types' => array_map(function ($ticketType) {
  988. return [
  989. 'id' => $ticketType->getId(),
  990. 'code' => strtoupper($ticketType->getCode()),
  991. 'description' => $ticketType->getDescription(),
  992. 'isActive' => $ticketType->getIsActive(),
  993. ];
  994. }, $pagination->getItems()),
  995. 'pagination_data' => $paginationData,
  996. ];
  997. }
  998. public function paginateMembersTagCollection(Request $request)
  999. {
  1000. // Get base query
  1001. $params = $request->query->all();
  1002. $ticketRepository = $this->entityManager->getRepository(Ticket::class);
  1003. $baseQuery = $ticketRepository->prepareBasePaginationTagsQuery($params);
  1004. // Apply Pagination
  1005. $paginationResultsQuery = clone $baseQuery;
  1006. $paginationResultsQuery->select('COUNT(supportTag.id)');
  1007. $paginationQuery = $baseQuery->getQuery()->setHydrationMode(Query::HYDRATE_ARRAY)->setHint('knp_paginator.count', count($paginationResultsQuery->getQuery()->getResult()));
  1008. $paginationOptions = ['distinct' => true];
  1009. $pageNumber = !empty($params['page']) ? (int) $params['page'] : 1;
  1010. $itemsLimit = !empty($params['limit']) ? (int) $params['limit'] : $ticketRepository::DEFAULT_PAGINATION_LIMIT;
  1011. $pagination = $this->container->get('knp_paginator')->paginate($paginationQuery, $pageNumber, $itemsLimit, $paginationOptions);
  1012. // Process Pagination Response
  1013. $paginationParams = $pagination->getParams();
  1014. $paginationData = $pagination->getPaginationData();
  1015. $paginationParams['page'] = 'replacePage';
  1016. $paginationData['url'] = '#' . $this->container->get('uvdesk.service')->buildPaginationQuery($paginationParams);
  1017. if (in_array('UVDeskSupportCenterBundle', array_keys($this->container->getParameter('kernel.bundles')))) {
  1018. $articleRepository = $this->entityManager->getRepository(Article::class);
  1019. return [
  1020. 'tags' => array_map(function ($supportTag) use ($articleRepository) {
  1021. return [
  1022. 'id' => $supportTag['id'],
  1023. 'name' => $supportTag['name'],
  1024. 'ticketCount' => $supportTag['totalTickets'],
  1025. 'articleCount' => $articleRepository->getTotalArticlesBySupportTag($supportTag['id']),
  1026. ];
  1027. }, $pagination->getItems()),
  1028. 'pagination_data' => $paginationData,
  1029. ];
  1030. } else {
  1031. return [
  1032. 'tags' => array_map(function ($supportTag) {
  1033. return [
  1034. 'id' => $supportTag['id'],
  1035. 'name' => $supportTag['name'],
  1036. 'ticketCount' => $supportTag['totalTickets'],
  1037. ];
  1038. }, $pagination->getItems()),
  1039. 'pagination_data' => $paginationData,
  1040. ];
  1041. }
  1042. }
  1043. public function getTicketInitialThreadDetails(Ticket $ticket)
  1044. {
  1045. $initialThread = $this->entityManager->getRepository(Thread::class)->findOneBy([
  1046. 'ticket' => $ticket,
  1047. 'threadType' => 'create',
  1048. ]);
  1049. if (!empty($initialThread)) {
  1050. $author = $initialThread->getUser();
  1051. $authorInstance = 'agent' == $initialThread->getCreatedBy() ? $author->getAgentInstance() : $author->getCustomerInstance();
  1052. $threadDetails = [
  1053. 'id' => $initialThread->getId(),
  1054. 'source' => $initialThread->getSource(),
  1055. 'messageId' => $initialThread->getMessageId(),
  1056. 'threadType' => $initialThread->getThreadType(),
  1057. 'createdBy' => $initialThread->getCreatedBy(),
  1058. 'message' => html_entity_decode($initialThread->getMessage()),
  1059. 'attachments' => $initialThread->getAttachments(),
  1060. 'timestamp' => $initialThread->getCreatedAt()->getTimestamp(),
  1061. 'createdAt' => $initialThread->getCreatedAt()->format('d-m-Y h:ia'),
  1062. 'user' => $authorInstance->getPartialDetails(),
  1063. 'cc' => is_array($initialThread->getCc()) ? implode(', ', $initialThread->getCc()) : '',
  1064. ];
  1065. $attachments = $threadDetails['attachments']->getValues();
  1066. if (!empty($attachments)) {
  1067. $uvdeskFileSystemService = $this->container->get('uvdesk.core.file_system.service');
  1068. $threadDetails['attachments'] = array_map(function ($attachment) use ($uvdeskFileSystemService) {
  1069. return $uvdeskFileSystemService->getFileTypeAssociations($attachment);
  1070. }, $attachments);
  1071. }
  1072. }
  1073. return $threadDetails ?? null;
  1074. }
  1075. public function getCreateReply($ticketId, $firewall = 'member')
  1076. {
  1077. $qb = $this->entityManager->createQueryBuilder();
  1078. $qb->select("th,a,u.id as userId")->from(Thread::class, 'th')
  1079. ->leftJoin('th.ticket','t')
  1080. ->leftJoin('th.attachments', 'a')
  1081. ->leftJoin('th.user','u')
  1082. ->andWhere('t.id = :ticketId')
  1083. ->andWhere('th.threadType = :threadType')
  1084. ->setParameter('threadType','create')
  1085. ->setParameter('ticketId',$ticketId)
  1086. ->orderBy('th.id', 'DESC')
  1087. ->getMaxResults(1);
  1088. $threadResponse = $qb->getQuery()->getArrayResult();
  1089. if ((!empty($threadResponse[0][0]))) {
  1090. $threadDetails = $threadResponse[0][0];
  1091. $userService = $this->container->get('user.service');
  1092. if ($threadDetails['createdBy'] == 'agent') {
  1093. $threadDetails['user'] = $userService->getAgentDetailById($threadResponse[0]['userId']);
  1094. } else {
  1095. $threadDetails['user'] = $userService->getCustomerPartialDetailById($threadResponse[0]['userId']);
  1096. }
  1097. $threadDetails['reply'] = html_entity_decode($threadDetails['message']);
  1098. $threadDetails['formatedCreatedAt'] = $this->timeZoneConverter($threadDetails['createdAt']);
  1099. $threadDetails['timestamp'] = $userService->convertToDatetimeTimezoneTimestamp($threadDetails['createdAt']);
  1100. if (!empty($threadDetails['attachments'])) {
  1101. $entityManager = $this->entityManager;
  1102. $uvdeskFileSystemService = $this->container->get('uvdesk.core.file_system.service');
  1103. $threadDetails['attachments'] = array_map(function ($attachment) use ($entityManager, $uvdeskFileSystemService, $firewall) {
  1104. $attachmentReferenceObject = $entityManager->getReference(Attachment::class, $attachment['id']);
  1105. return $uvdeskFileSystemService->getFileTypeAssociations($attachmentReferenceObject, $firewall);
  1106. }, $threadDetails['attachments']);
  1107. }
  1108. }
  1109. return $threadDetails ?? null;
  1110. }
  1111. public function hasAttachments($ticketId) {
  1112. $qb = $this->entityManager->createQueryBuilder();
  1113. $qb->select("DISTINCT COUNT(a.id) as attachmentCount")->from(Thread::class, 'th')
  1114. ->leftJoin('th.ticket','t')
  1115. ->leftJoin('th.attachments','a')
  1116. ->andWhere('t.id = :ticketId')
  1117. ->setParameter('ticketId',$ticketId);
  1118. return intval($qb->getQuery()->getSingleScalarResult());
  1119. }
  1120. public function getAgentDraftReply()
  1121. {
  1122. $signature = $this->getUser()->getAgentInstance()->getSignature();
  1123. return str_replace( "\n", '<br/>', $signature);
  1124. }
  1125. public function trans($text)
  1126. {
  1127. return $this->container->get('translator')->trans($text);
  1128. }
  1129. public function getAllSources()
  1130. {
  1131. $sources = ['email' => 'Email', 'website' => 'Website'];
  1132. return $sources;
  1133. }
  1134. public function getCustomLabelDetails($container)
  1135. {
  1136. $currentUser = $container->get('user.service')->getCurrentUser();
  1137. $qb = $this->entityManager->createQueryBuilder();
  1138. $qb->select('COUNT(DISTINCT t) as ticketCount,sl.id')->from(Ticket::class, 't')
  1139. ->leftJoin('t.supportLabels','sl')
  1140. ->andWhere('sl.user = :userId')
  1141. ->setParameter('userId', $currentUser->getId())
  1142. ->groupBy('sl.id');
  1143. $ticketCountResult = $qb->getQuery()->getResult();
  1144. $data = array();
  1145. $qb = $this->entityManager->createQueryBuilder();
  1146. $qb->select('sl.id,sl.name,sl.colorCode')->from(SupportLabel::class, 'sl')
  1147. ->andWhere('sl.user = :userId')
  1148. ->setParameter('userId', $currentUser->getId());
  1149. $labels = $qb->getQuery()->getResult();
  1150. foreach ($labels as $key => $label) {
  1151. $labels[$key]['count'] = 0;
  1152. foreach ($ticketCountResult as $ticketCount) {
  1153. if (($label['id'] == $ticketCount['id']))
  1154. $labels[$key]['count'] = $ticketCount['ticketCount'] ?: 0;
  1155. }
  1156. }
  1157. return $labels;
  1158. }
  1159. public function getLabels($request = null)
  1160. {
  1161. static $labels;
  1162. if (null !== $labels)
  1163. return $labels;
  1164. $qb = $this->entityManager->createQueryBuilder();
  1165. $qb->select('sl')->from(SupportLabel::class, 'sl')
  1166. ->andWhere('sl.user = :userId')
  1167. ->setParameter('userId', $this->getUser()->getId());
  1168. if ($request) {
  1169. $qb->andWhere("sl.name LIKE :labelName");
  1170. $qb->setParameter('labelName', '%'.urldecode(trim($request->query->get('query'))).'%');
  1171. }
  1172. return $labels = $qb->getQuery()->getArrayResult();
  1173. }
  1174. public function getTicketCollaborators($ticketId)
  1175. {
  1176. $qb = $this->entityManager->createQueryBuilder();
  1177. $qb->select("DISTINCT c.id, c.email, CONCAT(c.firstName,' ', c.lastName) AS name, userInstance.profileImagePath, userInstance.profileImagePath as smallThumbnail")->from(Ticket::class, 't')
  1178. ->leftJoin('t.collaborators', 'c')
  1179. ->leftJoin('c.userInstance', 'userInstance')
  1180. ->andWhere('t.id = :ticketId')
  1181. ->andWhere('userInstance.supportRole = :roles')
  1182. ->setParameter('ticketId', $ticketId)
  1183. ->setParameter('roles', 4)
  1184. ->orderBy('name','ASC');
  1185. return $qb->getQuery()->getArrayResult();
  1186. }
  1187. public function getTicketTagsById($ticketId)
  1188. {
  1189. $qb = $this->entityManager->createQueryBuilder();
  1190. $qb->select('tg')->from(Tag::class, 'tg')
  1191. ->leftJoin('tg.tickets' ,'t')
  1192. ->andWhere('t.id = :ticketId')
  1193. ->setParameter('ticketId', $ticketId);
  1194. return $qb->getQuery()->getArrayResult();
  1195. }
  1196. public function getTicketLabels($ticketId)
  1197. {
  1198. $qb = $this->entityManager->createQueryBuilder();
  1199. $qb->select('DISTINCT sl.id,sl.name,sl.colorCode')->from(Ticket::class, 't')
  1200. ->leftJoin('t.supportLabels','sl')
  1201. ->leftJoin('sl.user','slu')
  1202. ->andWhere('slu.id = :userId')
  1203. ->andWhere('t.id = :ticketId')
  1204. ->setParameter('userId', $this->getUser()->getId())
  1205. ->setParameter('ticketId', $ticketId);
  1206. $result = $qb->getQuery()->getResult();
  1207. return $result ? $result : [];
  1208. }
  1209. public function getUserLabels()
  1210. {
  1211. $qb = $this->entityManager->createQueryBuilder();
  1212. $qb->select('sl')->from(SupportLabel::class, 'sl')
  1213. ->leftJoin('sl.user','slu')
  1214. ->andWhere('slu.id = :userId')
  1215. ->setParameter('userId', $this->getUser()->getId());
  1216. $result = $qb->getQuery()->getResult();
  1217. return $result ? $result : [];
  1218. }
  1219. public function getTicketLabelsAll($ticketId)
  1220. {
  1221. $qb = $this->entityManager->createQueryBuilder();
  1222. $qb->select('DISTINCT sl.id,sl.name,sl.colorCode')->from(Ticket::class, 't')
  1223. ->leftJoin('t.supportLabels','sl')
  1224. ->andWhere('t.id = :ticketId')
  1225. ->setParameter('ticketId', $ticketId);
  1226. $result = $qb->getQuery()->getResult();
  1227. return $result ? $result : [];
  1228. }
  1229. public function getManualWorkflow()
  1230. {
  1231. $preparedResponseIds = [];
  1232. $groupIds = [];
  1233. $teamIds = [];
  1234. $userId = $this->container->get('user.service')->getCurrentUser()->getAgentInstance()->getId();
  1235. $preparedResponseRepo = $this->entityManager->getRepository(PreparedResponses::class)->findAll();
  1236. foreach ($preparedResponseRepo as $pr) {
  1237. if ($userId == $pr->getUser()->getId()) {
  1238. //Save the ids of the saved reply.
  1239. array_push($preparedResponseIds, (int)$pr->getId());
  1240. }
  1241. }
  1242. // Get the ids of the Group(s) the current user is associated with.
  1243. $query = "select * from uv_user_support_groups where userInstanceId =".$userId;
  1244. $connection = $this->entityManager->getConnection();
  1245. $stmt = $connection->prepare($query);
  1246. $stmt->execute();
  1247. $result = $stmt->fetchAll();
  1248. foreach ($result as $row) {
  1249. array_push($groupIds, $row['supportGroupId']);
  1250. }
  1251. // Get all the saved reply's ids that is associated with the user's group(s).
  1252. $query = "select * from uv_prepared_response_support_groups";
  1253. $stmt = $connection->prepare($query);
  1254. $stmt->execute();
  1255. $result = $stmt->fetchAll();
  1256. foreach ($result as $row) {
  1257. if (in_array($row['group_id'], $groupIds)) {
  1258. array_push($preparedResponseIds, (int) $row['savedReply_id']);
  1259. }
  1260. }
  1261. // Get the ids of the Team(s) the current user is associated with.
  1262. $query = "select * from uv_user_support_teams";
  1263. $connection = $this->entityManager->getConnection();
  1264. $stmt = $connection->prepare($query);
  1265. $stmt->execute();
  1266. $result = $stmt->fetchAll();
  1267. foreach($result as $row) {
  1268. if ($row['userInstanceId'] == $userId) {
  1269. array_push($teamIds, $row['supportTeamId']);
  1270. }
  1271. }
  1272. $query = "select * from uv_prepared_response_support_teams";
  1273. $stmt = $connection->prepare($query);
  1274. $stmt->execute();
  1275. $result = $stmt->fetchAll();
  1276. foreach ($result as $row) {
  1277. if (in_array($row['subgroup_id'], $teamIds)) {
  1278. array_push($preparedResponseIds, (int)$row['savedReply_id']);
  1279. }
  1280. }
  1281. $qb = $this->entityManager->createQueryBuilder();
  1282. $qb->select('DISTINCT mw')
  1283. ->from(PreparedResponses::class, 'mw')
  1284. ->where('mw.status = 1')
  1285. ->andWhere('mw.id IN (:ids)')
  1286. ->setParameter('ids', $preparedResponseIds);
  1287. return $qb->getQuery()->getResult();
  1288. }
  1289. public function getSavedReplies()
  1290. {
  1291. $savedReplyIds = [];
  1292. $groupIds = [];
  1293. $teamIds = [];
  1294. $userId = $this->container->get('user.service')->getCurrentUser()->getAgentInstance()->getId();
  1295. $savedReplyRepo = $this->entityManager->getRepository(SavedReplies::class)->findAll();
  1296. foreach ($savedReplyRepo as $sr) {
  1297. if ($userId == $sr->getUser()->getId()) {
  1298. //Save the ids of the saved reply.
  1299. array_push($savedReplyIds, (int)$sr->getId());
  1300. }
  1301. }
  1302. // Get the ids of the Group(s) the current user is associated with.
  1303. $query = "select * from uv_user_support_groups where userInstanceId =".$userId;
  1304. $connection = $this->entityManager->getConnection();
  1305. $stmt = $connection->prepare($query);
  1306. $stmt->execute();
  1307. $result = $stmt->fetchAll();
  1308. foreach ($result as $row) {
  1309. array_push($groupIds, $row['supportGroupId']);
  1310. }
  1311. // Get all the saved reply's ids that is associated with the user's group(s).
  1312. $query = "select * from uv_saved_replies_groups";
  1313. $stmt = $connection->prepare($query);
  1314. $stmt->execute();
  1315. $result = $stmt->fetchAll();
  1316. foreach ($result as $row) {
  1317. if (in_array($row['group_id'], $groupIds)) {
  1318. array_push($savedReplyIds, (int) $row['savedReply_id']);
  1319. }
  1320. }
  1321. // Get the ids of the Team(s) the current user is associated with.
  1322. $query = "select * from uv_user_support_teams";
  1323. $connection = $this->entityManager->getConnection();
  1324. $stmt = $connection->prepare($query);
  1325. $stmt->execute();
  1326. $result = $stmt->fetchAll();
  1327. foreach ($result as $row) {
  1328. if ($row['userInstanceId'] == $userId) {
  1329. array_push($teamIds, $row['supportTeamId']);
  1330. }
  1331. }
  1332. $query = "select * from uv_saved_replies_teams";
  1333. $stmt = $connection->prepare($query);
  1334. $stmt->execute();
  1335. $result = $stmt->fetchAll();
  1336. foreach ($result as $row) {
  1337. if (in_array($row['subgroup_id'], $teamIds)) {
  1338. array_push($savedReplyIds, (int)$row['savedReply_id']);
  1339. }
  1340. }
  1341. $qb = $this->entityManager->createQueryBuilder();
  1342. $qb->select('DISTINCT sr')
  1343. ->from(SavedReplies::class, 'sr')
  1344. ->Where('sr.id IN (:ids)')
  1345. ->setParameter('ids', $savedReplyIds);
  1346. return $qb->getQuery()->getResult();
  1347. }
  1348. public function getPriorities()
  1349. {
  1350. static $priorities;
  1351. if (null !== $priorities)
  1352. return $priorities;
  1353. $qb = $this->entityManager->createQueryBuilder();
  1354. $qb->select('tp')->from(TicketPriority::class, 'tp');
  1355. return $priorities = $qb->getQuery()->getArrayResult();
  1356. }
  1357. public function getTicketLastThread($ticketId)
  1358. {
  1359. $qb = $this->entityManager->createQueryBuilder();
  1360. $qb->select("th")->from(Thread::class, 'th')
  1361. ->leftJoin('th.ticket','t')
  1362. ->andWhere('t.id = :ticketId')
  1363. ->setParameter('ticketId',$ticketId)
  1364. ->orderBy('th.id', 'DESC');
  1365. return $qb->getQuery()->setMaxResults(1)->getSingleResult();
  1366. }
  1367. public function getlastReplyAgentName($ticketId)
  1368. {
  1369. $qb = $this->entityManager->createQueryBuilder();
  1370. $qb->select("u.id,CONCAT(u.firstName,' ', u.lastName) AS name,u.firstName")->from(Thread::class, 'th')
  1371. ->leftJoin('th.ticket','t')
  1372. ->leftJoin('th.user', 'u')
  1373. ->leftJoin('u.userInstance', 'userInstance')
  1374. ->andWhere('userInstance.supportRole != :roles')
  1375. ->andWhere('t.id = :ticketId')
  1376. ->andWhere('th.threadType = :threadType')
  1377. ->setParameter('threadType','reply')
  1378. ->andWhere('th.createdBy = :createdBy')
  1379. ->setParameter('createdBy','agent')
  1380. ->setParameter('ticketId',$ticketId)
  1381. ->setParameter('roles', 4)
  1382. ->orderBy('th.id', 'DESC');
  1383. $result = $qb->getQuery()->setMaxResults(1)->getResult();
  1384. return $result ? $result[0] : null;
  1385. }
  1386. public function getLastReply($ticketId, $userType = null)
  1387. {
  1388. $queryBuilder = $this->entityManager->createQueryBuilder();
  1389. $queryBuilder->select("th, a, u.id as userId")
  1390. ->from(Thread::class, 'th')
  1391. ->leftJoin('th.ticket','t')
  1392. ->leftJoin('th.attachments', 'a')
  1393. ->leftJoin('th.user','u')
  1394. ->andWhere('t.id = :ticketId')
  1395. ->andWhere('th.threadType = :threadType')
  1396. ->setParameter('threadType','reply')
  1397. ->setParameter('ticketId',$ticketId)
  1398. ->orderBy('th.id', 'DESC')
  1399. ->getMaxResults(1);
  1400. if (!empty($userType)) {
  1401. $queryBuilder->andWhere('th.createdBy = :createdBy')->setParameter('createdBy', $userType);
  1402. }
  1403. $threadResponse = $queryBuilder->getQuery()->getArrayResult();
  1404. if (!empty($threadResponse[0][0])) {
  1405. $threadDetails = $threadResponse[0][0];
  1406. $userService = $this->container->get('user.service');
  1407. if ($threadDetails['createdBy'] == 'agent') {
  1408. $threadDetails['user'] = $userService->getAgentDetailById($threadResponse[0]['userId']);
  1409. } else {
  1410. $threadDetails['user'] = $userService->getCustomerPartialDetailById($threadResponse[0]['userId']);
  1411. }
  1412. $threadDetails['reply'] = html_entity_decode($threadDetails['message']);
  1413. $threadDetails['formatedCreatedAt'] = $this->timeZoneConverter($threadDetails['createdAt']);
  1414. $threadDetails['timestamp'] = $userService->convertToDatetimeTimezoneTimestamp($threadDetails['createdAt']);
  1415. if (!empty($threadDetails['attachments'])) {
  1416. $entityManager = $this->entityManager;
  1417. $uvdeskFileSystemService = $this->container->get('uvdesk.core.file_system.service');
  1418. $threadDetails['attachments'] = array_map(function ($attachment) use ($entityManager, $uvdeskFileSystemService) {
  1419. $attachmentReferenceObject = $this->entityManager->getReference(Attachment::class, $attachment['id']);
  1420. return $uvdeskFileSystemService->getFileTypeAssociations($attachmentReferenceObject);
  1421. }, $threadDetails['attachments']);
  1422. }
  1423. }
  1424. return $threadDetails ?? null;
  1425. }
  1426. public function getSavedReplyContent($savedReplyId, $ticketId)
  1427. {
  1428. $ticket = $this->entityManager->getRepository(Ticket::class)->find($ticketId);
  1429. $savedReply = $this->entityManager->getRepository(SavedReplies::class)->findOneById($savedReplyId);
  1430. $emailPlaceholders = $this->getSavedReplyPlaceholderValues($ticket, 'customer');
  1431. return $this->container->get('email.service')->processEmailContent($savedReply->getMessage(), $emailPlaceholders, true);
  1432. }
  1433. public function getSavedReplyPlaceholderValues($ticket, $type = "customer")
  1434. {
  1435. $variables = array();
  1436. $variables['ticket.id'] = $ticket->getId();
  1437. $variables['ticket.subject'] = $ticket->getSubject();
  1438. $variables['ticket.status'] = $ticket->getStatus()->getCode();
  1439. $variables['ticket.priority'] = $ticket->getPriority()->getCode();
  1440. if ($ticket->getSupportGroup())
  1441. $variables['ticket.group'] = $ticket->getSupportGroup()->getName();
  1442. else
  1443. $variables['ticket.group'] = '';
  1444. $variables['ticket.team'] = ($ticket->getSupportTeam() ? $ticket->getSupportTeam()->getName() : '');
  1445. $customer = $this->container->get('user.service')->getCustomerPartialDetailById($ticket->getCustomer()->getId());
  1446. $variables['ticket.customerName'] = $customer['name'];
  1447. $variables['ticket.customerEmail'] = $customer['email'];
  1448. $userService = $this->container->get('user.service');
  1449. $variables['ticket.agentName'] = '';
  1450. $variables['ticket.agentEmail'] = '';
  1451. if ($ticket->getAgent()) {
  1452. $agent = $this->container->get('user.service')->getAgentDetailById($ticket->getAgent()->getId());
  1453. if ($agent) {
  1454. $variables['ticket.agentName'] = $agent['name'];
  1455. $variables['ticket.agentEmail'] = $agent['email'];
  1456. }
  1457. }
  1458. $router = $this->container->get('router');
  1459. if ($type == 'customer') {
  1460. $ticketListURL = $router->generate('helpdesk_customer_ticket_collection', [
  1461. 'id' => $ticket->getId(),
  1462. ], UrlGeneratorInterface::ABSOLUTE_URL);
  1463. } else {
  1464. $ticketListURL = $router->generate('helpdesk_member_ticket_collection', [
  1465. 'id' => $ticket->getId(),
  1466. ], UrlGeneratorInterface::ABSOLUTE_URL);
  1467. }
  1468. $variables['ticket.link'] = sprintf("<a href='%s'>#%s</a>", $ticketListURL, $ticket->getId());
  1469. return $variables;
  1470. }
  1471. public function isEmailBlocked($email, $website)
  1472. {
  1473. $flag = false;
  1474. $email = strtolower($email);
  1475. $knowlegeBaseWebsite = $this->entityManager->getRepository(KnowledgebaseWebsite::class)->findOneBy(['website' => $website->getId(), 'isActive' => 1]);
  1476. $list = $this->container->get('user.service')->getWebsiteSpamDetails($knowlegeBaseWebsite);
  1477. // Blacklist
  1478. if (!empty($list['blackList']['email']) && in_array($email, $list['blackList']['email'])) {
  1479. // Emails
  1480. $flag = true;
  1481. } elseif (!empty($list['blackList']['domain'])) {
  1482. // Domains
  1483. foreach ($list['blackList']['domain'] as $domain) {
  1484. if (strpos($email, $domain)) {
  1485. $flag = true;
  1486. break;
  1487. }
  1488. }
  1489. }
  1490. // Whitelist
  1491. if ($flag) {
  1492. if (isset($email, $list['whiteList']['email']) && in_array($email, $list['whiteList']['email'])) {
  1493. // Emails
  1494. return false;
  1495. } elseif (isset($list['whiteList']['domain'])) {
  1496. // Domains
  1497. foreach ($list['whiteList']['domain'] as $domain) {
  1498. if (strpos($email, $domain)) {
  1499. $flag = false;
  1500. }
  1501. }
  1502. }
  1503. }
  1504. return $flag;
  1505. }
  1506. public function timeZoneConverter($dateFlag)
  1507. {
  1508. $website = $this->entityManager->getRepository(Website::class)->findOneBy(['code' => 'Knowledgebase']);
  1509. $timeZone = $website->getTimezone();
  1510. $timeFormat = $website->getTimeformat();
  1511. $activeUser = $this->container->get('user.service')->getSessionUser();
  1512. $agentTimeZone = !empty($activeUser) ? $activeUser->getTimezone() : null;
  1513. $agentTimeFormat = !empty($activeUser) ? $activeUser->getTimeformat() : null;
  1514. $parameterType = gettype($dateFlag);
  1515. if ($parameterType == 'string') {
  1516. if (is_null($agentTimeZone) && is_null($agentTimeFormat)) {
  1517. if(is_null($timeZone) && is_null($timeFormat)){
  1518. $datePattern = date_create($dateFlag);
  1519. return date_format($datePattern,'d-m-Y h:ia');
  1520. } else {
  1521. $dateFlag = new \DateTime($dateFlag);
  1522. $datePattern = $dateFlag->setTimezone(new \DateTimeZone($timeZone));
  1523. return date_format($datePattern, $timeFormat);
  1524. }
  1525. } else {
  1526. $dateFlag = new \DateTime($dateFlag);
  1527. $datePattern = $dateFlag->setTimezone(new \DateTimeZone($agentTimeZone));
  1528. return date_format($datePattern, $agentTimeFormat);
  1529. }
  1530. } else {
  1531. if (is_null($agentTimeZone) && is_null($agentTimeFormat)){
  1532. if (is_null($timeZone) && is_null($timeFormat)) {
  1533. return date_format($dateFlag,'d-m-Y h:ia');
  1534. } else {
  1535. $datePattern = $dateFlag->setTimezone(new \DateTimeZone($timeZone));
  1536. return date_format($datePattern, $timeFormat);
  1537. }
  1538. } else {
  1539. $datePattern = $dateFlag->setTimezone(new \DateTimeZone($agentTimeZone));
  1540. return date_format($datePattern, $agentTimeFormat);
  1541. }
  1542. }
  1543. }
  1544. public function fomatTimeByPreference($dbTime,$timeZone,$timeFormat,$agentTimeZone,$agentTimeFormat)
  1545. {
  1546. if (is_null($agentTimeZone) && is_null($agentTimeFormat)) {
  1547. if (is_null($timeZone) && is_null($timeFormat)) {
  1548. $dateTimeZone = $dbTime;
  1549. $timeFormatString = 'd-m-Y h:ia';
  1550. } else {
  1551. $dateTimeZone = $dbTime->setTimezone(new \DateTimeZone($timeZone));
  1552. $timeFormatString = $timeFormat;
  1553. }
  1554. } else {
  1555. $dateTimeZone = $dbTime->setTimezone(new \DateTimeZone($agentTimeZone));
  1556. $timeFormatString = $agentTimeFormat;
  1557. }
  1558. $time['dateTimeZone'] = $dateTimeZone;
  1559. $time['timeFormatString'] = $timeFormatString;
  1560. return $time;
  1561. }
  1562. public function isTicketAccessGranted(Ticket $ticket, User $user = null, $firewall = 'members')
  1563. {
  1564. // @TODO: Take current firewall into consideration (access check on behalf of agent/customer)
  1565. if (empty($user)) {
  1566. $user = $this->container->get('user.service')->getSessionUser();
  1567. }
  1568. if (empty($user)) {
  1569. return false;
  1570. } else {
  1571. $agentInstance = $user->getAgentInstance();
  1572. if (empty($agentInstance)) {
  1573. return false;
  1574. }
  1575. }
  1576. if ($agentInstance->getSupportRole()->getId() == 3 && in_array($agentInstance->getTicketAccessLevel(), [2, 3, 4])) {
  1577. $accessLevel = $agentInstance->getTicketAccessLevel();
  1578. // Check if user has been given inidividual access
  1579. if ($ticket->getAgent() != null && $ticket->getAgent()->getId() == $user->getId()) {
  1580. return true;
  1581. }
  1582. if ($accessLevel == 2 || $accessLevel == 3) {
  1583. // Check if user belongs to a support team assigned to ticket
  1584. $teamReferenceIds = array_map(function ($team) { return $team->getId(); }, $agentInstance->getSupportTeams()->toArray());
  1585. if ($ticket->getSupportTeam() != null && in_array($ticket->getSupportTeam()->getId(), $teamReferenceIds)) {
  1586. return true;
  1587. } else if ($accessLevel == 2) {
  1588. // Check if user belongs to a support group assigned to ticket
  1589. $groupReferenceIds = array_map(function ($group) { return $group->getId(); }, $agentInstance->getSupportGroups()->toArray());
  1590. if ($ticket->getSupportGroup() != null && in_array($ticket->getSupportGroup()->getId(), $groupReferenceIds)) {
  1591. return true;
  1592. }
  1593. }
  1594. }
  1595. return false;
  1596. }
  1597. return true;
  1598. }
  1599. public function addTicketCustomFields($thread, $submittedCustomFields = [], $uploadedFilesCollection = [])
  1600. {
  1601. $customFieldsService = null;
  1602. $customFieldsEntityReference = null;
  1603. if ($this->userService->isFileExists('apps/uvdesk/custom-fields')) {
  1604. $customFieldsService = $this->container->get('uvdesk_package_custom_fields.service');
  1605. $customFieldsEntityReference = UVDeskCommunityPackages\CustomFields\Entity\CustomFields::class;
  1606. $customFieldValuesEntityReference = UVDeskCommunityPackages\CustomFields\Entity\CustomFieldsValues::class;
  1607. $ticketCustomFieldValuesEntityReference = UVDeskCommunityPackages\CustomFields\Entity\TicketCustomFieldsValues::class;
  1608. } else if ($this->userService->isFileExists('apps/uvdesk/form-component')) {
  1609. $customFieldsService = $this->container->get('uvdesk_package_form_component.service');
  1610. $customFieldsEntityReference = UVDeskCommunityPackages\FormComponent\Entity\CustomFields::class;
  1611. $customFieldValuesEntityReference = UVDeskCommunityPackages\FormComponent\Entity\CustomFieldsValues::class;
  1612. $ticketCustomFieldValuesEntityReference = UVDeskCommunityPackages\FormComponent\Entity\TicketCustomFieldsValues::class;
  1613. } else {
  1614. return;
  1615. }
  1616. $ticket = $thread->getTicket();
  1617. $customFieldsCollection = $this->entityManager->getRepository($customFieldsEntityReference)->findAll();
  1618. $customFieldValuesEntityRepository = $this->entityManager->getRepository($customFieldValuesEntityReference);
  1619. foreach ($customFieldsCollection as $customFields) {
  1620. if (in_array($customFields->getFieldType(), ['select', 'checkbox', 'radio']) && !count($customFields->getCustomFieldValues())) {
  1621. continue;
  1622. }
  1623. if (
  1624. !empty($submittedCustomFields)
  1625. && $customFields->getFieldType() != 'file'
  1626. && isset($submittedCustomFields[$customFields->getId()])
  1627. ) {
  1628. // Check if custom field dependency criterias are fullfilled
  1629. if (
  1630. count($customFields->getCustomFieldsDependency())
  1631. && !in_array($ticket->getType(), $customFields->getCustomFieldsDependency()->toArray())
  1632. ) {
  1633. continue;
  1634. }
  1635. // Save ticket custom fields
  1636. $ticketCustomField = new $ticketCustomFieldValuesEntityReference();
  1637. $ticketCustomField
  1638. ->setTicket($ticket)
  1639. ->setTicketCustomFieldsValues($customFields)
  1640. ->setValue(json_encode($submittedCustomFields[$customFields->getId()]))
  1641. ;
  1642. if (in_array($customFields->getFieldType(), ['select', 'checkbox', 'radio'])) {
  1643. // Add custom field values mapping too
  1644. if (is_array($submittedCustomFields[$customFields->getId()])) {
  1645. foreach ($submittedCustomFields[$customFields->getId()] as $value) {
  1646. $ticketCustomFieldValues = $customFieldValuesEntityRepository->findOneBy([
  1647. 'id' => $value,
  1648. 'customFields' => $customFields,
  1649. ]);
  1650. if (!empty($ticketCustomFieldValues)) {
  1651. $ticketCustomField
  1652. ->setTicketCustomFieldValueValues($ticketCustomFieldValues)
  1653. ;
  1654. }
  1655. }
  1656. } else {
  1657. $ticketCustomFieldValues = $customFieldValuesEntityRepository->findOneBy([
  1658. 'id' => $submittedCustomFields[$customFields->getId()],
  1659. 'customFields' => $customFields,
  1660. ]);
  1661. if (!empty($ticketCustomFieldValues)) {
  1662. $ticketCustomField
  1663. ->setTicketCustomFieldValueValues($ticketCustomFieldValues)
  1664. ;
  1665. }
  1666. }
  1667. }
  1668. $this->entityManager->persist($ticketCustomField);
  1669. $this->entityManager->flush();
  1670. } else if (
  1671. !empty($uploadedFilesCollection)
  1672. && isset($uploadedFilesCollection[$customFields->getId()])
  1673. ) {
  1674. // Upload files
  1675. $path = '/custom-fields/ticket/' . $ticket->getId() . '/';
  1676. $fileNames = $this->fileUploadService->uploadFile($uploadedFilesCollection[$customFields->getid()], $path, true);
  1677. if (!empty($fileNames)) {
  1678. // Save files entry to attachment table
  1679. try {
  1680. $newFilesNames = $customFieldsService->addFilesEntryToAttachmentTable([$fileNames], $thread);
  1681. foreach ($newFilesNames as $value) {
  1682. // Save ticket custom fields
  1683. $ticketCustomField = new $ticketCustomFieldValuesEntityReference();
  1684. $ticketCustomField
  1685. ->setTicket($ticket)
  1686. ->setTicketCustomFieldsValues($customFields)
  1687. ->setValue(json_encode([
  1688. 'name' => $value['name'],
  1689. 'path' => $value['path'],
  1690. 'id' => $value['id'],
  1691. ]))
  1692. ;
  1693. $this->entityManager->persist($ticketCustomField);
  1694. $this->entityManager->flush();
  1695. }
  1696. } catch (\Exception $e) {
  1697. // @TODO: Log execption message
  1698. }
  1699. }
  1700. }
  1701. }
  1702. }
  1703. // return attachemnt for initial thread
  1704. public function getInitialThread($ticketId)
  1705. {
  1706. $firstThread = null;
  1707. $intialThread = $this->entityManager->getRepository(Thread::class)->findBy(['ticket'=>$ticketId]);
  1708. foreach ($intialThread as $key => $value) {
  1709. if ($value->getThreadType() == "create"){
  1710. $firstThread = $value;
  1711. }
  1712. }
  1713. return $firstThread;
  1714. }
  1715. public function getTicketConditions()
  1716. {
  1717. $conditions = array(
  1718. 'ticket' => [
  1719. ('mail') => array(
  1720. [
  1721. 'lable' => ('from_mail'),
  1722. 'value' => 'from_mail',
  1723. 'match' => 'email'
  1724. ],
  1725. [
  1726. 'lable' => ('to_mail'),
  1727. 'value' => 'to_mail',
  1728. 'match' => 'email'
  1729. ],
  1730. ),
  1731. ('API') => array(
  1732. [
  1733. 'lable' => ('Domain'),
  1734. 'value' => 'domain',
  1735. 'match' => 'api'
  1736. ],
  1737. [
  1738. 'lable' => ('Locale'),
  1739. 'value' => 'locale',
  1740. 'match' => 'api'
  1741. ],
  1742. ),
  1743. ('ticket') => array(
  1744. [
  1745. 'lable' => ('subject'),
  1746. 'value' => 'subject',
  1747. 'match' => 'string'
  1748. ],
  1749. [
  1750. 'lable' => ('description'),
  1751. 'value' => 'description',
  1752. 'match' => 'string'
  1753. ],
  1754. [
  1755. 'lable' => ('subject_or_description'),
  1756. 'value' => 'subject_or_description',
  1757. 'match' => 'string'
  1758. ],
  1759. [
  1760. 'lable' => ('priority'),
  1761. 'value' => 'priority',
  1762. 'match' => 'select'
  1763. ],
  1764. [
  1765. 'lable' => ('type'),
  1766. 'value' => 'type',
  1767. 'match' => 'select'
  1768. ],
  1769. [
  1770. 'lable' => ('status'),
  1771. 'value' => 'status',
  1772. 'match' => 'select'
  1773. ],
  1774. [
  1775. 'lable' => ('source'),
  1776. 'value' => 'source',
  1777. 'match' => 'select'
  1778. ],
  1779. [
  1780. 'lable' => ('created'),
  1781. 'value' => 'created',
  1782. 'match' => 'date'
  1783. ],
  1784. [
  1785. 'lable' => ('agent'),
  1786. 'value' => 'agent',
  1787. 'match' => 'select'
  1788. ],
  1789. [
  1790. 'lable' => ('group'),
  1791. 'value' => 'group',
  1792. 'match' => 'select'
  1793. ],
  1794. [
  1795. 'lable' => ('team'),
  1796. 'value' => 'team',
  1797. 'match' => 'select'
  1798. ],
  1799. ),
  1800. ('customer') => array(
  1801. [
  1802. 'lable' => ('customer_name'),
  1803. 'value' => 'customer_name',
  1804. 'match' => 'string'
  1805. ],
  1806. [
  1807. 'lable' => ('customer_email'),
  1808. 'value' => 'customer_email',
  1809. 'match' => 'email'
  1810. ],
  1811. ),
  1812. ],
  1813. 'task' => [
  1814. ('task') => array(
  1815. [
  1816. 'lable' => ('subject'),
  1817. 'value' => 'subject',
  1818. 'match' => 'string'
  1819. ],
  1820. [
  1821. 'lable' => ('description'),
  1822. 'value' => 'description',
  1823. 'match' => 'string'
  1824. ],
  1825. [
  1826. 'lable' => ('subject_or_description'),
  1827. 'value' => 'subject_or_description',
  1828. 'match' => 'string'
  1829. ],
  1830. [
  1831. 'lable' => ('priority'),
  1832. 'value' => 'priority',
  1833. 'match' => 'select'
  1834. ],
  1835. [
  1836. 'lable' => ('stage'),
  1837. 'value' => 'stage',
  1838. 'match' => 'select'
  1839. ],
  1840. [
  1841. 'lable' => ('created'),
  1842. 'value' => 'created',
  1843. 'match' => 'date'
  1844. ],
  1845. [
  1846. 'lable' => ('agent_name'),
  1847. 'value' => 'agent_name',
  1848. 'match' => 'select'
  1849. ],
  1850. [
  1851. 'lable' => ('agent_email'),
  1852. 'value' => 'agent_email',
  1853. 'match' => 'select'
  1854. ],
  1855. ),
  1856. ]
  1857. );
  1858. return $conditions;
  1859. }
  1860. public function getAgentMatchConditions()
  1861. {
  1862. return [
  1863. 'email' => array(
  1864. [
  1865. 'lable' => ('is'),
  1866. 'value' => 'is'
  1867. ],
  1868. [
  1869. 'lable' => ('isNot'),
  1870. 'value' => 'isNot'
  1871. ],
  1872. [
  1873. 'lable' => ('contains'),
  1874. 'value' => 'contains'
  1875. ],
  1876. [
  1877. 'lable' => ('notContains'),
  1878. 'value' => 'notContains'
  1879. ],
  1880. ),
  1881. 'api' => array(
  1882. [
  1883. 'lable' => ('is'),
  1884. 'value' => 'is'
  1885. ],
  1886. [
  1887. 'lable' => ('contains'),
  1888. 'value' => 'contains'
  1889. ],
  1890. ),
  1891. 'string' => array(
  1892. [
  1893. 'lable' => ('is'),
  1894. 'value' => 'is'
  1895. ],
  1896. [
  1897. 'lable' => ('isNot'),
  1898. 'value' => 'isNot'
  1899. ],
  1900. [
  1901. 'lable' => ('contains'),
  1902. 'value' => 'contains'
  1903. ],
  1904. [
  1905. 'lable' => ('notContains'),
  1906. 'value' => 'notContains'
  1907. ],
  1908. [
  1909. 'lable' => ('startWith'),
  1910. 'value' => 'startWith'
  1911. ],
  1912. [
  1913. 'lable' => ('endWith'),
  1914. 'value' => 'endWith'
  1915. ],
  1916. ),
  1917. 'select' => array(
  1918. [
  1919. 'lable' => ('is'),
  1920. 'value' => 'is'
  1921. ],
  1922. ),
  1923. 'date' => array(
  1924. [
  1925. 'lable' => ('before'),
  1926. 'value' => 'before'
  1927. ],
  1928. [
  1929. 'lable' => ('beforeOn'),
  1930. 'value' => 'beforeOn'
  1931. ],
  1932. [
  1933. 'lable' => ('after'),
  1934. 'value' => 'after'
  1935. ],
  1936. [
  1937. 'lable' => ('afterOn'),
  1938. 'value' => 'afterOn'
  1939. ],
  1940. ),
  1941. 'datetime' => array(
  1942. [
  1943. 'lable' => ('before'),
  1944. 'value' => 'beforeDateTime'
  1945. ],
  1946. [
  1947. 'lable' => ('beforeOn'),
  1948. 'value' => 'beforeDateTimeOn'
  1949. ],
  1950. [
  1951. 'lable' => ('after'),
  1952. 'value' => 'afterDateTime'
  1953. ],
  1954. [
  1955. 'lable' => ('afterOn'),
  1956. 'value' => 'afterDateTimeOn'
  1957. ],
  1958. ),
  1959. 'time' => array(
  1960. [
  1961. 'lable' => ('before'),
  1962. 'value' => 'beforeTime'
  1963. ],
  1964. [
  1965. 'lable' => ('beforeOn'),
  1966. 'value' => 'beforeTimeOn'
  1967. ],
  1968. [
  1969. 'lable' => ('after'),
  1970. 'value' => 'afterTime'
  1971. ],
  1972. [
  1973. 'lable' => ('afterOn'),
  1974. 'value' => 'afterTimeOn'
  1975. ],
  1976. ),
  1977. 'number' => array(
  1978. [
  1979. 'lable' => ('is'),
  1980. 'value' => 'is'
  1981. ],
  1982. [
  1983. 'lable' => ('isNot'),
  1984. 'value' => 'isNot'
  1985. ],
  1986. [
  1987. 'lable' => ('contains'),
  1988. 'value' => 'contains'
  1989. ],
  1990. [
  1991. 'lable' => ('greaterThan'),
  1992. 'value' => 'greaterThan'
  1993. ],
  1994. [
  1995. 'lable' => ('lessThan'),
  1996. 'value' => 'lessThan'
  1997. ],
  1998. ),
  1999. ];
  2000. }
  2001. public function getTicketMatchConditions()
  2002. {
  2003. return [
  2004. 'email' => array(
  2005. [
  2006. 'lable' => ('is'),
  2007. 'value' => 'is'
  2008. ],
  2009. [
  2010. 'lable' => ('isNot'),
  2011. 'value' => 'isNot'
  2012. ],
  2013. [
  2014. 'lable' => ('contains'),
  2015. 'value' => 'contains'
  2016. ],
  2017. [
  2018. 'lable' => ('notContains'),
  2019. 'value' => 'notContains'
  2020. ],
  2021. ),
  2022. 'api' => array(
  2023. [
  2024. 'lable' => ('is'),
  2025. 'value' => 'is'
  2026. ],
  2027. [
  2028. 'lable' => ('contains'),
  2029. 'value' => 'contains'
  2030. ],
  2031. ),
  2032. 'string' => array(
  2033. [
  2034. 'lable' => ('is'),
  2035. 'value' => 'is'
  2036. ],
  2037. [
  2038. 'lable' => ('isNot'),
  2039. 'value' => 'isNot'
  2040. ],
  2041. [
  2042. 'lable' => ('contains'),
  2043. 'value' => 'contains'
  2044. ],
  2045. [
  2046. 'lable' => ('notContains'),
  2047. 'value' => 'notContains'
  2048. ],
  2049. [
  2050. 'lable' => ('startWith'),
  2051. 'value' => 'startWith'
  2052. ],
  2053. [
  2054. 'lable' => ('endWith'),
  2055. 'value' => 'endWith'
  2056. ],
  2057. ),
  2058. 'select' => array(
  2059. [
  2060. 'lable' => ('is'),
  2061. 'value' => 'is'
  2062. ],
  2063. [
  2064. 'lable' => ('isNot'),
  2065. 'value' => 'isNot'
  2066. ],
  2067. ),
  2068. 'date' => array(
  2069. [
  2070. 'lable' => ('before'),
  2071. 'value' => 'before'
  2072. ],
  2073. [
  2074. 'lable' => ('beforeOn'),
  2075. 'value' => 'beforeOn'
  2076. ],
  2077. [
  2078. 'lable' => ('after'),
  2079. 'value' => 'after'
  2080. ],
  2081. [
  2082. 'lable' => ('afterOn'),
  2083. 'value' => 'afterOn'
  2084. ],
  2085. ),
  2086. 'datetime' => array(
  2087. [
  2088. 'lable' => ('before'),
  2089. 'value' => 'beforeDateTime'
  2090. ],
  2091. [
  2092. 'lable' => ('beforeOn'),
  2093. 'value' => 'beforeDateTimeOn'
  2094. ],
  2095. [
  2096. 'lable' => ('after'),
  2097. 'value' => 'afterDateTime'
  2098. ],
  2099. [
  2100. 'lable' => ('afterOn'),
  2101. 'value' => 'afterDateTimeOn'
  2102. ],
  2103. ),
  2104. 'time' => array(
  2105. [
  2106. 'lable' => ('before'),
  2107. 'value' => 'beforeTime'
  2108. ],
  2109. [
  2110. 'lable' => ('beforeOn'),
  2111. 'value' => 'beforeTimeOn'
  2112. ],
  2113. [
  2114. 'lable' => ('after'),
  2115. 'value' => 'afterTime'
  2116. ],
  2117. [
  2118. 'lable' => ('afterOn'),
  2119. 'value' => 'afterTimeOn'
  2120. ],
  2121. ),
  2122. 'number' => array(
  2123. [
  2124. 'lable' => ('is'),
  2125. 'value' => 'is'
  2126. ],
  2127. [
  2128. 'lable' => ('isNot'),
  2129. 'value' => 'isNot'
  2130. ],
  2131. [
  2132. 'lable' => ('contains'),
  2133. 'value' => 'contains'
  2134. ],
  2135. [
  2136. 'lable' => ('greaterThan'),
  2137. 'value' => 'greaterThan'
  2138. ],
  2139. [
  2140. 'lable' => ('lessThan'),
  2141. 'value' => 'lessThan'
  2142. ],
  2143. ),
  2144. ];
  2145. }
  2146. public function getTargetAction() {
  2147. return [
  2148. '4' => ['response' => ['time' => '2', 'unit' => 'hours'], 'resolve' => ['time' => '8', 'unit' => 'hours'], 'operational' => 'calendarHours', 'isActive' => 'on'],
  2149. '3' => ['response' => ['time' => '4', 'unit' => 'hours'], 'resolve' => ['time' => '1', 'unit' => 'days'], 'operational' => 'calendarHours', 'isActive' => 'on'],
  2150. '2' => ['response' => ['time' => '8', 'unit' => 'hours'], 'resolve' => ['time' => '3', 'unit' => 'days'], 'operational' => 'calendarHours', 'isActive' => 'on'],
  2151. '1' => ['response' => ['time' => '16', 'unit' => 'hours'], 'resolve' => ['time' => '5', 'unit' => 'days'], 'operational' => 'calendarHours', 'isActive' => 'on'],
  2152. ];
  2153. }
  2154. public function getTicketActions($force = false)
  2155. {
  2156. $actionArray = array(
  2157. 'ticket' => [
  2158. 'priority' => ('action.priority'),
  2159. 'type' => ('action.type'),
  2160. 'status' => ('action.status'),
  2161. 'tag' => ('action.tag'),
  2162. 'note' => ('action.note'),
  2163. 'label' => ('action.label'),
  2164. 'assign_agent' => ('action.assign_agent'),
  2165. 'assign_group' => ('action.assign_group'),
  2166. 'assign_team' => ('action.assign_team'),
  2167. 'mail_agent' => ('action.mail_agent'),
  2168. 'mail_group' => ('action.mail_group'),
  2169. 'mail_team' => ('action.mail_team'),
  2170. 'mail_customer' => ('action.mail_customer'),
  2171. 'mail_last_collaborator' => ('action.mail_last_collaborator'),
  2172. 'mail_all_collaborators' => ('action.mail_all_collaborators'),
  2173. 'delete_ticket' => ('action.delete_ticket'),
  2174. 'mark_spam' => ('action.mark_spam'),
  2175. ],
  2176. 'task' => [
  2177. 'reply' => ('action.reply'),
  2178. 'mail_agent' => ('action.mail_agent'),
  2179. 'mail_members' => ('action.mail_members'),
  2180. 'mail_last_member' => ('action.mail_last_member'),
  2181. ],
  2182. 'customer' => [
  2183. 'mail_customer' => ('action.mail_customer'),
  2184. ],
  2185. 'agent' => [
  2186. 'mail_agent' => ('action.mail_agent'),
  2187. 'task_transfer' => ('action.task_transfer'),
  2188. 'assign_agent' => ('action.assign_agent'),
  2189. 'assign_group' => ('action.assign_group'),
  2190. 'assign_team' => ('action.assign_team'),
  2191. ],
  2192. );
  2193. $actionRoleArray = [
  2194. 'ticket->priority' => 'ROLE_AGENT_UPDATE_TICKET_PRIORITY',
  2195. 'ticket->type' => 'ROLE_AGENT_UPDATE_TICKET_TYPE',
  2196. 'ticket->status' => 'ROLE_AGENT_UPDATE_TICKET_STATUS',
  2197. 'ticket->tag' => 'ROLE_AGENT_ADD_TAG',
  2198. 'ticket->note' => 'ROLE_AGENT_ADD_NOTE',
  2199. 'ticket->assign_agent' => 'ROLE_AGENT_ASSIGN_TICKET',
  2200. 'ticket->assign_group' => 'ROLE_AGENT_ASSIGN_TICKET_GROUP',
  2201. 'ticket->assign_team' => 'ROLE_AGENT_ASSIGN_TICKET_GROUP',
  2202. 'ticket->mail_agent' => 'ROLE_AGENT',
  2203. 'ticket->mail_group' => 'ROLE_AGENT_MANAGE_GROUP',
  2204. 'ticket->mail_team' => 'ROLE_AGENT_MANAGE_SUB_GROUP',
  2205. 'ticket->mail_customer' => 'ROLE_AGENT',
  2206. 'ticket->mail_last_collaborator' => 'ROLE_AGENT',
  2207. 'ticket->mail_all_collaborators' => 'ROLE_AGENT',
  2208. 'ticket->delete_ticket' => 'ROLE_AGENT_DELETE_TICKET',
  2209. 'ticket->mark_spam' => 'ROLE_AGENT_UPDATE_TICKET_STATUS',
  2210. 'ticket->label' => 'ROLE_ADMIN',
  2211. 'task->reply' => 'ROLE_AGENT',
  2212. 'task->mail_agent' => 'ROLE_AGENT',
  2213. 'task->mail_members' => 'ROLE_AGENT',
  2214. 'task->mail_last_member' => 'ROLE_AGENT',
  2215. 'customer->mail_customer' => 'ROLE_AGENT',
  2216. 'agent->mail_agent' => 'ROLE_AGENT',
  2217. 'agent->task_transfer' => 'ROLE_AGENT_EDIT_TASK',
  2218. 'agent->assign_agent' => 'ROLE_AGENT_ASSIGN_TICKET',
  2219. 'agent->assign_group' => 'ROLE_AGENT_ASSIGN_TICKET_GROUP',
  2220. 'agent->assign_team' => 'ROLE_AGENT_ASSIGN_TICKET_GROUP',
  2221. ];
  2222. $resultArray = [];
  2223. foreach ($actionRoleArray as $action => $role) {
  2224. if ($role == 'ROLE_AGENT' || $this->container->get('user.service')->checkPermission($role) || $force) {
  2225. $actionPath = explode('->', $action);
  2226. $resultArray[$actionPath[0]][$actionPath[1]] = $actionArray[$actionPath[0]][$actionPath[1]];
  2227. }
  2228. }
  2229. $repo = $this->container->get('doctrine.orm.entity_manager')->getRepository('WebkulAppBundle:ECommerceChannel');
  2230. $ecomArray= [];
  2231. $ecomChannels = $repo->getActiveChannelsByCompany($this->container->get('user.service')->getCurrentCompany());
  2232. foreach ($ecomChannels as $channel) {
  2233. $ecomArray['add_order_to_' . $channel['id']] = ('Add order to: ') . $channel['title'];
  2234. }
  2235. $resultArray['ticket'] = array_merge($resultArray['ticket'], $ecomArray);
  2236. return $resultArray;
  2237. }
  2238. }