Properties/Templates of categories with >1 categories

Creating and modifying plugins.
User avatar
Don Chambers
Regular
Posts: 3638
Joined: Mon Feb 13, 2006 2:40 am
Location: Chicago, IL, USA
Contact:

Properties/Templates of categories with >1 categories

Post by Don Chambers » Sun Nov 25, 2007 6:30 pm

I am trying to figure out a method to "feature" entries. One possibility was the creation of a category "featured", in addition to my normal categories. An entry might start off in its regular category, but occasionall, I might modify the entry to also belong to the category "featured".

I need to be able to change the template (actually, the template options) by category. So, for my regular categories, I have each category assigned to the same template (BP), but using different options. Works fine.... until I assign an entry to this second category "featured". That category has not, and will not, be given any unique template or template options. The moment an entry belongs to more than a single category, the template options for it's "primary" category no longer apply. This happens regardless of the order of the "Properties/Templates of Categories" and "Category Assignment" plugins.

1) What needs to happen to keep unique template options by category when an entry belongs to more than one category???

2) Unique template options by category does not seem to work for sub-categories. Any chance of that happening?

User avatar
garvinhicking
Core Developer
Posts: 30020
Joined: Tue Sep 16, 2003 9:45 pm
Location: Cologne, Germany
Contact:

Re: Properties/Templates of categories with >1 categorie

Post by garvinhicking » Mon Nov 26, 2007 11:16 am

Hi!

That's true. How should a plugin detect when an entry belongs to multiple entries, which one to use? There is not "First category", because category assignments are all equal. That's why it resorts to the default template.

So, you'll definitely need to assign that entry then only to a single entry, or create your own custom plugin for it (modify the plugin and hardcode your category name into the PHP detection routine).

2) Unique template options by category does not seem to work for sub-categories. Any chance of that happening?


This should work, a sub-category is just the same like a category - they both have a single ID by which the detection is done.

However, subcategories do not inherit any template options. You need to assign template options to each subcategory on its own.

Regards,
Garvin
# Garvin Hicking (s9y Developer)
# Did I help you? Consider making me happy: http://wishes.garv.in/
# or use my PayPal account "paypal {at} supergarv (dot) de"
# My "other" hobby: http://flickr.garv.in/

User avatar
Don Chambers
Regular
Posts: 3638
Joined: Mon Feb 13, 2006 2:40 am
Location: Chicago, IL, USA
Contact:

Post by Don Chambers » Mon Nov 26, 2007 4:26 pm

Garvin - If the Properties/Templates of Categories cannot determine which category to use if there is more than one, could it contain an option to ignore certain categories, perhaps by selecting them from a list?

User avatar
garvinhicking
Core Developer
Posts: 30020
Joined: Tue Sep 16, 2003 9:45 pm
Location: Cologne, Germany
Contact:

Post by garvinhicking » Mon Nov 26, 2007 4:45 pm

Hi!

Don Chambers wrote:Garvin - If the Properties/Templates of Categories cannot determine which category to use if there is more than one, could it contain an option to ignore certain categories, perhaps by selecting them from a list?


Hm, would that really be useful? Then you must maintain your list of ignored categories, that sounds very clumsy to me...

I think this is a very specific issue you're trying to do...I really think a custom PHP plugin is the way it should be dealt with, I don't think a user-interface could properly show that...

Regards,
Garvin
# Garvin Hicking (s9y Developer)
# Did I help you? Consider making me happy: http://wishes.garv.in/
# or use my PayPal account "paypal {at} supergarv (dot) de"
# My "other" hobby: http://flickr.garv.in/

User avatar
Don Chambers
Regular
Posts: 3638
Joined: Mon Feb 13, 2006 2:40 am
Location: Chicago, IL, USA
Contact:

Post by Don Chambers » Mon Nov 26, 2007 5:42 pm

Now that I have looked further, I agree. Forget about it for now. Thanks though!! :)

User avatar
Don Chambers
Regular
Posts: 3638
Joined: Mon Feb 13, 2006 2:40 am
Location: Chicago, IL, USA
Contact:

