diff --git a/local/modules/Front/Config/front.xml b/local/modules/Front/Config/front.xml index 4f32372a3..0a987eaa2 100644 --- a/local/modules/Front/Config/front.xml +++ b/local/modules/Front/Config/front.xml @@ -200,6 +200,15 @@ + + + Front\Controller\FeedController::generateAction + catalog + + + + + Thelia\Controller\Front\DefaultController::noAction diff --git a/local/modules/Front/Controller/FeedController.php b/local/modules/Front/Controller/FeedController.php new file mode 100644 index 000000000..d9e3a5c5c --- /dev/null +++ b/local/modules/Front/Controller/FeedController.php @@ -0,0 +1,200 @@ + + */ +class FeedController extends BaseFrontController { + + + /** + * Folder name for feeds cache + */ + const FEED_CACHE_DIR = "feeds"; + + /** + * Key prefix for feed cache + */ + const FEED_CACHE_KEY = "feed"; + + + /** + * render the RSS feed + * + * @param $context string The context of the feed : catalog, content. default: catalog + * @param $lang string The lang of the feed : fr_FR, en_US, ... default: default language of the site + * @param $id string The id of the parent element. The id of the main parent category for catalog context. + * The id of the content folder for content context + * @return Response + */ + public function generateAction($context, $lang, $id) + { + + /** @var Request $request */ + $request = $this->getRequest(); + + // context + if ("" === $context){ + $context = "catalog"; + } else if (! in_array($context, array("catalog", "content")) ){ + $this->pageNotFound(); + } + + // the locale : fr, en, + if ("" !== $lang) { + if (! $this->checkLang($lang)){ + $this->pageNotFound(); + } + } else { + try{ + $lang = Lang::getDefaultLanguage(); + $lang = $lang->getLocale(); + } catch (\RuntimeException $ex){ + // @todo generate error page + throw new \RuntimeException("No default language is defined. Please define one."); + } + } + if (null === $lang = LangQuery::create()->findOneByLocale($lang)){ + $this->pageNotFound(); + } + $lang = $lang->getId(); + + // check if element exists and is visible + if ("" !== $id){ + if (false === $this->checkId($context, $id)){ + $this->pageNotFound(); + } + } + + $flush = $request->query->get("flush", ""); + + // check if feed already in cache + $cacheContent = false; + + $cacheDir = $this->getCacheDir(); + $cacheKey = self::FEED_CACHE_KEY . $lang . $context . $id; + $cacheExpire = intval(ConfigQuery::read("feed_ttl", '7200')) ?: 7200; + + $cacheDriver = new FilesystemCache($cacheDir); + if (!($this->checkAdmin() && "" !== $flush)){ + $cacheContent = $cacheDriver->fetch($cacheKey); + } else { + $cacheDriver->delete($cacheKey); + } + + // if not in cache + if (false === $cacheContent){ + // render the view + $cacheContent = $this->renderRaw( + "feed", + array( + "_context_" => $context, + "_lang_" => $lang, + "_id_" => $id + ) + ); + // save cache + $cacheDriver->save($cacheKey, $cacheContent, $cacheExpire); + } + + $response = new Response(); + $response->setContent($cacheContent); + $response->headers->set('Content-Type', 'application/rss+xml'); + + return $response; + } + + + /** + * get the cache directory for feeds + * + * @return mixed|string + */ + protected function getCacheDir() + { + $cacheDir = $this->container->getParameter("kernel.cache_dir"); + $cacheDir = rtrim($cacheDir, '/'); + $cacheDir .= '/' . self::FEED_CACHE_DIR . '/'; + + return $cacheDir; + } + + /** + * Check if current user has ADMIN role + * + * @return bool + */ + protected function checkAdmin(){ + return $this->getSecurityContext()->hasAdminUser(); + } + + + /** + * Check if a lang is used + * + * @param $lang The lang code. e.g.: fr + * @return bool true if the language is used, otherwise false + */ + private function checkLang($lang) + { + // load locals + $lang = LangQuery::create() + ->findOneByLocale($lang); + + return (null !== $lang); + } + + + /** + * Ckeck if the element exists and is visible + * + * @param $context string catalog or content + * @param $id string id of the element + * @return bool + */ + private function checkId($context, $id) + { + $ret = false; + if (is_numeric($id)){ + if ("catalog" === $context){ + $cat = CategoryQuery::create()->findPk($id); + $ret = (null !== $cat && $cat->getVisible()); + } else { + $folder = FolderQuery::create()->findPk($id); + $ret = (null !== $folder && $folder->getVisible()); + } + } + return $ret; + } + +} \ No newline at end of file