13 replies [Last post]
setfree's picture
Offline
Uber Donor
Joined: 12/16/2007
Juice: 436
Was this information Helpful?

I need to add the ability to filter the product list by a CCK field value. I have done a lot of searching and reading, but am still unsure how to do this. From what I understand, I will need to create a Views view and use exposed filters. This makes sense, except I'm can't figure out how to override Ubercart's default product list.

To be clear: I don't need to change the catalog block or pages -- only the listing when you drill all the way down to the product list (Product Photo, Title, Price & Add to Cart), this is where I need to add the filter to the top of the page.

I found that Ubercart installed a view called "uc_products". I was hoping that I could simply enable this view and it would override the default product list. No luck.

I would really appreciate any help with pointing me in the right direction Smiling

Thanks!

Finbarr's picture
Offline
Joined: 07/13/2009
Juice: 46
Re: Add filter to product list? (Need some direction please)

I want to do almost exactly the same thing.. but there doesn't seem to be any easy way.

setfree's picture
Offline
Uber Donor
Joined: 12/16/2007
Juice: 436
Re: Re: Add filter to product list? (Need some direction please)

I ended up having to hack UberCart core. Sigh. I was able to put in a few hooks into uc_catalog.pages.inc that allowed me to pass in sql overrides and a header into the uc_product_table and it's working okay. I know hacking core is not good but it was the only way I found that I could accomplish what I needed.