Post by Don Chambers » Fri Nov 30, 2007 11:23 pm

Garvin - I know you think this might be clumsy, but I see value in the ability to switch templates based on category, but I still need multiple categories.

Ideally, it would be as I described before..... identifying, from a list, categories that I want to be ignored by the plugin. However, if that isn't something that can be incorporated into the plugin, how can I eliminate category id's 3, 7 & 12 from this:

Code: Select all

        if ($serendipity['GET']['id']) {
            $entry = serendipity_fetchEntry('id', $serendipity['GET']['id']);
            if (count($entry['categories']) == 1) {
                if (serendipity_db_bool($this->get_config('fixcat'))) {
                    $serendipity['GET']['category'] = (int)$entry['categories'][0]['categoryid'];
                    header('X-FixEntry-Cat: true');
                }
                return (int)$entry['categories'][0]['categoryid'];
            }
        }

User avatar
garvinhicking
Core Developer
Posts: 30020
Joined: Tue Sep 16, 2003 9:45 pm
Location: Cologne, Germany
Contact:

Post by garvinhicking » Fri Nov 30, 2007 11:28 pm

Hi!

Code: Select all

if ($serendipity['GET']['id']) {
    $entry = serendipity_fetchEntry('id', $serendipity['GET']['id']);
    $last_cat = 0;
    if (is_array($entry['categories'])) {
        $remove_cat = array('3', '7', '12');
        foreach($entry['categories'] AS $idx => $cat) {
            if ($cat['categoryid'], $remove_cat)) {
                unset($entry['categories'][$idx]);
            } else {
                $last_cat = $idx;
            }
        }
    }
   
    if (count($entry['categories']) > 0) {
        if (serendipity_db_bool($this->get_config('fixcat'))) {
            $serendipity['GET']['category'] = (int)$entry['categories'][$last_cat]['categoryid'];
            header('X-FixEntry-Cat: true');
        }
        return (int)$entry['categories'][$last_cat]['categoryid'];
    }
}
# Garvin Hicking (s9y Developer)
# Did I help you? Consider making me happy: http://wishes.garv.in/
# or use my PayPal account "paypal {at} supergarv (dot) de"
# My "other" hobby: http://flickr.garv.in/

User avatar
Don Chambers
Regular
Posts: 3638
Joined: Mon Feb 13, 2006 2:40 am
Location: Chicago, IL, USA
Contact:

Post by Don Chambers » Sat Dec 01, 2007 2:03 am

Thanks Garvin - based on your input, the entire function now looks like this (I removed category 12):

Code: Select all

    function getID() {
        global $serendipity;

        if ($serendipity['GET']['category'] && !isset($serendipity['GET']['id'])) {
            return (int)$serendipity['GET']['category'];
        }

        if ($serendipity['GET']['id']) {
            $entry = serendipity_fetchEntry('id', $serendipity['GET']['id']);
            $last_cat = 0;
            if (is_array($entry['categories'])) {
                $remove_cat = array('3', '7');
                foreach($entry['categories'] AS $idx => $cat) {
                    if ($cat['categoryid'], $remove_cat)) {
                        unset($entry['categories'][$idx]);
                    } else {
                        $last_cat = $idx;
                    }
                }
            }
   
            if (count($entry['categories']) > 0) {
                if (serendipity_db_bool($this->get_config('fixcat'))) {
                    $serendipity['GET']['category'] = (int)$entry['categories'][$last_cat]['categoryid'];
                    header('X-FixEntry-Cat: true');
                }
                return (int)$entry['categories'][$last_cat]['categoryid'];
            }
        }

        return 'default';
    }


I get the following error: Parse error: syntax error, unexpected ',' on line 130. Line 130 is:

Code: Select all

