Ordering bug

Mar 2, 2012 at 3:42 PM

Hi there!

I noticed a bug which orders terms inside taxonomies in a wrong way - it causes terms to be shown inside wrong parents. It happens when you enter hierarchical terms in not a particular order. For example, if you have a following hierarchy:

1. Parent 1
   1.1 Child 1.1
   1.2 Child 1.2
2. Parent 2
   2.1 Child 2.1
   2.2 Child 2.2
3. Parent 3
   3.1 Child 3.1
   3.2 Child 3.2

Now, if you are entering this hierarchy in this order - 2, 1, 3, 3.2, 1.1, 2.2, 3.1, 1.2, 2.1, children will be shown under different parents than they were originally chosen.

The reason for this is that Comparison in TermPart class is guided by FullPath which is basically a path of IDs - NOT the weights. For this reason I changed a TermPart to add a property:

public WeightPart { get; set; }

And changed CompareTo method like this:

public int CompareTo(TermPart other) {
    if(other.Path == this.Path) {
        var weight = Weight.CompareTo(other.Weight);
                
        if(weight != 0) {
            return weight; 
        }
        // if same weight, compare by name
        return this.Name.CompareTo(other.Name);
    }

    return WeightPath.CompareTo(other.WeightPath);
}

The second part of the change is modifying TaxonomyService. It starts by adding this method:

private static void SetWeightPaths(IEnumerable<TermPart> terms)
{
    foreach (var term in terms)
    {
        var path = term.Path;
        var weightPath = term.Weight.ToString();

        while (!string.IsNullOrEmpty(path))
        {
            var parent = terms.Where(t => t.FullPath + "/" == path && t.TaxonomyId == term.TaxonomyId)
                .FirstOrDefault();
            if (parent == null)
                break;

            path = parent.Path;
            weightPath = parent.Weight + "/" + weightPath;
        }

        term.WeightPath = weightPath;
    }
}

And now you have to call it in appropriate times, by changing the following methods:

public IEnumerable<TermPart> GetTerms(int taxonomyId) {
    var list = _contentManager.Query<TermPart, TermPartRecord>()
        .Where(x => x.TaxonomyId == taxonomyId)
        .WithQueryHints(new QueryHints().ExpandRecords<AutoroutePartRecord, TitlePartRecord>())
        .List();

    SetWeightPaths(list);
    return list.OrderBy(t => t);
}
public IEnumerable<TermPart> GetAllTerms() {
    var list = _contentManager.Query<TermPart, TermPartRecord>().List();

    SetWeightPaths(list);

    return list.OrderBy(t => t);
}
public IEnumerable<TermPart> GetTermsForContentItem(int contentItemId, string field = null) {
    var list = String.IsNullOrEmpty(field) 
        ? _termContentItemRepository.Fetch(x => x.TermsPartRecord.ContentItemRecord.Id == contentItemId).Select(t => GetTerm(t.TermRecord.Id))
        : _termContentItemRepository.Fetch(x => x.TermsPartRecord.Id == contentItemId && x.Field == field).Select(t => GetTerm(t.TermRecord.Id));

    SetWeightPaths(list);

    return list.OrderBy(t => t);
}
public IEnumerable<TermPart> GetChildren(TermPart term){
    var rootPath = term.FullPath + "/";

    var list = _contentManager.Query<TermPart, TermPartRecord>()
        .Where(x => x.Path.StartsWith(rootPath))
        .List();

    SetWeightPaths(list);

    return list.OrderBy(t => t);
}
And that's it!