Finbarr's picture
Offline
Joined: 07/13/2009
Juice: 46
Re: Re: Re: Add filter to product list? (Need some direction ple

Any chance you could put the code here? I don't know where to start!

setfree's picture
Offline
Uber Donor
Joined: 12/16/2007
Juice: 436
Re: Re: Re: Re: Add filter to product list? (Need some direction

I don't know that what I did was the best to accomplish what I need to, but it works.

This is an excerpt of the code in uc_catalog.pages.inc, the code between //SAO ****** is the hacks that I added. The module_invoke_all() functions gives the uc_catalog module a chance to have other module modify the output. I used hooks in my own module to selectivly modify the SQL queries, arguments for these queries, and output a header at the top of the page.

Example page: http://classappliance.com/appliance-catalog/refrigerators/side-x-side-di...

Hope this helps.

<?php
//..........
$sql = "SELECT DISTINCT(n.nid), n.sticky, n.title, n.created, p.model, p.sell_price, p.ordering
    FROM {node} n
      INNER JOIN {term_node} tn ON n.vid = tn.vid
      INNER JOIN {uc_products} AS p ON n.vid = p.vid
    WHERE tn.tid = %d AND n.status = 1
      AND n.type IN ("
. db_placeholders($types, 'varchar') .") ". $order;

 

$sql_count = "SELECT COUNT(DISTINCT(n.nid))
    FROM {node} n
      INNER JOIN {term_node} tn ON n.vid = tn.vid
      INNER JOIN {uc_products} AS p ON n.vid = p.vid
    WHERE tn.tid = %d
      AND n.status = 1
      AND n.type IN ("
. db_placeholders($types, 'varchar') .")";

//SAO >**************************************************************************************************************
// Created hook to give other modules a chance to modify the SQL queries for the product table and pager
$custom_sql = module_invoke_all('uc_catalog_sql', $types, $order);
if (
$custom_sql[0]) {
  
$sql = $custom_sql[0];
  
$sql_count = $custom_sql[1];  
}
//SAO <**************************************************************************************************************

 

$sql = db_rewrite_sql($sql);
 
$sql_count = db_rewrite_sql($sql_count);
 
$sql_args = array($catalog->tid);

//SAO >**************************************************************************************************************
// Created hook to add $sql_args (SQL Arguments) before calling query
 
$sql_args = module_invoke_all('uc_catalog_sql_args',$sql_args);
//SAO <**************************************************************************************************************
 
 
foreach ($types as $type) {
   
$sql_args[] = $type;
  }
 
$catalog->products = array();
 
$result = pager_query($sql, variable_get('uc_product_nodes_per_page', 12), 0, $sql_count, $sql_args);
  while (
$node = db_fetch_object($result)) {
   
$catalog->products[] = $node->nid;
  }
  if (
count($catalog->products)) {
    if (
count($links)) {
     
$output .= theme('links', $links, array('class' => 'links inline uc-categories')) ."<br />\n";
    }
   
$output .= $catalog->description;

//SAO >**************************************************************************************************************
// Created HOOK to display catalog header used to display list of manufacturers for filtering purposes
 
$catalog_header = module_invoke_all('uc_catalog_header',$catalog->tid);
 
$output .= $catalog_header['header'];
//SAO <**************************************************************************************************************   

   

$output .= theme('uc_catalog_products', $catalog->products);
   
$output .= theme('pager');

//.................
?>
Finbarr's picture
Offline
Joined: 07/13/2009
Juice: 46
Re: Re: Re: Re: Re: Add filter to product list? (Need some direc

Thanks very much for sharing this. The difficulty I have with drupal sometimes is not knowing where to put code. I understand where and why you have put that code there. My question now is, where would you put the functions that are called by the hooks uc_catalog_sql, uc_catalog_sql_args and uc_catalog_header?

setfree's picture
Offline
Uber Donor
Joined: 12/16/2007
Juice: 436
Re: Re: Re: Re: Re: Re: Add filter to product list? (Need some d

They would go in your own module that will handle the hooks to generate your filtering.

For example:

<?php
function YOUR_MODULE_NAME_uc_catalog_sql($types, $order){

if (

$check_if_custom_SQL_Query_is_Needed){
 
// Create your custom SQL queries here
 
return array($sql, $sql_count);       
}
return
FALSE;
}
?>
Finbarr's picture
Offline
Joined: 07/13/2009
Juice: 46
Re: Re: Re: Re: Re: Re: Re: Add filter to product list? (Need so

Ok, thankyou very much for your help. Slowly piecing it together!

Finbarr's picture
Offline
Joined: 07/13/2009
Juice: 46
You don't need to hack core here!

Setfree, I've been pondering this for a couple of weeks, and a solution that is exactly the same is yours, without hacking core, is possible.

In your theme folder, in template.php file, add the function

theme_name_uc_catalog_browse

copy and paste your uc_catalog.pages's theme_uc_catalog_browse function.

You can then replace uc_catalog.pages with the core version.

I have also worked out a way to change the fields displayed in uc_product_table without hacking core, but that's not what you were looking for.

setfree's picture
Offline
Uber Donor
Joined: 12/16/2007
Juice: 436
Re: You don't need to hack core here!

Thank you! This is great information that I will try out soon. It will be great to get rid of the core-hack and keep the same functionality Smiling

setfree's picture
Offline
Uber Donor
Joined: 12/16/2007
Juice: 436
Re: You don't need to hack core here!

Working perfect, thanks for the tip!

justageek's picture
Offline
Bug Finder
Joined: 10/29/2008
Juice: 189
views should have worked, I think

Hey guys, sorry I didn't see this sooner. I think views should have worked perfectly. You should be able to create a simple view selected content type Product and then use the exposed filter on your cck field, as you mentioned.

I have also done similar things with taxonomy menu, which is pretty cool at creating menu blocks from your term vocabularies, and then it lets you drill down on taxonomy url's.

setfree's picture
Offline
Uber Donor
Joined: 12/16/2007
Juice: 436
Re: views should have worked, I think

Yeah, early on I was looking into Views as a solution but it didn't meet some of the criteria. Maybe I misunderstood what would have been involved to use Views and it's exposed filters?

Project Criteria / Troublespots

  • Views would require overriding the current store catalog, including theming, which was already functioning great. The only change needed was to add a 'brand' filter to the bottom level catalog pages.
  • Views doesn't allow creating exposed filter containing a drop-down selection populated with the values of free-form CCK values on it's nodes/products.
  • Views doesn't allow filtering the filter-list to show only values contained in the current catalog category (current view).

I know this is all possible with Views filter overriding, but the time/complexity involved to override the store catalog with Views and then customize the Views filters would have probably exceeded the time to override the UC catalog and insert a custom filter.

justageek's picture
Offline
Bug Finder
Joined: 10/29/2008
Juice: 189
not sure what you mean, so let me try again

"Views doesn't allow creating exposed filter containing a drop-down selection populated with the values of free-form CCK values on it's nodes/products."

You are correct if you mean by free-form that you have a text box where the user just enters the Brand. That's not what I thought you had. If you use a CCK field and create a list of allowed values for that field then present it to the user as a select field, then you can add an exposed filter to the existing Catalog view and choose 'allowed values' as the filter, and views will create a select field on your catalog page that can then be used to filter by Brand. It will apply this filter to the catalog along with any other filter you have added, such as category.

If you don't want to edit the included catalog view, you can copy it and it will pretty much bring all the theming along with it.

But, as you mentioned, if your cck field is a free-form text field, then you are correct that views doesn't do it out of the box. You could, however, create some basic module code with hook_form_alter that would let you create your own html select from the entered values in the database, and you wouldn't have to hack core ubercart fields. Basically, you add your exposed filter to your catalog view, then write a module function that overrides its output and spits out your own html select for filtering. I can find a link to a post about if you you are interested.

It definitely isn't simple, but it is not harder that the custom code you have already done.