if ($cat['categoryid'], $remove_cat)) {

User avatar
Don Chambers
Regular
Posts: 3638
Joined: Mon Feb 13, 2006 2:40 am
Location: Chicago, IL, USA
Contact:

Post by Don Chambers » Sat Dec 01, 2007 5:39 pm

Don Chambers wrote: Line 130 is:

Code: Select all

if ($cat['categoryid'], $remove_cat)) {


Well, it has taken quite awhile, but I think I tracked it down. Is line 130 supposed to be this??:

Code: Select all

 if (in_array($cat['categoryid'], $remove_cat)) { 

User avatar
Don Chambers
Regular
Posts: 3638
Joined: Mon Feb 13, 2006 2:40 am
Location: Chicago, IL, USA
Contact:

Post by Don Chambers » Sat Dec 01, 2007 8:41 pm

I'm just going to answer my own question. YES - the "in_array" was the missing piece! Thank you very much Garvin for the original code! When I find the time, I want to see if I can work out a backend ability to select the categories I want to "ignore".

Do not underestimate the usefulness of this - the scenario I needed this for was as follows:

Most entries are categorized for a primary purpose, and for that purpose, an entry will never be in multiple categories. In otherwords, an entry will fall into the category Red, Blue, Green, Yellow, etc. It cannot be Red AND Green. Only one category will apply for this primary purpose.

However, each entry MIGHT also fall into additional categories, like "featured", "recommended" etc.

I only want the template change for that first category... for all "blue" entries, I want my blue template. However, I want the ability to list all entries that are "featured", inclusive of all Red, Blue, Green, etc. It is for these categories that I want my default template.

Hope that makes sense, because I see this concept being very valuable. Without the ability to ignore these "secondary" categories (featured, recommended, etc), I cannot switch the template based on the my "primary" category.

I realize this means I need to manage my list of "ignored" categories, but those are going to be very few compared to what I am referring to as my "primary" category, which will be numerous.

User avatar
garvinhicking
Core Developer
Posts: 30020
Joined: Tue Sep 16, 2003 9:45 pm
Location: Cologne, Germany
Contact:

Post by garvinhicking » Sun Dec 02, 2007 3:58 pm

Hi!

Ah, terribly sorry. Missed the in_array(),yes. Good debugging skills! :)

Regards,
Garvin
# Garvin Hicking (s9y Developer)
# Did I help you? Consider making me happy: http://wishes.garv.in/
# or use my PayPal account "paypal {at} supergarv (dot) de"
# My "other" hobby: http://flickr.garv.in/

User avatar
judebert
Regular
Posts: 2478
Joined: Sat Oct 15, 2005 6:57 am
Location: Orlando, FL
Contact:

Post by judebert » Mon Dec 03, 2007 1:46 am

I've been thinking about this for a while. It seems to me that entries with multiple categories fall into to three cases: where only one of the categories has a specified template, where more than one has a specified template, and where none have a specified template.

Where only one category has a specified template, we could use its template. For the other cases, the default template would have to be used. This would eliminate the need to keep a list of "ignored" categories -- just don't assign those categories a template.

Code: Select all

    function getID() {
        global $serendipity;

        if ($serendipity['GET']['category'] && !isset($serendipity['GET']['id'])) {
            return (int)$serendipity['GET']['category'];
        }

        if ($serendipity['GET']['id']) {
            $entry = serendipity_fetchEntry('id', $serendipity['GET']['id']);

            // Find all the categories that have custom templates
            $cids = serendipity_db_query("SELECT categoryid FROM {$serendipity['dbPrefix']}categorytemplates");
            if (!is_array($cids)) {
                    $cids = array($cids);
            }

            // Find all the categories of this entry that have custom templates
            $custom = array();
            foreach($entry['categories'] AS $idx => $cat) {
                if (in_array($cat['categoryid'], $cids)) {
                  $custom[] = $cat['categoryid'];
                }
            }

            // Set up and return the custom category
            if (count($custom) == 1) {
                if (serendipity_db_bool($this->get_config('fixcat'))) {
                    $serendipity['GET']['category'] = (int)$custom[0];
                    header('X-FixEntry-Cat: true');
                }
                return (int)$custom[0];
            }
        }

        return 'default';
    }


If you prefer the "last category" thing, which provides an idea of precedence, just change the custom code thusly:

Code: Select all

            // Find all the categories of this entry that have custom templates
            $custom = false;
            foreach($entry['categories'] AS $idx => $cat) {
                if (in_array($cat['categoryid'], $cids)) {
                  $custom = $cat['categoryid'];
                }
            }

            // Set up and return the custom category
            if ($custom !== false) {
                if (serendipity_db_bool($this->get_config('fixcat'))) {
                    $serendipity['GET']['category'] = (int)$custom;
                    header('X-FixEntry-Cat: true');
                }
                return (int)$custom;
            }
        }


