Jump to content

Modification de la navigation à facettes


Recommended Posts

Bonjour,

 

Je souhaite rajouter une petite fonction au module de navigation à facettes, mais je bloque un peu.

 

Tous mes produits ont une "supplier_reference"

Je souhaite pouvoir filtrer en front office avec 3 cases radio :

 

"Tout" (par défaut)

"Produits individuels" -> supplier_reference ne contient pas "B"

"Produits groupés" -> supplier_reference contient "B"

 

J'arrive a faire le filtre "à la main" en modifiant blocklayered.php :

 

function getProductByFilters,

En testant successivement les 3 valeurs de $filtre_ref, ça fonctionne

 

ligne ~2475, pour calculer le bon nombre de produits après filtre

 

 if (version_compare(_PS_VERSION_,'1.5','>'))
  $query_filters_from .= Shop::addSqlAssociation('product', 'p');

 $filtre_ref = 'LIKE "%"'; // SI TOUT
 //$filtre_ref = 'NOT LIKE "%B%"'; // SI INDIVIDUEL
 //$filtre_ref = 'LIKE "%B%"'; // SI GROUPE

 $all_products_out = self::query('
 SELECT p.`id_product` id_product
 FROM `'._DB_PREFIX_.'product` p
 '.$price_filter_query_out.'
 '.$query_filters_from.'
 WHERE 1 '.$query_filters_where.' GROUP BY id_product');

 $all_products_in = self::query('
 SELECT p.`id_product` id_product
 FROM `'._DB_PREFIX_.'product` p
 '.$price_filter_query_in.'
 '.$query_filters_from.'
 WHERE 1 '.$query_filters_where.' AND p.supplier_reference '.$filtre_ref.' GROUP BY id_product');

 

Puis un peu plus bas, modification de la query pour inclure le même filtre :

 

  SELECT
p.*,
'.($alias_where == 'p' ? '' : 'product_shop.*,' ).'
'.$alias_where.'.id_category_default,
pl.*,
i.id_image,
il.legend,
m.name manufacturer_name,
DATEDIFF('.$alias_where.'.`date_add`, DATE_SUB(NOW(), INTERVAL '.(Validate::isUnsignedInt(Configuration::get('PS_NB_DAYS_NEW_PRODUCT')) ? Configuration::get('PS_NB_DAYS_NEW_PRODUCT') : 20).' DAY)) > 0 AS new
  FROM `'._DB_PREFIX_.'category_product` cp
  LEFT JOIN '._DB_PREFIX_.'category c ON (c.id_category = cp.id_category)
  LEFT JOIN `'._DB_PREFIX_.'product` p ON p.`id_product` = cp.`id_product`
  '.$join.'
  LEFT JOIN '._DB_PREFIX_.'product_lang pl ON (pl.id_product = p.id_product)
  LEFT JOIN '._DB_PREFIX_.'image i ON (i.id_product = p.id_product AND i.cover = 1)
  LEFT JOIN '._DB_PREFIX_.'image_lang il ON (i.id_image = il.id_image AND il.id_lang = '.(int)($cookie->id_lang).')
  LEFT JOIN '._DB_PREFIX_.'manufacturer m ON (m.id_manufacturer = p.id_manufacturer)
  WHERE '.$alias_where.'.`active` = 1 AND
  '.(Configuration::get('PS_LAYERED_FULL_TREE') ? 'c.nleft >= '.(int)$parent->nleft.'
  AND c.nright <= '.(int)$parent->nright : 'c.id_category = '.(int)$id_parent).'
  AND c.active = 1
  AND p.supplier_reference '.$filtre_ref.'
  AND pl.id_lang = '.(int)$cookie->id_lang.'
  AND p.id_product IN ('.implode(',', $product_id_list).')'
  .' GROUP BY p.id_product ORDER BY '.Tools::getProductsOrder('by', Tools::getValue('orderby'), true).' '.Tools::getProductsOrder('way', Tools::getValue('orderway')).
  ' LIMIT '.(((int)$this->page - 1) * $n.','.$n));

 

Je modifie blocklayered.tpl et j'ajoute au formulaire :

 

  <input type="radio" name="filtre_ref_radio" value="tout">Tous produits<br />
  <input type="radio" name="filtre_ref_radio" value="indiv">Produits individuels<br />
  <input type="radio" name="filtre_ref_radio" value="pack">Produits en PACK
 </form>

 

Maintenant mon problème est de récupérer la valeur de "filtre_ref_radio" pour la manipuler dans le fichier blocklayered.php, et ainsi faire un test du genre :

 

 if (filtre_ref_radio == 'tout') $filtre_ref = 'LIKE "%"';
 if (filtre_ref_radio == 'indiv') $filtre_ref = 'NOT LIKE "%B%"';
 if (filtre_ref_radio == 'pack') $filtre_ref = 'LIKE "%B%"';

 

Mais je ne trouve pas comment passer cette valeur... Je regarde actuellement dans blocklayered.js, mais c'est un peu confus.

 

Merci d'avance à ceux qui voudront m'aider, les modifications que je fais actuellement sont sur un serveur local, au besoin je peux donner l'accès si vous voulez regarder, dites-moi.

Edited by afipc (see edit history)
Link to comment
Share on other sites

Dans blocklayered.js on trouve 2 sections relatives aux boutons radio :

 

// Click on checkbox
$('#layered_form input[type=checkbox], #layered_form input[type=radio], #layered_form select').live('change', function()
{
 reloadContent();
});

 

$('#layered_block_left .radio').live('click', function() {
 var name = $(this).attr('name');
 $.each($(this).parent().parent().find('input[type=button]'), function (it, item) {
  if ($(item).hasClass('on') && $(item).attr('name') != name) {
   $(item).click();
  }
 });
 return true;
});

 

Dans la 2ème fonction il est question du "name" de l'élément, mais j'ai du mal à comprendre ce qu'elle fait.

Ensuite, comme le montre la 1ère fonction, il faut regarder dans la "function reloadContent(params_plus)" qui forme une query ajax pour adapter l'affichage, là encore c'est assez abstrait...

Link to comment
Share on other sites

J'y suis presque... Pour récupérer la valeur de mon bouton radio dans blocklayerred.php :

 

 if ($_GET['filtre_ref_radio'] == 'tout' OR $_GET['filtre_ref_radio'] == '') $filtre_ref = 'LIKE "%"';
 if ($_GET['filtre_ref_radio'] == 'indiv') $filtre_ref = 'NOT LIKE "%B%"';
 if ($_GET['filtre_ref_radio'] == 'pack') $filtre_ref = 'LIKE "%B%"';

 

Le test si le radio est vide à la première ligne sert à forcer l'affichage de "tout" par défaut.

 

Je souhaite que la coche soit sélectionnée pour le filtre en cours, j'envoie une variable au tpl via smarty, dans la function generateFiltersBlock($selected_filters) :

 

  if ($_GET['filtre_ref_radio'] == '') $smarty->assign('filtre_ref_coche', 'tout');
  else $smarty->assign('filtre_ref_coche', $_GET['filtre_ref_radio']);

  return $this->display(__FILE__, 'blocklayered.tpl');

 

Et mon formulaire devient :

 

  <input type="radio" name="filtre_ref_radio" value="tout" {if $filtre_ref_coche == 'tout'}checked{/if}>Tous produits<br />
  <input type="radio" name="filtre_ref_radio" value="indiv" {if $filtre_ref_coche == 'indiv'}checked{/if}>Produits individuels<br />
  <input type="radio" name="filtre_ref_radio" value="pack" {if $filtre_ref_coche == 'pack'}checked{/if}>Produits en PACK

 

Comme j'ai le filtre fabricant dans le module, il me reste à trouver comment mettre à jour le nombre de produits par fabricant, ainsi que le nom des fabricants, quand le filtre référence est activé (pour l'instant dans les 3 cas, c'est toujours le nombre de produits total qui apparaît, et tous les noms de fabricants)

Edited by afipc (see edit history)
Link to comment
Share on other sites

Voilà j'ai trouvé, dans la function getFilterBlock($selected_filters = array())

 

Je définis la valeur de ma variable $filtre_ref comme auparavant

 

 if ($_GET['filtre_ref_radio'] == 'tout' OR $_GET['filtre_ref_radio'] == '') $filtre_ref = 'LIKE "%"';
 if ($_GET['filtre_ref_radio'] == 'indiv') $filtre_ref = 'NOT LIKE "%B%"';
 if ($_GET['filtre_ref_radio'] == 'pack') $filtre_ref = 'LIKE "%B%"';

 $filter_blocks = array();
 foreach ($filters as $filter)

 

Puis plus bas je modifie la query qui va chercher les fabricants et les quantités

 

   case 'manufacturer':
 $sql_query['select'] = 'SELECT m.name, COUNT(DISTINCT p.id_product) nbr, m.id_manufacturer ';
 $sql_query['from'] = '
 FROM `'._DB_PREFIX_.'category_product` cp
 INNER JOIN  `'._DB_PREFIX_.'category` c ON (c.id_category = cp.id_category)
 INNER JOIN '._DB_PREFIX_.'product p ON (p.id_product = cp.id_product)
 INNER JOIN '._DB_PREFIX_.'manufacturer m ON (m.id_manufacturer = p.id_manufacturer) ';
 $sql_query['where'] = 'WHERE
 '.(Configuration::get('PS_LAYERED_FULL_TREE') ? 'c.nleft >= '.(int)$parent->nleft.'
 AND c.nright <= '.(int)$parent->nright : 'c.id_category = '.(int)$id_parent).'
 AND c.active = 1
 AND p.supplier_reference '.$filtre_ref.'
 AND '.$alias.'.active = 1';
 $sql_query['group'] = ' GROUP BY p.id_manufacturer ';

 

Je crois que c'est tout bon comme ça

Link to comment
Share on other sites

Dans le formulaire, mettre le texte des boutons radios entre :

<label for="...">...</label>

 

Permet de cliquer aussi sur ce texte pour valider le choix, en plus du bouton rond.

Il faut aussi donner un ID pour chaque radio, que l'on renseigne dans for="..."

Edited by afipc (see edit history)
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...