UserPreferences

SubCategories


SubCategories Plugin Documentation

  1. SubCategories Plugin Documentation
    1. Installation
    2. Setup
    3. Template Usage
    4. API Usage

Installation

Download one of the following files:

And install the files contained within as follows:

Setup

Click the link provided for SubCategories in the MovableType Main Menu to bring up the setup interface. If you are using a version of MovableType earlier than 3.0, you will need to manually load mt-sc.cgi in your browser.

If the link for the plugin does not appear, please verify that all files are installed in the correct locations according to the Installation section.

To set a parent/child relationship, first scroll to the blog in which you wish to set that relationship. Then, select the parent category from the first dropdown list and the child category from the second. Click the Set button and the child category will be set as a subcategory of the parent if there are no problems.

To remove a parent/child relationship, click the unset parent link next to any child category.

To configure the SubCategories options, enter the desired Category Label Delimeter and check the checkbox if you would like to try the Parent Category Archive Rebuilding feature.

Category Label Delimeter

This feature provides the ability to specifiy a category hierarchy within the label of a single category in the MovableType category creation interface.

For example, say you wanted to create the following category hierarchy, and none of these categories currently exist.

To start with, create a category through MT with the following label (assuming the default Category Label Delimeter of '::'):

Alpha :: Beta :: Delta

To verify the hierarchy creation, bring up the SubCategories configuration interface and verify that the following hierarchy has been created:

