src/ApplicationBundle/Modules/BookingDemo/Controller/BookingDemoPublicController.php line 26

Open in your IDE?
  1. <?php
  2. namespace ApplicationBundle\Modules\BookingDemo\Controller;
  3. use ApplicationBundle\Controller\GenericController;
  4. use CompanyGroupBundle\Entity\DemoRequest;
  5. use CompanyGroupBundle\Entity\DemoRequestSlot;
  6. use Symfony\Component\HttpFoundation\JsonResponse;
  7. use Symfony\Component\HttpFoundation\Request;
  8. use Symfony\Component\HttpFoundation\Response;
  9. class BookingDemoPublicController extends GenericController
  10. {
  11.     private static $slotHours = [
  12.         '09:00''09:20''09:40',
  13.         '10:00''10:20''10:40',
  14.         '11:00''11:20''11:40',
  15.         '14:00''14:20''14:40',
  16.         '15:00''15:20''15:40',
  17.         '16:00''16:20''16:40',
  18.     ];
  19.     public function BookingPageAction(Request $request)
  20.     {
  21.         return $this->render('@BookingDemo/pages/book_demo.html.twig', [
  22.             'page_title' => 'Book a Demo — HoneyBee ERP',
  23.         ]);
  24.     }
  25.     public function GetAvailableSlotsAction(Request $request$date '')
  26.     {
  27.         if (!$date || !preg_match('/^\d{4}-\d{2}-\d{2}$/'$date)) {
  28.             return new JsonResponse(['success' => false'slots' => []]);
  29.         }
  30.         $em $this->getDoctrine()->getManager('company_group');
  31.         $dayStart = new \DateTime($date ' 00:00:00');
  32.         $dayEnd   = new \DateTime($date ' 23:59:59');
  33.         $confirmedSlots $em->getRepository('CompanyGroupBundle\Entity\DemoConfirmed')
  34.             ->createQueryBuilder('c')
  35.             ->where('c.confirmedStart >= :dayStart AND c.confirmedStart <= :dayEnd')
  36.             ->setParameter('dayStart'$dayStart)
  37.             ->setParameter('dayEnd'$dayEnd)
  38.             ->getQuery()
  39.             ->getResult();
  40.         $bookedTimes = [];
  41.         foreach ($confirmedSlots as $cs) {
  42.             $bookedTimes[] = $cs->getConfirmedStart()->format('H:i');
  43.         }
  44.         $now   = new \DateTime();
  45.         $slots = [];
  46.         foreach (self::$slotHours as $time) {
  47.             $slotDt = new \DateTime($date ' ' $time ':00');
  48.             if ($slotDt <= $now) continue;
  49.             $slots[] = [
  50.                 'time'      => $time,
  51.                 'available' => !in_array($time$bookedTimes),
  52.             ];
  53.         }
  54.         return new JsonResponse(['success' => true'slots' => $slots]);
  55.     }
  56.     public function SubmitBookingAction(Request $request)
  57.     {
  58.         if (!$request->isMethod('POST')) {
  59.             return $this->redirectToRoute('book_demo_page');
  60.         }
  61.         $name         trim($request->request->get('name'''));
  62.         $email        trim($request->request->get('email'''));
  63.         $phone        trim($request->request->get('phone'''));
  64.         $companyName  trim($request->request->get('company_name'''));
  65.         $businessType trim($request->request->get('business_type'''));
  66.         $slots        $request->request->get('slots', []);
  67.         if (!$name || !filter_var($emailFILTER_VALIDATE_EMAIL) || empty($slots)) {
  68.             return new JsonResponse(['success' => false'message' => 'Please fill all required fields and select at least one slot.']);
  69.         }
  70.         $em $this->getDoctrine()->getManager('company_group');
  71.         $demoRequest = new DemoRequest();
  72.         $demoRequest->setName($name)
  73.             ->setEmail($email)
  74.             ->setPhone($phone)
  75.             ->setCompanyName($companyName)
  76.             ->setBusinessType($businessType)
  77.             ->setStatus('pending')
  78.             ->setMeetingToken(bin2hex(random_bytes(24)));
  79.         $em->persist($demoRequest);
  80.         $em->flush();
  81.         $priority 1;
  82.         foreach (array_slice($slots03) as $slotStr) {
  83.             $parts explode('|'$slotStr);
  84.             if (count($parts) !== 2) continue;
  85.             [$dateStr$timeStr] = $parts;
  86.             if (!preg_match('/^\d{4}-\d{2}-\d{2}$/'$dateStr)) continue;
  87.             if (!preg_match('/^\d{2}:\d{2}$/'$timeStr)) continue;
  88.             $start = new \DateTime($dateStr ' ' $timeStr ':00');
  89.             $end   = clone $start;
  90.             $end->modify('+20 minutes');
  91.             $slot = new DemoRequestSlot();
  92.             $slot->setRequestId($demoRequest->getId())
  93.                 ->setStartTime($start)
  94.                 ->setEndTime($end)
  95.                 ->setPriorityOrder($priority++);
  96.             $em->persist($slot);
  97.         }
  98.         $em->flush();
  99.         $this->sendPendingEmails($demoRequest$em);
  100.         return new JsonResponse([
  101.             'success' => true,
  102.             'message' => 'Your demo request has been submitted! We will confirm shortly.',
  103.         ]);
  104.     }
  105.     public function MeetingPageAction(Request $request$token '')
  106.     {
  107.         if (!$token) {
  108.             throw $this->createNotFoundException('Invalid meeting link.');
  109.         }
  110.         $em $this->getDoctrine()->getManager('company_group');
  111.         $demoRequest $em->getRepository('CompanyGroupBundle\Entity\DemoRequest')
  112.             ->findOneBy(['meetingToken' => $token'status' => 'confirmed']);
  113.         if (!$demoRequest) {
  114.             throw $this->createNotFoundException('Meeting not found or not yet confirmed.');
  115.         }
  116.         $confirmed $em->getRepository('CompanyGroupBundle\Entity\DemoConfirmed')
  117.             ->findOneBy(['requestId' => $demoRequest->getId()]);
  118.         if (!$confirmed) {
  119.             throw $this->createNotFoundException('Confirmed meeting details not found.');
  120.         }
  121.         $now   = new \DateTime();
  122.         $start $confirmed->getConfirmedStart();
  123.         $end   $confirmed->getConfirmedEnd();
  124.         $phase 'upcoming';
  125.         if ($now >= $start && $now <= $end) {
  126.             $phase 'live';
  127.         } elseif ($now $end) {
  128.             $phase 'expired';
  129.         }
  130.         return $this->render('@BookingDemo/pages/meeting.html.twig', [
  131.             'page_title'  => 'HoneyBee ERP Demo Meeting',
  132.             'demoRequest' => $demoRequest,
  133.             'confirmed'   => $confirmed,
  134.             'phase'       => $phase,
  135.             'startTs'     => $start->getTimestamp() * 1000,
  136.             'endTs'       => $end->getTimestamp() * 1000,
  137.         ]);
  138.     }
  139.     private function getAdminEmails(): array
  140.     {
  141.         $default = ['emrul.hasan@ourhoneybee.eu''mozibul.yasser@ourhoneybee.eu'];
  142.         try {
  143.             $raw $this->getParameter('demo_admin_emails');
  144.             if (!$raw) return $default;
  145.             $parsed array_filter(array_map('trim'explode(','$raw)));
  146.             return $parsed ?: $default;
  147.         } catch (\Exception $e) {
  148.             return $default;
  149.         }
  150.     }
  151.     private function smtpBase(): array
  152.     {
  153.         try {
  154.             return [
  155.                 'senderHash' => '_CUSTOM_',
  156.                 'smtpServer' => $this->getParameter('mailer_host'),
  157.                 'smtpPort'   => (int) $this->getParameter('mailer_port'),
  158.                 'userName'   => $this->getParameter('mailer_user'),
  159.                 'password'   => $this->getParameter('mailer_password'),
  160.                 'fromAddress'=> $this->getParameter('mailer_user'),
  161.             ];
  162.         } catch (\Exception $e) {
  163.             return ['senderHash' => '_DEFAULT_'];
  164.         }
  165.     }
  166.     private function sendPendingEmails(DemoRequest $demoRequest$em)
  167.     {
  168.         try {
  169.             $mailModule $this->get('mail_module');
  170.             $smtp       $this->smtpBase();
  171.             $mailModule->sendMyMail(array_merge($smtp, [
  172.                 'toAddress'    => $demoRequest->getEmail(),
  173.                 'subject'      => 'Your HoneyBee ERP Demo Request — Pending Confirmation',
  174.                 'mailTemplate' => '@BookingDemo/email/booking_pending_user.html.twig',
  175.                 'templateData' => [
  176.                     'name'        => $demoRequest->getName(),
  177.                     'companyName' => $demoRequest->getCompanyName() ?: '',
  178.                 ],
  179.             ]));
  180.             $subject      'New Demo Request — ' $demoRequest->getName() . ' (' . ($demoRequest->getCompanyName() ?: 'N/A') . ')';
  181.             $templateData = [
  182.                 'demoRequest' => [
  183.                     'id'           => $demoRequest->getId(),
  184.                     'name'         => $demoRequest->getName(),
  185.                     'email'        => $demoRequest->getEmail(),
  186.                     'phone'        => $demoRequest->getPhone() ?: '',
  187.                     'companyName'  => $demoRequest->getCompanyName() ?: '',
  188.                     'businessType' => $demoRequest->getBusinessType() ?: '',
  189.                 ],
  190.             ];
  191.             foreach ($this->getAdminEmails() as $adminEmail) {
  192.                 $mailModule->sendMyMail(array_merge($smtp, [
  193.                     'toAddress'    => $adminEmail,
  194.                     'subject'      => $subject,
  195.                     'mailTemplate' => '@BookingDemo/email/booking_pending_admin.html.twig',
  196.                     'templateData' => $templateData,
  197.                 ]));
  198.             }
  199.         } catch (\Exception $e) {
  200.             // Email failure must not break the booking flow
  201.         }
  202.     }
  203. }