product loop : order by min and max price

This commit is contained in:
Etienne Roudeix
2013-08-20 15:22:34 +02:00
parent ef756979bd
commit 9e3d8bcc5e

View File

@@ -109,6 +109,8 @@ class Product extends BaseLoop
* ie : attribute_non_strict_match="promo,new" * 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. * 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="*" * you can set all the attributes as non strict : attribute_non_strict_match="*"
*
* In order to allow such a process, we will have to make a LEFT JOIN foreach of the following case.
*/ */
new Argument( new Argument(
'attribute_non_strict_match', 'attribute_non_strict_match',
@@ -144,6 +146,7 @@ class Product extends BaseLoop
$attributeNonStrictMatch = $this->getAttribute_non_strict_match(); $attributeNonStrictMatch = $this->getAttribute_non_strict_match();
$isPSELeftJoinList = array(); $isPSELeftJoinList = array();
$isProductPriceLeftJoinList = array();
$id = $this->getId(); $id = $this->getId();
@@ -235,16 +238,17 @@ class Product extends BaseLoop
if(null !== $min_price) { if(null !== $min_price) {
$isPSELeftJoinList[] = 'is_min_price'; $isPSELeftJoinList[] = 'is_min_price';
$isProductPriceLeftJoinList['is_min_price'] = 'min_price_data';
$minPriceJoin = new Join(); $minPriceJoin = new Join();
$minPriceJoin->addExplicitCondition(ProductSaleElementsTableMap::TABLE_NAME, 'ID', 'min_price_pse', ProductPriceTableMap::TABLE_NAME, 'PRODUCT_SALE_ELEMENTS_ID', 'is_min_price'); $minPriceJoin->addExplicitCondition(ProductSaleElementsTableMap::TABLE_NAME, 'ID', 'is_min_price', ProductPriceTableMap::TABLE_NAME, 'PRODUCT_SALE_ELEMENTS_ID', 'min_price_data');
$minPriceJoin->setJoinType(Criteria::LEFT_JOIN); $minPriceJoin->setJoinType(Criteria::LEFT_JOIN);
$search->joinProductSaleElements('min_price_pse', Criteria::LEFT_JOIN) $search->joinProductSaleElements('is_min_price', Criteria::LEFT_JOIN)
->addJoinObject($minPriceJoin) ->addJoinObject($minPriceJoin)
->condition('in_promo', '`min_price_pse`.promo'. Criteria::EQUAL .'1') ->condition('in_promo', '`is_min_price`.promo'. Criteria::EQUAL .'1')
->condition('not_in_promo', '`min_price_pse`.promo'. Criteria::NOT_EQUAL .'1') ->condition('not_in_promo', '`is_min_price`.promo'. Criteria::NOT_EQUAL .'1')
->condition('min_promo_price', '`is_min_price`.promo_price' . Criteria::GREATER_EQUAL . '?', $min_price, \PDO::PARAM_STR) ->condition('min_promo_price', '`min_price_data`.promo_price' . Criteria::GREATER_EQUAL . '?', $min_price, \PDO::PARAM_STR)
->condition('min_price', '`is_min_price`.price' . Criteria::GREATER_EQUAL . '?', $min_price, \PDO::PARAM_STR) ->condition('min_price', '`min_price_data`.price' . Criteria::GREATER_EQUAL . '?', $min_price, \PDO::PARAM_STR)
->combine(array('in_promo', 'min_promo_price'), Criteria::LOGICAL_AND, 'in_promo_min_price') ->combine(array('in_promo', 'min_promo_price'), Criteria::LOGICAL_AND, 'in_promo_min_price')
->combine(array('not_in_promo', 'min_price'), Criteria::LOGICAL_AND, 'not_in_promo_min_price') ->combine(array('not_in_promo', 'min_price'), Criteria::LOGICAL_AND, 'not_in_promo_min_price')
->where(array('not_in_promo_min_price', 'in_promo_min_price'), Criteria::LOGICAL_OR); ->where(array('not_in_promo_min_price', 'in_promo_min_price'), Criteria::LOGICAL_OR);
@@ -254,16 +258,17 @@ class Product extends BaseLoop
if(null !== $max_price) { if(null !== $max_price) {
$isPSELeftJoinList[] = 'is_max_price'; $isPSELeftJoinList[] = 'is_max_price';
$isProductPriceLeftJoinList['is_max_price'] = 'max_price_data';
$minPriceJoin = new Join(); $minPriceJoin = new Join();
$minPriceJoin->addExplicitCondition(ProductSaleElementsTableMap::TABLE_NAME, 'ID', 'max_price_pse', ProductPriceTableMap::TABLE_NAME, 'PRODUCT_SALE_ELEMENTS_ID', 'is_max_price'); $minPriceJoin->addExplicitCondition(ProductSaleElementsTableMap::TABLE_NAME, 'ID', 'is_max_price', ProductPriceTableMap::TABLE_NAME, 'PRODUCT_SALE_ELEMENTS_ID', 'max_price_data');
$minPriceJoin->setJoinType(Criteria::LEFT_JOIN); $minPriceJoin->setJoinType(Criteria::LEFT_JOIN);
$search->joinProductSaleElements('max_price_pse', Criteria::LEFT_JOIN) $search->joinProductSaleElements('is_max_price', Criteria::LEFT_JOIN)
->addJoinObject($minPriceJoin) ->addJoinObject($minPriceJoin)
->condition('in_promo', '`max_price_pse`.promo'. Criteria::EQUAL .'1') ->condition('in_promo', '`is_max_price`.promo'. Criteria::EQUAL .'1')
->condition('not_in_promo', '`max_price_pse`.promo'. Criteria::NOT_EQUAL .'1') ->condition('not_in_promo', '`is_max_price`.promo'. Criteria::NOT_EQUAL .'1')
->condition('min_promo_price', '`is_max_price`.promo_price' . Criteria::LESS_EQUAL . '?', $max_price, \PDO::PARAM_STR) ->condition('min_promo_price', '`max_price_data`.promo_price' . Criteria::LESS_EQUAL . '?', $max_price, \PDO::PARAM_STR)
->condition('max_price', '`is_max_price`.price' . Criteria::LESS_EQUAL . '?', $max_price, \PDO::PARAM_STR) ->condition('max_price', '`max_price_data`.price' . Criteria::LESS_EQUAL . '?', $max_price, \PDO::PARAM_STR)
->combine(array('in_promo', 'min_promo_price'), Criteria::LOGICAL_AND, 'in_promo_max_price') ->combine(array('in_promo', 'min_promo_price'), Criteria::LOGICAL_AND, 'in_promo_max_price')
->combine(array('not_in_promo', 'max_price'), Criteria::LOGICAL_AND, 'not_in_promo_max_price') ->combine(array('not_in_promo', 'max_price'), Criteria::LOGICAL_AND, 'not_in_promo_max_price')
->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);
@@ -290,19 +295,46 @@ class Product extends BaseLoop
*/ */
if(count($isPSELeftJoinList) == 0) { if(count($isPSELeftJoinList) == 0) {
//
$isPSELeftJoinList[] = "global"; $isPSELeftJoinList[] = "global";
$search->joinProductSaleElements('global', Criteria::LEFT_JOIN); $search->joinProductSaleElements('global', Criteria::LEFT_JOIN);
} if(count($isProductPriceLeftJoinList) == 0) {
$isProductPriceLeftJoinList['global'] = 'global_price_data';
$minPriceJoin = new Join();
$minPriceJoin->addExplicitCondition(ProductSaleElementsTableMap::TABLE_NAME, 'ID', 'global', ProductPriceTableMap::TABLE_NAME, 'PRODUCT_SALE_ELEMENTS_ID', 'global_price_data');
$minPriceJoin->setJoinType(Criteria::LEFT_JOIN);
$search->addJoinObject($minPriceJoin);
} }
$booleanMatchesPromoList = array(); /*
$booleanMatchesNewnessList = array(); * we need to test all promo field from our previous conditions. Indeed ie:
* product P0, attributes color : red
* P0red is in promo and is the only attribute combinaton available.
* so the product might be consider as in promo (in outputs and ordering)
* We got the following loop to display in promo AND new product but we don't care it's the same attribute which is new and in promo :
* {loop type="product" promo="1" new="1" attribute_non_strict_match="promo,new"} {/loop}
* our request will so far returns 1 line
*
* is_promo.ID | is_promo.PROMO | is_promo.NEWNESS | is_new.ID | is_new.PROMO | is_new.NEWNESS
* NULL NULL NULL red_id 1 0
*
* So that we can say the product is in global promo only with is_promo.PROMO, we must acknowledge it with (is_promo.PROMO OR is_new.PROMO)
*/
$booleanMatchedPromoList = array();
$booleanMatchedNewnessList = array();
foreach($isPSELeftJoinList as $isPSELeftJoin) { foreach($isPSELeftJoinList as $isPSELeftJoin) {
$booleanMatchesPromoList[] = '`' . $isPSELeftJoin . '`.PROMO'; $booleanMatchedPromoList[] = '`' . $isPSELeftJoin . '`.PROMO';
$booleanMatchesNewnessList[] = '`' . $isPSELeftJoin . '`.NEWNESS'; $booleanMatchedNewnessList[] = '`' . $isPSELeftJoin . '`.NEWNESS';
} }
$search->withColumn('MAX(' . implode(' OR ', $booleanMatchesPromoList) . ')', 'main_product_is_promo'); $booleanMatchedPriceList = array();
$search->withColumn('MAX(' . implode(' OR ', $booleanMatchesNewnessList) . ')', 'main_product_is_new'); foreach($isProductPriceLeftJoinList as $pSE => $isProductPriceLeftJoin) {
$booleanMatchedPriceList[] = 'CASE WHEN `' . $pSE . '`.PROMO=1 THEN `' . $isProductPriceLeftJoin . '`.PROMO_PRICE ELSE `' . $isProductPriceLeftJoin . '`.PRICE END';
}
$search->withColumn('MAX(' . implode(' OR ', $booleanMatchedPromoList) . ')', 'main_product_is_promo');
$search->withColumn('MAX(' . implode(' OR ', $booleanMatchedNewnessList) . ')', 'main_product_is_new');
$search->withColumn('MAX(' . implode(' OR ', $booleanMatchedPriceList) . ')', 'real_highest_price');
$search->withColumn('MIN(' . implode(' OR ', $booleanMatchedPriceList) . ')', 'real_lowest_price');
$current = $this->getCurrent(); $current = $this->getCurrent();
@@ -427,10 +459,10 @@ class Product extends BaseLoop
$search->addDescendingOrderByColumn(\Thelia\Model\Map\ProductI18nTableMap::TITLE); $search->addDescendingOrderByColumn(\Thelia\Model\Map\ProductI18nTableMap::TITLE);
break; break;
case "min_price": case "min_price":
$search->addAscendingOrderByColumn('real_price', Criteria::ASC); $search->addAscendingOrderByColumn('real_lowest_price', Criteria::ASC);
break; break;
case "max_price": case "max_price":
$search->addDescendingOrderByColumn('real_price'); $search->addDescendingOrderByColumn('real_lowest_price');
break; break;
case "manual": case "manual":
if(null === $category || count($category) != 1) if(null === $category || count($category) != 1)