A better? implementation for UpdateTerms

Developer
Jul 26, 2012 at 11:53 AM

I've run into an issue when using the UpdateTerms method in a certain case:

  1. I have attached 3 TaxonomyFields to the BlogPost type: Categories, Tags and Athletes
  2. I have a ContentHandler derived class called BlogPostPartHandler that handles the OnPublishing event. This handler invokes UpdateTerms when the blog post is published

What happens is that when I hit the Publish button, the TaxonomyFieldDriver will be invoked 3 times, invoking UpdateTerms. The first time the Categories terms will be moved to the end of the Terms of the content item. The second time the Tags terms will be moved to the end. The third time the Athlete terms will be moved to the end.

So far so good, but now the OnPublishing event will be raised. My handler will call UpdateTerms for the Athlete terms. However, because they are now at the end of the Terms list of the content item, UpdateTerms will remove the number of terms to be updated at the start of the list, but right now there are the Categories terms. So I lose my Categories terms.

This problem seems to be easily fixed by changing the implementation as follows:

public void UpdateTerms(ContentItem contentItem, IEnumerable<TermPart> terms, string field) {
            var termsPart = contentItem.As<TermsPart>();

            // removing current terms for specific field
            var fieldIds = termsPart.Terms
                .Where(t => t.Field == field)
                .Select((t, i) => t.TermRecord.Id)
                .OrderByDescending(i => i)
                .ToList();
            
            foreach(var fieldId in fieldIds) {
                var termContentItem = termsPart.Terms.FirstOrDefault(t => t.TermRecord.Id == fieldId);

                if(termContentItem != null)
                    termsPart.Terms.Remove(termContentItem);
            }
            
            // adding new terms list
            foreach(var term in terms) {
                termsPart.Terms.Add( 
                    new TermContentItem {
                        TermsPartRecord = termsPart.Record, 
                        TermRecord = term.Record, Field = field
                    });
            }
        }

Basically, it finds the terms to be removed based on the TermRecord.Id instead of doing it by index.

This has been tested and works and would like to hear any thoughts on this change, e.g. does anyone see any problem with this implementation. If not, I will create a ticket.

Aug 9, 2012 at 3:10 PM

Create away!

Developer
Aug 9, 2012 at 6:17 PM

Thanks for reminding me :)

Developer
Aug 9, 2012 at 6:19 PM

Ticket: http://orchardtaxonomies.codeplex.com/workitem/66