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

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