@@ -200,6 +200,15 @@
|
||||
</route>
|
||||
<!-- end sitemap generator -->
|
||||
|
||||
<!-- feed generator -->
|
||||
<route id="feed.process" path="/feed/{context}/{lang}/{id}">
|
||||
<default key="_controller">Front\Controller\FeedController::generateAction</default>
|
||||
<default key="context">catalog</default>
|
||||
<default key="lang"></default>
|
||||
<default key="id"></default>
|
||||
</route>
|
||||
<!-- end feed generator -->
|
||||
|
||||
<!-- Default Route -->
|
||||
<route id="default" path="/{_view}">
|
||||
<default key="_controller">Thelia\Controller\Front\DefaultController::noAction</default>
|
||||
|
||||
200
local/modules/Front/Controller/FeedController.php
Normal file
200
local/modules/Front/Controller/FeedController.php
Normal file
@@ -0,0 +1,200 @@
|
||||
<?php
|
||||
/*************************************************************************************/
|
||||
/* This file is part of the Thelia package. */
|
||||
/* */
|
||||
/* Copyright (c) OpenStudio */
|
||||
/* email : dev@thelia.net */
|
||||
/* web : http://www.thelia.net */
|
||||
/* */
|
||||
/* For the full copyright and license information, please view the LICENSE.txt */
|
||||
/* file that was distributed with this source code. */
|
||||
/*************************************************************************************/
|
||||
|
||||
|
||||
namespace Front\Controller;
|
||||
|
||||
use Doctrine\Common\Cache\FilesystemCache;
|
||||
use Thelia\Controller\Front\BaseFrontController;
|
||||
use Thelia\Core\HttpFoundation\Request;
|
||||
use Thelia\Core\HttpFoundation\Response;
|
||||
use Thelia\Log\Tlog;
|
||||
use Thelia\Model\Base\FolderQuery;
|
||||
use Thelia\Model\CategoryQuery;
|
||||
use Thelia\Model\ConfigQuery;
|
||||
use Thelia\Model\Folder;
|
||||
use Thelia\Model\Lang;
|
||||
use Thelia\Model\LangQuery;
|
||||
|
||||
/**
|
||||
* Controller uses to generate RSS Feeds
|
||||
*
|
||||
* A default cache of 2 hours is used to avoid attack. You can flush cache if you have `ADMIN` role and pass flush=1 in
|
||||
* query string parameter.
|
||||
*
|
||||
* @package Front\Controller
|
||||
* @author Julien Chanséaume <jchanseaume@openstudio.fr>
|
||||
*/
|
||||
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_FR, en_US,
|
||||
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 string 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);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Check 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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -46,7 +46,8 @@ INSERT INTO `config` (`name`, `value`, `secured`, `hidden`, `created_at`, `updat
|
||||
('thelia_extra_version','', 1, 1, NOW(), NOW()),
|
||||
('front_cart_country_cookie_name','fcccn', 1, 1, NOW(), NOW()),
|
||||
('front_cart_country_cookie_expires','2592000', 1, 1, NOW(), NOW()),
|
||||
('sitemap_ttl','7200', 1, 1, NOW(), NOW());
|
||||
('sitemap_ttl','7200', 1, 1, NOW(), NOW()),
|
||||
('feed_ttl','7200', 1, 1, NOW(), NOW());
|
||||
|
||||
|
||||
INSERT INTO `config_i18n` (`id`, `locale`, `title`, `description`, `chapo`, `postscriptum`) VALUES
|
||||
|
||||
@@ -12,6 +12,8 @@ INSERT INTO `config` (`name`, `value`, `secured`, `hidden`, `created_at`, `updat
|
||||
('front_cart_country_cookie_expires','2592000', 1, 1, NOW(), NOW());
|
||||
INSERT INTO `config` (`name`, `value`, `secured`, `hidden`, `created_at`, `updated_at`) VALUES
|
||||
('sitemap_ttl','7200', 1, 1, NOW(), NOW());
|
||||
INSERT INTO `config` (`name`, `value`, `secured`, `hidden`, `created_at`, `updated_at`) VALUES
|
||||
('feed_ttl','7200', 1, 1, NOW(), NOW());
|
||||
|
||||
ALTER TABLE `module` ADD INDEX `idx_module_activate` (`activate`);
|
||||
|
||||
|
||||
0
templates/frontOffice/default/I18n/en_US.php
Normal file → Executable file
0
templates/frontOffice/default/I18n/en_US.php
Normal file → Executable file
4
templates/frontOffice/default/I18n/fr_FR.php
Normal file → Executable file
4
templates/frontOffice/default/I18n/fr_FR.php
Normal file → Executable file
@@ -16,6 +16,10 @@ return array(
|
||||
'Address' => 'Adresse',
|
||||
'Address %nb' => 'Adresse n°',
|
||||
'Address Update' => 'Mise à jour de l\'adresse',
|
||||
'All contents' => 'Tous les contenus',
|
||||
'All contents in' => 'tous les contenus de',
|
||||
'All products' => 'Tous les produits',
|
||||
'All products in' => 'Tous les produits de',
|
||||
'Amount' => 'Montant',
|
||||
'Availability' => 'Disponibilité',
|
||||
'Available' => 'Disponible',
|
||||
|
||||
@@ -18,6 +18,11 @@
|
||||
{/loop}
|
||||
{/block}
|
||||
|
||||
{* Feeds *}
|
||||
{block name="feeds"}
|
||||
<link rel="alternate" type="application/rss+xml" title="{intl l='All products in'} {category attr='title'}" href="{url path="/feed/catalog/{lang attr="locale"}/{content attr="id"}"}" />
|
||||
{/block}
|
||||
|
||||
{* Breadcrumb *}
|
||||
{block name='no-return-functions' append}
|
||||
{$breadcrumbs = []}
|
||||
|
||||
@@ -18,6 +18,11 @@
|
||||
{/loop}
|
||||
{/block}
|
||||
|
||||
{* Feeds *}
|
||||
{block name="feeds"}
|
||||
<link rel="alternate" type="application/rss+xml" title="{intl l='All contents in'} {content attr='title'}" href="{url path="/feed/content/{lang attr="locale"}/{content attr="id"}"}" />
|
||||
{/block}
|
||||
|
||||
{* Breadcrumb *}
|
||||
{block name='no-return-functions' append}
|
||||
{$breadcrumbs = []}
|
||||
|
||||
69
templates/frontOffice/default/feed.html
Normal file
69
templates/frontOffice/default/feed.html
Normal file
@@ -0,0 +1,69 @@
|
||||
<?xml version="1.0"?>
|
||||
<rss version="2.0">
|
||||
{* @todo order item by create date desc *}
|
||||
{assign var="store_name" value="{config key="store_name"}"}
|
||||
{loop type="lang" name="lang" id=$_lang_}
|
||||
{assign var="locale" value="{$LOCALE}"}
|
||||
{/loop}
|
||||
{if $_context_ == "catalog"}
|
||||
<channel>
|
||||
{if $_id_ == "" }
|
||||
<title>{intl l="All products in"} {$store_name}</title>
|
||||
<link>{url path="/"}</link>
|
||||
<description>{$store_name}</description>
|
||||
<language>{$locale|replace:'_':'-'|lower}</language>
|
||||
<lastBuildDate>{$smarty.now|date_format:'r'}</lastBuildDate>
|
||||
<generator>Thelia 2.0</generator>
|
||||
{else}
|
||||
{loop type="category" name="category" id=$_id_ lang=$_lang_ }
|
||||
<title>{intl l="All products in"} {$TITLE} - {$store_name}</title>
|
||||
<link>{$URL}</link>
|
||||
<description>{$CHAPO}</description>
|
||||
<language>{$LOCALE|replace:'_':'-'|lower}</language>
|
||||
<pubDate>{format_date date=$UPDATE_DATE format="r"}</pubDate>
|
||||
<lastBuildDate>{$smarty.now|date_format:'r'}</lastBuildDate>
|
||||
<generator>Thelia 2.0</generator>
|
||||
{/loop}
|
||||
{/if}
|
||||
{loop type="product" name="product" category_default=$_id_ lang=$_lang_ order="id_reverse" }
|
||||
<item>
|
||||
<title>{$TITLE}</title>
|
||||
<link>{$URL}</link>
|
||||
<description>{$CHAPO}</description>
|
||||
<pubDate>{format_date date=$CREATE_DATE format="r"}</pubDate>
|
||||
<guid>{$URL}</guid>
|
||||
</item>
|
||||
{/loop}
|
||||
</channel>
|
||||
{else}
|
||||
<channel>
|
||||
{if $_id_ == "" }
|
||||
<title>{intl l="All contents in"} {$store_name}</title>
|
||||
<link>{url path="/"}</link>
|
||||
<description>{$store_name}</description>
|
||||
<language>{$locale|replace:'_':'-'|lower}</language>
|
||||
<lastBuildDate>{$smarty.now|date_format:'r'}</lastBuildDate>
|
||||
<generator>Thelia 2.0</generator>
|
||||
{else}
|
||||
{loop type="folder" name="folder" id=$_id_ lang=$_lang_ }
|
||||
<title>{intl l="All contents in"} {$TITLE} - {$store_name}</title>
|
||||
<link>{$URL}</link>
|
||||
<description>{$CHAPO}</description>
|
||||
<language>{$LOCALE|replace:'_':'-'|lower}</language>
|
||||
<pubDate>{format_date date=$UPDATE_DATE format="r"}</pubDate>
|
||||
<lastBuildDate>{$smarty.now|date_format:'r'}</lastBuildDate>
|
||||
<generator>Thelia 2.0</generator>
|
||||
{/loop}
|
||||
{/if}
|
||||
{loop type="content" name="content" folder_default=$_id_ lang=$_lang_ }
|
||||
<item>
|
||||
<title>{$TITLE}</title>
|
||||
<link>{$URL}</link>
|
||||
<description>{$CHAPO}</description>
|
||||
<pubDate>{format_date date=$CREATE_DATE format="r"}</pubDate>
|
||||
<guid>{$URL}</guid>
|
||||
</item>
|
||||
{/loop}
|
||||
</channel>
|
||||
{/if}
|
||||
</rss>
|
||||
@@ -64,6 +64,11 @@ GNU General Public License : http://www.gnu.org/licenses/
|
||||
{images file='assets/img/favicon.ico'}<link rel="shortcut icon" type="image/x-icon" href="{$asset_url}">{/images}
|
||||
{images file='assets/img/favicon.png'}<link rel="icon" type="image/png" href="{$asset_url}" />{/images}
|
||||
|
||||
{* Feeds *}
|
||||
<link rel="alternate" type="application/rss+xml" title="{intl l='All products'}" href="{url path="/feed/catalog/{lang attr="locale"}"}" />
|
||||
<link rel="alternate" type="application/rss+xml" title="{intl l='All contents'}" href="{url path="/feed/content/{lang attr="locale"}"}" />
|
||||
{block name="feeds"}{/block}
|
||||
|
||||
{* HTML5 shim and Respond.js IE8 support of HTML5 elements and media queries *}
|
||||
<!--[if lt IE 9]>
|
||||
<script src="//oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js"></script>
|
||||
|
||||
Reference in New Issue
Block a user