big progress on product loop
This commit is contained in:
@@ -99,6 +99,22 @@ class Product extends BaseLoop
|
|||||||
new TypeCollection(
|
new TypeCollection(
|
||||||
new Type\IntToCombinedStringsListType()
|
new Type\IntToCombinedStringsListType()
|
||||||
)
|
)
|
||||||
|
),
|
||||||
|
/*
|
||||||
|
* promo, new, quantity and weight may differ depending on the different attributes
|
||||||
|
* by default, product loop will look for at least 1 attribute which matches all the loop criteria : attribute_non_strict_match="none"
|
||||||
|
* you can also provide a list of non-strict attributes.
|
||||||
|
* ie : attribute_non_strict_match="promo,new"
|
||||||
|
* loop will return the product if he has at least an attribute in promo and at least an attribute as new ; even if it's not the same attribute.
|
||||||
|
* you can set all the attributes as non strict : attribute_non_strict_match="*"
|
||||||
|
*/
|
||||||
|
new Argument(
|
||||||
|
'attribute_non_strict_match',
|
||||||
|
new TypeCollection(
|
||||||
|
new Type\EnumListType(array('min_stock', 'promo', 'new', 'min_weight', 'max_weight', 'min_price', 'max_price')),
|
||||||
|
new Type\EnumType(array('*', 'none'))
|
||||||
|
),
|
||||||
|
'none'
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -115,6 +131,20 @@ class Product extends BaseLoop
|
|||||||
|
|
||||||
//$search->withColumn('CASE WHEN ' . ProductTableMap::PROMO . '=1 THEN ' . ProductTableMap::PRICE2 . ' ELSE ' . ProductTableMap::PRICE . ' END', 'real_price');
|
//$search->withColumn('CASE WHEN ' . ProductTableMap::PROMO . '=1 THEN ' . ProductTableMap::PRICE2 . ' ELSE ' . ProductTableMap::PRICE . ' END', 'real_price');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Criteria::INNER_JOIN in second parameter for joinWithI18n exclude query without translation.
|
||||||
|
*
|
||||||
|
* @todo : verify here if we want results for row without translations.
|
||||||
|
*/
|
||||||
|
|
||||||
|
$search->joinWithI18n(
|
||||||
|
$this->request->getSession()->getLocale(),
|
||||||
|
(ConfigQuery::read("default_lang_without_translation", 1)) ? Criteria::LEFT_JOIN : Criteria::INNER_JOIN
|
||||||
|
);
|
||||||
|
|
||||||
|
$attributeNonStrictMatch = $this->getAttribute_non_strict_match();
|
||||||
|
$usedAttributeNonStrictMatchList = array();
|
||||||
|
|
||||||
$id = $this->getId();
|
$id = $this->getId();
|
||||||
|
|
||||||
if (!is_null($id)) {
|
if (!is_null($id)) {
|
||||||
@@ -149,27 +179,70 @@ class Product extends BaseLoop
|
|||||||
$new = $this->getNew();
|
$new = $this->getNew();
|
||||||
|
|
||||||
if ($new === true) {
|
if ($new === true) {
|
||||||
$search->joinProductSaleElements('is_new', Criteria::INNER_JOIN)
|
$usedAttributeNonStrictMatchList[] = 'new';
|
||||||
->addJoinCondition('is_new', "`is_new`.NEWNESS = 1");
|
$search->joinProductSaleElements('is_new', Criteria::LEFT_JOIN)
|
||||||
|
->addJoinCondition('is_new', '`is_new`.NEWNESS = 1')
|
||||||
|
->where('NOT ISNULL(`is_new`.ID)');
|
||||||
} else if($new === false) {
|
} else if($new === false) {
|
||||||
$search->joinProductSaleElements('is_new', Criteria::INNER_JOIN)
|
$usedAttributeNonStrictMatchList[] = 'new';
|
||||||
->addJoinCondition('is_new', "`is_new`.NEWNESS = 0");
|
$search->joinProductSaleElements('is_new', Criteria::LEFT_JOIN)
|
||||||
|
->addJoinCondition('is_new', '`is_new`.NEWNESS = 0')
|
||||||
|
->where('NOT ISNULL(`is_new`.ID)');
|
||||||
}
|
}
|
||||||
|
|
||||||
$promo = $this->getPromo();
|
$promo = $this->getPromo();
|
||||||
|
|
||||||
if ($promo === true) {
|
if ($promo === true) {
|
||||||
$search->joinProductSaleElements('is_promo', Criteria::INNER_JOIN)
|
$usedAttributeNonStrictMatchList[] = 'promo';
|
||||||
->addJoinCondition('is_promo', "`is_promo`.PROMO = 1");
|
$search->joinProductSaleElements('is_promo', Criteria::LEFT_JOIN)
|
||||||
|
->addJoinCondition('is_promo', "`is_promo`.PROMO = 1")
|
||||||
|
->where('NOT ISNULL(`is_promo`.ID)');
|
||||||
} else if($promo === false) {
|
} else if($promo === false) {
|
||||||
$search->joinProductSaleElements('is_promo', Criteria::INNER_JOIN)
|
$usedAttributeNonStrictMatchList[] = 'promo';
|
||||||
->addJoinCondition('is_promo', "`is_promo`.PROMO = 0");
|
$search->joinProductSaleElements('is_promo', Criteria::LEFT_JOIN)
|
||||||
|
->addJoinCondition('is_promo', "`is_promo`.PROMO = 0")
|
||||||
|
->where('NOT ISNULL(`is_promo`.ID)');
|
||||||
}
|
}
|
||||||
|
|
||||||
$min_stock = $this->getMin_stock();
|
$min_stock = $this->getMin_stock();
|
||||||
|
|
||||||
if (null != $min_stock) {
|
if (null != $min_stock) {
|
||||||
$search->filterByQuantity($min_stock, Criteria::GREATER_EQUAL);
|
$usedAttributeNonStrictMatchList[] = 'min_stock';
|
||||||
|
$search->joinProductSaleElements('is_min_stock', Criteria::LEFT_JOIN)
|
||||||
|
->addJoinCondition('is_min_stock', "`is_min_stock`.QUANTITY > ?", $min_stock, null, \PDO::PARAM_INT)
|
||||||
|
->where('NOT ISNULL(`is_min_stock`.ID)');
|
||||||
|
}
|
||||||
|
|
||||||
|
$min_weight = $this->getMin_weight();
|
||||||
|
|
||||||
|
if (null != $min_weight) {
|
||||||
|
$usedAttributeNonStrictMatchList[] = 'min_weight';
|
||||||
|
$search->joinProductSaleElements('is_min_weight', Criteria::LEFT_JOIN)
|
||||||
|
->addJoinCondition('is_min_weight', "`is_min_weight`.WEIGHT > ?", $min_weight, null, \PDO::PARAM_INT)
|
||||||
|
->where('NOT ISNULL(`is_min_weight`.ID)');
|
||||||
|
}
|
||||||
|
|
||||||
|
$max_weight = $this->getMax_weight();
|
||||||
|
|
||||||
|
if (null != $max_weight) {
|
||||||
|
$usedAttributeNonStrictMatchList[] = 'max_weight';
|
||||||
|
$search->joinProductSaleElements('is_max_weight', Criteria::LEFT_JOIN)
|
||||||
|
->addJoinCondition('is_max_weight', "`is_max_weight`.WEIGHT < ?", $max_weight, null, \PDO::PARAM_INT)
|
||||||
|
->where('NOT ISNULL(`is_max_weight`.ID)');
|
||||||
|
}
|
||||||
|
|
||||||
|
if( $attributeNonStrictMatch != '*' ) {
|
||||||
|
if($attributeNonStrictMatch == 'none') {
|
||||||
|
$actuallyUsedAttributeNonStrictMatchList = $usedAttributeNonStrictMatchList;
|
||||||
|
} else {
|
||||||
|
$actuallyUsedAttributeNonStrictMatchList = array_values(array_intersect($usedAttributeNonStrictMatchList, $attributeNonStrictMatch));
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach($actuallyUsedAttributeNonStrictMatchList as $key => $actuallyUsedAttributeNonStrictMatch) {
|
||||||
|
if($key == 0)
|
||||||
|
continue;
|
||||||
|
$search->where('`is_' . $actuallyUsedAttributeNonStrictMatch . '`.ID=' . '`is_' . $actuallyUsedAttributeNonStrictMatchList[$key-1] . '`.ID');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//$min_price = $this->getMin_price();
|
//$min_price = $this->getMin_price();
|
||||||
@@ -206,17 +279,7 @@ class Product extends BaseLoop
|
|||||||
->where(array('not_in_promo_max_price', 'in_promo_max_price'), Criteria::LOGICAL_OR);
|
->where(array('not_in_promo_max_price', 'in_promo_max_price'), Criteria::LOGICAL_OR);
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
/*$min_weight = $this->getMin_weight();
|
/**/
|
||||||
|
|
||||||
if(null !== $min_weight) {
|
|
||||||
$search->filterByWeight($min_weight, Criteria::GREATER_EQUAL);
|
|
||||||
}
|
|
||||||
|
|
||||||
$max_weight = $this->getMax_weight();
|
|
||||||
|
|
||||||
if(null !== $max_weight) {
|
|
||||||
$search->filterByWeight($max_weight, Criteria::LESS_EQUAL);
|
|
||||||
}*/
|
|
||||||
|
|
||||||
$current = $this->getCurrent();
|
$current = $this->getCurrent();
|
||||||
|
|
||||||
@@ -256,57 +319,6 @@ class Product extends BaseLoop
|
|||||||
|
|
||||||
if ($visible != BooleanOrBothType::ANY) $search->filterByVisible($visible ? 1 : 0);
|
if ($visible != BooleanOrBothType::ANY) $search->filterByVisible($visible ? 1 : 0);
|
||||||
|
|
||||||
$orders = $this->getOrder();
|
|
||||||
|
|
||||||
foreach($orders as $order) {
|
|
||||||
switch ($order) {
|
|
||||||
case "alpha":
|
|
||||||
$search->addAscendingOrderByColumn(\Thelia\Model\Map\ProductI18nTableMap::TITLE);
|
|
||||||
break;
|
|
||||||
case "alpha_reverse":
|
|
||||||
$search->addDescendingOrderByColumn(\Thelia\Model\Map\ProductI18nTableMap::TITLE);
|
|
||||||
break;
|
|
||||||
/*case "min_price":
|
|
||||||
$search->orderBy('real_price', Criteria::ASC);
|
|
||||||
break;
|
|
||||||
case "max_price":
|
|
||||||
$search->orderBy('real_price', Criteria::DESC);
|
|
||||||
break;*/
|
|
||||||
case "manual":
|
|
||||||
if(null === $category || count($category) != 1)
|
|
||||||
throw new \InvalidArgumentException('Manual order cannot be set without single category argument');
|
|
||||||
$search->orderByPosition(Criteria::ASC);
|
|
||||||
break;
|
|
||||||
case "manual_reverse":
|
|
||||||
if(null === $category || count($category) != 1)
|
|
||||||
throw new \InvalidArgumentException('Manual order cannot be set without single category argument');
|
|
||||||
$search->orderByPosition(Criteria::DESC);
|
|
||||||
break;
|
|
||||||
case "ref":
|
|
||||||
$search->orderByRef(Criteria::ASC);
|
|
||||||
break;
|
|
||||||
/*case "promo":
|
|
||||||
$search->orderByPromo(Criteria::DESC);
|
|
||||||
break;
|
|
||||||
case "new":
|
|
||||||
$search->orderByNewness(Criteria::DESC);
|
|
||||||
break;*/
|
|
||||||
case "given_id":
|
|
||||||
if(null === $id)
|
|
||||||
throw new \InvalidArgumentException('Given_id order cannot be set without `id` argument');
|
|
||||||
foreach($id as $singleId) {
|
|
||||||
$givenIdMatched = 'given_id_matched_' . $singleId;
|
|
||||||
$search->withColumn(ProductTableMap::ID . "='$singleId'", $givenIdMatched);
|
|
||||||
$search->orderBy($givenIdMatched, Criteria::DESC);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case "random":
|
|
||||||
$search->clearOrderByColumns();
|
|
||||||
$search->addAscendingOrderByColumn('RAND()');
|
|
||||||
break(2);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$exclude = $this->getExclude();
|
$exclude = $this->getExclude();
|
||||||
|
|
||||||
if (!is_null($exclude)) {
|
if (!is_null($exclude)) {
|
||||||
@@ -378,19 +390,59 @@ class Product extends BaseLoop
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Criteria::INNER_JOIN in second parameter for joinWithI18n exclude query without translation.
|
|
||||||
*
|
|
||||||
* @todo : verify here if we want results for row without translations.
|
|
||||||
*/
|
|
||||||
|
|
||||||
$search->joinWithI18n(
|
|
||||||
$this->request->getSession()->getLocale(),
|
|
||||||
(ConfigQuery::read("default_lang_without_translation", 1)) ? Criteria::LEFT_JOIN : Criteria::INNER_JOIN
|
|
||||||
);
|
|
||||||
|
|
||||||
$search->groupBy(ProductTableMap::ID);
|
$search->groupBy(ProductTableMap::ID);
|
||||||
|
|
||||||
|
$orders = $this->getOrder();
|
||||||
|
|
||||||
|
foreach($orders as $order) {
|
||||||
|
switch ($order) {
|
||||||
|
case "alpha":
|
||||||
|
$search->addAscendingOrderByColumn(\Thelia\Model\Map\ProductI18nTableMap::TITLE);
|
||||||
|
break;
|
||||||
|
case "alpha_reverse":
|
||||||
|
$search->addDescendingOrderByColumn(\Thelia\Model\Map\ProductI18nTableMap::TITLE);
|
||||||
|
break;
|
||||||
|
/*case "min_price":
|
||||||
|
$search->orderBy('real_price', Criteria::ASC);
|
||||||
|
break;
|
||||||
|
case "max_price":
|
||||||
|
$search->orderBy('real_price', Criteria::DESC);
|
||||||
|
break;*/
|
||||||
|
case "manual":
|
||||||
|
if(null === $category || count($category) != 1)
|
||||||
|
throw new \InvalidArgumentException('Manual order cannot be set without single category argument');
|
||||||
|
$search->orderByPosition(Criteria::ASC);
|
||||||
|
break;
|
||||||
|
case "manual_reverse":
|
||||||
|
if(null === $category || count($category) != 1)
|
||||||
|
throw new \InvalidArgumentException('Manual order cannot be set without single category argument');
|
||||||
|
$search->orderByPosition(Criteria::DESC);
|
||||||
|
break;
|
||||||
|
case "ref":
|
||||||
|
$search->orderByRef(Criteria::ASC);
|
||||||
|
break;
|
||||||
|
/*case "promo":
|
||||||
|
$search->orderByPromo(Criteria::DESC);
|
||||||
|
break;
|
||||||
|
case "new":
|
||||||
|
$search->orderByNewness(Criteria::DESC);
|
||||||
|
break;*/
|
||||||
|
case "given_id":
|
||||||
|
if(null === $id)
|
||||||
|
throw new \InvalidArgumentException('Given_id order cannot be set without `id` argument');
|
||||||
|
foreach($id as $singleId) {
|
||||||
|
$givenIdMatched = 'given_id_matched_' . $singleId;
|
||||||
|
$search->withColumn(ProductTableMap::ID . "='$singleId'", $givenIdMatched);
|
||||||
|
$search->orderBy($givenIdMatched, Criteria::DESC);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "random":
|
||||||
|
$search->clearOrderByColumns();
|
||||||
|
$search->addAscendingOrderByColumn('RAND()');
|
||||||
|
break(2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
$products = $this->search($search, $pagination);
|
$products = $this->search($search, $pagination);
|
||||||
|
|
||||||
$loopResult = new LoopResult();
|
$loopResult = new LoopResult();
|
||||||
@@ -417,5 +469,4 @@ class Product extends BaseLoop
|
|||||||
|
|
||||||
return $loopResult;
|
return $loopResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -75,8 +75,9 @@ class TheliaLoop extends AbstractSmartyPlugin
|
|||||||
{
|
{
|
||||||
$type = $this->getParam($params, 'type');
|
$type = $this->getParam($params, 'type');
|
||||||
|
|
||||||
if (null == $type)
|
if (null == $type) {
|
||||||
throw new \InvalidArgumentException("Missing 'type' parameter in count arguments");
|
throw new \InvalidArgumentException("Missing 'type' parameter in count arguments");
|
||||||
|
}
|
||||||
|
|
||||||
$loop = $this->createLoopInstance($params);
|
$loop = $this->createLoopInstance($params);
|
||||||
|
|
||||||
@@ -101,13 +102,15 @@ class TheliaLoop extends AbstractSmartyPlugin
|
|||||||
{
|
{
|
||||||
$name = $this->getParam($params, 'name');
|
$name = $this->getParam($params, 'name');
|
||||||
|
|
||||||
if (null == $name)
|
if (null == $name) {
|
||||||
throw new \InvalidArgumentException("Missing 'name' parameter in loop arguments");
|
throw new \InvalidArgumentException("Missing 'name' parameter in loop arguments");
|
||||||
|
}
|
||||||
|
|
||||||
$type = $this->getParam($params, 'type');
|
$type = $this->getParam($params, 'type');
|
||||||
|
|
||||||
if (null == $type)
|
if (null == $type) {
|
||||||
throw new \InvalidArgumentException("Missing 'type' parameter in loop arguments");
|
throw new \InvalidArgumentException("Missing 'type' parameter in loop arguments");
|
||||||
|
}
|
||||||
|
|
||||||
if ($content === null) {
|
if ($content === null) {
|
||||||
// Check if a loop with the same name exists in the current scope, and abort if it's the case.
|
// Check if a loop with the same name exists in the current scope, and abort if it's the case.
|
||||||
@@ -272,6 +275,105 @@ class TheliaLoop extends AbstractSmartyPlugin
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Process {unionloop name="loop name" type="loop type" ... } ... {/unionloop} block
|
||||||
|
*
|
||||||
|
* @param $params
|
||||||
|
* @param $content
|
||||||
|
* @param $template
|
||||||
|
* @param $repeat
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
* @throws \InvalidArgumentException
|
||||||
|
*/
|
||||||
|
public function theliaUnion($params, $content, $template, &$repeat)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
|
||||||
|
$name = $this->getParam($params, 'name');
|
||||||
|
|
||||||
|
if (null == $name)
|
||||||
|
throw new \InvalidArgumentException("Missing 'name' parameter in unionloop arguments");
|
||||||
|
|
||||||
|
$type = $this->getParam($params, 'type');
|
||||||
|
|
||||||
|
if (null == $type)
|
||||||
|
throw new \InvalidArgumentException("Missing 'type' parameter in unionloop arguments");
|
||||||
|
|
||||||
|
if ($content === null) {
|
||||||
|
// Check if a loop with the same name exists in the current scope, and abort if it's the case.
|
||||||
|
if (array_key_exists($name, $this->varstack)) {
|
||||||
|
throw new \InvalidArgumentException("A loop named '$name' already exists in the current scope.");
|
||||||
|
}
|
||||||
|
|
||||||
|
$loop = $this->createLoopInstance($params);
|
||||||
|
|
||||||
|
self::$pagination[$name] = null;
|
||||||
|
|
||||||
|
$loopResults = $loop->exec(self::$pagination[$name]);
|
||||||
|
|
||||||
|
$this->loopstack[$name] = $loopResults;
|
||||||
|
|
||||||
|
// Pas de résultat ? la boucle est terminée, ne pas évaluer le contenu.
|
||||||
|
if ($loopResults->isEmpty()) $repeat = false;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
$loopResults = $this->loopstack[$name];
|
||||||
|
|
||||||
|
$loopResults->next();
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($loopResults->valid()) {
|
||||||
|
$loopResultRow = $loopResults->current();
|
||||||
|
|
||||||
|
// On first iteration, save variables that may be overwritten by this loop
|
||||||
|
if (! isset($this->varstack[$name])) {
|
||||||
|
|
||||||
|
$saved_vars = array();
|
||||||
|
|
||||||
|
$varlist = $loopResultRow->getVars();
|
||||||
|
$varlist[] = 'LOOP_COUNT';
|
||||||
|
$varlist[] = 'LOOP_TOTAL';
|
||||||
|
|
||||||
|
foreach($varlist as $var) {
|
||||||
|
$saved_vars[$var] = $template->getTemplateVars($var);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->varstack[$name] = $saved_vars;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach($loopResultRow->getVarVal() as $var => $val) {
|
||||||
|
$template->assign($var, $val);
|
||||||
|
}
|
||||||
|
|
||||||
|
$repeat = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Assign meta information
|
||||||
|
$template->assign('LOOP_COUNT', 1 + $loopResults->key());
|
||||||
|
$template->assign('LOOP_TOTAL', $loopResults->getCount());
|
||||||
|
|
||||||
|
// Loop is terminated. Cleanup.
|
||||||
|
if (! $repeat) {
|
||||||
|
// Restore previous variables values before terminating
|
||||||
|
if (isset($this->varstack[$name])) {
|
||||||
|
foreach($this->varstack[$name] as $var => $value) {
|
||||||
|
$template->assign($var, $value);
|
||||||
|
}
|
||||||
|
|
||||||
|
unset($this->varstack[$name]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($content !== null) {
|
||||||
|
if ($loopResults->isEmpty()) {
|
||||||
|
$content = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
return $content;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if a loop has returned results. The loop shoud have been executed before, or an
|
* Check if a loop has returned results. The loop shoud have been executed before, or an
|
||||||
* InvalidArgumentException is thrown
|
* InvalidArgumentException is thrown
|
||||||
@@ -372,6 +474,7 @@ class TheliaLoop extends AbstractSmartyPlugin
|
|||||||
new SmartyPluginDescriptor('block' , 'elseloop', $this, 'theliaElseloop'),
|
new SmartyPluginDescriptor('block' , 'elseloop', $this, 'theliaElseloop'),
|
||||||
new SmartyPluginDescriptor('block' , 'ifloop', $this, 'theliaIfLoop'),
|
new SmartyPluginDescriptor('block' , 'ifloop', $this, 'theliaIfLoop'),
|
||||||
new SmartyPluginDescriptor('block' , 'pageloop', $this, 'theliaPageLoop'),
|
new SmartyPluginDescriptor('block' , 'pageloop', $this, 'theliaPageLoop'),
|
||||||
|
new SmartyPluginDescriptor('block' , 'union', $this, 'theliaUnion'),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,7 +12,7 @@
|
|||||||
<h3><a name="#REF">PRODUCT : #REF (#LOOP_COUNT / #LOOP_TOTAL)</a></h3>
|
<h3><a name="#REF">PRODUCT : #REF (#LOOP_COUNT / #LOOP_TOTAL)</a></h3>
|
||||||
<h4>#TITLE</h4>
|
<h4>#TITLE</h4>
|
||||||
<p>#DESCRIPTION</p>
|
<p>#DESCRIPTION</p>
|
||||||
{ifloop rel="acc"}
|
{*ifloop rel="acc"}
|
||||||
<h5>Accessories</h5>
|
<h5>Accessories</h5>
|
||||||
<ul>
|
<ul>
|
||||||
{loop name="acc" type="accessory" product="#ID" order="accessory"}
|
{loop name="acc" type="accessory" product="#ID" order="accessory"}
|
||||||
@@ -22,7 +22,7 @@
|
|||||||
{/ifloop}
|
{/ifloop}
|
||||||
{elseloop rel="acc"}
|
{elseloop rel="acc"}
|
||||||
<h5>No accessory</h5>
|
<h5>No accessory</h5>
|
||||||
{/elseloop}
|
{/elseloop*}
|
||||||
{ifloop rel="ft"}
|
{ifloop rel="ft"}
|
||||||
<h5>Features</h5>
|
<h5>Features</h5>
|
||||||
<ul>
|
<ul>
|
||||||
@@ -44,7 +44,7 @@
|
|||||||
<h3><a name="#REF">PRODUCT : #REF (#LOOP_COUNT / #LOOP_TOTAL)</a></h3>
|
<h3><a name="#REF">PRODUCT : #REF (#LOOP_COUNT / #LOOP_TOTAL)</a></h3>
|
||||||
<h4>#TITLE</h4>
|
<h4>#TITLE</h4>
|
||||||
<p>#DESCRIPTION</p>
|
<p>#DESCRIPTION</p>
|
||||||
{ifloop rel="acc"}
|
{*ifloop rel="acc"}
|
||||||
<h5>Accessories</h5>
|
<h5>Accessories</h5>
|
||||||
<ul>
|
<ul>
|
||||||
{loop name="acc" type="accessory" product="#ID" order="accessory"}
|
{loop name="acc" type="accessory" product="#ID" order="accessory"}
|
||||||
@@ -54,7 +54,7 @@
|
|||||||
{/ifloop}
|
{/ifloop}
|
||||||
{elseloop rel="acc"}
|
{elseloop rel="acc"}
|
||||||
<h5>No accessory</h5>
|
<h5>No accessory</h5>
|
||||||
{/elseloop}
|
{/elseloop*}
|
||||||
{ifloop rel="ft"}
|
{ifloop rel="ft"}
|
||||||
<h5>Features</h5>
|
<h5>Features</h5>
|
||||||
<ul>
|
<ul>
|
||||||
@@ -113,10 +113,16 @@
|
|||||||
|
|
||||||
<div style="border: solid 8px; margin: 0px; padding: 0px; width: 30%; float: left">
|
<div style="border: solid 8px; margin: 0px; padding: 0px; width: 30%; float: left">
|
||||||
|
|
||||||
{loop name="product" type="product" order="promo,min_price" exclude_category="3" new="on" promo="off"}
|
{*loop name="product" type="product" order="promo,min_price" exclude_category="3" new="on" promo="off"}
|
||||||
|
<h3>PRODUCT : #REF / #TITLE</h3>
|
||||||
|
{/loop*}
|
||||||
|
|
||||||
|
{loop name="product" type="product" new="on" promo="off"}
|
||||||
<h3>PRODUCT : #REF / #TITLE</h3>
|
<h3>PRODUCT : #REF / #TITLE</h3>
|
||||||
{/loop}
|
{/loop}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
{*loop name="product" type="product" order="ref" feature_availability="1: (1 | 2) , 2: 4, 3: 433"}
|
{*loop name="product" type="product" order="ref" feature_availability="1: (1 | 2) , 2: 4, 3: 433"}
|
||||||
<h3>PRODUCT : #REF / #TITLE</h3>
|
<h3>PRODUCT : #REF / #TITLE</h3>
|
||||||
price : #PRICE €<br />
|
price : #PRICE €<br />
|
||||||
|
|||||||
7
templates/default/debug.html
Normal file
7
templates/default/debug.html
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
{*loop name="product" type="product" new="on" promo="on" min_stock="20" attribute_non_strict_match="min_stock,promo"}
|
||||||
|
<h3>PRODUCT : #REF / #TITLE (#ID)</h3>
|
||||||
|
{/loop*}
|
||||||
|
|
||||||
|
{*loop name="product" type="product" min_weight="1000" max_weight="6000" attribute_non_strict_match="*"}
|
||||||
|
<h3>PRODUCT : #REF / #TITLE (#ID)</h3>
|
||||||
|
{/loop*}
|
||||||
Reference in New Issue
Block a user