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

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