vendor/uvdesk/core-framework/Controller/Ticket.php line 70

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\Form as CoreFrameworkBundleForms;
  6. use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
  7. use Webkul\UVDesk\CoreFrameworkBundle\Entity as CoreFrameworkBundleEntities;
  8. use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
  9. use Webkul\UVDesk\CoreFrameworkBundle\DataProxies as CoreFrameworkBundleDataProxies;
  10. use Webkul\UVDesk\CoreFrameworkBundle\Workflow\Events as CoreWorkflowEvents;
  11. use Webkul\UVDesk\CoreFrameworkBundle\Tickets\QuickActionButtonCollection;
  12. use Webkul\UVDesk\CoreFrameworkBundle\Repository\TicketRepository;
  13. use Webkul\UVDesk\CoreFrameworkBundle\Services\UserService;
  14. use Symfony\Contracts\Translation\TranslatorInterface;
  15. use Webkul\UVDesk\CoreFrameworkBundle\Services\UVDeskService;
  16. use Webkul\UVDesk\CoreFrameworkBundle\Services\TicketService;
  17. use Webkul\UVDesk\CoreFrameworkBundle\Services\EmailService;
  18. use Symfony\Component\EventDispatcher\EventDispatcherInterface;
  19. use Symfony\Component\HttpKernel\KernelInterface;
  20. use Doctrine\ORM\EntityManagerInterface;
  21. use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
  22. use Symfony\Component\DependencyInjection\ContainerInterface;
  23. use Webkul\UVDesk\CoreFrameworkBundle\Entity\Attachment;
  24. use Webkul\UVDesk\CoreFrameworkBundle\Entity\Thread;
  25. use Webkul\UVDesk\CoreFrameworkBundle\Entity\Ticket as CoreBundleTicket;
  26. use Webkul\UVDesk\CoreFrameworkBundle\Entity\Tag;
  27. use Webkul\UVDesk\CoreFrameworkBundle\Entity\TicketType;
  28. use Webkul\UVDesk\CoreFrameworkBundle\Entity\SupportRole;
  29. use Webkul\UVDesk\CoreFrameworkBundle\Entity\User;
  30. use Webkul\UVDesk\CoreFrameworkBundle\Entity\TicketPriority;
  31. use Webkul\UVDesk\CoreFrameworkBundle\Entity\TicketStatus;
  32. use Webkul\UVDesk\CoreFrameworkBundle\Entity as CoreEntities;
  33. class Ticket extends AbstractController
  34. {
  35. private $userService;
  36. private $translator;
  37. private $eventDispatcher;
  38. private $ticketService;
  39. private $emailService;
  40. private $entityManagerInterface;
  41. private $containerInterface;
  42. private $kernel;
  43. public function __construct(UserService $userService, TranslatorInterface $translator, TicketService $ticketService, EmailService $emailService, EventDispatcherInterface $eventDispatcher, KernelInterface $kernel, EntityManagerInterface $entityManagerInterface, ContainerInterface $containerInterface)
  44. {
  45. $this->userService = $userService;
  46. $this->emailService = $emailService;
  47. $this->translator = $translator;
  48. $this->ticketService = $ticketService;
  49. $this->eventDispatcher = $eventDispatcher;
  50. $this->entityManagerInterface = $entityManagerInterface;
  51. $this->containerInterface = $containerInterface;
  52. $this->kernel = $kernel;
  53. }
  54. public function listTicketCollection(Request $request)
  55. {
  56. $entityManager = $this->getDoctrine()->getManager();
  57. return $this->render('@UVDeskCoreFramework//ticketList.html.twig', [
  58. 'ticketStatusCollection' => $entityManager->getRepository(TicketStatus::class)->findAll(),
  59. 'ticketTypeCollection' => $entityManager->getRepository(TicketType::class)->findByIsActive(true),
  60. 'ticketPriorityCollection' => $entityManager->getRepository(TicketPriority::class)->findAll(),
  61. ]);
  62. }
  63. public function loadTicket($ticketId, QuickActionButtonCollection $quickActionButtonCollection, ContainerInterface $container)
  64. {
  65. $entityManager = $this->getDoctrine()->getManager();
  66. $userRepository = $entityManager->getRepository(User::class);
  67. $ticketRepository = $entityManager->getRepository(CoreBundleTicket::class);
  68. $ticket = $ticketRepository->findOneById($ticketId);
  69. if (empty($ticket)) {
  70. throw new NotFoundHttpException('Page not found!');
  71. }
  72. $user = $this->userService->getSessionUser();
  73. // Proceed only if user has access to the resource
  74. if (false == $this->ticketService->isTicketAccessGranted($ticket, $user)) {
  75. throw new \Exception('Access Denied', 403);
  76. }
  77. $agent = $ticket->getAgent();
  78. $customer = $ticket->getCustomer();
  79. if (! empty($agent)) {
  80. $ticketAssignAgent = $agent->getId();
  81. $currentUser = $user->getId();
  82. }
  83. // Mark as viewed by agents
  84. if (false == $ticket->getIsAgentViewed()) {
  85. $ticket->setIsAgentViewed(true);
  86. $entityManager->persist($ticket);
  87. $entityManager->flush();
  88. }
  89. // Ticket Authorization
  90. $supportRole = $user->getCurrentInstance()->getSupportRole()->getCode();
  91. switch($supportRole) {
  92. case 'ROLE_ADMIN':
  93. case 'ROLE_SUPER_ADMIN':
  94. break;
  95. case 'ROLE_AGENT':
  96. $accessLevel = (int) $user->getCurrentInstance()->getTicketAccessLevel();
  97. switch($accessLevel) {
  98. case TicketRepository::TICKET_GLOBAL_ACCESS:
  99. break;
  100. case TicketRepository::TICKET_GROUP_ACCESS:
  101. $supportGroups = array_map(function($supportGroup) { return $supportGroup->getId(); }, $user->getCurrentInstance()->getSupportGroups()->getValues());
  102. $ticketAccessableGroups = $ticket->getSupportGroup() ? [$ticket->getSupportGroup()->getId()] : [];
  103. if ($ticket->getSupportTeam()) {
  104. $ticketSupportTeamGroups = array_map(function($supportGroup) { return $supportGroup->getId(); }, $ticket->getSupportTeam()->getSupportGroups()->getValues());
  105. $ticketAccessableGroups = array_merge($ticketAccessableGroups, $ticketSupportTeamGroups);
  106. }
  107. $isAccessableGroupFound = false;
  108. foreach ($ticketAccessableGroups as $groupId) {
  109. if (in_array($groupId, $supportGroups)) {
  110. $isAccessableGroupFound = true;
  111. break;
  112. }
  113. }
  114. if (! $isAccessableGroupFound && !($ticketAssignAgent == $currentUser)) {
  115. throw new NotFoundHttpException('Page not found!');
  116. }
  117. break;
  118. case TicketRepository::TICKET_TEAM_ACCESS:
  119. $supportTeams = array_map(function($supportTeam) { return $supportTeam->getId(); }, $user->getCurrentInstance()->getSupportTeams()->getValues());
  120. $supportTeam = $ticket->getSupportTeam();
  121. if (!($supportTeam && in_array($supportTeam->getId(), $supportTeams)) && !($ticketAssignAgent == $currentUser)) {
  122. throw new NotFoundHttpException('Page not found!');
  123. }
  124. break;
  125. default:
  126. $collaborators = array_map( function ($collaborator) { return $collaborator->getId(); }, $ticket->getCollaborators()->getValues());
  127. $accessableAgents = array_merge($collaborators, $ticket->getAgent() ? [$ticket->getAgent()->getId()] : []);
  128. if (!in_array($user->getId(), $accessableAgents)) {
  129. throw new NotFoundHttpException('Page not found!');
  130. }
  131. break;
  132. }
  133. break;
  134. default:
  135. throw new NotFoundHttpException('Page not found!');
  136. }
  137. $quickActionButtonCollection->prepareAssets();
  138. return $this->render('@UVDeskCoreFramework//ticket.html.twig', [
  139. 'ticket' => $ticket,
  140. 'totalReplies' => $ticketRepository->countTicketTotalThreads($ticket->getId()),
  141. 'totalCustomerTickets' => ($ticketRepository->countCustomerTotalTickets($customer, $container) - 1),
  142. 'initialThread' => $this->ticketService->getTicketInitialThreadDetails($ticket),
  143. 'ticketAgent' => ! empty($agent) ? $agent->getAgentInstance()->getPartialDetails() : null,
  144. 'customer' => $customer->getCustomerInstance()->getPartialDetails(),
  145. 'currentUserDetails' => $user->getAgentInstance()->getPartialDetails(),
  146. 'supportGroupCollection' => $userRepository->getSupportGroups(),
  147. 'supportTeamCollection' => $userRepository->getSupportTeams(),
  148. 'ticketStatusCollection' => $entityManager->getRepository(TicketStatus::class)->findAll(),
  149. 'ticketTypeCollection' => $entityManager->getRepository(TicketType::class)->findByIsActive(true),
  150. 'ticketPriorityCollection' => $entityManager->getRepository(TicketPriority::class)->findAll(),
  151. 'ticketNavigationIteration' => $ticketRepository->getTicketNavigationIteration($ticket, $container),
  152. 'ticketLabelCollection' => $ticketRepository->getTicketLabelCollection($ticket, $user),
  153. ]);
  154. }
  155. public function saveTicket(Request $request)
  156. {
  157. $requestParams = $request->request->all();
  158. $entityManager = $this->getDoctrine()->getManager();
  159. $response = $this->redirect($this->generateUrl('helpdesk_member_ticket_collection'));
  160. if (
  161. $request->getMethod() != 'POST'
  162. || false == $this->userService->isAccessAuthorized('ROLE_AGENT_CREATE_TICKET')
  163. ) {
  164. return $response;
  165. }
  166. $website = $entityManager->getRepository(CoreEntities\Website::class)->findOneByCode('knowledgebase');
  167. if (
  168. ! empty($requestParams['from'])
  169. && $this->ticketService->isEmailBlocked($requestParams['from'], $website)
  170. ) {
  171. $request->getSession()->getFlashBag()->set('warning', $this->translator->trans('Warning ! Cannot create ticket, given email is blocked by admin.'));
  172. return $this->redirect($this->generateUrl('helpdesk_member_ticket_collection'));
  173. }
  174. // Get referral ticket if any
  175. $ticketValidationGroup = 'CreateTicket';
  176. $referralURL = $request->headers->get('referer');
  177. if (! empty($referralURL)) {
  178. $iterations = explode('/', $referralURL);
  179. $referralId = array_pop($iterations);
  180. $expectedReferralURL = $this->generateUrl('helpdesk_member_ticket', ['ticketId' => $referralId], UrlGeneratorInterface::ABSOLUTE_URL);
  181. if ($referralURL === $expectedReferralURL) {
  182. $referralTicket = $entityManager->getRepository(CoreBundleTicket::class)->findOneById($referralId);
  183. if (! empty($referralTicket)) {
  184. $ticketValidationGroup = 'CustomerCreateTicket';
  185. }
  186. }
  187. }
  188. $ticketType = $entityManager->getRepository(TicketType::class)->findOneById($requestParams['type']);
  189. try {
  190. if ($this->userService->isFileExists('apps/uvdesk/custom-fields')) {
  191. $customFieldsService = $this->get('uvdesk_package_custom_fields.service');
  192. } else if ($this->userService->isFileExists('apps/uvdesk/form-component')) {
  193. $customFieldsService = $this->get('uvdesk_package_form_component.service');
  194. }
  195. if (! empty($customFieldsService)) {
  196. extract($customFieldsService->customFieldsValidation($request, 'user'));
  197. }
  198. } catch (\Exception $e) {
  199. // @TODO: Log execption message
  200. }
  201. if (! empty($errorFlashMessage)) {
  202. $this->addFlash('warning', $errorFlashMessage);
  203. }
  204. $ticketProxy = new CoreFrameworkBundleDataProxies\CreateTicketDataClass();
  205. $form = $this->createForm(CoreFrameworkBundleForms\CreateTicket::class, $ticketProxy);
  206. // Validate Ticket Details
  207. $form->submit($requestParams);
  208. if (false == $form->isSubmitted() || false == $form->isValid()) {
  209. if (false === $form->isValid()) {
  210. // @TODO: We need to handle form errors gracefully.
  211. // We should also look into switching to an xhr request instead.
  212. // $form->getErrors(true);
  213. }
  214. return $this->redirect(!empty($referralURL) ? $referralURL : $this->generateUrl('helpdesk_member_ticket_collection'));
  215. }
  216. if ('CustomerCreateTicket' === $ticketValidationGroup && !empty($referralTicket)) {
  217. // Retrieve customer details from referral ticket
  218. $customer = $referralTicket->getCustomer();
  219. $customerPartialDetails = $customer->getCustomerInstance()->getPartialDetails();
  220. } else if (null != $ticketProxy->getFrom() && null != $ticketProxy->getName()) {
  221. // Create customer if account does not exists
  222. $customer = $entityManager->getRepository(User::class)->findOneByEmail($ticketProxy->getFrom());
  223. if (
  224. empty($customer)
  225. || null == $customer->getCustomerInstance()
  226. ) {
  227. $role = $entityManager->getRepository(SupportRole::class)->findOneByCode('ROLE_CUSTOMER');
  228. // Create User Instance
  229. $customer = $this->userService->createUserInstance($ticketProxy->getFrom(), $ticketProxy->getName(), $role, [
  230. 'source' => 'website',
  231. 'active' => true
  232. ]);
  233. }
  234. }
  235. $ticketData = [
  236. 'from' => $customer->getEmail(),
  237. 'name' => $customer->getFirstName() . ' ' . $customer->getLastName(),
  238. 'type' => $ticketProxy->getType(),
  239. 'subject' => $ticketProxy->getSubject(),
  240. // @TODO: We need to enable support for html messages.
  241. // Our focus here instead should be to prevent XSS (filter js)
  242. 'message' => str_replace(['&lt;script&gt;', '&lt;/script&gt;'], '', htmlspecialchars($ticketProxy->getReply())),
  243. 'firstName' => $customer->getFirstName(),
  244. 'lastName' => $customer->getLastName(),
  245. 'type' => $ticketProxy->getType(),
  246. 'role' => 4,
  247. 'source' => 'website',
  248. 'threadType' => 'create',
  249. 'createdBy' => 'agent',
  250. 'customer' => $customer,
  251. 'user' => $this->getUser(),
  252. 'attachments' => $request->files->get('attachments'),
  253. ];
  254. $thread = $this->ticketService->createTicketBase($ticketData);
  255. $ticket = $thread->getTicket();
  256. // Trigger ticket created event
  257. try {
  258. $event = new CoreWorkflowEvents\Ticket\Create();
  259. $event
  260. ->setTicket($ticket)
  261. ;
  262. $this->eventDispatcher->dispatch($event, 'uvdesk.automation.workflow.execute');
  263. } catch (\Exception $e) {
  264. // Skip Automation
  265. }
  266. if (! empty($thread)) {
  267. $ticket = $thread->getTicket();
  268. if (
  269. $request->request->get('customFields')
  270. || $request->files->get('customFields')
  271. ) {
  272. $this->ticketService->addTicketCustomFields($thread, $request->request->get('customFields'), $request->files->get('customFields'));
  273. }
  274. $this->addFlash('success', $this->translator->trans('Success ! Ticket has been created successfully.'));
  275. if ($this->userService->isAccessAuthorized('ROLE_ADMIN')) {
  276. return $this->redirect($this->generateUrl('helpdesk_member_ticket', ['ticketId' => $ticket->getId()]));
  277. }
  278. } else {
  279. $this->addFlash('warning', $this->translator->trans('Could not create ticket, invalid details.'));
  280. }
  281. return $this->redirect(!empty($referralURL) ? $referralURL : $this->generateUrl('helpdesk_member_ticket_collection'));
  282. }
  283. public function listTicketTypeCollection(Request $request)
  284. {
  285. if (! $this->userService->isAccessAuthorized('ROLE_AGENT_MANAGE_TICKET_TYPE')) {
  286. return $this->redirect($this->generateUrl('helpdesk_member_dashboard'));
  287. }
  288. return $this->render('@UVDeskCoreFramework/ticketTypeList.html.twig');
  289. }
  290. public function ticketType(Request $request)
  291. {
  292. if (! $this->userService->isAccessAuthorized('ROLE_AGENT_MANAGE_TICKET_TYPE')) {
  293. return $this->redirect($this->generateUrl('helpdesk_member_dashboard'));
  294. }
  295. $errorContext = [];
  296. $em = $this->getDoctrine()->getManager();
  297. if ($id = $request->attributes->get('ticketTypeId')) {
  298. $type = $em->getRepository(TicketType::class)->find($id);
  299. if (! $type) {
  300. $this->noResultFound();
  301. }
  302. } else {
  303. $type = new CoreFrameworkBundleEntities\TicketType();
  304. }
  305. if ($request->getMethod() == "POST") {
  306. $data = $request->request->all();
  307. $ticketType = $em->getRepository(TicketType::class)->findOneByCode($data['code']);
  308. if (
  309. ! empty($ticketType)
  310. && $id != $ticketType->getId()
  311. ) {
  312. $this->addFlash('warning', sprintf('Error! Ticket type with same name already exist'));
  313. } else {
  314. $type->setCode(trim($data['code']));
  315. $type->setDescription(trim($data['description']));
  316. $type->setIsActive(isset($data['isActive']) ? 1 : 0);
  317. $em->persist($type);
  318. $em->flush();
  319. if (! $request->attributes->get('ticketTypeId')) {
  320. $this->addFlash('success', $this->translator->trans('Success! Ticket type saved successfully.'));
  321. } else {
  322. $this->addFlash('success', $this->translator->trans('Success! Ticket type updated successfully.'));
  323. }
  324. return $this->redirect($this->generateUrl('helpdesk_member_ticket_type_collection'));
  325. }
  326. }
  327. return $this->render('@UVDeskCoreFramework/ticketTypeAdd.html.twig', array(
  328. 'type' => $type,
  329. 'errors' => json_encode($errorContext)
  330. ));
  331. }
  332. public function listTagCollection(Request $request)
  333. {
  334. if (!$this->userService->isAccessAuthorized('ROLE_AGENT_MANAGE_TAG')) {
  335. return $this->redirect($this->generateUrl('helpdesk_member_dashboard'));
  336. }
  337. $enabled_bundles = $this->getParameter('kernel.bundles');
  338. return $this->render('@UVDeskCoreFramework/supportTagList.html.twig', [
  339. 'articlesEnabled' => in_array('UVDeskSupportCenterBundle', array_keys($enabled_bundles)),
  340. ]);
  341. }
  342. public function removeTicketTagXHR($tagId, Request $request)
  343. {
  344. if (!$this->userService->isAccessAuthorized('ROLE_AGENT_MANAGE_TAG')) {
  345. return $this->redirect($this->generateUrl('helpdesk_member_dashboard'));
  346. }
  347. $json = [];
  348. if($request->getMethod() == "DELETE") {
  349. $em = $this->getDoctrine()->getManager();
  350. $tag = $em->getRepository(Tag::class)->find($tagId);
  351. if ($tag) {
  352. $em->remove($tag);
  353. $em->flush();
  354. $json['alertClass'] = 'success';
  355. $json['alertMessage'] = $this->translator->trans('Success ! Tag removed successfully.');
  356. }
  357. }
  358. $response = new Response(json_encode($json));
  359. $response->headers->set('Content-Type', 'application/json');
  360. return $response;
  361. }
  362. public function trashTicket(Request $request)
  363. {
  364. $ticketId = $request->attributes->get('ticketId');
  365. $entityManager = $this->getDoctrine()->getManager();
  366. $ticket = $entityManager->getRepository(CoreBundleTicket::class)->find($ticketId);
  367. if (! $ticket) {
  368. $this->noResultFound();
  369. }
  370. $user = $this->userService->getSessionUser();
  371. // Proceed only if user has access to the resource
  372. if (false == $this->ticketService->isTicketAccessGranted($ticket, $user)) {
  373. throw new \Exception('Access Denied', 403);
  374. }
  375. if (! $ticket->getIsTrashed()) {
  376. $ticket->setIsTrashed(1);
  377. $entityManager->persist($ticket);
  378. $entityManager->flush();
  379. }
  380. // Trigger ticket delete event
  381. $event = new CoreWorkflowEvents\Ticket\Delete();
  382. $event
  383. ->setTicket($ticket)
  384. ;
  385. $this->eventDispatcher->dispatch($event, 'uvdesk.automation.workflow.execute');
  386. $this->addFlash('success', $this->translator->trans('Success ! Ticket moved to trash successfully.'));
  387. return $this->redirectToRoute('helpdesk_member_ticket_collection');
  388. }
  389. // Delete a ticket ticket permanently
  390. public function deleteTicket(Request $request)
  391. {
  392. $ticketId = $request->attributes->get('ticketId');
  393. $entityManager = $this->getDoctrine()->getManager();
  394. $ticket = $entityManager->getRepository(CoreBundleTicket::class)->find($ticketId);
  395. if (! $ticket) {
  396. $this->noResultFound();
  397. }
  398. $user = $this->userService->getSessionUser();
  399. // Proceed only if user has access to the resource
  400. if (false == $this->ticketService->isTicketAccessGranted($ticket, $user)) {
  401. throw new \Exception('Access Denied', 403);
  402. }
  403. $entityManager->remove($ticket);
  404. $entityManager->flush();
  405. $this->addFlash('success', $this->translator->trans('Success ! Success ! Ticket Id #'. $ticketId .' has been deleted successfully.'));
  406. return $this->redirectToRoute('helpdesk_member_ticket_collection');
  407. }
  408. public function downloadZipAttachment(Request $request)
  409. {
  410. $threadId = $request->attributes->get('threadId');
  411. $attachmentRepository = $this->getDoctrine()->getManager()->getRepository(Attachment::class);
  412. $threadRepository = $this->getDoctrine()->getManager()->getRepository(Thread::class);
  413. $thread = $threadRepository->findOneById($threadId);
  414. $attachment = $attachmentRepository->findByThread($threadId);
  415. if (! $attachment) {
  416. $this->noResultFound();
  417. }
  418. $ticket = $thread->getTicket();
  419. $user = $this->userService->getSessionUser();
  420. // Proceed only if user has access to the resource
  421. if (false == $this->ticketService->isTicketAccessGranted($ticket, $user)) {
  422. throw new \Exception('Access Denied', 403);
  423. }
  424. $zipName = 'attachments/' .$threadId.'.zip';
  425. $zip = new \ZipArchive;
  426. $zip->open($zipName, \ZipArchive::CREATE);
  427. if (count($attachment)) {
  428. foreach ($attachment as $attach) {
  429. $zip->addFile(ltrim($attach->getPath(), '/'));
  430. }
  431. }
  432. $zip->close();
  433. $response = new Response();
  434. $response->setStatusCode(200);
  435. $response->headers->set('Content-type', 'application/zip');
  436. $response->headers->set('Content-Disposition', 'attachment; filename=' . $threadId . '.zip');
  437. $response->headers->set('Content-length', filesize($zipName));
  438. $response->sendHeaders();
  439. $response->setContent(readfile($zipName));
  440. return $response;
  441. }
  442. public function downloadAttachment(Request $request)
  443. {
  444. $attachmentId = $request->attributes->get('attachmendId');
  445. $attachment = $this->getDoctrine()->getManager()->getRepository(Attachment::class)->findOneById($attachmentId);
  446. $baseurl = $request->getScheme() . '://' . $request->getHttpHost() . $request->getBasePath();
  447. if (empty($attachment)) {
  448. $this->noResultFound();
  449. }
  450. $thread = $attachment->getThread();
  451. if (! empty($thread)) {
  452. $ticket = $thread->getTicket();
  453. $user = $this->userService->getSessionUser();
  454. // Proceed only if user has access to the resource
  455. if (false == $this->ticketService->isTicketAccessGranted($ticket, $user)) {
  456. throw new \Exception('Access Denied', 403);
  457. }
  458. }
  459. $path = $this->kernel->getProjectDir() . "/public/". $attachment->getPath();
  460. $response = new Response();
  461. $response->setStatusCode(200);
  462. $response->headers->set('Content-type', $attachment->getContentType());
  463. $response->headers->set('Content-Disposition', 'attachment; filename='. $attachment->getName());
  464. $response->headers->set('Content-Length', $attachment->getSize());
  465. $response->sendHeaders();
  466. $response->setContent(readfile($path));
  467. return $response;
  468. }
  469. /**
  470. * If customer is playing with url and no result is found then what will happen
  471. * @return
  472. */
  473. protected function noResultFound()
  474. {
  475. throw new NotFoundHttpException('Not Found!');
  476. }
  477. }