Either way, you get to keep both custom templates and multiple categories. The only performance hit is a single database lookup, which we might even alleviate by setting a property when the template assignments change.
Judebert
---
Website | Wishlist | PayPal

User avatar
Don Chambers
Regular
Posts: 3638
Joined: Mon Feb 13, 2006 2:40 am
Location: Chicago, IL, USA
Contact:

Post by Don Chambers » Mon Dec 03, 2007 4:22 am

Jude - thanks a bunch for your input on this issue! Unfortunately, after 6 hours of NFL football, and the beers that go with that, I cannot fully comprehend what you are doing right now! :lol:

However, if there is a way to not set a list of categories to "ignore", I guess I am for that...... as long as it can still do what I am now doing with the previously posted code.

1) the site is defined with a template. Any category that does not define its own template, or for page views that are not category-specific (archives, static pages, etc) uses this same "default" template.

2) If an entry has a SINGLE category, it can define its own template.

3) If an entry has MULTIPLE categories, the entry will use the template that is defined by the ONLY category to which it belongs which HAS defined a template. I suppose there needs to be some logic for how to handle the case that an entry belongs to more than one category, and more than one of those categories has defined a template.

So, how does your code fit with my explanation above?

For what it is worth, I cannot help if there still might be value to specifically identifying categories to "ignore"... it calls a bit of attention to the fact.

Another option is that the template plugin has a checkbox in the categories backend that does something like "Category has top priority for template definition"... or something like that.

User avatar
judebert
Regular
Posts: 2478
Joined: Sat Oct 15, 2005 6:57 am
Location: Orlando, FL
Contact:

Post by judebert » Tue Dec 04, 2007 3:28 am

Yes, it fits all three categories. In fact, it does exactly that.

First it grabs a list of all the categories that have custom templates defined.

Then it sorts through the categories that this current entry is included in. Instead of removing all ignored categories, though, it includes all categories with a custom template.

If the entry has only one custom template category, that's used. It if has no custom template categories, default is used. If it has more than one, well... we need to decide what to do at that point. The standard code uses the default template, but I also provided an example that does the same thing your code did: use the last category found. That's a kind of priority, since it uses whatever the database returns last (maybe Garvin knows what that will be; I'm guessing it's random).

We could also add some properties and a bit of code to determine which template to use in the multiple-template case. We could probably reuse the plugin code that lets you move them up and down...
Judebert
---
Website | Wishlist | PayPal

User avatar
Don Chambers
Regular
Posts: 3638
Joined: Mon Feb 13, 2006 2:40 am
Location: Chicago, IL, USA
Contact:

Post by Don Chambers » Tue Dec 04, 2007 3:43 am

I think this is great Jude!!!! Kudos. Now we need to sell Garvin on the idea.

OH GARVIN!!!!!! You listening? Anyone else? I think this concept of preserving template switching with multiple categories is important, so any and all chime in.

As far as determining priority if more than one category has a defined template is tricky - not just from a script perspective, but from a logical one as well.

The "last" category does not, IMHO, really make that much sense.... afterall, what is last? ID?? Alphabetical name? I agree there should be SOME priority, if we can find a way to set that, but if not, the fallback could be the default template... but again, if there is a way to set a priority, I think that would be superior. Just not sure how only ONE category can be set as a priority in the various combinations possible (ie, combinations of how a single entry can belong to multiple categories).

Post Reply