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

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->getCode(),
  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. case 'country':
  445. if (
  446. ! $ticket->getCountry()
  447. || $ticket->getCountry() != $requestContent['value']
  448. ) {
  449. $customer = $ticket->getCustomer();
  450. $customerTickets = $entityManager->getRepository(Ticket::class)->findBy([
  451. 'customer' => $customer->getId(),
  452. ]);
  453. foreach ($customerTickets as $customerTicket) {
  454. $customerTicket
  455. ->setCountry($requestContent['value'] ?? NULL);
  456. $entityManager->persist($customerTicket);
  457. }
  458. $entityManager->flush();
  459. return new Response(json_encode([
  460. 'alertClass' => 'success',
  461. 'alertMessage' => $this->translator->trans('Success ! Ticket country updated successfully.'),
  462. ]), 200, ['Content-Type' => 'application/json']);
  463. } else {
  464. return new Response(json_encode([
  465. 'alertClass' => 'success',
  466. 'alertMessage' => $this->translator->trans('No changes detected in the provided ticket country details.'),
  467. ]), 200, ['Content-Type' => 'application/json']);
  468. }
  469. default:
  470. break;
  471. }
  472. return new Response(json_encode([]), 400, ['Content-Type' => 'application/json']);
  473. }
  474. public function listTicketCollectionXHR(Request $request)
  475. {
  476. if ($request->isXmlHttpRequest()) {
  477. $paginationResponse = $this->ticketService->paginateMembersTicketCollection($request);
  478. return new Response(json_encode($paginationResponse), 200, ['Content-Type' => 'application/json']);
  479. }
  480. return new Response(json_encode([]), 404, ['Content-Type' => 'application/json']);
  481. }
  482. public function updateTicketCollectionXHR(Request $request)
  483. {
  484. if ($request->isXmlHttpRequest()) {
  485. $massResponse = $this->ticketService->massXhrUpdate($request);
  486. return new Response(json_encode($massResponse), 200, ['Content-Type' => 'application/json']);
  487. }
  488. return new Response(json_encode([]), 404);
  489. }
  490. public function loadTicketFilterOptionsXHR(Request $request)
  491. {
  492. $json = [];
  493. if ($request->isXmlHttpRequest()) {
  494. $requiredOptions = $request->request->all();
  495. foreach ($requiredOptions as $filterType => $values) {
  496. $json[$filterType] = $this->ticketService->getDemanedFilterOptions($filterType, $values);
  497. }
  498. }
  499. $response = new Response(json_encode($json));
  500. $response->headers->set('Content-Type', 'application/json');
  501. return $response;
  502. }
  503. public function saveTicketLabel(Request $request)
  504. {
  505. $entityManager = $this->getDoctrine()->getManager();
  506. $request = $this->container->get('request_stack')->getCurrentRequest();
  507. $requestContent = json_decode($request->getContent(), true);
  508. $ticket = $entityManager->getRepository(Ticket::class)->findOneById($requestContent['ticketId']);
  509. // Process only if user have ticket access
  510. if (false == $this->ticketService->isTicketAccessGranted($ticket)) {
  511. throw new \Exception('Access Denied', 403);
  512. }
  513. if ('POST' == $request->getMethod()) {
  514. $responseContent = [];
  515. $user = $this->userService->getSessionUser();
  516. $supportLabel = $entityManager->getRepository(SupportLabel::class)->findOneBy([
  517. 'user' => $user->getId(),
  518. 'name' => $requestContent['name'],
  519. ]);
  520. if (empty($supportLabel)) {
  521. $supportLabel = new SupportLabel();
  522. $supportLabel->setName($requestContent['name']);
  523. $supportLabel->setUser($user);
  524. $entityManager->persist($supportLabel);
  525. $entityManager->flush();
  526. }
  527. $ticketLabelCollection = $ticket->getSupportLabels()->toArray();
  528. if (empty($ticketLabelCollection)) {
  529. $ticket->addSupportLabel($supportLabel);
  530. $entityManager->persist($ticket);
  531. $entityManager->flush();
  532. $responseContent['alertClass'] = 'success';
  533. $responseContent['alertMessage'] = $this->translator->trans(
  534. 'Label %label% added to ticket successfully', [
  535. '%label%' => $supportLabel->getName(),
  536. ]);
  537. } else {
  538. $isLabelAlreadyAdded = false;
  539. foreach ($ticketLabelCollection as $ticketLabel) {
  540. if ($supportLabel->getId() == $ticketLabel->getId()) {
  541. $isLabelAlreadyAdded = true;
  542. break;
  543. }
  544. }
  545. if (false == $isLabelAlreadyAdded) {
  546. $ticket->addSupportLabel($supportLabel);
  547. $entityManager->persist($ticket);
  548. $entityManager->flush();
  549. $responseContent['alertClass'] = 'success';
  550. $responseContent['alertMessage'] = $this->translator->trans(
  551. 'Label %label% added to ticket successfully', [
  552. '%label%' => $supportLabel->getName(),
  553. ]);
  554. } else {
  555. $responseContent['alertClass'] = 'warning';
  556. $responseContent['alertMessage'] = $this->translator->trans(
  557. 'Label %label% already added to ticket', [
  558. '%label%' => $supportLabel->getName(),
  559. ]);
  560. }
  561. }
  562. $responseContent['label'] = [
  563. 'id' => $supportLabel->getId(),
  564. 'name' => $supportLabel->getName(),
  565. 'color' => $supportLabel->getColorCode(),
  566. ];
  567. return new Response(json_encode($responseContent), 200, ['Content-Type' => 'application/json']);
  568. }
  569. return new Response(json_encode([]), 404, ['Content-Type' => 'application/json']);
  570. }
  571. public function getLabels($request = null)
  572. {
  573. static $labels;
  574. if (null !== $labels)
  575. return $labels;
  576. $qb = $this->em->createQueryBuilder();
  577. $qb->select('tl')->from(TicketLabel::class, 'tl')
  578. ->andWhere('tl.labelUser = :labelUserId')
  579. ->andWhere('tl.company = :companyId')
  580. ->setParameter('labelUserId', $this->getUser()->getId())
  581. ->setParameter('companyId', $this->getCompany()->getId());
  582. if($request) {
  583. $qb->andWhere("tl.name LIKE :labelName");
  584. $qb->setParameter('labelName', '%'.urldecode($request->query->get('query')).'%');
  585. }
  586. return $labels = $qb->getQuery()->getArrayResult();
  587. }
  588. public function loadTicketSearchFilterOptions(Request $request)
  589. {
  590. if (true === $request->isXmlHttpRequest()) {
  591. switch ($request->query->get('type')) {
  592. case 'agent':
  593. $filtersResponse = $this->userService->getAgentPartialDataCollection($request);
  594. break;
  595. case 'customer':
  596. $filtersResponse = $this->userService->getCustomersPartial($request);
  597. break;
  598. case 'group':
  599. $filtersResponse = $this->userService->getSupportGroups($request);
  600. break;
  601. case 'team':
  602. $filtersResponse = $this->userService->getSupportTeams($request);
  603. break;
  604. case 'tag':
  605. $filtersResponse = $this->ticketService->getTicketTags($request);
  606. break;
  607. case 'label':
  608. $searchTerm = $request->query->get('query');
  609. $entityManager = $this->getDoctrine()->getManager();
  610. $supportLabelQuery = $entityManager->createQueryBuilder()->select('supportLabel')
  611. ->from(SupportLabel::class, 'supportLabel')
  612. ->where('supportLabel.user = :user')->setParameter('user', $this->userService->getSessionUser());
  613. if (!empty($searchTerm)) {
  614. $supportLabelQuery->andWhere('supportLabel.name LIKE :labelName')->setParameter('labelName', '%' . urldecode($searchTerm) . '%');
  615. }
  616. $supportLabelCollection = $supportLabelQuery->getQuery()->getArrayResult();
  617. return new Response(json_encode($supportLabelCollection), 200, ['Content-Type' => 'application/json']);
  618. break;
  619. default:
  620. break;
  621. }
  622. }
  623. return new Response(json_encode([]), 404, ['Content-Type' => 'application/json']);
  624. }
  625. public function loadTicketCollectionSearchFilterOptionsXHR(Request $request)
  626. {
  627. $json = [];
  628. if ($request->isXmlHttpRequest()) {
  629. if ($request->query->get('type') == 'agent') {
  630. $json = $this->userService->getAgentsPartialDetails($request);
  631. } elseif ($request->query->get('type') == 'customer') {
  632. $json = $this->userService->getCustomersPartial($request);
  633. } elseif ($request->query->get('type') == 'group') {
  634. $json = $this->userService->getSupportGroups($request);
  635. } elseif ($request->query->get('type') == 'team') {
  636. $json = $this->userService->getSupportTeams($request);
  637. } elseif ($request->query->get('type') == 'tag') {
  638. $json = $this->ticketService->getTicketTags($request);
  639. } elseif ($request->query->get('type') == 'label') {
  640. $json = $this->ticketService->getLabels($request);
  641. }
  642. }
  643. return new Response(json_encode($json), 200, ['Content-Type' => 'application/json']);
  644. }
  645. public function listTicketTypeCollectionXHR(Request $request)
  646. {
  647. if (! $this->userService->isAccessAuthorized('ROLE_AGENT_MANAGE_TICKET_TYPE')) {
  648. return $this->redirect($this->generateUrl('helpdesk_member_dashboard'));
  649. }
  650. if (true === $request->isXmlHttpRequest()) {
  651. $paginationResponse = $this->ticketService->paginateMembersTicketTypeCollection($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 removeTicketTypeXHR($typeId, Request $request)
  657. {
  658. if (! $this->userService->isAccessAuthorized('ROLE_AGENT_MANAGE_TICKET_TYPE')) {
  659. return $this->redirect($this->generateUrl('helpdesk_member_dashboard'));
  660. }
  661. $json = [];
  662. if ($request->getMethod() == "DELETE") {
  663. $em = $this->getDoctrine()->getManager();
  664. $id = $request->attributes->get('typeId');
  665. $type = $em->getRepository(TicketType::class)->find($id);
  666. // $this->get('event.manager')->trigger([
  667. // 'event' => 'type.deleted',
  668. // 'entity' => $type
  669. // ]);
  670. $em->remove($type);
  671. $em->flush();
  672. $json['alertClass'] = 'success';
  673. $json['alertMessage'] = $this->translator->trans('Success ! Type removed successfully.');
  674. }
  675. $response = new Response(json_encode($json));
  676. $response->headers->set('Content-Type', 'application/json');
  677. return $response;
  678. }
  679. public function listTagCollectionXHR(Request $request)
  680. {
  681. if (! $this->userService->isAccessAuthorized('ROLE_AGENT_MANAGE_TAG')) {
  682. return $this->redirect($this->generateUrl('helpdesk_member_dashboard'));
  683. }
  684. if (true === $request->isXmlHttpRequest()) {
  685. $paginationResponse = $this->ticketService->paginateMembersTagCollection($request);
  686. return new Response(json_encode($paginationResponse), 200, ['Content-Type' => 'application/json']);
  687. }
  688. return new Response(json_encode([]), 404, ['Content-Type' => 'application/json']);
  689. }
  690. public function applyTicketPreparedResponseXHR(Request $request)
  691. {
  692. $id = $request->attributes->get('id');
  693. $ticketId = $request->attributes->get('ticketId');
  694. $ticket = $this->getDoctrine()->getManager()->getRepository(Ticket::class)->findOneById($ticketId);
  695. // Process only if user have ticket access
  696. if (false == $this->ticketService->isTicketAccessGranted($ticket)) {
  697. return $this->redirect($this->generateUrl('helpdesk_member_dashboard'));
  698. }
  699. $event = new GenericEvent($id, [
  700. 'entity' => $ticket
  701. ]);
  702. $this->eventDispatcher->dispatch($event, 'uvdesk.automation.prepared_response.execute');
  703. $this->addFlash('success', $this->translator->trans('Success ! Prepared Response applied successfully.'));
  704. return $this->redirect($this->generateUrl('helpdesk_member_ticket',['ticketId' => $ticketId]));
  705. }
  706. public function loadTicketSavedReplies(Request $request)
  707. {
  708. $json = array();
  709. $data = $request->query->all();
  710. if ($request->isXmlHttpRequest()) {
  711. $json['message'] = $this->ticketService->getSavedReplyContent($data['id'],$data['ticketId']);
  712. }
  713. $response = new Response(json_encode($json));
  714. return $response;
  715. }
  716. public function createTicketTagXHR(Request $request)
  717. {
  718. $json = [];
  719. $content = json_decode($request->getContent(), true);
  720. $em = $this->getDoctrine()->getManager();
  721. $ticket = $em->getRepository(Ticket::class)->find($content['ticketId']);
  722. // Process only if user have ticket access
  723. if (false == $this->ticketService->isTicketAccessGranted($ticket)) {
  724. throw new \Exception('Access Denied', 403);
  725. }
  726. if ($request->getMethod() == "POST") {
  727. $tag = new CoreFrameworkBundleEntities\Tag();
  728. if ($content['name'] != "") {
  729. $checkTag = $em->getRepository(Tag::class)->findOneBy(array('name' => $content['name']));
  730. if (! $checkTag) {
  731. $tag->setName($content['name']);
  732. $em->persist($tag);
  733. $em->flush();
  734. //$json['tag'] = json_decode($this->objectSerializer($tag));
  735. $ticket->addSupportTag($tag);
  736. } else {
  737. //$json['tag'] = json_decode($this->objectSerializer($checkTag));
  738. $ticket->addSupportTag($checkTag);
  739. }
  740. $em->persist($ticket);
  741. $em->flush();
  742. $json['alertClass'] = 'success';
  743. $json['alertMessage'] = $this->translator->trans('Success ! Tag added successfully.');
  744. } else {
  745. $json['alertClass'] = 'danger';
  746. $json['alertMessage'] = $this->translator->trans('Please enter tag name.');
  747. }
  748. } elseif ($request->getMethod() == "DELETE") {
  749. $tag = $em->getRepository(Tag::class)->findOneBy(array('id' => $request->attributes->get('id')));
  750. if ($tag) {
  751. $articles = $em->getRepository(ArticleTags::class)->findOneBy(array('tagId' => $tag->getId()));
  752. if ($articles)
  753. foreach ($articles as $entry) {
  754. $em->remove($entry);
  755. }
  756. $ticket->removeSupportTag($tag);
  757. $em->persist($ticket);
  758. $em->flush();
  759. $json['alertClass'] = 'success';
  760. $json['alertMessage'] = $this->translator->trans('Success ! Tag unassigned successfully.');
  761. } else {
  762. $json['alertClass'] = 'danger';
  763. $json['alertMessage'] = $this->translator->trans('Error ! Invalid tag.');
  764. }
  765. }
  766. $response = new Response(json_encode($json));
  767. $response->headers->set('Content-Type', 'application/json');
  768. return $response;
  769. }
  770. public function getSearchFilterOptionsXhr(Request $request)
  771. {
  772. $json = [];
  773. if ($request->isXmlHttpRequest()) {
  774. if ($request->query->get('type') == 'agent') {
  775. $json = $this->userService->getAgentsPartialDetails($request);
  776. } elseif ($request->query->get('type') == 'customer') {
  777. $json = $this->userService->getCustomersPartial($request);
  778. } elseif ($request->query->get('type') == 'group') {
  779. $json = $this->userService->getSupportGroups($request);
  780. } elseif ($request->query->get('type') == 'team') {
  781. $json = $this->userService->getSupportTeams($request);
  782. } elseif ($request->query->get('type') == 'tag') {
  783. $json = $this->ticketService->getTicketTags($request);
  784. } elseif ($request->query->get('type') == 'label') {
  785. $json = $this->ticketService->getLabels($request);
  786. }
  787. }
  788. $response = new Response(json_encode($json));
  789. $response->headers->set('Content-Type', 'application/json');
  790. return $response;
  791. }
  792. public function updateCollaboratorXHR(Request $request)
  793. {
  794. $json = [];
  795. $content = json_decode($request->getContent(), true);
  796. $em = $this->getDoctrine()->getManager();
  797. $ticket = $em->getRepository(Ticket::class)->find($content['ticketId']);
  798. // Process only if user have ticket access
  799. if (false == $this->ticketService->isTicketAccessGranted($ticket)) {
  800. throw new \Exception('Access Denied', 403);
  801. }
  802. if ($request->getMethod() == "POST") {
  803. if ($content['email'] == $ticket->getCustomer()->getEmail()) {
  804. $json['alertClass'] = 'danger';
  805. $json['alertMessage'] = $this->translator->trans('Error ! Customer can not be added as collaborator.');
  806. } else {
  807. $data = array(
  808. 'from' => $content['email'],
  809. 'firstName' => ($firstName = ucfirst(current(explode('@', $content['email'])))),
  810. 'lastName' => ' ',
  811. 'role' => 4,
  812. );
  813. $supportRole = $em->getRepository(SupportRole::class)->findOneByCode('ROLE_CUSTOMER');
  814. $collaborator = $this->userService->createUserInstance($data['from'], $data['firstName'], $supportRole, $extras = ["active" => true]);
  815. $checkTicket = $em->getRepository(Ticket::class)->isTicketCollaborator($ticket, $content['email']);
  816. if (!$checkTicket) {
  817. $ticket->addCollaborator($collaborator);
  818. $em->persist($ticket);
  819. $em->flush();
  820. $ticket->lastCollaborator = $collaborator;
  821. if ($collaborator->getCustomerInstance()) {
  822. $json['collaborator'] = $collaborator->getCustomerInstance()->getPartialDetails();
  823. } else {
  824. $json['collaborator'] = $collaborator->getAgentInstance()->getPartialDetails();
  825. }
  826. $event = new CoreWorkflowEvents\Ticket\Collaborator();
  827. $event
  828. ->setTicket($ticket)
  829. ;
  830. $this->eventDispatcher->dispatch($event, 'uvdesk.automation.workflow.execute');
  831. $json['alertClass'] = 'success';
  832. $json['alertMessage'] = $this->translator->trans('Success ! Collaborator added successfully.');
  833. } else {
  834. $json['alertClass'] = 'danger';
  835. $message = "Collaborator is already added.";
  836. $json['alertMessage'] = $this->translator->trans('Error ! ' . $message);
  837. }
  838. }
  839. } elseif ($request->getMethod() == "DELETE") {
  840. $collaborator = $em->getRepository(User::class)->findOneBy(array('id' => $request->attributes->get('id')));
  841. if ($collaborator) {
  842. $ticket->removeCollaborator($collaborator);
  843. $em->persist($ticket);
  844. $em->flush();
  845. $json['alertClass'] = 'success';
  846. $json['alertMessage'] = $this->translator->trans('Success ! Collaborator removed successfully.');
  847. } else {
  848. $json['alertClass'] = 'danger';
  849. $json['alertMessage'] = $this->translator->trans('Error ! Invalid Collaborator.');
  850. }
  851. }
  852. $response = new Response(json_encode($json));
  853. $response->headers->set('Content-Type', 'application/json');
  854. return $response;
  855. }
  856. // Apply quick Response action
  857. public function getTicketQuickViewDetailsXhr(Request $request, ContainerInterface $container)
  858. {
  859. $json = [];
  860. if ($request->isXmlHttpRequest()) {
  861. $ticketId = $request->query->get('ticketId');
  862. $json = $this->getDoctrine()->getRepository(Ticket::class)->getTicketDetails($request->query, $container);
  863. }
  864. $response = new Response(json_encode($json));
  865. $response->headers->set('Content-Type', 'application/json');
  866. return $response;
  867. }
  868. public function updateTicketTagXHR(Request $request, $tagId)
  869. {
  870. $content = json_decode($request->getContent(), true);
  871. $entityManager = $this->getDoctrine()->getManager();
  872. if (isset($content['name']) && $content['name'] != "") {
  873. $checkTag = $entityManager->getRepository(Tag::class)->findOneBy(array('id' => $tagId));
  874. if ($checkTag) {
  875. $checkTag->setName($content['name']);
  876. $entityManager->persist($checkTag);
  877. $entityManager->flush();
  878. }
  879. $json['alertClass'] = 'success';
  880. $json['alertMessage'] = $this->translator->trans('Success ! Tag updated successfully.');
  881. }
  882. $response = new Response(json_encode($json));
  883. $response->headers->set('Content-Type', 'application/json');
  884. return $response;
  885. }
  886. public function removeTicketTagXHR($tagId)
  887. {
  888. $entityManager = $this->getDoctrine()->getManager();
  889. $checkTag = $entityManager->getRepository(Tag::class)->findOneBy(array('id' => $tagId));
  890. if ($checkTag) {
  891. $entityManager->remove($checkTag);
  892. $entityManager->flush();
  893. $json['alertClass'] = 'success';
  894. $json['alertMessage'] = $this->translator->trans('Success ! Tag removed successfully.');
  895. }
  896. $response = new Response(json_encode($json));
  897. $response->headers->set('Content-Type', 'application/json');
  898. return $response;
  899. }
  900. }