/** * Filter the `core.request` event to decorated the action * * @param GetResponseEvent $event * * @return void * * @throws InternalErrorException * @throws PageNotFoundException */ public function onCoreRequest(GetResponseEvent $event) { $request = $event->getRequest(); $cms = $this->cmsSelector->retrieve(); if (!$cms) { throw new InternalErrorException('No CMS Manager available'); } // true cms page if ($request->get('_route') == PageInterface::PAGE_ROUTE_CMS_NAME) { return; } if (!$this->decoratorStrategy->isRequestDecorable($request)) { return; } $site = $this->siteSelector->retrieve(); if (!$site) { throw new InternalErrorException('No site available for the current request with uri ' . htmlspecialchars($request->getUri(), ENT_QUOTES)); } if ($site->getLocale() && $site->getLocale() != $request->get('_locale')) { throw new PageNotFoundException(sprintf('Invalid locale - site.locale=%s - request._locale=%s', $site->getLocale(), $request->get('_locale'))); } try { $page = $cms->getPageByRouteName($site, $request->get('_route')); if (!$page->getEnabled() && !$this->cmsSelector->isEditor()) { throw new PageNotFoundException(sprintf('The page is not enabled : id=%s', $page->getId())); } $cms->setCurrentPage($page); } catch (PageNotFoundException $e) { return; } }
/** * Handles a native error * * @param GetResponseForExceptionEvent $event * * @throws mixed */ private function handleNativeError(GetResponseForExceptionEvent $event) { if (true === $this->debug) { return; } if (true === $this->status) { return; } $this->status = true; $exception = $event->getException(); $statusCode = $exception instanceof HttpExceptionInterface ? $exception->getStatusCode() : 500; $cmsManager = $this->cmsManagerSelector->retrieve(); if ($event->getRequest()->get('_route') && !$this->decoratorStrategy->isRouteNameDecorable($event->getRequest()->get('_route'))) { return; } if (!$this->decoratorStrategy->isRouteUriDecorable($event->getRequest()->getPathInfo())) { return; } if (!$this->hasErrorCode($statusCode)) { return; } $message = sprintf('%s: %s (uncaught exception) at %s line %s', get_class($exception), $exception->getMessage(), $exception->getFile(), $exception->getLine()); $this->logException($exception, $exception, $message); try { $page = $this->getErrorCodePage($statusCode); $cmsManager->setCurrentPage($page); $response = $this->pageServiceManager->execute($page, $event->getRequest(), array(), new Response('', $statusCode)); } catch (\Exception $e) { $this->logException($exception, $e); $event->setException($e); $this->handleInternalError($event); return; } $event->setResponse($response); }
/** * {@inheritdoc} */ public final function onKernelRequest(GetResponseEvent $event) { if (!$this->decoratorStrategy->isRouteUriDecorable($event->getRequest()->getPathInfo())) { return; } $this->handleKernelRequest($event); if ($this->site) { if ($this->site->getTitle()) { $this->seoPage->setTitle($this->site->getTitle()); } if ($this->site->getMetaDescription()) { $this->seoPage->addMeta('name', 'description', $this->site->getMetaDescription()); } if ($this->site->getMetaKeywords()) { $this->seoPage->addMeta('name', 'keywords', $this->site->getMetaKeywords()); } } }
/** * Filter the `core.response` event to decorate the action. * * @param FilterResponseEvent $event * * @throws InternalErrorException */ public function onCoreResponse(FilterResponseEvent $event) { $cms = $this->cmsSelector->retrieve(); $response = $event->getResponse(); $request = $event->getRequest(); if ($this->cmsSelector->isEditor()) { $response->setPrivate(); if (!$request->cookies->has('sonata_page_is_editor')) { $response->headers->setCookie(new Cookie('sonata_page_is_editor', 1)); } } $page = $cms->getCurrentPage(); // display a validation page before redirecting, so the editor can edit the current page if ($page && $response->isRedirection() && $this->cmsSelector->isEditor() && !$request->get('_sonata_page_skip')) { $response = new Response($this->templating->render('SonataPageBundle:Page:redirect.html.twig', array('response' => $response, 'page' => $page))); $response->setPrivate(); $event->setResponse($response); return; } if (!$this->decoratorStrategy->isDecorable($event->getRequest(), $event->getRequestType(), $response)) { return; } if (!$this->cmsSelector->isEditor() && $request->cookies->has('sonata_page_is_editor')) { $response->headers->clearCookie('sonata_page_is_editor'); } if (!$page) { throw new InternalErrorException('No page instance available for the url, run the sonata:page:update-core-routes and sonata:page:create-snapshots commands'); } // only decorate hybrid page or page with decorate = true if (!$page->isHybrid() || !$page->getDecorate()) { return; } $parameters = array('content' => $response->getContent()); $response = $this->pageServiceManager->execute($page, $request, $parameters, $response); if (!$this->cmsSelector->isEditor() && $page->isCms()) { $response->setTtl($page->getTtl()); } $event->setResponse($response); }
/** * Handles a native error. * * @param GetResponseForExceptionEvent $event * * @throws mixed */ private function handleNativeError(GetResponseForExceptionEvent $event) { if (true === $this->debug) { return; } if (true === $this->status) { return; } $this->status = true; $exception = $event->getException(); $statusCode = $exception instanceof HttpExceptionInterface ? $exception->getStatusCode() : 500; $cmsManager = $this->cmsManagerSelector->retrieve(); if ($event->getRequest()->get('_route') && !$this->decoratorStrategy->isRouteNameDecorable($event->getRequest()->get('_route'))) { return; } if (!$this->decoratorStrategy->isRouteUriDecorable($event->getRequest()->getPathInfo())) { return; } if (!$this->hasErrorCode($statusCode)) { return; } $message = sprintf('%s: %s (uncaught exception) at %s line %s', get_class($exception), $exception->getMessage(), $exception->getFile(), $exception->getLine()); $this->logException($exception, $exception, $message); try { $page = $this->getErrorCodePage($statusCode); $cmsManager->setCurrentPage($page); if ($page->getSite()->getLocale() !== $event->getRequest()->getLocale()) { // Compare locales because Request returns the default one if null. // If 404, LocaleListener from HttpKernel component of Symfony is not called. // It uses the "_locale" attribute set by SiteSelectorInterface to set the request locale. // So in order to translate messages, force here the locale with the site. $event->getRequest()->setLocale($page->getSite()->getLocale()); } $response = $this->pageServiceManager->execute($page, $event->getRequest(), array(), new Response('', $statusCode)); } catch (\Exception $e) { $this->logException($exception, $e); $event->setException($e); $this->handleInternalError($event); return; } $event->setResponse($response); }
/** * Updates site page routes with all routes available in Symfony router service * * @param SiteInterface $site A page bundle site instance * @param OutputInterface $output A Symfony console output * * @return void */ public function update(SiteInterface $site, OutputInterface $output = null) { $message = sprintf(" > <info>Updating core routes for site</info> : <comment>%s - %s</comment>", $site->getName(), $site->getUrl()); $this->writeln($output, array(str_repeat('=', strlen($message)), "", $message, "", str_repeat('=', strlen($message)))); $knowRoutes = array(); $root = $this->pageManager->getPageByUrl($site, '/'); // no root url for the given website, create one if (!$root) { $root = $this->pageManager->create(array('routeName' => PageInterface::PAGE_ROUTE_CMS_NAME, 'name' => 'Homepage', 'url' => '/', 'site' => $site, 'requestMethod' => isset($requirements['_method']) ? $requirements['_method'] : 'GET|POST|HEAD|DELETE|PUT', 'slug' => '/')); $this->pageManager->save($root); } // Iterate over declared routes from the routing mechanism foreach ($this->router->getRouteCollection()->all() as $name => $route) { $name = trim($name); $knowRoutes[] = $name; $page = $this->pageManager->findOneBy(array('routeName' => $name, 'site' => $site->getId())); $routeHostRegex = $route->compile()->getHostRegex(); if (!$this->decoratorStrategy->isRouteNameDecorable($name) || !$this->decoratorStrategy->isRouteUriDecorable($route->getPath()) || null !== $routeHostRegex && !preg_match($routeHostRegex, $site->getHost())) { if ($page) { $page->setEnabled(false); $this->writeln($output, sprintf(' <error>DISABLE</error> <error>% -50s</error> %s', $name, $route->getPath())); } else { continue; } } $update = true; if (!$page) { $update = false; $requirements = $route->getRequirements(); $page = $this->pageManager->create(array('routeName' => $name, 'name' => $name, 'url' => $route->getPath(), 'site' => $site, 'requestMethod' => isset($requirements['_method']) ? $requirements['_method'] : 'GET|POST|HEAD|DELETE|PUT')); } if (!$page->getParent() && $page->getId() != $root->getId()) { $page->setParent($root); } $page->setSlug($route->getPath()); $page->setUrl($route->getPath()); $page->setRequestMethod(isset($requirements['_method']) ? $requirements['_method'] : 'GET|POST|HEAD|DELETE|PUT'); $this->pageManager->save($page); $this->writeln($output, sprintf(' <info>%s</info> % -50s %s', $update ? 'UPDATE ' : 'CREATE ', $name, $route->getPath())); } // Iterate over error pages foreach ($this->exceptionListener->getHttpErrorCodes() as $name) { $name = trim($name); $knowRoutes[] = $name; $page = $this->pageManager->findOneBy(array('routeName' => $name, 'site' => $site->getId())); if (!$page) { $params = array('routeName' => $name, 'name' => $name, 'decorate' => false, 'site' => $site); $page = $this->pageManager->create($params); $this->writeln($output, sprintf(' <info>%s</info> % -50s %s', 'CREATE ', $name, '')); } // an internal page or an error page should not have any parent (no direct access) $page->setParent(null); $this->pageManager->save($page); } $has = false; foreach ($this->pageManager->getHybridPages($site) as $page) { if (!$page->isHybrid() || $page->isInternal()) { continue; } if (!in_array($page->getRouteName(), $knowRoutes)) { if (!$has) { $has = true; $this->writeln($output, array('', 'Some hybrid pages does not exist anymore', str_repeat('-', 80))); } $this->writeln($output, sprintf(' <error>ERROR</error> %s', $page->getRouteName())); } } if ($has) { $this->writeln($output, <<<MSG <error> *WARNING* : Pages has been updated however some pages do not exist anymore. You must remove them manually. </error> MSG ); } }