Make WordPress Core

Opened 16 years ago

Closed 16 years ago

#2328 closed enhancement (fixed)

Provide structured access to category list

Reported by: coppit Owned by:
Milestone: 2.1 Priority: normal
Severity: normal Version: 2.0.1
Component: Template Keywords: categories list list_cats bg|has-patch bg|commit
Focuses: Cc:


list_cats is an ugly way to filter the category list. Can you add a filter that passes a category list data structure for filtering, instead of the HTML? As things are now, I have to parse the HTML permalink structure in order to figure out the category, and then rebuild the HTML based on my modifications.

http://comox.textdrive.com/pipermail/wp-hackers/2006-January/004106.html for my original post on wp-hackers.

Attachments (2)

2328.diff (556 bytes) - added by davidhouse 16 years ago.
2328.2.diff (1.4 KB) - added by davidhouse 16 years ago.

Download all attachments as: .zip

Change History (13)

#1 @davidhouse
16 years ago

Attached patch puts the categories array through list_cats_cats before building the list. That should be structured enough.

Notice that you can already manipulate list_cats_exclusions to do what you want:

function list_cats_handler($exs) {
    global $excluded_categories;
    $exs .= 'AND cat_id != ' . implode($excluded_categories, ' AND cat_id != ');

add_filter('list_cats_cats', 'list_cats_handler');

However it'd be nice to have the general, more structured hook available anyway.

16 years ago

#2 @davidhouse
16 years ago

  • Keywords bg|has-patch added
  • Severity changed from normal to enhancement

#3 @davidhouse
16 years ago

Sorry, you'd need to return $exs in that function above.

#4 @davidhouse
16 years ago

  • Keywords bg|commit added

#5 @majelbstoat
16 years ago

  • Keywords bg|has-patch bg|commit removed
  • Milestone set to 2.1
  • Version changed from 2.0 to 2.0.1

This could be deserving of it's own ticket, but it's related to this so...

The $categories argument to wp_list_cats() is useless, because I have to use the $args to pass it, which is a string and $categories in list_cats() is an object array. I could write my own wrapper interface to list_cats(), but offering the same customisation as wp_list_cats() involves duplicating all of its argument handling code, which is a tremendous waste.

The filter in the place you suggest, while useful, does not give us access to $sort_column, $sort_order or $exclusions, which means if we want to generate our own subset of categories to overwrite the given, the outputted list and format might not match the user's expectations.

Three options then:

1) Keep the filter where it is, but add those three arguments as well.
2) Fix wp_list_cats somehow to allow categories to be specified.
3) Remove the categories argument handler from wp_list_cats and move your filter into wp_list_cats, underneath the argument handling code, but before the call to list_cats, so that we can generate our own category subsets.

I like option 3, but Coppit and I might have diverging views on how useful this is...

At the moment, hope you don't mind, but I'd like to remove commit on this patch until an approach that solves both problems can be found.

#6 @davidhouse
16 years ago

  • Keywords bg|has-patch bg|commit added

Let me try to sum up what you're asking for here:

  • A filter that passes the categories to be outputted in an array so they can be modified, some removed or whatever
  • Access to the exclusions list so you can control which categories are output and which aren't (although you could theoretically do this by just removing this from the array that my filter provides)
  • Access to the sort order/column parameters

And the resolutions in order:

  • My filter. Although you rightfully said that the $categories parameter is pointless, if you don't pass it in it will be filled from the DB. So if you pass nothing in then you'll recieve the entire list of categories from the DB if you hook my filter. You can then remove/modify any you like.
  • Filter list_cats_exclusions, as above (although there was a typo in my above comment, the first parameter to the add_filter call was meant to be 'list_cats_exclusions').
  • Start a new bug, as this is completely unrelated to anything so far.

You would have been right to remove the bg|commit tag had the patch not fixed your problem, but I believe it does, so I'm readding it.

#7 @majelbstoat
16 years ago

Let me explain a bit more clearly my position.

Say I would like to return a subset of each category (along with a correct post count), containing only posts written in 2005. This could easily be any other filtering parameter (tags, language, author, etc).

Now, with the solution you have provided in place, I am given an array of all the defined categories plus a full post count for each category, minus any exclusions I make with list_cats_exclusions. However, I don't want to exclude whole categories, just parts of each, so list_cats_exclusions doesn't help.

Using list_cats_cats, I'd be able to look at the array and regenerate a post count for each category based on my criteria. But, I still might end up with categories that have 0 posts. I suppose I could use list_cats_exclusions to exclude those categories but this means calculating the post count twice, once in each function.

A much better solution, I believe, is a unified one that actually provides an opportunity to give list_cats a set of categories that the plugin wants to return, combined with blog author options such as "hide these specific, private categories and order them by how many posts we have". I can't see a good solution to this (not particularly uncommon) problem using the functionality that your patch provides. If you can see an elegant solution to the problem outlined above using your supplied patch, I'd be all for it. And, seeing as wp_list_cats is the only function that calls list_cats, and outputs a structured category list, I believe it is related.

#8 @davidhouse
16 years ago

If the count gets down to 0 for any category, just remove it from the array.

function adjust_cat_counts($cats) {
    foreach ($cats as $k => $cat) {
        $cat->category_count = get_cat_count_after_subsetting($cat);
        if ($cat->category_count <= 0) {
    return $cats;

#9 @majelbstoat
16 years ago

Yep, that would work :) Ok, you convinced me! +1 from me (not that that means too much!)

#10 @davidhouse
16 years ago

Here's a new patch, which adds a get_categories filter to get_categories(), a get_bookmarks filter for get_bookmarks() and a get_pages filter for get_pages(). I'm not using list_cats_cats anymore so I can have a more consistent naming scheme.

16 years ago

#11 @ryan
16 years ago

  • Resolution set to fixed
  • Status changed from new to closed

(In [3691]) List filters from David House. fixes #2328

Note: See TracTickets for help on using tickets.