Merge branch 'master' of https://github.com/thelia/thelia
Conflicts: templates/default/login.html
This commit is contained in:
@@ -219,10 +219,10 @@ abstract class BaseLoop
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \ModelCriteria $search
|
||||
* @param $pagination
|
||||
* @param ModelCriteria $search
|
||||
* @param $pagination
|
||||
*
|
||||
* @return array|\PropelModelPager
|
||||
* @return array|\Propel\Runtime\Util\PropelModelPager
|
||||
*/
|
||||
protected function searchWithPagination(ModelCriteria $search, &$pagination)
|
||||
{
|
||||
@@ -242,18 +242,21 @@ abstract class BaseLoop
|
||||
* @param array $columns the i18n columns
|
||||
* @param string $foreignTable the specified table (default to criteria table)
|
||||
* @param string $foreignKey the foreign key in this table (default to criteria table)
|
||||
*
|
||||
* @return mixed the locale
|
||||
*/
|
||||
protected function configureI18nProcessing(ModelCriteria $search, $columns = array('TITLE', 'CHAPO', 'DESCRIPTION', 'POSTSCRIPTUM'), $foreignTable = null, $foreignKey = 'ID') {
|
||||
protected function configureI18nProcessing(ModelCriteria $search, $columns = array('TITLE', 'CHAPO', 'DESCRIPTION', 'POSTSCRIPTUM'), $foreignTable = null, $foreignKey = 'ID', $forceReturn = false) {
|
||||
|
||||
/* manage translations */
|
||||
ModelCriteriaTools::getI18n(
|
||||
return ModelCriteriaTools::getI18n(
|
||||
$this->getBackend_context(),
|
||||
$this->getLang(),
|
||||
$search,
|
||||
$this->request->getSession()->getLocale(),
|
||||
$columns,
|
||||
$foreignTable,
|
||||
$foreignKey
|
||||
$foreignKey,
|
||||
$forceReturn
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -97,7 +97,7 @@ class Category extends BaseLoop
|
||||
$search = CategoryQuery::create();
|
||||
|
||||
/* manage translations */
|
||||
$this->configureI18nProcessing($search);
|
||||
$locale = $this->configureI18nProcessing($search);
|
||||
|
||||
$id = $this->getId();
|
||||
|
||||
@@ -184,7 +184,7 @@ class Category extends BaseLoop
|
||||
->set("DESCRIPTION", $category->getVirtualColumn('i18n_DESCRIPTION'))
|
||||
->set("POSTSCRIPTUM", $category->getVirtualColumn('i18n_POSTSCRIPTUM'))
|
||||
->set("PARENT", $category->getParent())
|
||||
->set("URL", $category->getUrl())
|
||||
->set("URL", $category->getUrl($locale))
|
||||
->set("PRODUCT_COUNT", $category->countChild())
|
||||
->set("VISIBLE", $category->getVisible() ? "1" : "0")
|
||||
->set("POSITION", $category->getPosition())
|
||||
|
||||
@@ -87,7 +87,7 @@ class Content extends BaseLoop
|
||||
$search = ContentQuery::create();
|
||||
|
||||
/* manage translations */
|
||||
$this->configureI18nProcessing($search);
|
||||
$locale = $this->configureI18nProcessing($search);
|
||||
|
||||
$id = $this->getId();
|
||||
|
||||
@@ -220,7 +220,7 @@ class Content extends BaseLoop
|
||||
->set("DESCRIPTION", $content->getVirtualColumn('i18n_DESCRIPTION'))
|
||||
->set("POSTSCRIPTUM", $content->getVirtualColumn('i18n_POSTSCRIPTUM'))
|
||||
->set("POSITION", $content->getPosition())
|
||||
->set("URL", $content->getUrl())
|
||||
->set("URL", $content->getUrl($locale))
|
||||
;
|
||||
|
||||
$loopResult->addRow($loopResultRow);
|
||||
|
||||
@@ -87,7 +87,8 @@ class FeatureValue extends BaseLoop
|
||||
$search,
|
||||
array('TITLE', 'CHAPO', 'DESCRIPTION', 'POSTSCRIPTUM'),
|
||||
FeatureAvTableMap::TABLE_NAME,
|
||||
'FEATURE_AV_ID'
|
||||
'FEATURE_AV_ID',
|
||||
true
|
||||
);
|
||||
|
||||
$feature = $this->getFeature();
|
||||
|
||||
@@ -79,7 +79,7 @@ class Folder extends BaseLoop
|
||||
$search = FolderQuery::create();
|
||||
|
||||
/* manage translations */
|
||||
$this->configureI18nProcessing($search);
|
||||
$locale = $this->configureI18nProcessing($search);
|
||||
|
||||
$id = $this->getId();
|
||||
|
||||
@@ -162,7 +162,7 @@ class Folder extends BaseLoop
|
||||
->set("DESCRIPTION", $folder->getVirtualColumn('i18n_DESCRIPTION'))
|
||||
->set("POSTSCRIPTUM", $folder->getVirtualColumn('i18n_POSTSCRIPTUM'))
|
||||
->set("PARENT", $folder->getParent())
|
||||
->set("URL", $folder->getUrl())
|
||||
->set("URL", $folder->getUrl($locale))
|
||||
->set("CONTENT_COUNT", $folder->countChild())
|
||||
->set("VISIBLE", $folder->getVisible() ? "1" : "0")
|
||||
->set("POSITION", $folder->getPosition())
|
||||
|
||||
@@ -137,7 +137,7 @@ class Product extends BaseLoop
|
||||
$search = ProductQuery::create();
|
||||
|
||||
/* manage translations */
|
||||
$this->configureI18nProcessing($search);
|
||||
$locale = $this->configureI18nProcessing($search);
|
||||
|
||||
$attributeNonStrictMatch = $this->getAttribute_non_strict_match();
|
||||
$isPSELeftJoinList = array();
|
||||
@@ -514,7 +514,7 @@ class Product extends BaseLoop
|
||||
->set("CHAPO", $product->getVirtualColumn('i18n_CHAPO'))
|
||||
->set("DESCRIPTION", $product->getVirtualColumn('i18n_DESCRIPTION'))
|
||||
->set("POSTSCRIPTUM", $product->getVirtualColumn('i18n_POSTSCRIPTUM'))
|
||||
->set("URL", $product->getUrl())
|
||||
->set("URL", $product->getUrl($locale))
|
||||
->set("BEST_PRICE", $product->getVirtualColumn('real_lowest_price'))
|
||||
->set("IS_PROMO", $product->getVirtualColumn('main_product_is_promo'))
|
||||
->set("IS_NEW", $product->getVirtualColumn('main_product_is_new'))
|
||||
|
||||
@@ -40,11 +40,7 @@ class ParserContext implements \IteratorAggregate
|
||||
public function __construct(Request $request)
|
||||
{
|
||||
// Setup basic variables
|
||||
$this
|
||||
->set('BASE_URL' , ConfigQuery::read('base_url', '/'))
|
||||
->set('INDEX_PAGE' , URL::getIndexPage())
|
||||
->set('RETURN_TO_URL' , URL::absoluteUrl($request->getSession()->getReturnToUrl()))
|
||||
->set('THELIA_VERSION' , ConfigQuery::read('thelia_version', 'undefined'))
|
||||
$this->set('THELIA_VERSION' , ConfigQuery::read('thelia_version', 'undefined'))
|
||||
;
|
||||
}
|
||||
|
||||
|
||||
@@ -47,14 +47,15 @@ class UrlGenerator extends AbstractSmartyPlugin
|
||||
public function generateUrlFunction($params, &$smarty)
|
||||
{
|
||||
// the path to process
|
||||
$path = $this->getParam($params, 'path');
|
||||
$path = $this->getParam($params, 'path');
|
||||
|
||||
$target = $this->getParam($params, 'target', null);
|
||||
$target = $this->getParam($params, 'target', null);
|
||||
|
||||
$url = URL::absoluteUrl($path, $this->getArgsFromParam($params, array('path', 'target')));
|
||||
$url = URL::absoluteUrl($path, $this->getArgsFromParam($params, array('path', 'target')));
|
||||
|
||||
if ($target != null) $url .= '#'.$target;
|
||||
return $url;
|
||||
if ($target != null) $url .= '#'.$target;
|
||||
|
||||
return $url;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -81,6 +82,15 @@ class UrlGenerator extends AbstractSmartyPlugin
|
||||
return $this->generateViewUrlFunction($params, true);
|
||||
}
|
||||
|
||||
public function navigateToUrlFunction($params, &$smarty)
|
||||
{
|
||||
$to = $this->getParam($params, 'to', null);
|
||||
|
||||
$toMethod = $this->getNavigateToMethod($to);
|
||||
|
||||
return $this->$toMethod();
|
||||
}
|
||||
|
||||
protected function generateViewUrlFunction($params, $forAdmin)
|
||||
{
|
||||
// the view name (without .html)
|
||||
@@ -125,7 +135,50 @@ class UrlGenerator extends AbstractSmartyPlugin
|
||||
return array(
|
||||
new SmartyPluginDescriptor('function', 'url', $this, 'generateUrlFunction'),
|
||||
new SmartyPluginDescriptor('function', 'viewurl', $this, 'generateFrontViewUrlFunction'),
|
||||
new SmartyPluginDescriptor('function', 'admin_viewurl', $this, 'generateAdminViewUrlFunction')
|
||||
new SmartyPluginDescriptor('function', 'admin_viewurl', $this, 'generateAdminViewUrlFunction'),
|
||||
new SmartyPluginDescriptor('function', 'navigate', $this, 'navigateToUrlFunction'),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array sur le format "to_value" => "method_name"
|
||||
*/
|
||||
protected function getNavigateToValues()
|
||||
{
|
||||
return array(
|
||||
"current" => "getCurrentUrl",
|
||||
"return_to" => "getReturnToUrl",
|
||||
"index" => "getIndexUrl",
|
||||
);
|
||||
}
|
||||
|
||||
protected function getNavigateToMethod($to)
|
||||
{
|
||||
if($to === null) {
|
||||
throw new \InvalidArgumentException("Missing 'to' parameter in `navigate` substitution.");
|
||||
}
|
||||
|
||||
$navigateToValues = $this->getNavigateToValues();
|
||||
|
||||
if(!array_key_exists($to, $navigateToValues)) {
|
||||
throw new \InvalidArgumentException("Incorrect value for parameter `to` in `navigate` substitution.");
|
||||
}
|
||||
|
||||
return $navigateToValues[$to];
|
||||
}
|
||||
|
||||
protected function getCurrentUrl()
|
||||
{
|
||||
return URL::retrieveCurrent($this->request);
|
||||
}
|
||||
|
||||
protected function getReturnToUrl()
|
||||
{
|
||||
return URL::absoluteUrl($this->request->getSession()->getReturnToUrl());
|
||||
}
|
||||
|
||||
protected function getIndexUrl()
|
||||
{
|
||||
return Url::getIndexPage();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ namespace Thelia\Model;
|
||||
|
||||
use Thelia\Model\Base\Category as BaseCategory;
|
||||
use Propel\Runtime\ActiveQuery\Criteria;
|
||||
use Thelia\Tools\URL;
|
||||
|
||||
class Category extends BaseCategory
|
||||
{
|
||||
@@ -15,8 +16,9 @@ class Category extends BaseCategory
|
||||
return CategoryQuery::countChild($this->getId());
|
||||
}
|
||||
|
||||
public function getUrl()
|
||||
public function getUrl($locale)
|
||||
{
|
||||
return URL::retrieve('category', $this->getId(), $locale);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -74,4 +76,4 @@ class Category extends BaseCategory
|
||||
return $countProduct;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,4 +22,14 @@ class ConfigQuery extends BaseConfigQuery {
|
||||
|
||||
return $value ? $value->getValue() : $default;
|
||||
}
|
||||
|
||||
public static function getDefaultLangWhenNoTranslationAvailable()
|
||||
{
|
||||
return ConfigQuery::read("default_lang_without_translation", 1);
|
||||
}
|
||||
|
||||
public static function isRewritingEnable()
|
||||
{
|
||||
return self::read("rewriting_enable") == 1;
|
||||
}
|
||||
} // ConfigQuery
|
||||
|
||||
@@ -3,11 +3,12 @@
|
||||
namespace Thelia\Model;
|
||||
|
||||
use Thelia\Model\Base\Content as BaseContent;
|
||||
use Thelia\Tools\URL;
|
||||
|
||||
class Content extends BaseContent
|
||||
{
|
||||
public function getUrl()
|
||||
public function getUrl($locale)
|
||||
{
|
||||
|
||||
return URL::retrieve('content', $this->getId(), $locale);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
namespace Thelia\Model;
|
||||
|
||||
use Thelia\Model\Base\Folder as BaseFolder;
|
||||
use Thelia\Tools\URL;
|
||||
|
||||
class Folder extends BaseFolder
|
||||
{
|
||||
@@ -14,9 +15,9 @@ class Folder extends BaseFolder
|
||||
return FolderQuery::countChild($this->getId());
|
||||
}
|
||||
|
||||
public function getUrl()
|
||||
public function getUrl($locale)
|
||||
{
|
||||
|
||||
return URL::retrieve('folder', $this->getId(), $locale);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -162,9 +162,9 @@ class RewritingUrlTableMap extends TableMap
|
||||
// columns
|
||||
$this->addPrimaryKey('ID', 'Id', 'INTEGER', true, null, null);
|
||||
$this->addColumn('URL', 'Url', 'VARCHAR', true, 255, null);
|
||||
$this->addColumn('VIEW', 'View', 'VARCHAR', false, 255, null);
|
||||
$this->addColumn('VIEW', 'View', 'VARCHAR', true, 255, null);
|
||||
$this->addColumn('VIEW_ID', 'ViewId', 'VARCHAR', false, 255, null);
|
||||
$this->addColumn('VIEW_LOCALE', 'ViewLocale', 'VARCHAR', false, 255, null);
|
||||
$this->addColumn('VIEW_LOCALE', 'ViewLocale', 'VARCHAR', true, 255, null);
|
||||
$this->addForeignKey('REDIRECTED', 'Redirected', 'INTEGER', 'rewriting_url', 'ID', false, null, null);
|
||||
$this->addColumn('CREATED_AT', 'CreatedAt', 'TIMESTAMP', false, null, null);
|
||||
$this->addColumn('UPDATED_AT', 'UpdatedAt', 'TIMESTAMP', false, null, null);
|
||||
|
||||
@@ -3,12 +3,12 @@
|
||||
namespace Thelia\Model;
|
||||
|
||||
use Thelia\Model\Base\Product as BaseProduct;
|
||||
use Thelia\Model\ProductSaleElements;
|
||||
use Thelia\Tools\URL;
|
||||
|
||||
class Product extends BaseProduct
|
||||
{
|
||||
public function getUrl()
|
||||
public function getUrl($locale)
|
||||
{
|
||||
|
||||
return URL::retrieve('product', $this->getId(), $locale);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@ class ModelCriteriaTools
|
||||
* @param null $foreignTable
|
||||
* @param string $foreignKey
|
||||
*/
|
||||
public static function getFrontEndI18n(ModelCriteria &$search, $requestedLocale, $columns, $foreignTable, $foreignKey)
|
||||
public static function getFrontEndI18n(ModelCriteria &$search, $requestedLocale, $columns, $foreignTable, $foreignKey, $forceReturn = false)
|
||||
{
|
||||
if($foreignTable === null) {
|
||||
$foreignTable = $search->getTableMap()->getName();
|
||||
@@ -33,16 +33,16 @@ class ModelCriteriaTools
|
||||
$aliasPrefix = $foreignTable . '_';
|
||||
}
|
||||
|
||||
$defaultLangWithoutTranslation = ConfigQuery::read("default_lang_without_translation", 1);
|
||||
$defaultLangWithoutTranslation = ConfigQuery::getDefaultLangWhenNoTranslationAvailable();
|
||||
|
||||
$requestedLocaleI18nAlias = 'requested_locale_i18n';
|
||||
$defaultLocaleI18nAlias = 'default_locale_i18n';
|
||||
|
||||
if (!$defaultLangWithoutTranslation == 0) {
|
||||
$requestedLocaleI18nAlias = $aliasPrefix . 'requested_locale_i18n';
|
||||
$defaultLocaleI18nAlias = $aliasPrefix . 'default_locale_i18n';
|
||||
|
||||
if($defaultLangWithoutTranslation == 0) {
|
||||
|
||||
$requestedLocaleJoin = new Join();
|
||||
$requestedLocaleJoin->addExplicitCondition($search->getTableMap()->getName(), $foreignKey, null, $foreignTable . '_i18n', 'ID', $requestedLocaleI18nAlias);
|
||||
$requestedLocaleJoin->setJoinType(Criteria::INNER_JOIN);
|
||||
$requestedLocaleJoin->setJoinType($forceReturn === false ? Criteria::INNER_JOIN : Criteria::LEFT_JOIN);
|
||||
|
||||
$search->addJoinObject($requestedLocaleJoin, $requestedLocaleI18nAlias)
|
||||
->addJoinCondition($requestedLocaleI18nAlias ,'`' . $requestedLocaleI18nAlias . '`.LOCALE = ?', $requestedLocale, null, \PDO::PARAM_STR);
|
||||
@@ -71,7 +71,9 @@ class ModelCriteriaTools
|
||||
|
||||
$search->withColumn('NOT ISNULL(`' . $requestedLocaleI18nAlias . '`.`ID`)', $aliasPrefix . 'IS_TRANSLATED');
|
||||
|
||||
$search->where('NOT ISNULL(`' . $requestedLocaleI18nAlias . '`.ID)')->_or()->where('NOT ISNULL(`' . $defaultLocaleI18nAlias . '`.ID)');
|
||||
if($forceReturn === false) {
|
||||
$search->where('NOT ISNULL(`' . $requestedLocaleI18nAlias . '`.ID)')->_or()->where('NOT ISNULL(`' . $defaultLocaleI18nAlias . '`.ID)');
|
||||
}
|
||||
|
||||
foreach($columns as $column) {
|
||||
$search->withColumn('CASE WHEN NOT ISNULL(`' . $requestedLocaleI18nAlias . '`.ID) THEN `' . $requestedLocaleI18nAlias . '`.`' . $column . '` ELSE `' . $defaultLocaleI18nAlias . '`.`' . $column . '` END', $aliasPrefix . 'i18n_' . $column);
|
||||
@@ -79,7 +81,7 @@ class ModelCriteriaTools
|
||||
}
|
||||
}
|
||||
|
||||
public static function getBackEndI18n(ModelCriteria &$search, $requestedLocale, $columns, $foreignTable, $foreignKey)
|
||||
public static function getBackEndI18n(ModelCriteria &$search, $requestedLocale, $columns = array('TITLE', 'CHAPO', 'DESCRIPTION', 'POSTSCRIPTUM'), $foreignTable = null, $foreignKey = 'ID')
|
||||
{
|
||||
if($foreignTable === null) {
|
||||
$foreignTable = $search->getTableMap()->getName();
|
||||
@@ -104,7 +106,7 @@ class ModelCriteriaTools
|
||||
}
|
||||
}
|
||||
|
||||
public static function getI18n($backendContext, $requestedLangId, ModelCriteria &$search, $currentLocale, $columns, $foreignTable, $foreignKey)
|
||||
public static function getI18n($backendContext, $requestedLangId, ModelCriteria &$search, $currentLocale, $columns, $foreignTable, $foreignKey, $forceReturn = false)
|
||||
{
|
||||
// If a lang has been requested, find the related Lang object, and get the locale
|
||||
if ($requestedLangId !== null) {
|
||||
@@ -125,7 +127,9 @@ class ModelCriteriaTools
|
||||
if ($backendContext) {
|
||||
self::getBackEndI18n($search, $locale, $columns, $foreignTable, $foreignKey);
|
||||
} else {
|
||||
self::getFrontEndI18n($search, $locale, $columns, $foreignTable, $foreignKey);
|
||||
self::getFrontEndI18n($search, $locale, $columns, $foreignTable, $foreignKey, $forceReturn);
|
||||
}
|
||||
|
||||
return $locale;
|
||||
}
|
||||
}
|
||||
|
||||
35
core/lib/Thelia/Rewriting/RewritingResolver.php
Executable file
35
core/lib/Thelia/Rewriting/RewritingResolver.php
Executable file
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
/*************************************************************************************/
|
||||
/* */
|
||||
/* Thelia */
|
||||
/* */
|
||||
/* Copyright (c) OpenStudio */
|
||||
/* email : info@thelia.net */
|
||||
/* web : http://www.thelia.net */
|
||||
/* */
|
||||
/* This program is free software; you can redistribute it and/or modify */
|
||||
/* it under the terms of the GNU General Public License as published by */
|
||||
/* the Free Software Foundation; either version 3 of the License */
|
||||
/* */
|
||||
/* This program is distributed in the hope that it will be useful, */
|
||||
/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
|
||||
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
|
||||
/* GNU General Public License for more details. */
|
||||
/* */
|
||||
/* You should have received a copy of the GNU General Public License */
|
||||
/* along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||
/* */
|
||||
/*************************************************************************************/
|
||||
namespace Thelia\Rewriting;
|
||||
|
||||
/**
|
||||
* Class RewritingResolver
|
||||
* @package Thelia\Rewriting
|
||||
* @author Etienne Roudeix <eroudeix@openstudio.fr>
|
||||
*
|
||||
* This class provides methods to resolve rewritten URL as a query
|
||||
*/
|
||||
class RewritingResolver
|
||||
{
|
||||
|
||||
}
|
||||
119
core/lib/Thelia/Rewriting/RewritingRetriever.php
Executable file
119
core/lib/Thelia/Rewriting/RewritingRetriever.php
Executable file
@@ -0,0 +1,119 @@
|
||||
<?php
|
||||
/*************************************************************************************/
|
||||
/* */
|
||||
/* Thelia */
|
||||
/* */
|
||||
/* Copyright (c) OpenStudio */
|
||||
/* email : info@thelia.net */
|
||||
/* web : http://www.thelia.net */
|
||||
/* */
|
||||
/* This program is free software; you can redistribute it and/or modify */
|
||||
/* it under the terms of the GNU General Public License as published by */
|
||||
/* the Free Software Foundation; either version 3 of the License */
|
||||
/* */
|
||||
/* This program is distributed in the hope that it will be useful, */
|
||||
/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
|
||||
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
|
||||
/* GNU General Public License for more details. */
|
||||
/* */
|
||||
/* You should have received a copy of the GNU General Public License */
|
||||
/* along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||
/* */
|
||||
/*************************************************************************************/
|
||||
namespace Thelia\Rewriting;
|
||||
|
||||
use Propel\Runtime\ActiveQuery\Criteria;
|
||||
use Thelia\Model\Base\RewritingUrlQuery;
|
||||
use Thelia\Model\Map\RewritingUrlTableMap;
|
||||
|
||||
/**
|
||||
* Class RewritingRetriever
|
||||
* @package Thelia\Rewriting
|
||||
* @author Etienne Roudeix <eroudeix@openstudio.fr>
|
||||
*
|
||||
* This class provides methods to retrieve a rewritten URL from a query
|
||||
*/
|
||||
class RewritingRetriever
|
||||
{
|
||||
/**
|
||||
* @param $view
|
||||
* @param $viewLocale
|
||||
* @param $viewId
|
||||
*
|
||||
* @return null|$url
|
||||
*/
|
||||
public function getViewUrl($view, $viewLocale, $viewId)
|
||||
{
|
||||
$url = $this->getViewUrlQuery($view, $viewId, $viewLocale);
|
||||
|
||||
return $url === null ? null : $url->getUrl();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $view
|
||||
* @param $viewId
|
||||
* @param $viewLocale
|
||||
*
|
||||
* @return null|RewritingUrl
|
||||
*/
|
||||
protected function getViewUrlQuery($view, $viewId, $viewLocale)
|
||||
{
|
||||
return RewritingUrlQuery::create()
|
||||
->joinRewritingArgument('ra', Criteria::LEFT_JOIN)
|
||||
->where('ISNULL(`ra`.REWRITING_URL_ID)')
|
||||
->filterByView($view)
|
||||
->filterByViewLocale($viewLocale)
|
||||
->filterByViewId($viewId)
|
||||
->filterByRedirected(null)
|
||||
->orderByUpdatedAt(Criteria::DESC)
|
||||
->findOne();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $view
|
||||
* @param $viewLocale
|
||||
* @param null $viewId
|
||||
* @param array $viewOtherParameters
|
||||
*
|
||||
* @return null|$url
|
||||
*/
|
||||
public function getSpecificUrl($view, $viewLocale, $viewId = null, $viewOtherParameters = array())
|
||||
{
|
||||
$urlQuery = RewritingUrlQuery::create()
|
||||
->joinRewritingArgument('ra', Criteria::LEFT_JOIN)
|
||||
->withColumn('`ra`.REWRITING_URL_ID', 'ra_REWRITING_URL_ID')
|
||||
->filterByView($view)
|
||||
->filterByViewLocale($viewLocale)
|
||||
->filterByViewId($viewId)
|
||||
->filterByRedirected(null)
|
||||
->orderByUpdatedAt(Criteria::DESC);
|
||||
|
||||
$otherParametersCount = count($viewOtherParameters);
|
||||
if($otherParametersCount > 0) {
|
||||
$parameterConditions = array();
|
||||
|
||||
foreach($viewOtherParameters as $parameter => $value) {
|
||||
$conditionName = 'other_parameter_condition_' . count($parameterConditions);
|
||||
$urlQuery->condition('parameter_condition', '`ra`.PARAMETER= ?', $parameter, \PDO::PARAM_STR)
|
||||
->condition('value_condition', '`ra`.VALUE = ?', $value, \PDO::PARAM_STR)
|
||||
->combine(array('parameter_condition', 'value_condition'), Criteria::LOGICAL_AND, $conditionName);
|
||||
$parameterConditions[] = $conditionName;
|
||||
}
|
||||
|
||||
$urlQuery->where($parameterConditions, Criteria::LOGICAL_OR);
|
||||
|
||||
$urlQuery->groupBy(RewritingUrlTableMap::ID);
|
||||
|
||||
$urlQuery->condition('count_condition_1', 'COUNT(' . RewritingUrlTableMap::ID . ') = ?', $otherParametersCount, \PDO::PARAM_INT) // ensure we got all the asked parameters (provided by the query)
|
||||
->condition('count_condition_2', 'COUNT(' . RewritingUrlTableMap::ID . ') = (SELECT COUNT(*) FROM rewriting_argument WHERE rewriting_argument.REWRITING_URL_ID = ra_REWRITING_URL_ID)'); // ensure we don't miss any parameters (needed to match the rewritten url)
|
||||
|
||||
$urlQuery->having(array('count_condition_1', 'count_condition_2'), Criteria::LOGICAL_AND);
|
||||
} else {
|
||||
$urlQuery->where('ISNULL(`ra`.REWRITING_URL_ID)');
|
||||
}
|
||||
|
||||
$url = $urlQuery->findOne();
|
||||
|
||||
return $url === null ? null : $url->getUrl();
|
||||
}
|
||||
}
|
||||
44
core/lib/Thelia/Tests/Rewriting/RewritingRetrieverTest.php
Executable file
44
core/lib/Thelia/Tests/Rewriting/RewritingRetrieverTest.php
Executable file
@@ -0,0 +1,44 @@
|
||||
<?php
|
||||
/*************************************************************************************/
|
||||
/* */
|
||||
/* Thelia */
|
||||
/* */
|
||||
/* Copyright (c) OpenStudio */
|
||||
/* email : info@thelia.net */
|
||||
/* web : http://www.thelia.net */
|
||||
/* */
|
||||
/* This program is free software; you can redistribute it and/or modify */
|
||||
/* it under the terms of the GNU General Public License as published by */
|
||||
/* the Free Software Foundation; either version 3 of the License */
|
||||
/* */
|
||||
/* This program is distributed in the hope that it will be useful, */
|
||||
/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
|
||||
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
|
||||
/* GNU General Public License for more details. */
|
||||
/* */
|
||||
/* You should have received a copy of the GNU General Public License */
|
||||
/* along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||
/* */
|
||||
/*************************************************************************************/
|
||||
|
||||
namespace Thelia\Tests\Rewriting;
|
||||
|
||||
use Thelia\Rewriting\RewritingRetriever;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Etienne Roudeix <eroudeix@openstudio.fr>
|
||||
*
|
||||
*/
|
||||
class RewritingRetrieverTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
public function testGetViewUrl()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public function testGetSpecificUrl()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
39
core/lib/Thelia/Tests/Tools/URLTest.php
Executable file
39
core/lib/Thelia/Tests/Tools/URLTest.php
Executable file
@@ -0,0 +1,39 @@
|
||||
<?php
|
||||
/*************************************************************************************/
|
||||
/* */
|
||||
/* Thelia */
|
||||
/* */
|
||||
/* Copyright (c) OpenStudio */
|
||||
/* email : info@thelia.net */
|
||||
/* web : http://www.thelia.net */
|
||||
/* */
|
||||
/* This program is free software; you can redistribute it and/or modify */
|
||||
/* it under the terms of the GNU General Public License as published by */
|
||||
/* the Free Software Foundation; either version 3 of the License */
|
||||
/* */
|
||||
/* This program is distributed in the hope that it will be useful, */
|
||||
/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
|
||||
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
|
||||
/* GNU General Public License for more details. */
|
||||
/* */
|
||||
/* You should have received a copy of the GNU General Public License */
|
||||
/* along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||
/* */
|
||||
/*************************************************************************************/
|
||||
|
||||
namespace Thelia\Tests\Type;
|
||||
|
||||
use Thelia\Tools\URL;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Etienne Roudeix <eroudeix@openstudio.fr>
|
||||
*
|
||||
*/
|
||||
class URLTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
public function testRetrieve()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
@@ -23,7 +23,9 @@
|
||||
|
||||
namespace Thelia\Tools;
|
||||
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Thelia\Model\ConfigQuery;
|
||||
use Thelia\Rewriting\RewritingRetriever;
|
||||
|
||||
class URL
|
||||
{
|
||||
@@ -51,7 +53,11 @@ class URL
|
||||
// Already absolute ?
|
||||
if (substr($path, 0, 4) != 'http') {
|
||||
|
||||
$root = $path_only == self::PATH_TO_FILE ? ConfigQuery::read('base_url', '/') : self::getIndexPage();
|
||||
/**
|
||||
* @etienne : can't be done here for it's already done in ::viewUrl / ::adminViewUrl
|
||||
*/
|
||||
//$root = $path_only == self::PATH_TO_FILE ? ConfigQuery::read('base_url', '/') : self::getIndexPage();
|
||||
$root = $path_only == self::PATH_TO_FILE ? ConfigQuery::read('base_url', '/') : '';
|
||||
|
||||
$base = rtrim($root, '/') . '/' . ltrim($path, '/');
|
||||
} else
|
||||
@@ -101,4 +107,50 @@ class URL
|
||||
|
||||
return self::absoluteUrl($path, $parameters);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $view
|
||||
* @param $viewId
|
||||
* @param $viewLocale
|
||||
*
|
||||
* @return null|string
|
||||
*/
|
||||
public static function retrieve($view, $viewId, $viewLocale)
|
||||
{
|
||||
$rewrittenUrl = null;
|
||||
if(ConfigQuery::isRewritingEnable()) {
|
||||
$retriever = new RewritingRetriever();
|
||||
$rewrittenUrl = $retriever->getViewUrl($view, $viewLocale, $viewId);
|
||||
}
|
||||
|
||||
return $rewrittenUrl === null ? self::viewUrl($view, array($view . '_id' => $viewId, 'locale' => $viewLocale)) : $rewrittenUrl;
|
||||
}
|
||||
|
||||
public static function retrieveCurrent(Request $request)
|
||||
{
|
||||
$rewrittenUrl = null;
|
||||
if(ConfigQuery::isRewritingEnable()) {
|
||||
$view = $request->query->get('view', null);
|
||||
$viewLocale = $request->query->get('locale', null);
|
||||
$viewId = $view === null ? null : $request->query->get($view . '_id', null);
|
||||
|
||||
$allParameters = $request->query->all();
|
||||
$allParametersWithoutView = $allParameters;
|
||||
if($view !== null) {
|
||||
unset($allParametersWithoutView['view']);
|
||||
}
|
||||
$allOtherParameters = $allParametersWithoutView;
|
||||
if($viewLocale !== null) {
|
||||
unset($allOtherParameters['locale']);
|
||||
}
|
||||
if($viewId !== null) {
|
||||
unset($allOtherParameters[$view . '_id']);
|
||||
}
|
||||
|
||||
$retriever = new RewritingRetriever();
|
||||
$rewrittenUrl = $retriever->getSpecificUrl($view, $viewLocale, $viewId, $allOtherParameters);
|
||||
}
|
||||
|
||||
return $rewrittenUrl === null ? self::viewUrl($view, $allParametersWithoutView) : $rewrittenUrl;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,6 +7,8 @@ INSERT INTO `lang`(`id`,`title`,`code`,`locale`,`url`,`by_default`,`created_at`,
|
||||
INSERT INTO `config` (`name`, `value`, `secured`, `hidden`, `created_at`, `updated_at`) VALUES
|
||||
('session_config.default', '1', 1, 1, NOW(), NOW()),
|
||||
('verifyStock', '1', 1, 0, NOW(), NOW()),
|
||||
('default_lang_without_translation', '1', 1, 0, NOW(), NOW()),
|
||||
('rewriting_enable', '0', 1, 0, NOW(), NOW()),
|
||||
('imagine_graphic_driver', 'gd', 1, 0, NOW(), NOW()),
|
||||
('default_images_quality_percent', '75', 1, 0, NOW(), NOW()),
|
||||
('original_image_delivery_mode', 'symlink', 1, 0, NOW(), NOW()),
|
||||
|
||||
@@ -1443,9 +1443,9 @@ CREATE TABLE `rewriting_url`
|
||||
(
|
||||
`id` INTEGER NOT NULL AUTO_INCREMENT,
|
||||
`url` VARCHAR(255) NOT NULL,
|
||||
`view` VARCHAR(255),
|
||||
`view` VARCHAR(255) NOT NULL,
|
||||
`view_id` VARCHAR(255),
|
||||
`view_locale` VARCHAR(255),
|
||||
`view_locale` VARCHAR(255) NOT NULL,
|
||||
`redirected` INTEGER,
|
||||
`created_at` DATETIME,
|
||||
`updated_at` DATETIME,
|
||||
|
||||
@@ -1096,9 +1096,9 @@
|
||||
<table name="rewriting_url" namespace="Thelia\Model">
|
||||
<column autoIncrement="true" name="id" primaryKey="true" required="true" type="INTEGER" />
|
||||
<column name="url" required="true" size="255" type="VARCHAR" />
|
||||
<column name="view" size="255" type="VARCHAR" />
|
||||
<column name="view" required="true" size="255" type="VARCHAR" />
|
||||
<column name="view_id" size="255" type="VARCHAR" />
|
||||
<column name="view_locale" size="255" type="VARCHAR" />
|
||||
<column name="view_locale" required="true" size="255" type="VARCHAR" />
|
||||
<column name="redirected" type="INTEGER" />
|
||||
<foreign-key foreignTable="rewriting_url" name="fk_rewriting_url_redirected" onDelete="RESTRICT" onUpdate="RESTRICT">
|
||||
<reference foreign="id" local="redirected" />
|
||||
|
||||
@@ -69,7 +69,7 @@
|
||||
</form>
|
||||
{/loop}
|
||||
|
||||
<div class="view-shop"><a href="{$INDEX_PAGE}" title="{intl l='View site'}" target="_blank"><i class="icon-white icon-eye-open"></i> {intl l="View shop"}</a></div>
|
||||
<div class="view-shop"><a href="{navigate to="index"}" title="{intl l='View site'}" target="_blank"><i class="icon-white icon-eye-open"></i> {intl l="View shop"}</a></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -164,4 +164,4 @@
|
||||
<div class="brandbar brandbar-wide container">
|
||||
<a class="brand" href="{url path='/admin'}">{images file='../assets/img/logo-thelia-34px.png'}<img src="{$asset_url}" alt="{intl l='Thelia, solution e-commerce libre'}" />{/images}</a>
|
||||
</div>
|
||||
{/elseloop}
|
||||
{/elseloop}
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
</ul>
|
||||
|
||||
{form name="thelia.cart.add" }
|
||||
{* We use $INDEX_PAGE as form action to avoid mixing post and get data *}
|
||||
{* We use {navigate to="index"} as form action to avoid mixing post and get data *}
|
||||
<form action="{url path="/cart/add" }" method="post" {form_enctype form=$form}>
|
||||
|
||||
{*
|
||||
|
||||
@@ -22,34 +22,10 @@
|
||||
|
||||
{loop name="product" type="product" category="#ID"}
|
||||
<div style="border: dashed 2px red; padding: 20px; margin: 10px;">
|
||||
<h3><a name="#REF">PRODUCT : #REF (#LOOP_COUNT / #LOOP_TOTAL)</a></h3>
|
||||
<h3><a href="#URL">PRODUCT #ID : #REF (#LOOP_COUNT / #LOOP_TOTAL)</a></h3>
|
||||
<h4>#TITLE</h4>
|
||||
<p>#DESCRIPTION</p>
|
||||
|
||||
{ifloop rel="acc"}
|
||||
<h5>Accessories</h5>
|
||||
<ul>
|
||||
{loop name="acc" type="accessory" product="#ID" order="accessory"}
|
||||
<li><a href="##REF">#REF</a></li>
|
||||
{/loop}
|
||||
</ul>
|
||||
{/ifloop}
|
||||
{elseloop rel="acc"}
|
||||
<h5>No accessory</h5>
|
||||
{/elseloop}
|
||||
|
||||
{ifloop rel="prod_ass_cont"}
|
||||
<h5>Associated Content</h5>
|
||||
<ul>
|
||||
{loop name="prod_ass_cont" type="associated_content" product="#ID" order="associated_content"}
|
||||
<li>#TITLE</li>
|
||||
{/loop}
|
||||
</ul>
|
||||
{/ifloop}
|
||||
{elseloop rel="prod_ass_cont"}
|
||||
<h5>No associated content</h5>
|
||||
{/elseloop}
|
||||
|
||||
{ifloop rel="ft"}
|
||||
<h5>Features</h5>
|
||||
<ul>
|
||||
@@ -67,29 +43,6 @@
|
||||
{elseloop rel="ft"}
|
||||
<h5>No feature</h5>
|
||||
{/elseloop}
|
||||
|
||||
<h5>Product sale elements</h5>
|
||||
|
||||
{assign var=current_product value=#ID}
|
||||
{loop name="pse" type="product_sale_elements" product="#ID"}
|
||||
<div style="border: solid 2px darkorange; padding: 5px; margin: 5px;">
|
||||
{loop name="combi" type="attribute_combination" product_sale_elements="#ID"}
|
||||
#ATTRIBUTE_TITLE = #ATTRIBUTE_AVAILABILITY_TITLE<br />
|
||||
{/loop}
|
||||
<br />#WEIGHT g
|
||||
<br /><strong>{if #IS_PROMO == 1} #PROMO_PRICE € (instead of #PRICE) {else} #PRICE € {/if}</strong>
|
||||
<br /><br />
|
||||
Add
|
||||
<select>
|
||||
{for $will=1 to #QUANTITY}
|
||||
<option>{$will}</option>
|
||||
{/for}
|
||||
</select>
|
||||
to my cart
|
||||
</ul>
|
||||
</div>
|
||||
{/loop}
|
||||
|
||||
</div>
|
||||
{/loop}
|
||||
{loop name="catgory1" type="category" parent="#ID"}
|
||||
@@ -110,75 +63,29 @@
|
||||
|
||||
{loop name="product" type="product" category="#ID"}
|
||||
|
||||
<div style="border: solid 1px green; padding: 20px; margin: 10px;">
|
||||
<h3><a name="#REF">PRODUCT : #REF (#LOOP_COUNT / #LOOP_TOTAL)</a></h3>
|
||||
<h4>#TITLE</h4>
|
||||
<p>#DESCRIPTION</p>
|
||||
<div style="border: solid 1px green; padding: 20px; margin: 10px;">
|
||||
<h3><a href="#URL">PRODUCT #ID : #REF (#LOOP_COUNT / #LOOP_TOTAL)</a></h3>
|
||||
<h4>#TITLE</h4>
|
||||
<p>#DESCRIPTION</p>
|
||||
|
||||
{ifloop rel="acc"}
|
||||
<h5>Accessories</h5>
|
||||
<ul>
|
||||
{loop name="acc" type="accessory" product="#ID" order="accessory"}
|
||||
<li><a href="##REF">#REF</a></li>
|
||||
{/loop}
|
||||
</ul>
|
||||
{/ifloop}
|
||||
{elseloop rel="acc"}
|
||||
<h5>No accessory</h5>
|
||||
{/elseloop}
|
||||
|
||||
{ifloop rel="prod_ass_cont"}
|
||||
<h5>Associated Content</h5>
|
||||
<ul>
|
||||
{loop name="prod_ass_cont" type="associated_content" product="#ID" order="associated_content"}
|
||||
<li>#TITLE</li>
|
||||
{/loop}
|
||||
</ul>
|
||||
{/ifloop}
|
||||
{elseloop rel="prod_ass_cont"}
|
||||
<h5>No associated content</h5>
|
||||
{/elseloop}
|
||||
|
||||
{ifloop rel="ft"}
|
||||
<h5>Features</h5>
|
||||
<ul>
|
||||
{loop name="ft" type="feature" order="manual" product="#ID"}
|
||||
<li>
|
||||
<strong>#TITLE</strong> :
|
||||
{loop name="ft_v" type="feature_value" product="{$current_product}" feature="#ID"}
|
||||
#TITLE / #PERSONAL_VALUE
|
||||
{ifloop rel="ft"}
|
||||
<h5>Features</h5>
|
||||
<ul>
|
||||
{assign var=current_product value=#ID}
|
||||
{loop name="ft" type="feature" order="manual" product="#ID"}
|
||||
<li>
|
||||
<strong>#TITLE</strong> :
|
||||
{loop name="ft_v" type="feature_value" product="{$current_product}" feature="#ID"}
|
||||
#TITLE / #PERSONAL_VALUE
|
||||
{/loop}
|
||||
</li>
|
||||
{/loop}
|
||||
</li>
|
||||
{/loop}
|
||||
</ul>
|
||||
{/ifloop}
|
||||
{elseloop rel="ft"}
|
||||
<h5>No feature</h5>
|
||||
{/elseloop}
|
||||
|
||||
<h5>Product sale elements</h5>
|
||||
|
||||
{assign var=current_product value=#ID}
|
||||
{loop name="pse" type="product_sale_elements" product="#ID"}
|
||||
<div style="border: solid 2px darkorange; padding: 5px; margin: 5px;">
|
||||
{loop name="combi" type="attribute_combination" product_sale_elements="#ID"}
|
||||
#ATTRIBUTE_TITLE = #ATTRIBUTE_AVAILABILITY_TITLE<br />
|
||||
{/loop}
|
||||
<br />#WEIGHT g
|
||||
<br /><strong>{if #IS_PROMO == 1} #PROMO_PRICE € (instead of #PRICE) {else} #PRICE € {/if}</strong>
|
||||
<br /><br />
|
||||
Add
|
||||
<select>
|
||||
{for $will=1 to #QUANTITY}
|
||||
<option>{$will}</option>
|
||||
{/for}
|
||||
</select>
|
||||
to my cart
|
||||
</ul>
|
||||
</div>
|
||||
{/loop}
|
||||
|
||||
</div>
|
||||
</ul>
|
||||
{/ifloop}
|
||||
{elseloop rel="ft"}
|
||||
<h5>No feature</h5>
|
||||
{/elseloop}
|
||||
</div>
|
||||
{/loop}
|
||||
</div>
|
||||
{/loop}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{include file="includes/header.html"}
|
||||
|
||||
{form name="thelia.customer.creation"}
|
||||
{* We use $INDEX_PAGE as form action to avoid mixing post and get data *}
|
||||
{* We use {navigate to="index"} as form action to avoid mixing post and get data *}
|
||||
<form action="{url path="/customer/create" }" method="post" {form_enctype form=$form}>
|
||||
{*
|
||||
The two fields below are not par of the form, they are here to defines
|
||||
@@ -16,7 +16,7 @@
|
||||
*}
|
||||
|
||||
{form_field form=$form field='success_url'}
|
||||
<input type="hidden" name="{$name}" value="{$RETURN_TO_URL}" /> {* the url the user is redirected to on login success *}
|
||||
<input type="hidden" name="{$name}" value="{navigate to="return_to"}" /> {* the url the user is redirected to on login success *}
|
||||
{/form_field}
|
||||
|
||||
{form_field form=$form field='auto_login'}
|
||||
|
||||
@@ -3,8 +3,8 @@
|
||||
<h1>{intl l='Please login'}</h1>
|
||||
|
||||
{form name="thelia.customer.login" }
|
||||
<form action="{url path='/customer/login'}" method="post" {form_enctype form=$form}>
|
||||
|
||||
<form action="{url path='/customer/login'}" method="post" {form_enctype form=$form}>
|
||||
{*
|
||||
The field below are not par of the Login form, it defines view to render if the form cannot be validated
|
||||
*}
|
||||
@@ -17,7 +17,7 @@
|
||||
*}
|
||||
|
||||
{form_field form=$form field='success_url'}
|
||||
<input type="hidden" name="{$name}" value="{$RETURN_TO_URL}" /> {* the url the user is redirected to on login success *}
|
||||
<input type="hidden" name="{$name}" value="{navigate to="return_to"}" /> {* the url the user is redirected to on login success *}
|
||||
{/form_field}
|
||||
|
||||
{*
|
||||
|
||||
88
templates/default/product.html
Executable file
88
templates/default/product.html
Executable file
@@ -0,0 +1,88 @@
|
||||
Here you are : {navigate to="current"}<br />
|
||||
From : {navigate to="return_to"}<br />
|
||||
Index : {navigate to="index"}<br />
|
||||
|
||||
<h1>Product page</h1>
|
||||
|
||||
{ifloop rel="product"}
|
||||
|
||||
{loop type="product" name="product" current="true"}
|
||||
|
||||
<div style="border: dashed 2px red; padding: 20px; margin: 10px;">
|
||||
<h2>PRODUCT (#ID) : #REF</h2>
|
||||
<h3>#TITLE</h3>
|
||||
<p>#DESCRIPTION</p>
|
||||
|
||||
{ifloop rel="acc"}
|
||||
<h4>Accessories</h4>
|
||||
<ul>
|
||||
{loop name="acc" type="accessory" product="#ID" order="accessory"}
|
||||
<li><a href="#URL">#REF</a></li>
|
||||
{/loop}
|
||||
</ul>
|
||||
{/ifloop}
|
||||
{elseloop rel="acc"}
|
||||
<h4>No accessory</h4>
|
||||
{/elseloop}
|
||||
|
||||
{ifloop rel="prod_ass_cont"}
|
||||
<h4>Associated Content</h4>
|
||||
<ul>
|
||||
{loop name="prod_ass_cont" type="associated_content" product="#ID" order="associated_content"}
|
||||
<li>#TITLE</li>
|
||||
{/loop}
|
||||
</ul>
|
||||
{/ifloop}
|
||||
{elseloop rel="prod_ass_cont"}
|
||||
<h4>No associated content</h4>
|
||||
{/elseloop}
|
||||
|
||||
{ifloop rel="ft"}
|
||||
<h4>Features</h4>
|
||||
<ul>
|
||||
{assign var=current_product value=#ID}
|
||||
{loop name="ft" type="feature" order="manual" product="#ID"}
|
||||
<li>
|
||||
<strong>#TITLE</strong> :
|
||||
{loop name="ft_v" type="feature_value" product="{$current_product}" feature="#ID"}
|
||||
#TITLE / #PERSONAL_VALUE
|
||||
{/loop}
|
||||
</li>
|
||||
{/loop}
|
||||
</ul>
|
||||
{/ifloop}
|
||||
{elseloop rel="ft"}
|
||||
<h4>No feature</h4>
|
||||
{/elseloop}
|
||||
|
||||
<h4>Product sale elements</h4>
|
||||
|
||||
{assign var=current_product value=#ID}
|
||||
{loop name="pse" type="product_sale_elements" product="#ID"}
|
||||
<div style="border: solid 2px darkorange; padding: 5px; margin: 5px;">
|
||||
{loop name="combi" type="attribute_combination" product_sale_elements="#ID"}
|
||||
#ATTRIBUTE_TITLE = #ATTRIBUTE_AVAILABILITY_TITLE<br />
|
||||
{/loop}
|
||||
<br />#WEIGHT g
|
||||
<br /><strong>{if #IS_PROMO == 1} #PROMO_PRICE € (instead of #PRICE) {else} #PRICE € {/if}</strong>
|
||||
<br /><br />
|
||||
Add
|
||||
<select>
|
||||
{for $will=1 to #QUANTITY}
|
||||
<option>{$will}</option>
|
||||
{/for}
|
||||
</select>
|
||||
to my cart
|
||||
</ul>
|
||||
</div>
|
||||
{/loop}
|
||||
|
||||
</div>
|
||||
|
||||
{/loop}
|
||||
|
||||
{/ifloop}
|
||||
|
||||
{elseloop rel="product"}
|
||||
<h2>Produit introuvable !</h2>
|
||||
{/elseloop}
|
||||
Reference in New Issue
Block a user