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

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