There are now two category labels that you can use to add Gamma into the category hierarchy:

  • Alpha :: Beta :: Gamma

  • Beta :: Gamma

  • The latter is preferable as the Alpha -> Beta relationship has already been established.

    Parent Category Archive Rebuilding

    If enabled, when an entry is saved with a primary category defined (this does not affect secondary categories), each of the category archives for all of the ancestor categories 1 will be rebuilt.

    This is an experimental feature currently, as the plugin must create a new instance of the main MovableType class within itself to do the rebuilding. This has been submitted to SixApart and will be addressed in a future release.

    Template Usage

    MTSubCategories

    MTSubCategories is a MTCategories replacement that will handle the subcategories that you define.

    Arguments:

    MTSubCatsIsFirst

    A conditional tag that is evaluated if the current subcategory is the first of its level.

    MTSubCatsIsLast

    A conditional tag that is evaluated if the current subcategory is the last of its level.

    MTSubCatsRecurse

    Recursively call the MTSubCategories container with the subcategories of the current category.

    Arguments

    MTParentCategories

    A container tag that starts with the top level parent of the current category and continues on down the path to the current category with each iteration of the container.

    Arguments:

    MTEntriesWithSubCategories

    A replacement MTEntries container tag that is aware of subcategories. Replace MTEntries with this in your Category Archive Templates to make them include all of the entries for that category's subcategories.

    Arguments:

    MTParentCategory

    A container tag that applies only the immediate parent of the current category.

    MTSubCategoryPath

    A short-cut tag (just a regular tag), that returns as if the following template code were being used:

    <MTParentCategories glue="/"><MTCategoryLabel dirify="1"></MTParentCategories>
    

    MTHasSubCategories

    A conditional tag that is evaluated if the current category has subcategories below it.

    MTHasParentCategory

    A conditional tag that is evaluated if the current category has a parent category above it.

    MTHasNoSubCategories

    A conditional tag that is evaluated if the current category has no subcategories below it.

    MTHasNoParentCategory

    A conditional tag that is evaluated if the current category has no parent category above it. This tag allows you to address the HTML relating to the top-level categories as they have no parents. If you are using nested unordered lists to create a CSS dropdown menu you'll need to apply a CSS id selector to just the root tag (if it were applied to all tags the code would be invalid). Here's how:

    <ul<MTHasNoParentCategory> id="nav"</MTHasNoParentCategory>>
    

    MTTopLevelCategories

    A clone of MTSubCategories, but it always starts at the top level of the category hierarchy.

    MTTopLevelParent

    A container tag that applies only the top level parent category of the current category.

    MTIfIsAncestor

    A conditinal tag that is evaluated only if the current category is an ancestor of the given category (i.e. on a path from the top level categories to the given category, the current category appears).

    Arguments:

    MTIfIsDescendant

    A conditional that that is evaluated only if the current category is a descendant of the given category (i.e. on a path from the top level categories to the current category, the given category appears).

    Arguments:

    Examples

    Category List

    Here is the template code to generate a list of categories using nested unordered lists:

    <MTSubCategories> 
    <MTSubCatIsFirst><ul></MTSubCatIsFirst>
    <li>
    <MTCategoryLabel>
    <MTSubCatsRecurse>
    </li>
    <MTSubCatIsLast></ul></MTSubCatIsLast>
    </MTSubCategories>
    Category Archive File Name

    Here is the template code to generate a file name for a category archive:

    archives/<MTSubCategoryPath>/index.php
    
    Category Breadcrumbs for an Entry

    Here is the template code to generate category breadcrumbs for a given entry:

    <MTEntryCategories glue=", ">
    <MTParentCategories glue = "&rarr; ">
    <a href="<$MTCategoryArchiveLink$>"
       title="<$MTCategoryDescription$>"><$MTCategoryLabel$></a>
    </MTParentCategories>
    </MTEntryCategories>
    

    Custom Category Sorting Method

    Here is an example of a custom category sorting method (placed in a extlib/rayners/CategorySorting.pm in this example):

    package rayners::CategorySorting;
    
    my %category_priorities = (
    # I want 'MT Plugins' to appear before 'MT Brainstorming'
    # followed by the rest
        'MT Plugins' => 1
        'MT Brainstorming' => 2,
    
    # And I want 'SubCategories' to be the first plugin listed,
    # followed by 'Entry' and then the rest of the plugins
    
        'SubCategories' => 1,
        'Entry' => 2,
    );
    
    sub cat_sort ($$) {
      my ($a, $b) = @_;
      
      my $a_pri = $category_priorities{$a->label} || 1000;
      my $b_pri = $category_priorities{$b->label} || 1000;
      unless ($a_pri == 1000 && $b_pri == 1000) {
        # At least one of them has a defined priority
        # so sort on that
        return $a_pri <=> $b_pri;
      }
    
      # Both are the default value (1000)
      # so sort alphabetically
    
      return $a->label cmp $b->label;
    }
    

    And the template code to make use of it:

    <MTSubCategories sort_method="rayners::CategorySorting::cat_sort">
    ...
    </MTSubCategories>
    

    API Usage

    rayners::SubCategory is a subclass of MT::Category that gives a plugin developer access to the data that is created by the SubCategories plugin.

    copy_cat ($cat)

    To create a rayners::SubCategory object from a given MT::Category object:

    my $subcat = rayners::SubCategory->copy_cat ($cat);
    

    parent

    If called in a scalar context, this method will return the parent category as a rayners::SubCategory object, or undef if there is none.

    # Immediate parent
    my $parent = $cat->parent;
    print "Parent is ".$parent->label;
    

    If called in an array context, this method will return the parent categories as an array of rayners::SubCategory objects, with the top level parent at the end of the array, or an empty array if there are none.

    # Array of parents (immediate ... top level)
    my @parents = $cat->parent;
    while (my $parent = pop @parents) {
        print $parent->label." -> ";
    }
    print $cat->label."\n";
    

    children

    This method will return an array of immediate children categories as an array of rayners::SubCategory objects.

    # Array of children
    my @children = $cat->children;
    if (scalar @children) {
        print "Children of ".$cat->label." are: ";
        print join (", ", map { $_->label } @children);
        print "\n";
    }
    

    is_ancestor ($child)

    Returns a true value if the category is on the path from the top level categories to $child. Returns a false value otherwise.

    my $parent_cat = rayners::SubCategory->load ({ label => 'MT Plugins' });
    my $child_cat = rayners::SubCategory->load ({ label => 'SubCategories' });
    
    if ($parent_cat->is_ancestor ($child_cat)) {
      print $parent_cat->label." is an ancestor of ".$child_cat->label."\n";
    }
    

    is_descendant ($parent)

    Returns a true value if $parent is an ancestor of the category. Returns a false value otherwise.

    my $parent_cat = rayners::SubCategory->load ({ label => 'MT Plugins' });
    my $child_cat = rayners::SubCategory->load ({ label => 'SubCategories' });
    
    if ($child_cat->is_descendant ($parent_cat)) {
      print $parent_cat->label." is an ancestor of ".$child_cat->label."\n";
    }
    

    Examples

    Generating a Complete List of SubCategories

    This code will create an array containing all of the SubCategories for a given category, any number of levels down.

    sub complete_subcats {
      my ($cat) = @_;
    
      # The array to return containing all of the children
      my @cats;
    
      # The temporary holding array
      # seeded with the given categories children
      my @kids = $cat->children;
    
      # While there are categories in the holding array
      while (my $c = shift @kids) {
        # Add their children to the holding array
        push @kids, ($c->children);
    
        # Then add them to the array to return
        push @cats, $c;
      }
    
      return @cats;
    }