src/Controller/PageDefaultController.php line 684

Open in your IDE?
  1. <?php
  2. namespace App\Controller;
  3. use App\Entity\HtmlBlocks;
  4. use App\Entity\Page;
  5. use App\Entity\PagePreview;
  6. use App\Service\OpenAiService;
  7. use App\Service\SimpleCache;
  8. use Doctrine\ORM\EntityManagerInterface;
  9. use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
  10. use Symfony\Component\HttpFoundation\Request;
  11. use Symfony\Component\HttpFoundation\Response;
  12. use Symfony\Component\Routing\Annotation\Route;
  13. use Symfony\Component\Routing\RouterInterface;
  14. class PageDefaultController extends AbstractController
  15. {
  16.     private array $invalidSetters = [
  17.         'setCreatedAt',
  18.         'setUpdatedAt',
  19.         'setTranslatableLocale',
  20.     ];
  21.     public function __construct(private readonly \App\Service\ServiceController $serviceController, private readonly EntityManagerInterface $em, private readonly RouterInterface $router) {}
  22.     #[Route(path'/members/dash'name'members_dash')]
  23.     public function membersDash(): Response
  24.     {
  25.         return $this->render('@theme/members/members-dash.html.twig');
  26.     }
  27.     public function generateAndModifyMetaDataTags($page$componentEnity)
  28.     {
  29.         if (!$componentEnity) {
  30.             return $page;
  31.         }
  32.         $possibleMetaTitles = ['getHeadline''getHeading''getTitle''getName''getMetaTitle'];
  33.         $possibleMetaDescription = ['getContent''getDescription''getExcerpt''getMetaDescription'];
  34.         if ('' == $page->getMetatitle()) {
  35.             $page->setMetatitle($page->getTitle());
  36.         }
  37.         if ('' == $page->getMetadescription()) {
  38.             $page->setMetadescription($page->getContent());
  39.         }
  40.         $metaDataArray = [];
  41.         foreach ($possibleMetaTitles as $metaTitle) {
  42.             if (method_exists($componentEnity$metaTitle)) {
  43.                 $data call_user_func([$componentEnity$metaTitle]);
  44.                 if ('' != $data) {
  45.                     $metaDataArray['title'] = call_user_func([$componentEnity$metaTitle]);
  46.                 }
  47.             }
  48.         }
  49.         foreach ($possibleMetaDescription as $metaDescription) {
  50.             if (method_exists($componentEnity$metaDescription)) {
  51.                 $data call_user_func([$componentEnity$metaDescription]);
  52.                 if ('' != $data) {
  53.                     $metaDataArray['description'] = $data;
  54.                 }
  55.             }
  56.         }
  57.         if (method_exists($componentEnity'getOgImage')) {
  58.             $data call_user_func([$componentEnity'getOgImage']);
  59.             if ($data) {
  60.                 $metaDataArray['ogImage'] = $data;
  61.             }
  62.         }
  63.         if (method_exists($componentEnity'getOgImageAlt')) {
  64.             $data call_user_func([$componentEnity'getOgImageAlt']);
  65.             if ('' != $data) {
  66.                 $metaDataArray['ogImageAlt'] = $data;
  67.             }
  68.         }
  69.         if (array_key_exists('title'$metaDataArray)) {
  70.             $page->setMetatitle($metaDataArray['title'].' | '.$page->getMetatitle());
  71.         }
  72.         if (array_key_exists('description'$metaDataArray)) {
  73.             $page->setMetadescription(strip_tags((string) $metaDataArray['description']));
  74.         }
  75.         if (array_key_exists('ogImage'$metaDataArray)) {
  76.             $page->setOgImage($metaDataArray['ogImage']);
  77.         }
  78.         if (array_key_exists('ogImageAlt'$metaDataArray)) {
  79.             $page->setOgImageAlt(strip_tags((string) $metaDataArray['ogImageAlt']));
  80.         }
  81.         return $page;
  82.     }
  83.     public function routeToControllerName($routename)
  84.     {
  85.         $routes $this->router->getRouteCollection();
  86.         return $routes->get($routename)->getDefaults();
  87.     }
  88.     public function findPageSlugParameters($slug)
  89.     {
  90.         $matches = [];
  91.         $regex '/{(\w*)}/';
  92.         preg_match_all($regex, (string) $slug$matches);
  93.         return $matches[1];
  94.     }
  95.     public function pageChecks($page)
  96.     {
  97.         if (== $page->isActive()) {
  98.             return false;
  99.         }
  100.         return new \DateTime() >= $page->getViewableFrom();
  101.     }
  102.     #[Route(path'/switch-locale/{_locale}'name'switch_locale')]
  103.     public function switchLocale(mixed $_locale): \Symfony\Component\HttpFoundation\RedirectResponse
  104.     {
  105.         return $this->redirect('/');
  106.         // return $this->redirect($request->headers->get('referer'));
  107.     }
  108.     // public function changeLocale(Request $request, $_locale, $slug){
  109.     //  $pageData = $this->routeMatcher($request, $slug);
  110.     //  return $pageData;
  111.     // }
  112.     #[Route(path'/page.php'name'page_php_home')]
  113.     public function getMethodRouter(SimpleCache $cacheRequest $request)
  114.     {
  115.         $params $request->query->all();
  116.         $debug $request->query->has('_debug');
  117.         $session $request->getSession();
  118.         $cmsComponentArray $this->serviceController->fetchCmsComponents();
  119.         // Using doctrine cache to store dynamic page slugs
  120.         // Used in twig function generatePath (converts id to slug) and assists links with translations
  121.         $slugCache $this->em->getRepository(Page::class)->findByLocale($request->getLocale());
  122.         $cache->set('slugCache'$slugCache);
  123.         if ($request->query->has('_locale')) {
  124.             $this->debug($debug'<p>CHANGING LOCALE</p>');
  125.             if ($request->getLocale() != $request->query->get('_locale')) {
  126.                 $session->set('_locale'$request->query->get('_locale'));
  127.                 $request->setLocale($session->get('_locale'$request->query->get('_locale')));
  128.                 return $this->redirect($this->generateUrl($request->get('_route'), $request->query->all()));
  129.             }
  130.         }
  131.         $structureEntities = [];
  132.         $pageID $request->query->get('page');
  133.         if (!is_numeric($pageID)) {
  134.             throw $this->createNotFoundException('No PageID passed');
  135.         }
  136.         $pageEntity $this->em->getRepository(Page::class)->find($pageID);
  137.         if (null === $pageEntity) {
  138.             throw $this->createNotFoundException('No Page found for id#'.$pageID);
  139.         }
  140.         $pageSlugArray explode('/'$pageEntity->getSlug());
  141.         $fullSegmentOrder = [];
  142.         if (count($pageSlugArray) > 1) {
  143.             $pageSlugArrayCount count($pageSlugArray);
  144.             for ($i 0$i < ($pageSlugArrayCount 1); ++$i) {
  145.                 if (array_key_exists($i$pageSlugArray) && substr_count($pageSlugArray[$i], '{') > 0) {
  146.                     $fullSegmentOrder[] = $pageSlugArray[$i];
  147.                     unset($pageSlugArray[$i]);
  148.                 }
  149.             }
  150.         }
  151.         $this->debug($debug'<p>'.$pageEntity->getSlug().'</p>');
  152.         if (substr_count($pageEntity->getSlug(), '{') > 0) {
  153.             foreach ($params as $key => $id) {
  154.                 $key strtolower($key);
  155.                 if (('_locale' != $key) || ('page' != $key) || ('_debug' != $key)) {
  156.                     $comkey $this->searchArrayKeyVal('slugEntity'$key$cmsComponentArray);
  157.                     $this->debug($debug"<p>Searching for '".$key."' against slugEntity in cmsComponentArray</p>");
  158.                     if (is_numeric($comkey)) {
  159.                         $order array_search($cmsComponentArray[$comkey]['slug'], $fullSegmentOrder);
  160.                         $this->debug($debug'<p>'.$order.' - '.$cmsComponentArray[$comkey]['slugEntity'].'</p>');
  161.                         $bundle str_replace('\\''', (string) $cmsComponentArray[$comkey]['bundle']).':'.$cmsComponentArray[$comkey]['slugEntity'];
  162.                         $structureEntities[$order] = $this->em->getRepository($bundle)->find($id);
  163.                     }
  164.                 }
  165.             }
  166.         }
  167.         $slugfixer implode('/'$pageSlugArray);
  168.         $slug $slugfixer;
  169.         ksort($structureEntities);
  170.         foreach ($structureEntities as $urlelement) {
  171.             $slug .= '/'.$urlelement->getSlug();
  172.         }
  173.         if ($debug) {
  174.             $this->debug($debug'<p>Path re-built to <strong>'.$slug.'</strong></p>');
  175.             $pageData $this->routeMatcherV2($requestltrim($slug'/'));
  176.             if (is_array($pageData)) {
  177.                 $pageAllowed $this->pageChecks($pageData['page']);
  178.                 if (false == $pageAllowed) {
  179.                     throw $this->createNotFoundException('Page view checks for PageID# "'.$pageData['page']->getId().'" has failed (disabled, before viewdate ect...) - so showing 404');
  180.                 }
  181.                 // HTML Blocks
  182.                 $htmlblocks = [];
  183.                 $assignedHtmlblocks $pageData['page']->getHtmlblocks();
  184.                 if ((is_countable($assignedHtmlblocks) ? count($assignedHtmlblocks) : 0) > 0) {
  185.                     $allHtmlBlocks $this->em->getRepository(HtmlBlocks::class)->findBy(['deleted' => false]);
  186.                     foreach ($assignedHtmlblocks as $assignedblock) {
  187.                         foreach ($allHtmlBlocks as $allHtmlBlock) {
  188.                             if ($assignedblock['blockId'] == $allHtmlBlock->getId()) {
  189.                                 $htmlblocks[] = [
  190.                                     'blockId' => $allHtmlBlock->getId(),
  191.                                     'position' => $assignedblock['position'],
  192.                                     'data' => $allHtmlBlock->getHtml(),
  193.                                 ];
  194.                             }
  195.                         }
  196.                     }
  197.                 }
  198.                 $pageMeta $pageData['page'];
  199.                 // replace metatitle if empty
  200.                 if ('' == $pageData['page']->getMetatitle()) {
  201.                     $pageMeta->setMetatitle($pageData['page']->getTitle());
  202.                 }
  203.                 // replace metatitles if exist on components
  204.                 foreach ($pageData['pageComponents'] as $pageComp) {
  205.                     $pageMeta $this->generateAndModifyMetaDataTags($pageData['page'], $pageComp['entity']);
  206.                 }
  207.                 return $this->render('@theme/templates/'.$pageData['page']->getTemplate()->getTemplateFile(), [
  208.                     'page' => $pageMeta,
  209.                     'slug' => $pageData['slug'],
  210.                     'pageComponents' => $pageData['pageComponents'],
  211.                     'pageHtmlBlocks' => $htmlblocks,
  212.                     'longUrl' => strtolower(implode('/'$params)),
  213.                 ]);
  214.             }   // this will be a redirect
  215.             return $pageData;
  216.         }
  217.         return $this->redirect(str_replace('//''/'$slug));
  218.     }
  219.     #[Route(path'/page-preview'name'page_preview_home')]
  220.     public function getPreviewMethodRouter(SimpleCache $cacheRequest $request)
  221.     {
  222.         $params $request->query->all();
  223.         $session $request->getSession();
  224.         $cmsComponentArray $this->serviceController->fetchCmsComponents();
  225.         // Using doctrine cache to store dynamic page slugs
  226.         // Used in twig function generatePath (converts id to slug) and assists links with translations
  227.         $slugCache $this->em->getRepository(Page::class)->findByLocale($request->getLocale());
  228.         $cache->set('slugCache'$slugCache);
  229.         if ($request->query->has('_locale') && $request->getLocale() != $request->query->get('_locale')) {
  230.             $session->set('_locale'$request->query->get('_locale'));
  231.             $request->setLocale($session->get('_locale'$request->query->get('_locale')));
  232.             return $this->redirect($this->generateUrl($request->get('_route'), $request->query->all()));
  233.         }
  234.         $structureEntities = [];
  235.         $pageID $request->query->get('id');
  236.         if (!is_numeric($pageID)) {
  237.             throw $this->createNotFoundException('No PageID passed');
  238.         }
  239.         $pageEntity $this->em->getRepository(Page::class)->find($pageID);
  240.         if (null === $pageEntity) {
  241.             throw $this->createNotFoundException('No Page found for id#'.$pageID);
  242.         }
  243.         if ($request->query->has('preview')) {
  244.             $previewId $request->query->get('preview');
  245.             $previewEntity $this->em->getRepository(PagePreview::class)->find($previewId);
  246.             if (null === $previewEntity) {
  247.                 throw $this->createNotFoundException('No PagePreview found for id#'.$previewId);
  248.             }
  249.             if ($previewEntity->getPage()->getId() != $pageEntity->getId()) {
  250.                 throw $this->createNotFoundException('PagePreview->pageID#'.$previewEntity->getPage()->getId().' does not match PageID#'.$pageID);
  251.             }
  252.             // get nessacary getters (dup content)
  253.             $validSetters $this->getSetters($previewEntity$pageEntity);
  254.             foreach ($validSetters as $validSetter) {
  255.                 if (in_array($validSetter$this->invalidSetters)) {
  256.                     continue;
  257.                 }
  258.                 $validGetter str_replace('set''get', (string) $validSetter);
  259.                 $pageEntity->{$validSetter}($previewEntity->{$validGetter}());
  260.             }
  261.         }
  262.         $pageSlugArray explode('/'$pageEntity->getSlug());
  263.         $fullSegmentOrder = [];
  264.         if (count($pageSlugArray) > 1) {
  265.             $pageSlugArrayCount count($pageSlugArray);
  266.             for ($i 0$i < ($pageSlugArrayCount 1); ++$i) {
  267.                 if (array_key_exists($i$pageSlugArray) && substr_count($pageSlugArray[$i], '{') > 0) {
  268.                     $fullSegmentOrder[] = $pageSlugArray[$i];
  269.                     unset($pageSlugArray[$i]);
  270.                 }
  271.             }
  272.         }
  273.         if (substr_count($pageEntity->getSlug(), '{') > 0) {
  274.             foreach ($params as $key => $id) {
  275.                 $key strtolower($key);
  276.                 if (('_locale' != $key) || ('page' != $key) || ('_debug' != $key)) {
  277.                     $comkey $this->searchArrayKeyVal('slugEntity'$key$cmsComponentArray);
  278.                     if (is_numeric($comkey)) {
  279.                         $order array_search($cmsComponentArray[$comkey]['slug'], $fullSegmentOrder);
  280.                         $bundle str_replace('\\''', (string) $cmsComponentArray[$comkey]['bundle']).':'.$cmsComponentArray[$comkey]['slugEntity'];
  281.                         $structureEntities[$order] = $this->em->getRepository($bundle)->find($id);
  282.                     }
  283.                 }
  284.             }
  285.         }
  286.         $slugfixer implode('/'$pageSlugArray);
  287.         $slug $slugfixer;
  288.         ksort($structureEntities);
  289.         foreach ($structureEntities as $urlelement) {
  290.             $slug .= '/'.$urlelement->getSlug();
  291.         }
  292.         $pageData $this->routeMatcherV2($requestltrim($slug'/'));
  293.         $pageData['page'] = $pageEntity;
  294.         if (is_array($pageData)) {
  295.             $pageAllowed $this->pageChecks($pageData['page']);
  296.             if (false == $pageAllowed) {
  297.                 throw $this->createNotFoundException('Page view checks for PageID# "'.$pageData['page']->getId().'" has failed (disabled, before viewdate ect...) - so showing 404');
  298.             }
  299.             // HTML Blocks
  300.             $htmlblocks = [];
  301.             $assignedHtmlblocks $pageData['page']->getHtmlblocks();
  302.             if ((is_countable($assignedHtmlblocks) ? count($assignedHtmlblocks) : 0) > 0) {
  303.                 $allHtmlBlocks $this->em->getRepository(HtmlBlocks::class)->findBy(['deleted' => false]);
  304.                 foreach ($assignedHtmlblocks as $assignedblock) {
  305.                     foreach ($allHtmlBlocks as $allHtmlBlock) {
  306.                         if ($assignedblock['blockId'] == $allHtmlBlock->getId()) {
  307.                             $htmlblocks[] = [
  308.                                 'blockId' => $allHtmlBlock->getId(),
  309.                                 'position' => $assignedblock['position'],
  310.                                 'data' => $allHtmlBlock->getHtml(),
  311.                             ];
  312.                         }
  313.                     }
  314.                 }
  315.             }
  316.             $pageMeta $pageData['page'];
  317.             // replace metatitle if empty
  318.             if ('' == $pageData['page']->getMetatitle()) {
  319.                 $pageMeta->setMetatitle($pageData['page']->getTitle());
  320.             }
  321.             // replace metatitles if exist on components
  322.             foreach ($pageData['pageComponents'] as $pageComp) {
  323.                 $pageMeta $this->generateAndModifyMetaDataTags($pageData['page'], $pageComp['entity']);
  324.             }
  325.             return $this->render('@theme/templates/'.$pageData['page']->getTemplate()->getTemplateFile(), [
  326.                 'page' => $pageMeta,
  327.                 'slug' => $pageData['slug'],
  328.                 'pageComponents' => $pageData['pageComponents'],
  329.                 'pageHtmlBlocks' => $htmlblocks,
  330.                 'longUrl' => strtolower(implode('/'$params)),
  331.                 'preview' => true,
  332.             ]);
  333.         }   // this will be a redirect
  334.         return $pageData;
  335.         return new Response('EOF');
  336.     }
  337.     public function routeMatcherV2($request$slug)
  338.     {
  339.         $multilingual $this->getParameter('multilingual');
  340.         $locale $request->getLocale();
  341.         $cmsComponentArray $this->serviceController->fetchCmsComponents();
  342.         $pageComponents = [];
  343.         $debug = (bool) $request->query->has('_debug');
  344.         $this->debug($debug'<p>ROUTER DEBUG<br/>This will show you feedback during the route match process</p>');
  345.         $this->debug($debug'<br/>Current Locale ['.$request->getLocale().']');
  346.         $this->debug($debug'<br/>Looking for: <strong>'.$slug.'</strong>');
  347.         // ////////////////////////
  348.         // SIMPLE MATCHES
  349.         // ////////////////////////
  350.         // simple direct match
  351.         // this will match the home page in any locale and any default 'en' page
  352.         $page $this->em->getRepository(Page::class)->findOneBy(['slug' => $slug'deleted' => false'active' => true]);
  353.         if (null !== $page) {
  354.             $pageComponents $this->getComponentData($debug$cmsComponentArray$page->getComponents(), $request$page->getId());
  355.             $this->debug($debug"<br/><span style='color:green' >(STEP1) Found - ".$page->getTitle().' (ID#'.$page->getId().')<br/>Will render page out of debug mode</span>');
  356.             return [
  357.                 'page' => $page,
  358.                 'slug' => $slug,
  359.                 'pageComponents' => $pageComponents,
  360.             ];
  361.         }
  362.         // simple direct match for SELECTED TRANSLATION
  363.         // this route will match translations - locales matched after query
  364.         $pageAll $this->em->getRepository(Page::class)->findAll();
  365.         foreach ($pageAll as $page) {
  366.             if ($page->getSlug() == $slug) {
  367.                 if (false == $request->query->has('preview') && ($page->isDeleted() || !$page->isActive())) {
  368.                     throw $this->createNotFoundException('Page Route for "'.$slug.'" has been deactived or deleted');
  369.                 }
  370.                 $pageComponents $this->getComponentData($debug$cmsComponentArray$page->getComponents(), $request$page->getId());
  371.                 $this->debug($debug"<br/><span style='color:green' >(STEP2- transaltion) Found - ".$page->getTitle().' (ID#'.$page->getId().')<br/>Will render page out of debug mode</span>');
  372.                 return [
  373.                     'page' => $page,
  374.                     'slug' => $slug,
  375.                     'pageComponents' => $pageComponents,
  376.                 ];
  377.             }
  378.         }
  379.         $this->debug($debug'<p>No direct matches found - looking for complex matches  (has a url component was used?)<br/>Checking All Pages:</p>');
  380.         // if no direct matches found  ( usually means a url component was used )
  381.         // ////////////////////////
  382.         // COMPLEX MATCHES
  383.         // ////////////////////////
  384.         $urlSegments explode('/', (string) $slug);
  385.         // ///////////////////////////////////////
  386.         // this is for debug reasons only ( logic repeated after this loop )
  387.         if ($debug) {
  388.             $this->debug($debug'<pre>');
  389.             $this->debug($debug'<p><strong>COMPLEX ROUTE MATCHING</strong></p>');
  390.             foreach ($pageAll as $page) {
  391.                 $pageSlugParametersArray $this->findPageSlugParameters($page->getSlug());
  392.                 $possiblePageSegments explode('/'$page->getSlug());
  393.                 $slugMatches array_intersect($urlSegments$possiblePageSegments);
  394.                 $count 0;
  395.                 $this->debug($debug'Looking for: <strong>'.$slug.'</strong><br/>');
  396.                 $this->debug($debug'Looking at : <strong>'.$page->getSlug().'</strong> - ID#'.$page->getId().'<br/>');
  397.                 if (count($possiblePageSegments) === count($urlSegments)) {
  398.                     $this->debug($debug"<span style='color:green; font-weight:bold' >Passed phase 1</span>");
  399.                     ++$count;
  400.                 }
  401.                 $this->debug($debug' - '.count($possiblePageSegments).'/'.count($urlSegments).' URL Segment Count');
  402.                 if ((is_countable($pageSlugParametersArray) ? count($pageSlugParametersArray) : 0) > 0) {
  403.                     ++$count;
  404.                     $this->debug($debug"<br/><span style='color:green; font-weight:bold' >Passed phase 2</span> - ".(is_countable($pageSlugParametersArray) ? count($pageSlugParametersArray) : 0).' URL Parameter Components');
  405.                 } else {
  406.                     $this->debug($debug'<br/>No URL components on this page');
  407.                 }
  408.                 if (count($slugMatches) > 0) {
  409.                     ++$count;
  410.                     $this->debug($debug"<br/><span style='color:green; font-weight:bold' >Passed phase 3</span> - ".count($slugMatches).' URL slug matches');
  411.                 } else {
  412.                     $this->debug($debug'<br/>No URL slug matches on this page');
  413.                 }
  414.                 if ((is_countable($pageSlugParametersArray) ? count($pageSlugParametersArray) : 0) + count($slugMatches) == count($urlSegments)) {
  415.                     ++$count;
  416.                     $this->debug($debug"<br/><span style='color:green; font-weight:bold' >Passed phase 4</span> - slugParameters + slugMatches = urlSegments");
  417.                 } else {
  418.                     $this->debug($debug'<br/>slugParameters + slugMatches dont add up to '.count($urlSegments));
  419.                 }
  420.                 if (== $count) {
  421.                     $this->debug($debug"<br/><span style='color:green; font-weight:bold' >SUCCESS!! - full match</span>");
  422.                     $confirmedDebugPage $page;
  423.                     $this->debug($debug"<br/><span style='color:green' >(STEP3- complex) Found - ".$confirmedDebugPage->getTitle().' (ID#'.$confirmedDebugPage->getId().')<br/>Will render page out of debug mode</span>');
  424.                 } else {
  425.                     $this->debug($debug'<br/>Not this page');
  426.                 }
  427.                 $this->debug($debug'<p>-----------------------------------</p>');
  428.             }// end of pages loop
  429.             if (!$confirmedDebugPage) {
  430.                 $this->debug($debug'<br/>Doh! - Route Not Matched ');
  431.             }
  432.             $this->debug($debug'</pre>');
  433.         }// end of debug
  434.         // /////////////////////////////////////
  435.         foreach ($pageAll as $page) {
  436.             $pageSlugParametersArray $this->findPageSlugParameters($page->getSlug());
  437.             $possiblePageSegments explode('/'$page->getSlug());
  438.             $slugMatches array_intersect($urlSegments$possiblePageSegments);
  439.             $count 0;
  440.             if (count($possiblePageSegments) === count($urlSegments)) {
  441.                 ++$count;
  442.             }
  443.             if ((is_countable($pageSlugParametersArray) ? count($pageSlugParametersArray) : 0) > 0) {
  444.                 ++$count;
  445.             }
  446.             if (count($slugMatches) > 0) {
  447.                 ++$count;
  448.             }
  449.             if ((is_countable($pageSlugParametersArray) ? count($pageSlugParametersArray) : 0) + count($slugMatches) == count($urlSegments)) {
  450.                 ++$count;
  451.             }
  452.             // Passed all 4 checks
  453.             if (== $count) {
  454.                 $confirmedPage $page;
  455.             }
  456.         }// end of pages loop
  457.         if (isset($confirmedPage)) {
  458.             $this->debug($debug'<p>Calling renderPageWithURLComponents</p>');
  459.             return $this->renderPageWithURLComponents($request$confirmedPage$slug$cmsComponentArray);
  460.         }
  461.         $this->debug($debug'<p><strong>STILL NO MATCH</strong> - START CHECKING TRANSLATIONS - with seperate indervidual url segments</p>');
  462.         // exit;
  463.         // //////////////////////////
  464.         // Lacale auto switcher
  465.         // //////////////////////////
  466.         // if page still not found check translations then change locale to match
  467.         // Note: for the switcher to work you have to refresh the page
  468.         if ($multilingual) {
  469.             $repository $this->em->getRepository(\Gedmo\Translatable\Entity\Translation::class);
  470.             foreach ($pageAll as $page) {
  471.                 $translations $repository->findTranslations($page);
  472.                 foreach ($translations as $locale => $fields) {
  473.                     foreach ($urlSegments as $segment) {
  474.                         $transSlug explode('/', (string) $fields['slug']);
  475.                         foreach ($transSlug as $transSlugSegment) {
  476.                             $this->debug($debug'<br/>['.$locale.']'.$segment.':'.$transSlugSegment);
  477.                             if ($segment === $transSlugSegment) {
  478.                                 $this->debug($debug' <strong> - Match ***</strong>');
  479.                                 $diffrentLanguagesWithSameSlug[$locale] = 0;
  480.                                 $setLocale $locale;
  481.                                 // wasnt sure which was the correct method - keeps changing!
  482.                                 $request->getSession()->set('_locale'$setLocale);
  483.                                 $request->setLocale($setLocale);
  484.                                 if ($debug) {
  485.                                     $this->debug($debug'<p><strong>*** REFRESHING PAGE IN ['.$setLocale.'] - autoswitching ***</strong></p>');
  486.                                 } elseif ($request->query->has('_locale')) {
  487.                                     $this->debug($debug'<br/>Already Redirected - preventing loop');
  488.                                 } else {
  489.                                     return $this->redirect('/'.$slug.'?_locale='.$setLocale);
  490.                                 }
  491.                             }
  492.                         }
  493.                     }
  494.                 }
  495.             }
  496.             // check if en from different locale
  497.             foreach ($pageAll as $page) {
  498.                 $page->setTranslatableLocale('en');
  499.                 $this->em->refresh($page);
  500.                 foreach ($urlSegments as $segment) {
  501.                     $locale 'en';
  502.                     $transSlug explode('/'$page->getSlug());
  503.                     foreach ($transSlug as $transSlugSegment) {
  504.                         $this->debug($debug'<br/>['.$locale.']'.$segment.':'.$transSlugSegment);
  505.                         if ($segment === $transSlugSegment) {
  506.                             $this->debug($debug' <strong> - Match ***</strong>');
  507.                             $diffrentLanguagesWithSameSlug[$locale] = 0;
  508.                             $setLocale $locale;
  509.                             // wasnt sure which was the correct method - keeps changing!
  510.                             $request->getSession()->set('_locale'$setLocale);
  511.                             $request->setLocale($setLocale);
  512.                             if ($debug) {
  513.                                 $this->debug($debug'<p><strong>*** REFRESHING PAGE IN ['.$setLocale.'] - autoswitching ***</strong></p>');
  514.                             } elseif ($request->query->has('_locale')) {
  515.                                 $this->debug($debug'<br/>Already Redirected - preventing loop');
  516.                             } else {
  517.                                 return $this->redirect('/'.$slug.'?_locale='.$setLocale);
  518.                             }
  519.                         }
  520.                     }
  521.                 }
  522.             }
  523.         } // end if($multilingual)
  524.         // return new Response('<p>End - showing 404 page</p>');
  525.         throw $this->createNotFoundException('Route not matched: showing 404 page');
  526.     }
  527.     public function renderPageWithURLComponents($request$confirmedPage$slug$cmsComponentArray)
  528.     {
  529.         $debug = (bool) $request->query->has('_debug');
  530.         $this->debug($debug'<br/>looking for components:<br/>');
  531.         $pageSlugParametersArray $this->findPageSlugParameters($confirmedPage->getSlug());
  532.         if ($debug) {
  533.             $this->debug($debug'Current URL components to match<br/>');
  534.             print_r($pageSlugParametersArray);
  535.             $this->debug($debug'<p>If more than one URL component then the last one will be checked by default ('.(is_countable($pageSlugParametersArray) ? count($pageSlugParametersArray) : 0).' Found)</p>');
  536.         }
  537.         // extra check
  538.         $slugPieces explode('/', (string) $slug);
  539.         $confirmedPagePieces explode('/', (string) $confirmedPage->getSlug());
  540.         foreach ($cmsComponentArray as $cmsComponent) {
  541.             if ('' != $cmsComponent['slug']) {
  542.                 $slugCheck str_replace(' ''', (string) $cmsComponent['slug']);
  543.                 $this->debug($debug'<br/>Lookin at: '.$slugCheck);
  544.                 if ($slugCheck == '{'.end($pageSlugParametersArray).'}') {
  545.                     if ($debug) {
  546.                         $this->debug($debug' - Matched<br/>');
  547.                         print_r($cmsComponent);
  548.                     }
  549.                     $slugKey array_search('{'.end($pageSlugParametersArray).'}'$confirmedPagePieces);
  550.                     if (!is_numeric($slugKey)) {
  551.                         $this->debug($debug'<p>Oh No! -Key not found for "{'.end($pageSlugParametersArray).'}" in '.$confirmedPage->getSlug().'</p>');
  552.                     } else {
  553.                         $this->debug($debug"<p>Using the slug '".$slugPieces[$slugKey]."' on ".stripslashes((string) $cmsComponent['bundle']).':'.$cmsComponent['slugEntity'].' </p>');
  554.                     }
  555.                     $component_find_slug $slugPieces[$slugKey];
  556.                     $pageComponents $this->getComponentData($debug$cmsComponentArray$confirmedPage->getComponents(), $request$confirmedPage->getId(), $component_find_slug$slugPieces$pageSlugParametersArray);
  557.                     return [
  558.                         'page' => $confirmedPage,
  559.                         'slug' => $slug,
  560.                         'pageComponents' => $pageComponents,
  561.                     ];
  562.                 }
  563.             }
  564.         }
  565.     }
  566.     public function getComponentData($debug$cmsComponentArray$pageComponents$request$confirmedPageId$component_find_slug null$slugPieces = [], $pageSlugParametersArray = [])
  567.     {
  568.         if ($debug) {
  569.             $this->debug($debug'<pre>');
  570.             $this->debug($debug'<strong>AVAILABLE COMPONENTS:</strong><br/>');
  571.             $this->debug($debug"<table cellpadding='10' width='100%'>");
  572.             $this->debug($debug"<tr style='border-bottom:1px solid #666; font-size:12px'><th>Name</th><th>Slug</th><th>SlugEntity</th><th>Route</th><th>Type</th><th>Bundle</th><tr>");
  573.             foreach ($cmsComponentArray as $com) {
  574.                 $this->debug($debug"<tr style='border-top:1px dashed #666; font-size:12px'>");
  575.                 $this->debug($debug"<td style='white-space:nowrap; padding-top:5px; padding-bottom:5px'>".$com['name'].'</td>');
  576.                 $this->debug($debug"<td style='white-space:nowrap'>".$com['slug'].'</td>');
  577.                 $this->debug($debug"<td style='white-space:nowrap'>".$com['slugEntity'].'</td>');
  578.                 $this->debug($debug"<td style='white-space:nowrap'>".$com['route'].'</td>');
  579.                 $this->debug($debug"<td style='white-space:nowrap'>".$com['componentType'].'</td>');
  580.                 $this->debug($debug"<td style='white-space:nowrap'>".$com['bundle'].'</td>');
  581.                 $this->debug($debug'<tr>');
  582.             }
  583.             $this->debug($debug'</table>');
  584.             $this->debug($debug'</pre>');
  585.             $this->debug($debug'<pre>');
  586.             $this->debug($debug'<strong>ACTIVE PAGE COMPONENTS:</strong><br/>');
  587.             $this->debug($debug"<table cellpadding='10' width='100%'>");
  588.             $this->debug($debug"<tr style='border-bottom:1px solid #666; font-size:12px'><th>Position</th><th>Route</th><tr>");
  589.             foreach ($pageComponents as $com) {
  590.                 $this->debug($debug"<tr style='border-top:1px dashed #666;  font-size:12px'>");
  591.                 $this->debug($debug"<td style='white-space:nowrap; padding-top:5px; padding-bottom:5px'>".$com['position'].'</td>');
  592.                 $this->debug($debug"<td style='white-space:nowrap'>".$com['route'].'</td>');
  593.             }
  594.             $this->debug($debug'</table>');
  595.             $this->debug($debug'</pre>');
  596.         }
  597.         $pageComponentsReturn = [];
  598.         // Find out which URL segments are dynamic by removing
  599.         // preceeding segments (parent and page)
  600.         $totalSlug is_countable($slugPieces) ? count($slugPieces) : 0;
  601.         $totalPara is_countable($pageSlugParametersArray) ? count($pageSlugParametersArray) : 0;
  602.         $diff $totalSlug $totalPara;
  603.         for ($i 0$i $diff; ++$i) {
  604.             unset($slugPieces[$i]);
  605.         }
  606.         $slugPieces array_values($slugPieces);
  607.         $this->debug($debug'<pre>');
  608.         $this->debug($debug'<p><strong>COMPONENT LINKING</strong></p>');
  609.         // Workout extra segments - these will have no route
  610.         // and componentType = 'segment'
  611.         $extraUrlSegments $pageSlugParametersArray;
  612.         if ((is_countable($pageSlugParametersArray) ? count($pageSlugParametersArray) : 0) > 1) {
  613.             unset($extraUrlSegments[(is_countable($extraUrlSegments) ? count($extraUrlSegments) : 0) - 1], $slugPieces[count($slugPieces) - 1]);
  614.             $extraUrlSegments array_values($extraUrlSegments);
  615.             $slugPieces array_values($slugPieces);
  616.             $this->debug($debug'<p>SEGMENT ONLY ('.count($extraUrlSegments).' found)</p>');
  617.             // $this->debug($debug, "<br/>The next 2 array keys and values should match up");
  618.             // $this->debug($debug, "<br/>".print_r($extraUrlSegments, true));
  619.             // $this->debug($debug, "<br/>".print_r($slugPieces, true));
  620.             foreach ($extraUrlSegments as $index => $segment) {
  621.                 $comkey $this->searchArrayKeyVal('slug''{'.$segment.'}'$cmsComponentArray);
  622.                 if (is_numeric($comkey)) {
  623.                     $entity $this->getEntityData(['component' => $cmsComponentArray[$comkey], 'slug' => $slugPieces[$index]], $request$debug);
  624.                     $entityId $entity->getId();
  625.                     if ($entityId) {
  626.                         $pageComponentsReturn[] = [
  627.                             'position' => null,
  628.                             'urlKey' => $cmsComponentArray[$comkey]['slugEntity'],
  629.                             'urlValue' => $entityId,
  630.                             'data' => null,
  631.                             'entity' => $entity,
  632.                         ];
  633.                     }
  634.                 } else {
  635.                     $this->debug($debug"<p>Dynamic Slug '".$slugPieces[$index]."' for URL Annotation '".$segment."' NOT FOUND - but can continue, you should check your routes/link</p>");
  636.                 }
  637.             }
  638.         }
  639.         // Check all page components
  640.         $comCount 0;
  641.         foreach ($pageComponents as $pageComponent) {
  642.             if (null != $pageComponent['route']) {
  643.                 ++$comCount;
  644.                 $this->debug($debug'<p>------------------------------</p>');
  645.                 $this->debug($debug'<p>COMPONENT '.$comCount.'</p>');
  646.                 // found pagecomponent
  647.                 $comkey $this->searchArrayKeyVal('route'$pageComponent['route'], $cmsComponentArray);
  648.                 if (!is_numeric($comkey)) {
  649.                     $this->debug($debug'<p>The component <strong>'.$pageComponent['route'].'</strong> not found - has it been deleted?</p>');
  650.                     $pageComponentsReturn[] = [
  651.                         'position' => $pageComponent['position'],
  652.                         'urlKey' => null,
  653.                         'urlValue' => null,
  654.                         'data' => '',
  655.                         'entity' => null,
  656.                     ];
  657.                 } else {
  658.                     $this->debug($debug'<p>Comkey (#'.$comkey.') found for = '.$pageComponent['route']);
  659.                     $action $this->routeToControllerName($cmsComponentArray[$comkey]['route']);
  660.                     $this->debug($debug'<br/>Controller = '.$cmsComponentArray[$comkey]['route'].'</p>');
  661.                     // Non-URL reliant (slugless) component
  662.                     if (null == $cmsComponentArray[$comkey]['slug']) {
  663.                         $this->debug($debug'<p>SLUGLESS:<br/>RENDERING CONTROLLER into  = <strong>'.$action['_controller'].'</strong></p>');
  664.                         // fetch component data
  665.                         $response $this->forward($action['_controller'], ['request' => $request'pageId' => $confirmedPageId]);
  666.                         $pageComponentsReturn[] = [
  667.                             'position' => $pageComponent['position'],
  668.                             'urlKey' => null,
  669.                             'urlValue' => null,
  670.                             'data' => $response->getContent(),
  671.                             'entity' => null,
  672.                         ];
  673.                     } else {
  674.                         // URL Component found
  675.                         $removal = ['{''}']; // used for str_replace
  676.                         $controllerSlug str_replace($removal'', (string) $cmsComponentArray[$comkey]['slug']);
  677.                         // Get entityID for getMethodRouterAction - used to assist with locale/translation switching
  678.                         $entity $this->getEntityData(['component' => $cmsComponentArray[$comkey], 'slug' => $component_find_slug], $request$debug);
  679.                         // dd(['component' => $cmsComponentArray[$comkey], 'slug' => $component_find_slug], $request, $debug);
  680.                         $entityId $entity->getId();
  681.                         // fetch component data
  682.                         $this->debug($debug'<p>SLUG REQUIRED:<br/>RENDERING CONTROLLER = <strong>'.$action['_controller'].'</strong></p>');
  683.                         $response $this->forward($action['_controller'], ['request' => $request'pageId' => $confirmedPageId$controllerSlug => $component_find_slug]);
  684.                         $pageComponentsReturn[] = [
  685.                             'position' => $pageComponent['position'],
  686.                             'urlKey' => $cmsComponentArray[$comkey]['slugEntity'],
  687.                             'urlValue' => $entityId,
  688.                             'data' => $response->getContent(),
  689.                             'entity' => $entity,
  690.                         ];
  691.                     }
  692.                 } // end if(!is_numeric($comkey)
  693.             }
  694.         }
  695.         $this->debug($debug'</pre>');
  696.         return $pageComponentsReturn;
  697.     }
  698.     public function getEntityData($data$request$debug)
  699.     {
  700.         $locale $request->getLocale();
  701.         // $queryEntity = str_replace('\\', '', $data['component']['bundle'].':'.$data['component']['slugEntity']);
  702.         // $queryEntity = str_replace('/', '', $queryEntity);
  703.         $queryEntity '\\'.$data['component']['bundle'].'\\Entity\\'.$data['component']['slugEntity'];
  704.         $this->debug($debug'<p>ENTITY QUERY - '.$queryEntity);
  705.         if ('en' != $locale) {
  706.             $entity $this->em->getRepository($queryEntity)->findSlugWithLocale($data['slug'], $locale);
  707.             $this->debug($debug'->findSlugWithLocale(<strong>'.$data['slug'].'</strong>, <strong>'.$locale.'</strong>)');
  708.         } else {
  709.             $entity $this->em->getRepository($queryEntity)->findOneBySlug($data['slug']);
  710.             $this->debug($debug'->findOneBySlug(<strong>'.$data['slug'].'</strong>)');
  711.         }
  712.         if ($entity) {
  713.             $this->debug($debug'<br/>RESULT: EntityId =<strong>'.$entity->getId().'</strong></p>');
  714.             return $entity;
  715.         }
  716.         return false;
  717.     }
  718.     public function searchArrayKeyVal($sKey$id$array)
  719.     {
  720.         foreach ($array as $key => $val) {
  721.             if ($val[$sKey] == $id) {
  722.                 return $key;
  723.             }
  724.         }
  725.         foreach ($array as $key => $val) {
  726.             if (strtolower((string) $val[$sKey]) === strtolower((string) $id)) {
  727.                 return $key;
  728.             }
  729.         }
  730.         return false;
  731.     }
  732.     public function isJson($string)
  733.     {
  734.         try {
  735.             json_decode((string) $stringfalse512JSON_THROW_ON_ERROR);
  736.             return true;
  737.         } catch (\JsonException) {
  738.             return false;
  739.         }
  740.     }
  741.     // function to compare entities and returns common setters
  742.     public function getSetters($entity$entity2)
  743.     {
  744.         $classMethods get_class_methods($entity);
  745.         $classMethods2 get_class_methods($entity2);
  746.         $settersArray = [];
  747.         foreach ($classMethods as $classMethod) {
  748.             if (str_starts_with($classMethod'set')) {
  749.                 foreach ($classMethods2 as $classMethod2) {
  750.                     if (str_starts_with($classMethod2'set') && $classMethod == $classMethod2) {
  751.                         $settersArray[] = $classMethod2;
  752.                     }
  753.                 }
  754.             }
  755.         }
  756.         return $settersArray;
  757.     }
  758.     // THIS ROUTE MUST BE THE VERY LAST ROUTE LOADED
  759.     #[Route(path'/'name'home'defaults: ['slug' => 'home'])]
  760.     #[Route(path'/{slug}'name'router'requirements: ['slug' => '.+'], priority: -10)]
  761.     public function router(SimpleCache $cacheRequest $requestmixed $slug)
  762.     {
  763.         $session $request->getSession();
  764.         $slugCache $this->em->getRepository(Page::class)->findByLocale($request->getLocale());
  765.         $cache->set('slugCache'$slugCache);
  766.         $debug $request->query->has('_debug');
  767.         $this->debug($debug'Current Locale -'.$request->getLocale().' | request Locale -'.$request->query->get('_locale'));
  768.         if ($request->query->has('_locale')) {
  769.             $this->debug($debug'<p>CHANGING LOCALE</p>');
  770.             if ($request->getLocale() != $request->query->get('_locale')) {
  771.                 $session->set('_locale'$request->query->get('_locale'));
  772.                 $request->setLocale($session->get('_locale'$request->query->get('_locale')));
  773.                 return $this->redirect('/'.$slug);
  774.             }
  775.         }
  776.         $pageData $this->routeMatcherV2($request$slug);
  777.         // REDIRECT CHECKER
  778.         $this->debug($debug'Checking for redirects...');
  779.         foreach ($pageData['pageComponents'] as $pageComponent) {
  780.             $redirectCheck $pageComponent['data'];
  781.             if ($this->isJson($redirectCheck)) {
  782.                 $decoded json_decode((string) $redirectCheckfalse512JSON_THROW_ON_ERROR);
  783.                 if (property_exists($decoded'componentRedirect') && null !== $decoded->componentRedirect) {
  784.                     $this->debug($debug'Redirect found ... will goto '.$decoded->componentRedirect);
  785.                     if (!$debug) {
  786.                         return $this->redirect($decoded->componentRedirect);
  787.                     }
  788.                 }
  789.             }
  790.         }
  791.         if (is_array($pageData)) {
  792.             $longUrl 'page.php?Page='.$pageData['page']->getId();
  793.             if (array_key_exists('pageComponents'$pageData) && null != $pageData['pageComponents']) {
  794.                 foreach ($pageData['pageComponents'] as $component) {
  795.                     if (array_key_exists('urlKey'$component) && null != $component['urlKey']) {
  796.                         $longUrl .= '&'.$component['urlKey'].'='.$component['urlValue'];
  797.                     }
  798.                 }
  799.             }
  800.             $pageAllowed $this->pageChecks($pageData['page']);
  801.             if (false == $pageAllowed) {
  802.                 throw $this->createNotFoundException('Page Checks for pageId "'.$pageData['page']->getId().'" has failed (disabled, before viewdate ect...) - showing 404');
  803.             }
  804.             // HTML Blocks
  805.             $htmlblocks = [];
  806.             $assignedHtmlblocks $pageData['page']->getHtmlblocks();
  807.             if ((is_countable($assignedHtmlblocks) ? count($assignedHtmlblocks) : 0) > 0) {
  808.                 $allHtmlBlocks $this->em->getRepository(HtmlBlocks::class)->findBy(['deleted' => false]);
  809.                 foreach ($assignedHtmlblocks as $assignedblock) {
  810.                     foreach ($allHtmlBlocks as $allHtmlBlock) {
  811.                         if ($assignedblock['blockId'] == $allHtmlBlock->getId()) {
  812.                             $htmlblocks[] = [
  813.                                 'blockId' => $allHtmlBlock->getId(),
  814.                                 'position' => $assignedblock['position'],
  815.                                 'data' => $allHtmlBlock->getHtml(),
  816.                             ];
  817.                         }
  818.                     }
  819.                 }
  820.             }
  821.             $pageMeta $pageData['page'];
  822.             // replace metatitle if empty
  823.             if ('' == $pageData['page']->getMetatitle()) {
  824.                 $pageMeta->setMetatitle($pageData['page']->getTitle());
  825.             }
  826.             // replace metatitles if exist on components
  827.             foreach ($pageData['pageComponents'] as $pageComp) {
  828.                 $pageMeta $this->generateAndModifyMetaDataTags($pageData['page'], $pageComp['entity']);
  829.             }
  830.             return $this->render('@theme/templates/'.$pageData['page']->getTemplate()->getTemplateFile(), [
  831.                 'page' => $pageMeta,
  832.                 'slug' => $pageData['slug'],
  833.                 'pageComponents' => $pageData['pageComponents'],
  834.                 'pageHtmlBlocks' => $htmlblocks,
  835.                 'longUrl' => strtolower($longUrl),
  836.             ]);
  837.         }   // this will be a redirect
  838.         return $pageData;
  839.     }
  840.     private function debug(bool $debug$message): void
  841.     {
  842.         if ($debug) {
  843.             echo $message;
  844.         }
  845.     }
  846.     #[Route(path'/open-ai'name'members_dash')]
  847.     public function testAi(OpenAiService $aiRequest $request): void
  848.     {
  849.         $ai->test('Please write me a blog post about the future of AI in web development');
  850.     }
  851. }