14

According to Google Code the Component Synchronizer powertool for Tridion 2011 is still a work in progress.

How else can I update all components to reflect a new schema fields default value?

p.s. I should contribute to the Component Synchronizer

As an alternative, I am trying to detect the empty value in a C# TBB Fragment at publish time. If the new field is blank (does not have the default value), then set the value in the package to the default value.

This is a metadata field published to the broker DB, so I can not handle it in DWT etc.. I can not handle it at presentation side for reasons I won't go into. I can not open up 1000+ components to update the value

Will this work?

Item itemComponent = package.GetByName(Package.ComponentName);
var component = engine.GetObject(package.GetValue("Component.ID")) as Component;

if(component.Metadata.SelectSingleNode("//*[local-name()='owner']")!=null)
{
    if(string.IsNullOrWhiteSpace(component.Metadata.SelectSingleNode("//*[local-name()='owner']").InnerText))
    {
       component.Metadata.SelectSingleNode("//*[local-name()='owner']").InnerText = "Chris";
    }
}
package.PushItem("Component", package.CreateTridionItem(ContentType.Component, component));

I have enabled

allowWriteOperationsInTemplates

Thanks

2 Answers 2

11

We have a small command line application we modify as needed to update schemas.

We use core services to call GetListXML on the folder containing the components we want to update:

public XElement GetAllComponents(string folderUri)
{
    var filter = new OrganizationalItemItemsFilterData()
    {
        ItemTypes = new[] { ItemType.Component },
        Recursive = true
    }
    return CORE_SERVICE.GetListXml(folderUri, filter);
}

We then have a simple loop that iterates through each component, checks to see if it uses the schema we want to update and if so we call a simple method to update the schema used by the component (both the starting folder and schema we're updating come from the app's config file but could as easily come from a command line argument.)

We change the code of this method slightly based on what we're trying to update. For instance if we just want to pickup a new field added to the schema we just do a checkout and checkin of the component like so (note we do conduct a simple check to make sure we're only updating 'parent' level components):

public bool UpdateComponentSchema(string componentId)
{
    try
    {
        // get parent level from componentId: tcm:12-234
        var parentLevel = componentId.Split(':')[1].Split('-')[0];
        var parentLocLevel = string.Format("-{0}-", parentLevel);
        var com = CORE_SERVICE.Read(componentId, new ReadOptions()) as ComponentData;
        var parentLocation = com.BluePrintInfo.OwningRepository.IdRef;
        // check parent location
        if (!parentLocation.Contains(parentLocLevel))
            return true;

        var component = CORE_SERVICE.TryCheckOut(componentId, null) as ComponentData;
        if (component != null)
        {
            try
            {
               CORE_SERVICE.CheckIn(componentId, null);
            }
            catch (FaultException fEx)
           {
              if (!fEx.Message.ToLower().Equals("the item is not checked-out.")) throw fEx;
           }
       }
     }
    catch (Exception ex)
    {
       throw ex;
    }
    return true;
}

Interestingly, if you update a schema this way the last modified date of the components don't even change.

If we want to update new fields with a specific value we can easily add code to do that after the code that does the component check-out.

We use the same general concept if we need to perform some sort of bulk update/modification of values in components that cannot be handled from within the CME.

We also perform extensive logging around the calls to UpdateComponentSchema so that we have a good record of the successes and failures. If needed we can have someone go back after the fact and touch the failures by hand but in general as long as we've made sure all components are checked in prior to running the app this runs pretty smoothly.

Usually we have our team in Hyderabad run these types of batch processing jobs for us as they are working during times when our United States based editors and producers are not editing content in the CME.

1
  • 2
    To follow up on a comment within Chris's question, we should probably be contributing to the Component Synchronizer as well. I assume at some point this sort of functionality is needed by everyone running Tridion and it is mildly silly for us all to have our own one-off solutions for the problem. Commented Mar 9, 2013 at 2:59
10

Aside from manual or core service scripts consider the PowerTools PowerShell option, compliments of Dominic Cronin, or Content Porter, especially useful to set defaults field values.

PowerTools 2011 has (a PowerShell Version of) Component Synchronizer. Dominic Cronin created a PowerShell version of Component Synchronizer branched within the PowerTools repository. If interested in helping, definitely reach out to see how we can integrate this into the CME Extension.

Content Porter . I've yet to try it, but Content Porter 2009 SP2 has an option to Synchronize content against Schema before importing.

SDL Live Content explains importing items without their schemas may mean they "may not be valid against the Schema found on the destination Content Manager."

But if you select Synchronize content against Schema before importing, Content Porter will attempt to:

  • Reorder fields to match the [target] Schema
  • Remove fields not present in the [target] Schema
  • Add fields to items, "on the condition that the fields are optional fields, or have a default value, or both."

This handles the typical schema changes, which I've outlined in this post.

Update: I describe Content Porter component synchronization on TridionDeveloper.

Update: Core Service now includes synchronization options (search online or see the documentation).

Warning: any synchronization approach can lead to data loss. Be sure to back-up and test your approach in DEV before automatically changing components. It's called PowerTools for a reason. ;-)

1
  • 2
    Indeed - quite some of the work is done. As Alvin suggests, the personal itch I was scratching was to run the synchroniser from the command line. Basically, the back end of the thing is there now, but it's not integrated into the UI. I do expect to put some effort into that integration in the coming months. Anyway - if you're not a Powershell person, don't be put off. What's built is a .NET assembly with a class you can instantiate and call methods on. The choice of client is up to you. Commented Mar 10, 2013 at 18:23

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.